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[] =
116 FILETYPES_COLUMN_FILTER = 0,
117 FILETYPES_COLUMN_DESCRIPTION,
118 FILETYPES_COLUMN_CLASS,
119 FILETYPES_COLUMN_WRITABLE,
120 FILETYPES_COLUMN_SIDECAR,
121 FILETYPES_COLUMN_COUNT
124 gchar *format_class_list[] = {
135 /* config memory values */
136 static ConfOptions *c_options = NULL;
143 static GtkWidget *configwindow = NULL;
144 static GtkListStore *filter_store = NULL;
145 static GtkTreeStore *accel_store = NULL;
147 static GtkWidget *safe_delete_path_entry;
149 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
150 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
151 static GtkWidget *color_profile_screen_file_entry;
152 static GtkWidget *external_preview_select_entry;
153 static GtkWidget *external_preview_extract_entry;
155 static GtkWidget *sidecar_ext_entry;
156 static GtkWidget *help_search_engine_entry;
159 #define CONFIG_WINDOW_DEF_WIDTH 700
160 #define CONFIG_WINDOW_DEF_HEIGHT 600
163 *-----------------------------------------------------------------------------
164 * option widget callbacks (private)
165 *-----------------------------------------------------------------------------
168 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
170 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
173 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
175 gint mins_secs_tenths, delay;
177 mins_secs_tenths = c_options->slideshow.delay %
178 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
180 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
181 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
184 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
185 SLIDESHOW_SUBSECOND_PRECISION;
188 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
190 gint hours, secs_tenths, delay;
192 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
193 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
196 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
203 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
205 gint hours_mins, delay;
207 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
209 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
210 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
211 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
213 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
214 SLIDESHOW_SUBSECOND_PRECISION;
218 *-----------------------------------------------------------------------------
219 * sync program to config window routine (private)
220 *-----------------------------------------------------------------------------
223 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
229 buf = gtk_entry_get_text(GTK_ENTRY(entry));
230 if (buf && strlen(buf) > 0)
235 *option = g_strdup(buf);
240 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
242 gchar *accel_path, *accel;
244 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
246 if (accel_path && accel_path[0])
249 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
250 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
260 static void config_window_apply(void)
262 gboolean refresh = FALSE;
267 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
269 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
270 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
271 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
272 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
273 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
274 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
275 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
277 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
278 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
279 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
280 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
281 options->file_ops.no_trash = c_options->file_ops.no_trash;
282 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
283 options->tools_restore_state = c_options->tools_restore_state;
284 options->save_window_positions = c_options->save_window_positions;
285 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
286 options->save_window_workspace = c_options->save_window_workspace;
287 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
288 options->show_window_ids = c_options->show_window_ids;
289 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
290 options->image.zoom_2pass = c_options->image.zoom_2pass;
291 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
292 options->image.limit_window_size = c_options->image.limit_window_size;
293 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
294 options->image.max_window_size = c_options->image.max_window_size;
295 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
296 options->image.max_autofit_size = c_options->image.max_autofit_size;
297 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
298 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
299 options->image.tile_size = c_options->image.tile_size;
300 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
301 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
303 if (options->thumbnails.max_width != c_options->thumbnails.max_width
304 || options->thumbnails.max_height != c_options->thumbnails.max_height
305 || options->thumbnails.quality != c_options->thumbnails.quality)
307 thumb_format_changed = TRUE;
309 options->thumbnails.max_width = c_options->thumbnails.max_width;
310 options->thumbnails.max_height = c_options->thumbnails.max_height;
311 options->thumbnails.quality = c_options->thumbnails.quality;
313 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
314 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
315 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
316 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
317 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
318 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
319 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
320 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
321 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
322 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
323 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
324 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
325 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
327 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
328 options->file_sort.natural = c_options->file_sort.natural;
329 options->file_filter.disable = c_options->file_filter.disable;
331 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
332 sidecar_ext_parse(options->sidecar.ext);
334 options->slideshow.random = c_options->slideshow.random;
335 options->slideshow.repeat = c_options->slideshow.repeat;
336 options->slideshow.delay = c_options->slideshow.delay;
338 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
339 options->image_lm_click_nav = c_options->image_lm_click_nav;
340 options->image_l_click_archive = c_options->image_l_click_archive;
341 options->image_l_click_video = c_options->image_l_click_video;
342 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
344 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
346 options->image.tile_cache_max = c_options->image.tile_cache_max;
347 options->image.image_cache_max = c_options->image.image_cache_max;
349 options->image.zoom_quality = c_options->image.zoom_quality;
351 options->image.zoom_increment = c_options->image.zoom_increment;
353 options->image.zoom_style = c_options->image.zoom_style;
355 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
358 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
359 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
360 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
362 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
363 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
364 options->image.border_color = c_options->image.border_color;
365 layout_colors_update();
366 view_window_colors_update();
369 options->image.alpha_color_1 = c_options->image.alpha_color_1;
370 options->image.alpha_color_2 = c_options->image.alpha_color_2;
372 options->fullscreen.screen = c_options->fullscreen.screen;
373 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
374 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
375 options->fullscreen.above = c_options->fullscreen.above;
376 if (c_options->image_overlay.template_string)
377 set_image_overlay_template_string(&options->image_overlay.template_string,
378 c_options->image_overlay.template_string);
379 if (c_options->image_overlay.font)
380 set_image_overlay_font_string(&options->image_overlay.font,
381 c_options->image_overlay.font);
382 options->image_overlay.text_red = c_options->image_overlay.text_red;
383 options->image_overlay.text_green = c_options->image_overlay.text_green;
384 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
385 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
386 options->image_overlay.background_red = c_options->image_overlay.background_red;
387 options->image_overlay.background_green = c_options->image_overlay.background_green;
388 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
389 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
390 options->update_on_time_change = c_options->update_on_time_change;
392 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
393 options->rot_invariant_sim = c_options->rot_invariant_sim;
395 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
397 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
398 options->circular_selection_lists = c_options->circular_selection_lists;
400 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
401 options->dnd_icon_size = c_options->dnd_icon_size;
402 options->clipboard_selection = c_options->clipboard_selection;
403 options->dnd_default_action = c_options->dnd_default_action;
405 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
406 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
407 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
408 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
409 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
410 options->metadata.confirm_write = c_options->metadata.confirm_write;
411 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
412 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
413 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
414 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
415 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
416 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
417 options->metadata.write_orientation = c_options->metadata.write_orientation;
418 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
419 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
420 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
421 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
422 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
423 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
424 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
425 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
426 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
427 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
428 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
429 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
430 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
431 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
432 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
433 options->stereo.fixed_w = c_options->stereo.fixed_w;
434 options->stereo.fixed_h = c_options->stereo.fixed_h;
435 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
436 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
437 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
438 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
440 options->info_keywords.height = c_options->info_keywords.height;
441 options->info_title.height = c_options->info_title.height;
442 options->info_comment.height = c_options->info_comment.height;
443 options->info_rating.height = c_options->info_rating.height;
445 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
446 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
448 options->marks_save = c_options->marks_save;
449 options->with_rename = c_options->with_rename;
450 options->collections_on_top = c_options->collections_on_top;
451 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
452 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
454 options->external_preview.enable = c_options->external_preview.enable;
455 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
456 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
458 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
460 options->star_rating.star = c_options->star_rating.star;
461 options->star_rating.rejected = c_options->star_rating.rejected;
463 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
466 set_debug_level(debug_c);
470 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
472 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
473 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
475 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
476 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
477 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
479 options->color_profile.render_intent = c_options->color_profile.render_intent;
484 options->mouse_button_8 = c_options->mouse_button_8;
485 options->mouse_button_9 = c_options->mouse_button_9;
487 options->override_disable_gpu = c_options->override_disable_gpu;
489 config_tab_keywords_save();
491 image_options_sync();
496 layout_refresh(NULL);
499 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
501 toolbar_apply(TOOLBAR_MAIN);
502 toolbar_apply(TOOLBAR_STATUS);
506 *-----------------------------------------------------------------------------
507 * config window main button callbacks (private)
508 *-----------------------------------------------------------------------------
511 static void config_window_close_cb(GtkWidget *widget, gpointer data)
513 gtk_widget_destroy(configwindow);
518 static void config_window_help_cb(GtkWidget *widget, gpointer data)
520 GtkWidget *notebook = data;
523 static gchar *html_section[] =
525 "GuideOptionsGeneral.html",
526 "GuideOptionsImage.html",
527 "GuideOptionsOSD.html",
528 "GuideOptionsWindow.html",
529 "GuideOptionsKeyboard.html",
530 "GuideOptionsFiltering.html",
531 "GuideOptionsMetadata.html",
532 "GuideOptionsKeywords.html",
533 "GuideOptionsColor.html",
534 "GuideOptionsStereo.html",
535 "GuideOptionsBehavior.html",
536 "GuideOptionsToolbar.html",
537 "GuideOptionsToolbar.html",
538 "GuideOptionsAdvanced.html"
541 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
542 help_window_show(html_section[i]);
545 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
547 config_window_close_cb(NULL, NULL);
551 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
554 GtkNotebook *notebook = data;
562 lw = layout_window_list->data;
564 window = gtk_widget_get_window(widget);
565 gdk_window_get_root_origin(window, &x, &y);
566 w = gdk_window_get_width(window);
567 h = gdk_window_get_height(window);
568 page_number = gtk_notebook_get_current_page(notebook);
570 lw->options.preferences_window.x = x;
571 lw->options.preferences_window.y = y;
572 lw->options.preferences_window.w = w;
573 lw->options.preferences_window.h = h;
574 lw->options.preferences_window.page_number = page_number;
576 config_window_apply();
577 layout_util_sync(lw);
578 save_options(options);
579 config_window_close_cb(NULL, NULL);
583 *-----------------------------------------------------------------------------
584 * config window setup (private)
585 *-----------------------------------------------------------------------------
588 static void quality_menu_cb(GtkWidget *combo, gpointer data)
592 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
596 *option = GDK_INTERP_NEAREST;
599 *option = GDK_INTERP_TILES;
602 *option = GDK_INTERP_BILINEAR;
607 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
611 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
615 *option = DND_ACTION_ASK;
618 *option = DND_ACTION_COPY;
621 *option = DND_ACTION_MOVE;
625 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
629 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
632 *option = CLIPBOARD_PRIMARY;
635 *option = CLIPBOARD_CLIPBOARD;
638 *option = CLIPBOARD_BOTH;
641 *option = CLIPBOARD_BOTH;
645 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
646 guint option, guint *option_c)
653 pref_table_label(table, column, row, text, 0.0);
655 combo = gtk_combo_box_text_new();
657 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
658 if (option == GDK_INTERP_NEAREST) current = 0;
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
660 if (option == GDK_INTERP_TILES) current = 1;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
662 if (option == GDK_INTERP_BILINEAR) current = 2;
664 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(quality_menu_cb), option_c);
669 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
670 gtk_widget_show(combo);
673 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
680 pref_table_label(table, column, row, text, 0.0);
682 combo = gtk_combo_box_text_new();
684 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
685 if (option == DND_ACTION_ASK) current = 0;
686 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
687 if (option == DND_ACTION_COPY) current = 1;
688 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
689 if (option == DND_ACTION_MOVE) current = 2;
691 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
693 g_signal_connect(G_OBJECT(combo), "changed",
694 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
696 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
697 gtk_widget_show(combo);
700 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
701 gint option, gint *option_c)
708 pref_table_label(table, column, row, text, 0.0);
710 combo = gtk_combo_box_text_new();
712 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
713 if (option == CLIPBOARD_PRIMARY) current = 0;
714 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
715 if (option == CLIPBOARD_CLIPBOARD) current = 1;
716 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
717 if (option == CLIPBOARD_BOTH) current = 2;
719 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
721 g_signal_connect(G_OBJECT(combo), "changed",
722 G_CALLBACK(clipboard_selection_menu_cb), option_c);
724 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
725 gtk_widget_show(combo);
728 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
732 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
735 *option = ZOOM_GEOMETRIC;
738 *option = ZOOM_ARITHMETIC;
741 *option = ZOOM_GEOMETRIC;
745 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
752 pref_table_label(table, column, row, text, 0.0);
754 combo = gtk_combo_box_text_new();
756 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
757 if (option == ZOOM_GEOMETRIC) current = 0;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
759 if (option == ZOOM_ARITHMETIC) current = 1;
761 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
763 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
765 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
766 gtk_widget_show(combo);
769 typedef struct _UseableMouseItems UseableMouseItems;
770 struct _UseableMouseItems
772 gchar *name; /* GtkActionEntry terminology */
777 static const UseableMouseItems useable_mouse_items[] = {
779 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
780 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
781 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
782 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
783 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
784 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
785 {"Home", N_("Home"), GTK_STOCK_HOME},
786 {"Up", N_("Up"), GTK_STOCK_GO_UP},
787 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
788 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
789 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
790 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
791 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
792 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
793 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
794 {"Search", N_("Search"), GTK_STOCK_FIND},
795 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
796 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
797 {"Copy", N_("Copy"), GTK_STOCK_COPY},
798 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
799 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
800 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
801 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
802 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
803 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
804 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
805 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
806 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
807 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
808 {"Print", N_("Print"), GTK_STOCK_PRINT},
809 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
810 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
811 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
812 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
813 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
814 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
815 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
816 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
817 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
818 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
819 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
820 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
821 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
822 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
823 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
824 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
825 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
826 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
827 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
828 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
829 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
830 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
831 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
832 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
833 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
834 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
835 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
836 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
837 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
838 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
839 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
840 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
841 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
842 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
843 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
844 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
845 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
846 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
847 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
851 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
853 gchar **option = data;
856 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
858 const UseableMouseItems *list = useable_mouse_items;
862 if (g_strcmp0(list->label, label) == 0)
870 *option = g_strdup(list->name);
874 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
875 gchar *option, gchar **option_c)
883 pref_table_label(table, column, row, text, 0.0);
885 combo = gtk_combo_box_text_new();
887 const UseableMouseItems *list = useable_mouse_items;
891 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
892 if (g_strcmp0(list->name, option) == 0)
900 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
902 g_signal_connect(G_OBJECT(combo), "changed",
903 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
905 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
906 gtk_widget_show(combo);
909 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
913 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
916 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
918 c_options->thumbnails.max_width = thumb_size_list[n].w;
919 c_options->thumbnails.max_height = thumb_size_list[n].h;
923 c_options->thumbnails.max_width = options->thumbnails.max_width;
924 c_options->thumbnails.max_height = options->thumbnails.max_height;
928 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
934 c_options->thumbnails.max_width = options->thumbnails.max_width;
935 c_options->thumbnails.max_height = options->thumbnails.max_height;
937 pref_table_label(table, column, row, text, 0.0);
939 combo = gtk_combo_box_text_new();
942 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
947 w = thumb_size_list[i].w;
948 h = thumb_size_list[i].h;
950 buf = g_strdup_printf("%d x %d", w, h);
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
954 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
961 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
962 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
968 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
969 g_signal_connect(G_OBJECT(combo), "changed",
970 G_CALLBACK(thumb_size_menu_cb), NULL);
972 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
973 gtk_widget_show(combo);
976 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
980 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
984 *option = PR_STEREO_NONE;
987 *option = PR_STEREO_ANAGLYPH_RC;
990 *option = PR_STEREO_ANAGLYPH_GM;
993 *option = PR_STEREO_ANAGLYPH_YB;
996 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
999 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
1002 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
1005 *option = PR_STEREO_ANAGLYPH_DB_RC;
1008 *option = PR_STEREO_ANAGLYPH_DB_GM;
1011 *option = PR_STEREO_ANAGLYPH_DB_YB;
1014 *option = PR_STEREO_HORIZ;
1017 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1020 *option = PR_STEREO_VERT;
1023 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1026 *option = PR_STEREO_FIXED;
1031 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1032 gint option, gint *option_c, gboolean add_fixed)
1039 pref_table_label(table, column, row, text, 0.0);
1041 combo = gtk_combo_box_text_new();
1043 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1045 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1046 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1047 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1048 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1049 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1050 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1051 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1052 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1053 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1054 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1056 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1058 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1059 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1060 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1061 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1062 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1066 if (option & PR_STEREO_HORIZ)
1069 if (option & PR_STEREO_HALF) current = 11;
1072 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1073 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1074 if (option & PR_STEREO_VERT)
1077 if (option & PR_STEREO_HALF) current = 13;
1082 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1083 if (option & PR_STEREO_FIXED) current = 14;
1086 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1088 g_signal_connect(G_OBJECT(combo), "changed",
1089 G_CALLBACK(stereo_mode_menu_cb), option_c);
1091 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1092 gtk_widget_show(combo);
1095 static void video_menu_cb(GtkWidget *combo, gpointer data)
1097 gchar **option = data;
1099 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1103 static void video_menu_populate(gpointer data, gpointer user_data)
1105 GtkWidget *combo = user_data;
1106 EditorDescription *ed = data;
1108 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1111 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1112 gchar *option, gchar **option_c)
1116 /* use lists since they are sorted */
1117 GList *eds = editor_list_get();
1121 pref_table_label(table, column, row, text, 0.0);
1123 combo = gtk_combo_box_text_new();
1124 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1125 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1127 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1129 g_signal_connect(G_OBJECT(combo), "changed",
1130 G_CALLBACK(video_menu_cb), option_c);
1132 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1133 gtk_widget_show(combo);
1136 static void filter_store_populate(void)
1140 if (!filter_store) return;
1142 gtk_list_store_clear(filter_store);
1144 work = filter_get_list();
1153 gtk_list_store_append(filter_store, &iter);
1154 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1158 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1159 gchar *new_text, gpointer data)
1161 GtkWidget *model = data;
1162 FilterEntry *fe = data;
1166 if (!new_text || strlen(new_text) < 1) return;
1168 tpath = gtk_tree_path_new_from_string(path_str);
1169 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1170 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1172 g_free(fe->extensions);
1173 fe->extensions = g_strdup(new_text);
1175 gtk_tree_path_free(tpath);
1179 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1180 gchar *new_text, gpointer data)
1182 GtkWidget *model = data;
1183 FilterEntry *fe = data;
1188 if (!new_text || !new_text[0]) return;
1190 tpath = gtk_tree_path_new_from_string(path_str);
1191 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1192 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1194 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1196 if (strcmp(new_text, _(format_class_list[i])) == 0)
1203 gtk_tree_path_free(tpath);
1207 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1208 gchar *new_text, gpointer data)
1210 GtkWidget *model = data;
1215 if (!new_text || !new_text[0]) return;
1217 tpath = gtk_tree_path_new_from_string(path_str);
1218 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1219 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1221 g_free(fe->description);
1222 fe->description = g_strdup(new_text);
1224 gtk_tree_path_free(tpath);
1227 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1228 gchar *path_str, gpointer data)
1230 GtkWidget *model = data;
1235 tpath = gtk_tree_path_new_from_string(path_str);
1236 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1237 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1239 fe->enabled = !fe->enabled;
1241 gtk_tree_path_free(tpath);
1245 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1246 gchar *path_str, gpointer data)
1248 GtkWidget *model = data;
1253 tpath = gtk_tree_path_new_from_string(path_str);
1254 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1255 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1257 fe->writable = !fe->writable;
1258 if (fe->writable) fe->allow_sidecar = FALSE;
1260 gtk_tree_path_free(tpath);
1264 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1265 gchar *path_str, gpointer data)
1267 GtkWidget *model = data;
1272 tpath = gtk_tree_path_new_from_string(path_str);
1273 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1274 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1276 fe->allow_sidecar = !fe->allow_sidecar;
1277 if (fe->allow_sidecar) fe->writable = FALSE;
1279 gtk_tree_path_free(tpath);
1283 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1284 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1288 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1290 switch (GPOINTER_TO_INT(data))
1293 g_object_set(GTK_CELL_RENDERER(cell),
1294 "active", fe->enabled, NULL);
1297 g_object_set(GTK_CELL_RENDERER(cell),
1298 "text", fe->extensions, NULL);
1300 case FE_DESCRIPTION:
1301 g_object_set(GTK_CELL_RENDERER(cell),
1302 "text", fe->description, NULL);
1305 g_object_set(GTK_CELL_RENDERER(cell),
1306 "text", _(format_class_list[fe->file_class]), NULL);
1309 g_object_set(GTK_CELL_RENDERER(cell),
1310 "active", fe->writable, NULL);
1312 case FE_ALLOW_SIDECAR:
1313 g_object_set(GTK_CELL_RENDERER(cell),
1314 "active", fe->allow_sidecar, NULL);
1319 static gboolean filter_add_scroll(gpointer data)
1323 GtkCellRenderer *cell;
1324 GtkTreeViewColumn *column;
1327 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1328 path = gtk_tree_path_new_from_indices(rows-1, -1);
1330 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1332 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1333 cell = g_list_last(list_cells)->data;
1335 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1336 path, column, FALSE, 0.0, 0.0 );
1337 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1338 path, column, cell, TRUE);
1340 gtk_tree_path_free(path);
1341 g_list_free(list_cells);
1346 static void filter_add_cb(GtkWidget *widget, gpointer data)
1348 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1349 filter_store_populate();
1351 g_idle_add((GSourceFunc)filter_add_scroll, data);
1354 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1356 GtkWidget *filter_view = data;
1357 GtkTreeSelection *selection;
1361 if (!filter_store) return;
1362 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1363 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1364 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1367 filter_remove_entry(fe);
1369 filter_store_populate();
1372 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1376 GtkTreeViewColumn *column;
1378 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1379 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1380 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1382 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1386 gtk_tree_path_free(path);
1391 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1394 filter_add_defaults();
1396 filter_store_populate();
1398 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1401 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1403 /* no op, only so cancel button appears */
1406 static void filter_default_cb(GtkWidget *widget, gpointer data)
1410 gd = generic_dialog_new(_("Reset filters"),
1411 "reset_filter", widget, TRUE,
1412 dummy_cancel_cb, data);
1413 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1414 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1415 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1416 gtk_widget_show(gd->dialog);
1419 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1421 GtkWidget *frame = data;
1423 gtk_widget_set_sensitive(frame,
1424 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1427 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1429 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1432 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1434 file_util_trash_clear();
1437 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1441 gd = generic_dialog_new(_("Clear trash"),
1442 "clear_trash", widget, TRUE,
1443 dummy_cancel_cb, NULL);
1444 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1445 _("This will remove the trash contents."), FALSE);
1446 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1447 entry = gtk_entry_new();
1448 gtk_widget_set_can_focus(entry, FALSE);
1449 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1450 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1451 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1452 gtk_widget_show(entry);
1453 gtk_widget_show(gd->dialog);
1456 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1458 GtkWidget *pTextView;
1459 GtkTextBuffer *pTextBuffer;
1463 pTextView = GTK_WIDGET(data);
1465 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1466 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1467 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1469 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1470 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1473 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1475 GtkTextView *text_view = data;
1476 GtkTextBuffer *buffer;
1478 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1479 if (!configwindow) return;
1481 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1482 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1485 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1489 gd = generic_dialog_new(_("Reset image overlay template string"),
1490 "reset_image_overlay_template_string", widget, TRUE,
1491 dummy_cancel_cb, data);
1492 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1493 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1494 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1495 gtk_widget_show(gd->dialog);
1498 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1500 help_window_show("GuideOptionsOSD.html");
1503 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1505 #if GTK_CHECK_VERSION(3,4,0)
1508 PangoFontDescription *font_desc;
1510 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1511 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1513 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1515 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1516 font = pango_font_description_to_string(font_desc);
1517 g_free(c_options->image_overlay.font);
1518 c_options->image_overlay.font = g_strdup(font);
1522 gtk_widget_destroy(dialog);
1526 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1527 c_options->image_overlay.font = g_strdup(font);
1531 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1534 #if GTK_CHECK_VERSION(3,4,0)
1537 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1538 colour.red = options->image_overlay.text_red;
1539 colour.green = options->image_overlay.text_green;
1540 colour.blue = options->image_overlay.text_blue;
1541 colour.alpha = options->image_overlay.text_alpha;
1542 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1543 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1545 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1547 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1548 c_options->image_overlay.text_red = colour.red*255;
1549 c_options->image_overlay.text_green = colour.green*255;
1550 c_options->image_overlay.text_blue = colour.blue*255;
1551 c_options->image_overlay.text_alpha = colour.alpha*255;
1553 gtk_widget_destroy(dialog);
1556 GtkColorSelection *colorsel;
1558 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1559 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1560 colour.red = options->image_overlay.text_red*257;
1561 colour.green = options->image_overlay.text_green*257;
1562 colour.blue = options->image_overlay.text_blue*257;
1563 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1564 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1565 gtk_color_selection_set_current_color(colorsel, &colour);
1566 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1568 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1570 gtk_color_selection_get_current_color(colorsel, &colour);
1571 c_options->image_overlay.text_red = colour.red/257;
1572 c_options->image_overlay.text_green = colour.green/257;
1573 c_options->image_overlay.text_blue = colour.blue/257;
1574 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1576 gtk_widget_destroy (dialog);
1581 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1584 #if GTK_CHECK_VERSION(3,4,0)
1587 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1588 colour.red = options->image_overlay.background_red;
1589 colour.green = options->image_overlay.background_green;
1590 colour.blue = options->image_overlay.background_blue;
1591 colour.alpha = options->image_overlay.background_alpha;
1592 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1593 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1595 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1597 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1598 c_options->image_overlay.background_red = colour.red*255;
1599 c_options->image_overlay.background_green = colour.green*255;
1600 c_options->image_overlay.background_blue = colour.blue*255;
1601 c_options->image_overlay.background_alpha = colour.alpha*255;
1603 gtk_widget_destroy(dialog);
1606 GtkColorSelection *colorsel;
1608 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1609 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1610 colour.red = options->image_overlay.background_red*257;
1611 colour.green = options->image_overlay.background_green*257;
1612 colour.blue = options->image_overlay.background_blue*257;
1613 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1614 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1615 gtk_color_selection_set_current_color(colorsel, &colour);
1616 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1618 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1620 gtk_color_selection_get_current_color(colorsel, &colour);
1621 c_options->image_overlay.background_red = colour.red/257;
1622 c_options->image_overlay.background_green = colour.green/257;
1623 c_options->image_overlay.background_blue = colour.blue/257;
1624 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1626 gtk_widget_destroy(dialog);
1630 static void accel_store_populate(void)
1633 GList *groups, *actions;
1635 const gchar *accel_path;
1639 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1641 gtk_tree_store_clear(accel_store);
1642 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1644 g_assert(lw && lw->ui_manager);
1645 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1648 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1651 action = GTK_ACTION(actions->data);
1652 accel_path = gtk_action_get_accel_path(action);
1653 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1655 gchar *label, *label2, *tooltip, *accel;
1656 g_object_get(action,
1657 "tooltip", &tooltip,
1661 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1667 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1671 gtk_tree_store_append(accel_store, &iter, NULL);
1672 gtk_tree_store_set(accel_store, &iter,
1675 AE_TOOLTIP, tooltip ? tooltip : "",
1676 AE_ACCEL, accel_path,
1684 actions = actions->next;
1687 groups = groups->next;
1691 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1696 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1698 gchar *accel1 = data;
1703 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1705 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1706 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1708 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1710 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1711 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1720 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1722 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1726 GtkAccelKey old_key, key;
1727 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1729 gtk_tree_model_get_iter(model, &iter, path);
1730 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1732 /* test if the accelerator can be stored without conflicts*/
1733 gtk_accel_map_lookup_entry(accel_path, &old_key);
1735 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1736 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1737 gtk_accel_map_lookup_entry(accel_path, &key);
1739 /* restore the original for now, the key will be really changed when the changes are confirmed */
1740 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1742 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1743 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1745 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1746 gtk_tree_path_free(path);
1750 static gboolean accel_default_scroll(GtkTreeView *data)
1754 GtkTreeViewColumn *column;
1756 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1757 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1758 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1760 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1764 gtk_tree_path_free(path);
1769 static void accel_default_cb(GtkWidget *widget, gpointer data)
1771 accel_store_populate();
1773 g_idle_add((GSourceFunc)accel_default_scroll, data);
1776 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1778 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1781 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1784 gchar *accel_path, *accel;
1786 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1787 gtk_accel_map_lookup_entry(accel_path, &key);
1788 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1790 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1792 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1797 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1799 GtkTreeSelection *selection;
1801 if (!accel_store) return;
1802 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1803 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1808 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1812 GtkWidget *scrolled;
1813 GtkWidget *viewport;
1815 scrolled = gtk_scrolled_window_new(NULL, NULL);
1816 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1817 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1818 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1819 label = gtk_label_new(title);
1820 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1821 gtk_widget_show(scrolled);
1823 viewport = gtk_viewport_new(NULL, NULL);
1824 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1825 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1826 gtk_widget_show(viewport);
1828 vbox = gtk_vbox_new(FALSE, 0);
1829 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1830 gtk_widget_show(vbox);
1835 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1837 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1839 c_options->thumbnails.spec_standard =TRUE;
1840 c_options->thumbnails.cache_into_dirs = FALSE;
1844 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1846 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1848 c_options->thumbnails.spec_standard =FALSE;
1849 c_options->thumbnails.cache_into_dirs = FALSE;
1853 static void cache_local_cb(GtkWidget *widget, gpointer data)
1855 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1857 c_options->thumbnails.cache_into_dirs = TRUE;
1858 c_options->thumbnails.spec_standard =FALSE;
1862 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1863 GdkEvent *event, gpointer userdata)
1865 if (pos == GTK_ENTRY_ICON_PRIMARY)
1867 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1871 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1875 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1876 GdkEvent *event, gpointer userdata)
1878 gchar *rating_symbol;
1880 if (pos == GTK_ENTRY_ICON_PRIMARY)
1882 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1883 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1884 g_free(rating_symbol);
1888 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1889 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1890 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1894 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1895 GdkEvent *event, gpointer userdata)
1897 gchar *rating_symbol;
1899 if (pos == GTK_ENTRY_ICON_PRIMARY)
1901 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1902 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1903 g_free(rating_symbol);
1907 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1908 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1909 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1913 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1915 GtkContainer *hbox = data;
1916 GString *str = g_string_new(NULL);
1917 GtkEntry *hex_code_entry;
1918 gchar *hex_code_full;
1921 guint64 hex_value = 0;
1923 list = gtk_container_get_children(hbox);
1925 hex_code_entry = g_list_nth_data(list, 2);
1926 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1928 hex_code = g_strsplit(hex_code_full, "+", 2);
1929 if (hex_code[0] && hex_code[1])
1931 hex_value = strtoull(hex_code[1], NULL, 16);
1933 if (!hex_value || hex_value > 0x10FFFF)
1935 hex_value = 0x003F; // Unicode 'Question Mark'
1937 str = g_string_append_unichar(str, (gunichar)hex_value);
1938 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1940 g_strfreev(hex_code);
1941 g_string_free(str, TRUE);
1942 g_free(hex_code_full);
1947 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1949 guint64 star_symbol;
1951 star_symbol = star_rating_symbol_test(widget, data);
1952 c_options->star_rating.star = star_symbol;
1955 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1957 guint64 rejected_symbol;
1959 rejected_symbol = star_rating_symbol_test(widget, data);
1960 c_options->star_rating.rejected = rejected_symbol;
1963 /* general options tab */
1964 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1965 typedef struct _TZData TZData;
1969 GCancellable *cancellable;
1971 GtkWidget *progress;
1973 GFile *timezone_database_gq;
1974 gchar *timezone_database_user;
1977 static void config_tab_general(GtkWidget *notebook)
1982 GtkWidget *group_frame;
1983 GtkWidget *subgroup;
1985 GtkWidget *ct_button;
1988 gint hours, minutes, remainder;
1990 GtkWidget *star_rating_entry;
1992 gchar *rating_symbol;
1995 GNetworkMonitor *net_mon;
1996 GSocketConnectable *geeqie_org;
1997 gboolean internet_available;
2000 vbox = scrolled_notebook_page(notebook, _("General"));
2002 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
2004 table = pref_table_new(group, 2, 2, FALSE, FALSE);
2005 add_thumb_size_menu(table, 0, 0, _("Size:"));
2006 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
2008 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2009 pref_label_new(hbox, _("Custom size: "));
2010 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2011 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2013 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2014 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2016 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2017 pref_checkbox_link_sensitivity(ct_button, subgroup);
2019 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2020 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2021 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2022 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2023 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2024 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2025 G_CALLBACK(cache_geeqie_cb), NULL);
2027 group_frame = pref_frame_new(subgroup, TRUE,
2028 _("Store thumbnails local to image folder (non-standard)"),
2029 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2030 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2031 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2032 G_CALLBACK(cache_local_cb), NULL);
2034 group_frame = pref_frame_new(subgroup, TRUE,
2035 _("Use standard thumbnail style and cache, shared with other applications"),
2036 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2037 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2038 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2039 G_CALLBACK(cache_standard_cb), NULL);
2041 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2042 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2044 pref_checkbox_new_int(group, _("Thumbnail color management"),
2045 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2047 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2049 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2050 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2052 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2053 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2054 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2056 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2057 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2060 pref_spacer(group, PREF_PAD_GROUP);
2062 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2064 c_options->star_rating.star = options->star_rating.star;
2065 c_options->star_rating.rejected = options->star_rating.rejected;
2067 str = g_string_new(NULL);
2068 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2069 pref_label_new(hbox, _("Star character: "));
2070 str = g_string_append_unichar(str, options->star_rating.star);
2071 pref_label_new(hbox, g_strdup(str->str));
2072 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2073 star_rating_entry = gtk_entry_new();
2074 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2075 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2076 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2077 gtk_widget_show(star_rating_entry);
2078 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2079 G_CALLBACK(star_rating_star_test_cb), hbox);
2080 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2081 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2082 gtk_widget_show(button);
2083 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."));
2084 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2085 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2086 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2087 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2088 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2089 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2090 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2091 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2092 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2093 G_CALLBACK(star_rating_star_icon_cb),
2096 g_string_free(str, TRUE);
2097 g_free(rating_symbol);
2099 str = g_string_new(NULL);
2100 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2101 pref_label_new(hbox, _("Rejected character: "));
2102 str = g_string_append_unichar(str, options->star_rating.rejected);
2103 pref_label_new(hbox, g_strdup(str->str));
2104 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2105 star_rating_entry = gtk_entry_new();
2106 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2107 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2108 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2109 gtk_widget_show(star_rating_entry);
2110 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2111 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2112 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2113 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2114 gtk_widget_show(button);
2115 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."));
2116 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2117 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2118 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2119 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2120 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2121 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2122 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2123 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2124 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2125 G_CALLBACK(star_rating_rejected_icon_cb),
2128 g_string_free(str, TRUE);
2129 g_free(rating_symbol);
2131 pref_spacer(group, PREF_PAD_GROUP);
2133 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2135 c_options->slideshow.delay = options->slideshow.delay;
2136 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2137 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2138 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2139 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2140 SLIDESHOW_SUBSECOND_PRECISION;
2142 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2144 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2146 options->slideshow.delay ? hours : 0.0,
2147 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2148 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2149 spin = pref_spin_new(hbox, ":" , NULL,
2151 options->slideshow.delay ? minutes: 0.0,
2152 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2153 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2154 spin = pref_spin_new(hbox, ":", NULL,
2155 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2156 options->slideshow.delay ? seconds : 10.0,
2157 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2158 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2160 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2161 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2163 pref_spacer(group, PREF_PAD_GROUP);
2165 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2167 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2168 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2169 pref_checkbox_new_int(group, _("Preload next image"),
2170 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2172 pref_checkbox_new_int(group, _("Refresh on file change"),
2173 options->update_on_time_change, &c_options->update_on_time_change);
2176 pref_spacer(group, PREF_PAD_GROUP);
2178 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2180 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2181 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2182 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2184 pref_spacer(group, PREF_PAD_GROUP);
2186 net_mon = g_network_monitor_get_default();
2187 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2188 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2189 g_object_unref(geeqie_org);
2191 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2192 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2194 if (!internet_available)
2196 gtk_widget_set_sensitive(group, FALSE);
2199 tz = g_new0(TZData, 1);
2201 path = path_from_utf8(TIMEZONE_DATABASE);
2202 basename = g_path_get_basename(path);
2203 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2207 if (isfile(tz->timezone_database_user))
2209 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2213 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2216 if (!internet_available)
2218 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"));
2222 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"));
2224 gtk_widget_show(button);
2226 pref_spacer(group, PREF_PAD_GROUP);
2228 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2230 help_search_engine_entry = gtk_entry_new();
2231 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2232 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2233 gtk_widget_show(help_search_engine_entry);
2235 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"));
2237 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2238 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2239 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2240 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2241 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2242 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2243 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2244 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2245 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2246 G_CALLBACK(help_search_engine_entry_icon_cb),
2247 help_search_engine_entry);
2251 static void config_tab_image(GtkWidget *notebook)
2256 GtkWidget *ct_button;
2257 GtkWidget *enlargement_button;
2260 GtkWidget *two_pass;
2262 GtkWidget *gpu_accel;
2265 vbox = scrolled_notebook_page(notebook, _("Image"));
2267 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2269 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2270 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2271 if (options->image.use_clutter_renderer && !options->disable_gpu)
2273 gtk_widget_set_sensitive(table, FALSE);
2277 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2278 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2279 if (options->disable_gpu && !options->override_disable_gpu)
2281 gtk_widget_set_sensitive(gpu_accel, FALSE);
2285 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2286 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2287 if (options->image.use_clutter_renderer && !options->disable_gpu)
2289 gtk_widget_set_sensitive(two_pass, FALSE);
2292 c_options->image.zoom_increment = options->image.zoom_increment;
2293 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2294 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2295 G_CALLBACK(zoom_increment_cb), NULL);
2296 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2298 c_options->image.zoom_style = options->image.zoom_style;
2299 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2300 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2302 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2304 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2305 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2306 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2307 spin = pref_spin_new_int(hbox, NULL, NULL,
2309 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2310 pref_checkbox_link_sensitivity(enlargement_button, spin);
2311 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."));
2313 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2314 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2315 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2316 spin = pref_spin_new_int(hbox, NULL, NULL,
2318 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2319 pref_checkbox_link_sensitivity(ct_button, spin);
2320 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."));
2322 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2323 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2325 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2326 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2328 options->image.tile_size, &c_options->image.tile_size);
2329 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."));
2331 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2333 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2334 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2336 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2337 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2339 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2340 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2342 c_options->image.border_color = options->image.border_color;
2344 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2345 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2347 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2348 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2350 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2351 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2356 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2358 LayoutWindow *lw = NULL;
2359 gchar *default_path;
2362 /* Get current lw */
2365 tmp_id = lw->options.id;
2366 lw->options.id = g_strdup("lw_default");
2368 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2369 save_default_layout_options_to_file(default_path, options, lw);
2370 g_free(lw->options.id);
2371 lw->options.id = tmp_id;
2372 g_free(default_path);
2375 #if GTK_CHECK_VERSION(3,22,0)
2376 static gboolean popover_cb(gpointer data)
2378 GtkPopover *popover = data;
2380 gtk_popover_popdown(popover);
2385 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2387 gtk_popover_popup(popover);
2389 g_timeout_add(2000, popover_cb, popover);
2392 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2396 popover = gtk_popover_new(parent);
2397 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2398 gtk_container_add (GTK_CONTAINER(popover), child);
2399 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2400 gtk_widget_show (child);
2406 static void config_tab_windows(GtkWidget *notebook)
2411 GtkWidget *subgroup;
2413 GtkWidget *ct_button;
2416 vbox = scrolled_notebook_page(notebook, _("Windows"));
2418 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2420 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2421 options->save_window_positions, &c_options->save_window_positions);
2423 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2424 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2425 pref_checkbox_link_sensitivity(ct_button, button);
2427 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2428 options->save_window_workspace, &c_options->save_window_workspace);
2429 pref_checkbox_link_sensitivity(ct_button, button);
2431 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2432 options->tools_restore_state, &c_options->tools_restore_state);
2434 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2435 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2437 pref_checkbox_new_int(group, _("Show window IDs"),
2438 options->show_window_ids, &c_options->show_window_ids);
2440 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2441 pref_label_new(subgroup, _("Use current layout for default: "));
2442 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2444 #if GTK_CHECK_VERSION(3,22,0)
2447 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2448 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2449 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2452 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2454 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2455 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2457 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2458 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2459 options->image.limit_window_size, &c_options->image.limit_window_size);
2460 spin = pref_spin_new_int(hbox, NULL, NULL,
2462 options->image.max_window_size, &c_options->image.max_window_size);
2463 pref_checkbox_link_sensitivity(ct_button, spin);
2465 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2467 c_options->fullscreen.screen = options->fullscreen.screen;
2468 c_options->fullscreen.above = options->fullscreen.above;
2469 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2470 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2471 gtk_widget_show(hbox);
2473 pref_checkbox_new_int(group, _("Smooth image flip"),
2474 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2475 pref_checkbox_new_int(group, _("Disable screen saver"),
2476 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2479 #define PRE_FORMATTED_COLUMNS 5
2480 static void config_tab_osd(GtkWidget *notebook)
2486 GtkWidget *image_overlay_template_view;
2487 GtkWidget *scrolled;
2488 GtkWidget *scrolled_pre_formatted;
2489 GtkTextBuffer *buffer;
2491 GtkWidget *subgroup;
2493 vbox = scrolled_notebook_page(notebook, _("OSD"));
2495 image_overlay_template_view = gtk_text_view_new();
2497 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2499 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2501 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2502 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2503 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2504 gtk_widget_show(scrolled_pre_formatted);
2505 gtk_widget_show(subgroup);
2507 pref_line(group, PREF_PAD_GAP);
2509 pref_label_new(group, _("Image overlay template"));
2511 scrolled = gtk_scrolled_window_new(NULL, NULL);
2512 gtk_widget_set_size_request(scrolled, 200, 150);
2513 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2514 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2515 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2516 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2517 gtk_widget_show(scrolled);
2519 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2520 _("Extensive formatting options are shown in the Help file"));
2522 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2523 gtk_widget_show(image_overlay_template_view);
2525 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2527 #if GTK_CHECK_VERSION(3,4,0)
2528 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2529 G_CALLBACK(image_overlay_set_font_cb), notebook);
2531 button = gtk_font_button_new();
2532 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2533 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2534 g_signal_connect(G_OBJECT(button), "font-set",
2535 G_CALLBACK(image_overlay_set_font_cb),NULL);
2537 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2538 gtk_widget_show(button);
2540 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2541 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2542 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2543 gtk_widget_show(button);
2545 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2546 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2547 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2548 gtk_widget_show(button);
2549 image_overlay_set_text_colours();
2551 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2552 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2553 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2554 gtk_widget_show(button);
2556 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2557 G_CALLBACK(image_overlay_help_cb), NULL);
2558 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2559 gtk_widget_show(button);
2561 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2562 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2563 g_signal_connect(G_OBJECT(buffer), "changed",
2564 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2566 pref_line(group, PREF_PAD_GAP);
2568 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), 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(_("%Exif.Image.Orientation%"));
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, _("Field separators"), 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(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2582 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2583 gtk_widget_show(label);
2584 pref_spacer(group,TRUE);
2586 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2587 hbox = gtk_hbox_new(FALSE, 0);
2588 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2589 gtk_widget_show(hbox);
2590 label = gtk_label_new(_("%path:39%"));
2591 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2592 gtk_widget_show(label);
2593 pref_spacer(group,TRUE);
2595 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2596 hbox = gtk_hbox_new(FALSE, 0);
2597 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2598 gtk_widget_show(hbox);
2599 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%"));
2600 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2601 gtk_widget_show(label);
2602 pref_spacer(group,TRUE);
2604 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2605 hbox = gtk_hbox_new(FALSE, 0);
2606 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2607 gtk_widget_show(hbox);
2608 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2609 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2610 gtk_widget_show(label);
2613 static GtkTreeModel *create_class_model(void)
2615 GtkListStore *model;
2619 /* create list store */
2620 model = gtk_list_store_new(1, G_TYPE_STRING);
2621 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2623 gtk_list_store_append(model, &iter);
2624 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2626 return GTK_TREE_MODEL (model);
2631 static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
2633 gint n = GPOINTER_TO_INT(data);
2635 FilterEntry *filter_a;
2636 FilterEntry *filter_b;
2638 gtk_tree_model_get(model, a, 0, &filter_a, -1);
2639 gtk_tree_model_get(model, b, 0, &filter_b, -1);
2643 case FILETYPES_COLUMN_DESCRIPTION:
2645 ret = g_utf8_collate(filter_a->description, filter_b->description);
2648 case FILETYPES_COLUMN_CLASS:
2650 ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
2653 case FILETYPES_COLUMN_WRITABLE:
2655 ret = filter_a->writable - filter_b->writable;
2658 case FILETYPES_COLUMN_SIDECAR:
2660 ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
2664 g_return_val_if_reached(0);
2670 static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
2673 gboolean ret = TRUE;
2675 gtk_tree_model_get(model, iter, 0, &fe, -1);
2677 if (g_strstr_len(fe->extensions, -1, key))
2685 static void config_tab_files(GtkWidget *notebook)
2692 GtkWidget *ct_button;
2693 GtkWidget *scrolled;
2694 GtkWidget *filter_view;
2695 GtkCellRenderer *renderer;
2696 GtkTreeSelection *selection;
2697 GtkTreeViewColumn *column;
2699 vbox = scrolled_notebook_page(notebook, _("Files"));
2701 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2703 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2704 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2705 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2706 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2707 pref_checkbox_new_int(group, _("Case sensitive sort"),
2708 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2709 pref_checkbox_new_int(group, _("Natural sort order"),
2710 options->file_sort.natural, &c_options->file_sort.natural);
2711 pref_checkbox_new_int(group, _("Disable file extension checks"),
2712 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2714 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2715 options->file_filter.disable, &c_options->file_filter.disable);
2718 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2720 sidecar_ext_entry = gtk_entry_new();
2721 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2722 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2723 gtk_widget_show(sidecar_ext_entry);
2725 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2727 frame = pref_group_parent(group);
2728 g_signal_connect(G_OBJECT(ct_button), "toggled",
2729 G_CALLBACK(filter_disable_cb), frame);
2730 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2732 scrolled = gtk_scrolled_window_new(NULL, NULL);
2733 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2734 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2735 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2736 gtk_widget_show(scrolled);
2738 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2739 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2740 g_object_unref(filter_store);
2741 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2742 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2744 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2746 column = gtk_tree_view_column_new();
2747 gtk_tree_view_column_set_title(column, _("Filter"));
2748 gtk_tree_view_column_set_resizable(column, TRUE);
2750 renderer = gtk_cell_renderer_toggle_new();
2751 g_signal_connect(G_OBJECT(renderer), "toggled",
2752 G_CALLBACK(filter_store_enable_cb), filter_store);
2753 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2754 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2755 GINT_TO_POINTER(FE_ENABLE), NULL);
2757 renderer = gtk_cell_renderer_text_new();
2758 g_signal_connect(G_OBJECT(renderer), "edited",
2759 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2760 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2761 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2762 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2763 GINT_TO_POINTER(FE_EXTENSION), NULL);
2764 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2766 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
2767 gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
2768 gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
2770 column = gtk_tree_view_column_new();
2771 gtk_tree_view_column_set_title(column, _("Description"));
2772 gtk_tree_view_column_set_resizable(column, TRUE);
2773 gtk_tree_view_column_set_fixed_width(column, 200);
2774 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2776 renderer = gtk_cell_renderer_text_new();
2777 g_signal_connect(G_OBJECT(renderer), "edited",
2778 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2779 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2780 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2781 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2782 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2783 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2784 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_DESCRIPTION, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_DESCRIPTION), NULL);
2785 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
2787 column = gtk_tree_view_column_new();
2788 gtk_tree_view_column_set_title(column, _("Class"));
2789 gtk_tree_view_column_set_resizable(column, TRUE);
2790 renderer = gtk_cell_renderer_combo_new();
2791 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2792 "model", create_class_model(),
2797 g_signal_connect(G_OBJECT(renderer), "edited",
2798 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2799 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2800 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2801 GINT_TO_POINTER(FE_CLASS), NULL);
2802 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2803 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_CLASS, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_CLASS), NULL);
2804 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
2806 column = gtk_tree_view_column_new();
2807 gtk_tree_view_column_set_title(column, _("Writable"));
2808 gtk_tree_view_column_set_resizable(column, FALSE);
2809 renderer = gtk_cell_renderer_toggle_new();
2810 g_signal_connect(G_OBJECT(renderer), "toggled",
2811 G_CALLBACK(filter_store_writable_cb), filter_store);
2812 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2813 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2814 GINT_TO_POINTER(FE_WRITABLE), NULL);
2815 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2816 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_WRITABLE, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_WRITABLE), NULL);
2817 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
2819 column = gtk_tree_view_column_new();
2820 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2821 gtk_tree_view_column_set_resizable(column, FALSE);
2822 renderer = gtk_cell_renderer_toggle_new();
2823 g_signal_connect(G_OBJECT(renderer), "toggled",
2824 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2825 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2826 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2827 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2828 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2829 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_SIDECAR, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_SIDECAR), NULL);
2830 gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
2832 filter_store_populate();
2833 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2834 gtk_widget_show(filter_view);
2836 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2838 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2839 G_CALLBACK(filter_default_cb), filter_view);
2840 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2841 gtk_widget_show(button);
2843 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2844 G_CALLBACK(filter_remove_cb), filter_view);
2845 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2846 gtk_widget_show(button);
2848 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2849 G_CALLBACK(filter_add_cb), filter_view);
2850 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2851 gtk_widget_show(button);
2855 static void config_tab_metadata(GtkWidget *notebook)
2860 GtkWidget *ct_button;
2864 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2867 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2869 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2871 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2872 #if GTK_CHECK_VERSION(3,16,0)
2873 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2874 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2876 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2879 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2880 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2882 gtk_widget_set_sensitive(ct_button, FALSE);
2885 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2886 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2888 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2889 label = pref_label_new(group, text);
2890 #if GTK_CHECK_VERSION(3,16,0)
2891 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2892 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2894 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2896 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2899 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2901 gtk_widget_set_sensitive(group, FALSE);
2904 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2905 pref_checkbox_link_sensitivity(ct_button, hbox);
2907 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2908 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2910 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2911 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2913 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2914 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2916 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2917 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2919 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2921 gtk_widget_set_sensitive(group, FALSE);
2924 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2925 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2928 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2929 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2930 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2932 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2933 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2935 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2936 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2938 gtk_widget_set_sensitive(ct_button, FALSE);
2941 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2943 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2944 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2946 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2947 pref_checkbox_link_sensitivity(ct_button, hbox);
2949 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2950 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2952 pref_checkbox_new_int(group, _("Write metadata on image change"),
2953 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2955 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2956 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2958 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2960 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2961 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2962 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");
2967 typedef struct _KeywordFindData KeywordFindData;
2968 struct _KeywordFindData
2975 GtkWidget *button_close;
2976 GtkWidget *button_stop;
2977 GtkWidget *button_start;
2978 GtkWidget *progress;
2986 guint idle_id; /* event source id */
2989 #define KEYWORD_DIALOG_WIDTH 400
2991 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2993 GList *list_d = NULL;
2994 GList *list_f = NULL;
2998 filelist_read(dir_fd, &list_f, &list_d);
3002 filelist_read(dir_fd, &list_f, NULL);
3005 list_f = filelist_filter(list_f, FALSE);
3006 list_d = filelist_filter(list_d, TRUE);
3008 kfd->list = g_list_concat(list_f, kfd->list);
3009 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
3012 static void keywords_find_reset(KeywordFindData *kfd)
3014 filelist_free(kfd->list);
3017 filelist_free(kfd->list_dir);
3018 kfd->list_dir = NULL;
3021 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
3023 KeywordFindData *kfd = data;
3025 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
3027 keywords_find_reset(kfd);
3028 generic_dialog_close(kfd->gd);
3032 static void keywords_find_finish(KeywordFindData *kfd)
3034 keywords_find_reset(kfd);
3036 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
3037 spinner_set_interval(kfd->spinner, -1);
3039 gtk_widget_set_sensitive(kfd->group, TRUE);
3040 gtk_widget_set_sensitive(kfd->button_start, TRUE);
3041 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3042 gtk_widget_set_sensitive(kfd->button_close, TRUE);
3045 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
3047 KeywordFindData *kfd = data;
3049 g_idle_remove_by_data(kfd);
3051 keywords_find_finish(kfd);
3054 static gboolean keywords_find_file(gpointer data)
3056 KeywordFindData *kfd = data;
3058 GtkTextBuffer *buffer;
3066 fd = kfd->list->data;
3067 kfd->list = g_list_remove(kfd->list, fd);
3069 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
3070 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3074 gtk_text_buffer_get_end_iter(buffer, &iter);
3075 tmp = g_strconcat(keywords->data, "\n", NULL);
3076 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3078 keywords = keywords->next;
3081 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3082 file_data_unref(fd);
3083 string_list_free(keywords);
3087 else if (kfd->list_dir)
3091 fd = kfd->list_dir->data;
3092 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3094 keywords_find_folder(kfd, fd);
3096 file_data_unref(fd);
3101 keywords_find_finish(kfd);
3106 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3108 KeywordFindData *kfd = data;
3111 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3113 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3114 parse_out_relatives(path);
3118 warning_dialog(_("Invalid folder"),
3119 _("The specified folder can not be found."),
3120 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3126 gtk_widget_set_sensitive(kfd->group, FALSE);
3127 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3128 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3129 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3130 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3132 dir_fd = file_data_new_dir(path);
3133 keywords_find_folder(kfd, dir_fd);
3134 file_data_unref(dir_fd);
3135 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3141 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3143 KeywordFindData *kfd;
3147 kfd = g_new0(KeywordFindData, 1);
3149 kfd->gd = generic_dialog_new(_("Search for keywords"),
3150 "search_for_keywords",
3153 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3154 kfd->gd->cancel_cb = keywords_find_close_cb;
3155 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3156 keywords_find_close_cb, FALSE);
3157 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3158 keywords_find_start_cb, FALSE);
3159 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3160 keywords_find_stop_cb, FALSE);
3161 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3163 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3165 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3166 pref_spacer(hbox, PREF_PAD_INDENT);
3167 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3169 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3170 pref_label_new(hbox, _("Folder:"));
3172 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3173 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3174 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3175 gtk_widget_show(label);
3177 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3179 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3180 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3182 kfd->progress = gtk_entry_new();
3183 gtk_widget_set_can_focus(kfd->progress, FALSE);
3184 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3185 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3186 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3187 gtk_widget_show(kfd->progress);
3189 kfd->spinner = spinner_new(NULL, -1);
3190 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3191 gtk_widget_show(kfd->spinner);
3195 gtk_widget_show(kfd->gd->dialog);
3198 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3200 const gchar *path = layout_get_path(NULL);
3202 if (!path || !*path) path = homedir();
3203 keywords_find_dialog(widget, path);
3206 static void config_tab_keywords_save()
3208 GtkTextIter start, end;
3209 GtkTextBuffer *buffer;
3210 GList *kw_list = NULL;
3216 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3217 gtk_text_buffer_get_bounds(buffer, &start, &end);
3219 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3221 kw_split = strtok(buffer_text, "\n");
3222 while (kw_split != NULL)
3228 if (g_strcmp0(work->data, kw_split) == 0)
3237 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3239 kw_split = strtok(NULL, "\n");
3242 keyword_list_set(kw_list);
3244 string_list_free(kw_list);
3245 g_free(buffer_text);
3248 static void config_tab_keywords(GtkWidget *notebook)
3254 GtkWidget *scrolled;
3256 GtkTextBuffer *buffer;
3259 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3261 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3263 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3265 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3266 G_CALLBACK(keywords_find_cb), keyword_text);
3267 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3270 keyword_text = gtk_text_view_new();
3271 gtk_widget_set_size_request(keyword_text, 20, 20);
3272 scrolled = gtk_scrolled_window_new(NULL, NULL);
3273 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3274 gtk_widget_show(scrolled);
3276 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3277 gtk_widget_show(keyword_text);
3279 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3281 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3282 gtk_text_buffer_create_tag(buffer, "monospace",
3283 "family", "monospace", NULL);
3285 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3286 gtk_text_buffer_get_start_iter(buffer, &iter);
3287 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3290 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3292 GList *kwl = keyword_list_get();
3293 kwl = g_list_first(kwl);
3296 gtk_text_buffer_get_end_iter (buffer, &iter);
3297 tmp = g_strconcat(kwl->data, "\n", NULL);
3298 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3303 gtk_text_buffer_set_modified(buffer, FALSE);
3310 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3312 gint *option = data;
3314 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3318 *option = INTENT_PERCEPTUAL;
3321 *option = INTENT_RELATIVE_COLORIMETRIC;
3324 *option = INTENT_SATURATION;
3327 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3332 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3333 gint option, gint *option_c)
3340 pref_table_label(table, column, row, text, 0.0);
3342 combo = gtk_combo_box_text_new();
3344 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3345 if (option == INTENT_PERCEPTUAL) current = 0;
3346 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3347 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3348 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3349 if (option == INTENT_SATURATION) current = 2;
3350 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3351 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3353 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3355 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3357 g_signal_connect(G_OBJECT(combo), "changed",
3358 G_CALLBACK(intent_menu_cb), option_c);
3360 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3361 gtk_widget_show(combo);
3365 static void config_tab_color(GtkWidget *notebook)
3374 vbox = scrolled_notebook_page(notebook, _("Color management"));
3376 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3378 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3381 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3382 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3384 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3385 pref_label_bold(label, TRUE, FALSE);
3387 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3388 pref_label_bold(label, TRUE, FALSE);
3390 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3391 pref_label_bold(label, TRUE, FALSE);
3393 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3398 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3399 pref_table_label(table, 0, i + 1, buf, 1.0);
3402 entry = gtk_entry_new();
3403 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3404 if (options->color_profile.input_name[i])
3406 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3408 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3409 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3410 gtk_widget_show(entry);
3411 color_profile_input_name_entry[i] = entry;
3413 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3414 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3415 gtk_widget_set_size_request(entry, 160, -1);
3416 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3417 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3418 gtk_widget_show(tabcomp);
3419 color_profile_input_file_entry[i] = entry;
3422 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3424 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3426 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3427 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3429 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3431 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3432 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3433 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3434 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3435 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3437 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3439 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3441 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3443 gtk_widget_show(tabcomp);
3446 /* advanced entry tab */
3447 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3449 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3451 c_options->file_ops.use_system_trash = FALSE;
3452 c_options->file_ops.no_trash = FALSE;
3456 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3458 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3460 c_options->file_ops.use_system_trash = TRUE;
3461 c_options->file_ops.no_trash = FALSE;
3465 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3467 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3469 c_options->file_ops.no_trash = TRUE;
3473 static void config_tab_behavior(GtkWidget *notebook)
3480 GtkWidget *ct_button;
3484 GtkWidget *with_rename;
3485 GtkWidget *collections_on_top;
3486 GtkWidget *hide_window_in_fullscreen;
3487 GtkWidget *checkbox;
3490 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3492 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3494 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3495 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3496 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3497 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3498 pref_checkbox_new_int(group, _("Enable Delete key"),
3499 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3501 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3502 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3504 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3505 pref_checkbox_link_sensitivity(ct_button, hbox);
3507 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3508 pref_label_new(hbox, _("Folder:"));
3510 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3511 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3512 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3513 gtk_widget_show(tabcomp);
3515 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3516 pref_checkbox_link_sensitivity(ct_button, hbox);
3518 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3519 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3520 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3521 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3522 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3523 G_CALLBACK(safe_delete_view_cb), NULL);
3524 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3525 gtk_widget_show(button);
3527 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3528 G_CALLBACK(safe_delete_clear_cb), NULL);
3529 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3530 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3531 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3533 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3534 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3536 gtk_widget_show(button);
3538 pref_spacer(group, PREF_PAD_GROUP);
3541 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3543 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3544 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3546 pref_checkbox_new_int(group, _("In place renaming"),
3547 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3549 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3550 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3552 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3553 options->circular_selection_lists, &c_options->circular_selection_lists);
3554 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3556 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3557 options->marks_save, &c_options->marks_save);
3558 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3560 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3561 options->with_rename, &c_options->with_rename);
3562 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3564 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3565 options->collections_on_top, &c_options->collections_on_top);
3566 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3568 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3569 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3570 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3572 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3573 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3575 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3576 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3578 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3579 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3581 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3582 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3584 pref_spacer(group, PREF_PAD_GROUP);
3586 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3588 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3589 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3590 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3591 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3592 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3593 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3594 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3595 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3596 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3597 options->image_l_click_archive, &c_options->image_l_click_archive);
3598 pref_checkbox_new_int(group, _("Play video by left click on image"),
3599 options->image_l_click_video, &c_options->image_l_click_video);
3600 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3601 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3603 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3604 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3605 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3606 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3607 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3609 pref_spacer(group, PREF_PAD_GROUP);
3611 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3613 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3614 options->override_disable_gpu, &c_options->override_disable_gpu);
3615 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3618 pref_spacer(group, PREF_PAD_GROUP);
3620 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3622 pref_spin_new_int(group, _("Debug level:"), NULL,
3623 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3625 pref_checkbox_new_int(group, _("Timer data"),
3626 options->log_window.timer_data, &c_options->log_window.timer_data);
3628 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3629 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3633 /* accelerators tab */
3634 static void config_tab_accelerators(GtkWidget *notebook)
3640 GtkWidget *scrolled;
3641 GtkWidget *accel_view;
3642 GtkCellRenderer *renderer;
3643 GtkTreeSelection *selection;
3644 GtkTreeViewColumn *column;
3646 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3648 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3650 scrolled = gtk_scrolled_window_new(NULL, NULL);
3651 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3652 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3653 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3654 gtk_widget_show(scrolled);
3656 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3658 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3659 g_object_unref(accel_store);
3660 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3661 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3663 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3665 renderer = gtk_cell_renderer_text_new();
3667 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3672 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3673 gtk_tree_view_column_set_resizable(column, TRUE);
3674 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3677 renderer = gtk_cell_renderer_accel_new();
3678 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3679 G_CALLBACK(accel_store_cleared_cb), accel_store);
3680 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3681 G_CALLBACK(accel_store_edited_cb), accel_store);
3684 g_object_set (renderer,
3686 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3689 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3694 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3695 gtk_tree_view_column_set_resizable(column, TRUE);
3696 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3698 renderer = gtk_cell_renderer_text_new();
3700 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3705 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3706 gtk_tree_view_column_set_resizable(column, TRUE);
3707 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3709 renderer = gtk_cell_renderer_text_new();
3711 column = gtk_tree_view_column_new_with_attributes("Accel",
3716 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3717 gtk_tree_view_column_set_resizable(column, TRUE);
3718 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3720 accel_store_populate();
3721 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3722 gtk_widget_show(accel_view);
3724 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3726 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3727 G_CALLBACK(accel_default_cb), accel_view);
3728 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3729 gtk_widget_show(button);
3731 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3732 G_CALLBACK(accel_reset_cb), accel_view);
3733 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3734 gtk_widget_show(button);
3737 /* toolbar main tab */
3738 static void config_tab_toolbar_main(GtkWidget *notebook)
3741 GtkWidget *toolbardata;
3744 lw = layout_window_list->data;
3746 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3748 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3749 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3750 gtk_widget_show(vbox);
3753 /* toolbar status tab */
3754 static void config_tab_toolbar_status(GtkWidget *notebook)
3757 GtkWidget *toolbardata;
3760 lw = layout_window_list->data;
3762 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3764 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3765 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3766 gtk_widget_show(vbox);
3770 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3772 return g_strcmp0((gchar *)a, (gchar *)b);
3775 static void config_tab_advanced(GtkWidget *notebook)
3779 GSList *formats_list;
3780 GList *extensions_list = NULL;
3783 GdkPixbufFormat *fm;
3785 GString *types_string = g_string_new(NULL);
3786 GtkWidget *types_string_label;
3787 GtkWidget *threads_string_label;
3788 GtkWidget *dupes_threads_spin;
3790 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3791 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3793 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3795 pref_spacer(group, PREF_PAD_GROUP);
3797 formats_list = gdk_pixbuf_get_formats();
3799 while (formats_list)
3801 fm = formats_list->data;
3802 extensions = gdk_pixbuf_format_get_extensions(fm);
3805 while (extensions[i])
3807 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3811 g_strfreev(extensions);
3812 formats_list = formats_list->next;
3815 while (extensions_list)
3817 if (types_string->len == 0)
3819 types_string = g_string_append(types_string, extensions_list->data);
3823 types_string = g_string_append(types_string, ", ");
3824 types_string = g_string_append(types_string, extensions_list->data);
3827 extensions_list = extensions_list->next;
3830 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3831 types_string_label = pref_label_new(group, types_string->str);
3832 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3834 pref_spacer(group, PREF_PAD_GROUP);
3836 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3837 external_preview_select_entry = gtk_entry_new();
3838 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3839 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3840 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3841 gtk_widget_show(tabcomp);
3843 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3844 external_preview_extract_entry = gtk_entry_new();
3845 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3846 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3847 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3848 gtk_widget_show(tabcomp);
3850 gtk_widget_show(vbox);
3852 g_slist_free(formats_list);
3853 string_list_free(extensions_list);
3854 g_string_free(types_string, TRUE);
3856 pref_spacer(group, PREF_PAD_GROUP);
3858 pref_line(vbox, PREF_PAD_SPACE);
3859 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3861 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.");
3862 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3864 pref_spacer(vbox, PREF_PAD_GROUP);
3866 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3867 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3871 static void config_tab_stereo(GtkWidget *notebook)
3879 GtkWidget *fs_button;
3880 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3882 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3884 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3885 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3887 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3888 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3889 pref_checkbox_new_int(box, _("Mirror left image"),
3890 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3891 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3892 pref_checkbox_new_int(box, _("Flip left image"),
3893 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3894 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3895 pref_checkbox_new_int(box, _("Mirror right image"),
3896 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3897 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3898 pref_checkbox_new_int(box, _("Flip right image"),
3899 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3900 pref_checkbox_new_int(group, _("Swap left and right images"),
3901 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3902 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3903 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3905 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3906 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3907 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3908 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3909 pref_checkbox_link_sensitivity(fs_button, box2);
3910 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3911 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3912 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3913 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3914 pref_checkbox_new_int(box, _("Mirror left image"),
3915 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3916 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3917 pref_checkbox_new_int(box, _("Flip left image"),
3918 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3919 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3920 pref_checkbox_new_int(box, _("Mirror right image"),
3921 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3922 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3923 pref_checkbox_new_int(box, _("Flip right image"),
3924 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3925 pref_checkbox_new_int(box2, _("Swap left and right images"),
3926 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3927 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3928 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3930 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3931 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3932 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3933 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3934 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3935 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3936 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3937 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3938 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3939 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3940 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3941 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3942 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3943 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3947 /* Main preferences window */
3948 static void config_window_create(LayoutWindow *lw)
3950 GtkWidget *win_vbox;
3952 GtkWidget *notebook;
3954 GtkWidget *ct_button;
3956 if (!c_options) c_options = init_options(NULL);
3958 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3959 DEBUG_NAME(configwindow);
3960 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3961 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3962 G_CALLBACK(config_window_delete), NULL);
3963 if (options->save_dialog_window_positions)
3965 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3966 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3970 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3972 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3973 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3975 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3976 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3977 gtk_widget_show(win_vbox);
3979 notebook = gtk_notebook_new();
3980 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3981 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3982 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3984 config_tab_general(notebook);
3985 config_tab_image(notebook);
3986 config_tab_osd(notebook);
3987 config_tab_windows(notebook);
3988 config_tab_accelerators(notebook);
3989 config_tab_files(notebook);
3990 config_tab_metadata(notebook);
3991 config_tab_keywords(notebook);
3992 config_tab_color(notebook);
3993 config_tab_stereo(notebook);
3994 config_tab_behavior(notebook);
3995 config_tab_toolbar_main(notebook);
3996 config_tab_toolbar_status(notebook);
3997 config_tab_advanced(notebook);
3999 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
4001 hbox = gtk_hbutton_box_new();
4002 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
4003 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
4004 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
4005 gtk_widget_show(hbox);
4007 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
4008 G_CALLBACK(config_window_help_cb), notebook);
4009 gtk_container_add(GTK_CONTAINER(hbox), button);
4010 gtk_widget_set_can_default(button, TRUE);
4011 gtk_widget_show(button);
4013 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
4014 G_CALLBACK(config_window_ok_cb), notebook);
4015 gtk_container_add(GTK_CONTAINER(hbox), button);
4016 gtk_widget_set_can_default(button, TRUE);
4017 gtk_widget_grab_default(button);
4018 gtk_widget_show(button);
4022 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
4023 G_CALLBACK(config_window_close_cb), NULL);
4024 gtk_container_add(GTK_CONTAINER(hbox), button);
4025 gtk_widget_set_can_default(button, TRUE);
4026 gtk_widget_show(button);
4028 if (!generic_dialog_get_alternative_button_order(configwindow))
4030 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
4033 gtk_widget_show(notebook);
4035 gtk_widget_show(configwindow);
4039 *-----------------------------------------------------------------------------
4040 * config window show (public)
4041 *-----------------------------------------------------------------------------
4044 void show_config_window(LayoutWindow *lw)
4048 gtk_window_present(GTK_WINDOW(configwindow));
4052 config_window_create(lw);
4061 void show_about_window(LayoutWindow *lw)
4063 GdkPixbuf *pixbuf_logo;
4064 GdkPixbuf *pixbuf_icon;
4065 gchar *authors[1000];
4070 gchar *timezone_path;
4074 #define LINE_LENGTH 1000
4075 gchar line[LINE_LENGTH];
4077 copyright = g_string_new(NULL);
4078 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");
4080 path = path_from_utf8(TIMEZONE_DATABASE);
4081 basename = g_path_get_basename(path);
4082 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
4083 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4085 cd = ZDOpenDatabase(timezone_path);
4088 copyright = g_string_append(copyright, ZDGetNotice(cd));
4089 ZDCloseDatabase(cd);
4093 g_free(timezone_path);
4097 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4098 fp = fopen(path, "r");
4101 while(fgets(line, LINE_LENGTH, fp))
4103 /* get rid of ending \n from fgets */
4104 line[strlen(line) - 1] = '\0';
4105 authors[i_authors] = g_strdup(line);
4108 authors[i_authors] = NULL;
4113 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4114 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4116 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4117 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4118 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4119 "title", _("About Geeqie"),
4121 "program-name", GQ_APPNAME,
4123 "logo", pixbuf_logo,
4124 "icon", pixbuf_icon,
4125 "website", GQ_WEBSITE,
4126 "website-label", "Website",
4127 "comments", comment,
4129 "translator-credits", _("translator-credits"),
4130 "wrap-license", TRUE,
4131 "license", copyright->str,
4134 g_string_free(copyright, TRUE);
4137 while(n < i_authors)
4147 static void image_overlay_set_text_colours()
4149 c_options->image_overlay.text_red = options->image_overlay.text_red;
4150 c_options->image_overlay.text_green = options->image_overlay.text_green;
4151 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4152 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4153 c_options->image_overlay.background_red = options->image_overlay.background_red;
4154 c_options->image_overlay.background_green = options->image_overlay.background_green;
4155 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4156 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4160 *-----------------------------------------------------------------------------
4161 * timezone database routines
4162 *-----------------------------------------------------------------------------
4165 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4167 GError *error = NULL;
4169 gchar *tmp_filename;
4171 if (!g_cancellable_is_cancelled(tz->cancellable))
4173 generic_dialog_close(tz->gd);
4177 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4179 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4180 move_file(tmp_filename, tz->timezone_database_user);
4181 g_free(tmp_filename);
4185 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4188 g_file_delete(tz->tmp_g_file, NULL, &error);
4189 g_object_unref(tz->tmp_g_file);
4190 tz->tmp_g_file = NULL;
4191 g_object_unref(tz->cancellable);
4192 g_object_unref(tz->timezone_database_gq);
4195 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4199 if (!g_cancellable_is_cancelled(tz->cancellable))
4201 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4205 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4209 g_cancellable_cancel(tz->cancellable);
4212 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4215 GError *error = NULL;
4216 GFileIOStream *io_stream;
4223 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4227 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4228 log_printf("Error: Download timezone database failed:\n%s", error->message);
4229 g_error_free(error);
4230 g_object_unref(tz->tmp_g_file);
4234 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4236 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4238 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4240 tz->progress = gtk_progress_bar_new();
4241 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4242 gtk_widget_show(tz->progress);
4244 gtk_widget_show(tz->gd->dialog);
4245 tz->cancellable = g_cancellable_new();
4246 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);
4248 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4251 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */