2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
381 options->dnd_default_action = c_options->dnd_default_action;
383 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
384 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
385 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
386 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
387 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
388 options->metadata.confirm_write = c_options->metadata.confirm_write;
389 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
390 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
391 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
392 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
393 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
394 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
395 options->metadata.write_orientation = c_options->metadata.write_orientation;
396 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
397 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
398 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
399 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
400 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
401 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
402 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
403 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
411 options->stereo.fixed_w = c_options->stereo.fixed_w;
412 options->stereo.fixed_h = c_options->stereo.fixed_h;
413 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
414 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
415 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
416 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
418 options->info_keywords.height = c_options->info_keywords.height;
419 options->info_title.height = c_options->info_title.height;
420 options->info_comment.height = c_options->info_comment.height;
421 options->info_rating.height = c_options->info_rating.height;
423 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
425 options->marks_save = c_options->marks_save;
426 options->with_rename = c_options->with_rename;
427 options->collections_on_top = c_options->collections_on_top;
428 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
430 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
432 options->star_rating.star = c_options->star_rating.star;
433 options->star_rating.rejected = c_options->star_rating.rejected;
435 set_debug_level(debug_c);
439 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
441 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
442 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
444 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
445 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
446 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
448 options->color_profile.render_intent = c_options->color_profile.render_intent;
453 options->mouse_button_8 = c_options->mouse_button_8;
454 options->mouse_button_9 = c_options->mouse_button_9;
456 config_tab_keywords_save();
458 image_options_sync();
463 layout_refresh(NULL);
466 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
468 toolbar_apply(TOOLBAR_MAIN);
469 toolbar_apply(TOOLBAR_STATUS);
473 *-----------------------------------------------------------------------------
474 * config window main button callbacks (private)
475 *-----------------------------------------------------------------------------
478 static void config_window_close_cb(GtkWidget *widget, gpointer data)
480 gtk_widget_destroy(configwindow);
485 static void config_window_help_cb(GtkWidget *widget, gpointer data)
487 GtkWidget *notebook = data;
490 static gchar *html_section[] =
492 "GuideOptionsGeneral.html",
493 "GuideOptionsImage.html",
494 "GuideOptionsOSD.html",
495 "GuideOptionsWindow.html",
496 "GuideOptionsKeyboard.html",
497 "GuideOptionsFiltering.html",
498 "GuideOptionsMetadata.html",
499 "GuideOptionsKeywords.html",
500 "GuideOptionsColor.html",
501 "GuideOptionsStereo.html",
502 "GuideOptionsBehavior.html",
503 "GuideOptionsToolbar.html",
504 "GuideOptionsToolbar.html"
507 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
508 help_window_show(html_section[i]);
511 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
513 config_window_close_cb(NULL, NULL);
517 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
520 lw = layout_window_list->data;
522 config_window_apply();
523 layout_util_sync(lw);
524 save_options(options);
525 config_window_close_cb(NULL, NULL);
529 *-----------------------------------------------------------------------------
530 * config window setup (private)
531 *-----------------------------------------------------------------------------
534 static void quality_menu_cb(GtkWidget *combo, gpointer data)
538 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
542 *option = GDK_INTERP_NEAREST;
545 *option = GDK_INTERP_TILES;
548 *option = GDK_INTERP_BILINEAR;
551 *option = GDK_INTERP_HYPER;
556 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
560 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
564 *option = DND_ACTION_ASK;
567 *option = DND_ACTION_COPY;
570 *option = DND_ACTION_MOVE;
574 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
578 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
590 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
591 guint option, guint *option_c)
598 pref_table_label(table, column, row, text, 0.0);
600 combo = gtk_combo_box_text_new();
602 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
603 if (option == GDK_INTERP_NEAREST) current = 0;
604 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
605 if (option == GDK_INTERP_TILES) current = 1;
606 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
607 if (option == GDK_INTERP_BILINEAR) current = 2;
608 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
609 if (option == GDK_INTERP_HYPER) current = 3;
611 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
613 g_signal_connect(G_OBJECT(combo), "changed",
614 G_CALLBACK(quality_menu_cb), option_c);
616 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
617 gtk_widget_show(combo);
620 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
627 pref_table_label(table, column, row, text, 0.0);
629 combo = gtk_combo_box_text_new();
631 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
632 if (option == DND_ACTION_ASK) current = 0;
633 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
634 if (option == DND_ACTION_COPY) current = 1;
635 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
636 if (option == DND_ACTION_MOVE) current = 2;
638 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
640 g_signal_connect(G_OBJECT(combo), "changed",
641 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
643 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
644 gtk_widget_show(combo);
647 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
648 gint option, gint *option_c)
655 pref_table_label(table, column, row, text, 0.0);
657 combo = gtk_combo_box_text_new();
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
660 if (option == PRIMARY) current = 0;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
662 if (option == CLIPBOARD) current = 1;
664 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(clipboard_selection_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 typedef struct _UseableMouseItems UseableMouseItems;
674 struct _UseableMouseItems
676 gchar *name; /* GtkActionEntry terminology */
681 static const UseableMouseItems useable_mouse_items[] = {
683 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
684 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
685 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
686 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
687 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
688 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
689 {"Home", N_("Home"), GTK_STOCK_HOME},
690 {"Up", N_("Up"), GTK_STOCK_GO_UP},
691 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
692 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
693 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
694 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
695 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
696 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
697 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
698 {"Search", N_("Search"), GTK_STOCK_FIND},
699 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
700 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
701 {"Copy", N_("Copy"), GTK_STOCK_COPY},
702 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
703 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
704 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
705 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
706 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
707 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
708 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
709 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
710 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
711 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
712 {"Print", N_("Print"), GTK_STOCK_PRINT},
713 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
714 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
715 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
716 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
717 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
718 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
719 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
720 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
721 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
722 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
723 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
724 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
725 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
726 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
727 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
728 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
729 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
730 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
731 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
732 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
733 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
734 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
735 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
736 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
737 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
738 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
739 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
740 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
741 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
742 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
743 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
744 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
745 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
746 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
747 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
748 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
749 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
750 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
751 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
755 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
757 gchar **option = data;
760 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
762 const UseableMouseItems *list = useable_mouse_items;
766 if (g_strcmp0(list->label, label) == 0)
774 *option = g_strdup(list->name);
778 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
779 gchar *option, gchar **option_c)
787 pref_table_label(table, column, row, text, 0.0);
789 combo = gtk_combo_box_text_new();
791 const UseableMouseItems *list = useable_mouse_items;
795 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
796 if (g_strcmp0(list->name, option) == 0)
804 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
806 g_signal_connect(G_OBJECT(combo), "changed",
807 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
809 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
810 gtk_widget_show(combo);
813 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
817 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
820 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
822 c_options->thumbnails.max_width = thumb_size_list[n].w;
823 c_options->thumbnails.max_height = thumb_size_list[n].h;
827 c_options->thumbnails.max_width = options->thumbnails.max_width;
828 c_options->thumbnails.max_height = options->thumbnails.max_height;
832 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
838 c_options->thumbnails.max_width = options->thumbnails.max_width;
839 c_options->thumbnails.max_height = options->thumbnails.max_height;
841 pref_table_label(table, column, row, text, 0.0);
843 combo = gtk_combo_box_text_new();
846 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
851 w = thumb_size_list[i].w;
852 h = thumb_size_list[i].h;
854 buf = g_strdup_printf("%d x %d", w, h);
855 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
858 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
865 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
866 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
872 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
873 g_signal_connect(G_OBJECT(combo), "changed",
874 G_CALLBACK(thumb_size_menu_cb), NULL);
876 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
877 gtk_widget_show(combo);
880 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
884 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
888 *option = PR_STEREO_NONE;
891 *option = PR_STEREO_ANAGLYPH_RC;
894 *option = PR_STEREO_ANAGLYPH_GM;
897 *option = PR_STEREO_ANAGLYPH_YB;
900 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
903 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
906 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
909 *option = PR_STEREO_ANAGLYPH_DB_RC;
912 *option = PR_STEREO_ANAGLYPH_DB_GM;
915 *option = PR_STEREO_ANAGLYPH_DB_YB;
918 *option = PR_STEREO_HORIZ;
921 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
924 *option = PR_STEREO_VERT;
927 *option = PR_STEREO_VERT | PR_STEREO_HALF;
930 *option = PR_STEREO_FIXED;
935 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
936 gint option, gint *option_c, gboolean add_fixed)
943 pref_table_label(table, column, row, text, 0.0);
945 combo = gtk_combo_box_text_new();
947 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
949 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
950 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
952 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
953 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
954 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
955 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
956 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
958 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
959 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
960 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
961 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
962 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
964 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
966 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
968 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
970 if (option & PR_STEREO_HORIZ)
973 if (option & PR_STEREO_HALF) current = 11;
976 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
977 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
978 if (option & PR_STEREO_VERT)
981 if (option & PR_STEREO_HALF) current = 13;
986 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
987 if (option & PR_STEREO_FIXED) current = 14;
990 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
992 g_signal_connect(G_OBJECT(combo), "changed",
993 G_CALLBACK(stereo_mode_menu_cb), option_c);
995 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
996 gtk_widget_show(combo);
999 static void video_menu_cb(GtkWidget *combo, gpointer data)
1001 gchar **option = data;
1003 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1007 static void video_menu_populate(gpointer data, gpointer user_data)
1009 GtkWidget *combo = user_data;
1010 EditorDescription *ed = data;
1012 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1015 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1016 gchar *option, gchar **option_c)
1020 /* use lists since they are sorted */
1021 GList *eds = editor_list_get();
1025 pref_table_label(table, column, row, text, 0.0);
1027 combo = gtk_combo_box_text_new();
1028 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1029 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1031 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1033 g_signal_connect(G_OBJECT(combo), "changed",
1034 G_CALLBACK(video_menu_cb), option_c);
1036 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1037 gtk_widget_show(combo);
1040 static void filter_store_populate(void)
1044 if (!filter_store) return;
1046 gtk_list_store_clear(filter_store);
1048 work = filter_get_list();
1057 gtk_list_store_append(filter_store, &iter);
1058 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1062 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1063 gchar *new_text, gpointer data)
1065 GtkWidget *model = data;
1066 FilterEntry *fe = data;
1070 if (!new_text || strlen(new_text) < 1) return;
1072 tpath = gtk_tree_path_new_from_string(path_str);
1073 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1074 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1076 g_free(fe->extensions);
1077 fe->extensions = g_strdup(new_text);
1079 gtk_tree_path_free(tpath);
1083 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1084 gchar *new_text, gpointer data)
1086 GtkWidget *model = data;
1087 FilterEntry *fe = data;
1092 if (!new_text || !new_text[0]) return;
1094 tpath = gtk_tree_path_new_from_string(path_str);
1095 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1096 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1098 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1100 if (strcmp(new_text, _(format_class_list[i])) == 0)
1107 gtk_tree_path_free(tpath);
1111 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1112 gchar *new_text, gpointer data)
1114 GtkWidget *model = data;
1119 if (!new_text || !new_text[0]) return;
1121 tpath = gtk_tree_path_new_from_string(path_str);
1122 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1123 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1125 g_free(fe->description);
1126 fe->description = g_strdup(new_text);
1128 gtk_tree_path_free(tpath);
1131 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1132 gchar *path_str, gpointer data)
1134 GtkWidget *model = data;
1139 tpath = gtk_tree_path_new_from_string(path_str);
1140 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1141 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1143 fe->enabled = !fe->enabled;
1145 gtk_tree_path_free(tpath);
1149 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1150 gchar *path_str, gpointer data)
1152 GtkWidget *model = data;
1157 tpath = gtk_tree_path_new_from_string(path_str);
1158 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1159 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1161 fe->writable = !fe->writable;
1162 if (fe->writable) fe->allow_sidecar = FALSE;
1164 gtk_tree_path_free(tpath);
1168 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1169 gchar *path_str, gpointer data)
1171 GtkWidget *model = data;
1176 tpath = gtk_tree_path_new_from_string(path_str);
1177 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1178 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1180 fe->allow_sidecar = !fe->allow_sidecar;
1181 if (fe->allow_sidecar) fe->writable = FALSE;
1183 gtk_tree_path_free(tpath);
1187 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1188 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1192 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1194 switch (GPOINTER_TO_INT(data))
1197 g_object_set(GTK_CELL_RENDERER(cell),
1198 "active", fe->enabled, NULL);
1201 g_object_set(GTK_CELL_RENDERER(cell),
1202 "text", fe->extensions, NULL);
1204 case FE_DESCRIPTION:
1205 g_object_set(GTK_CELL_RENDERER(cell),
1206 "text", fe->description, NULL);
1209 g_object_set(GTK_CELL_RENDERER(cell),
1210 "text", _(format_class_list[fe->file_class]), NULL);
1213 g_object_set(GTK_CELL_RENDERER(cell),
1214 "active", fe->writable, NULL);
1216 case FE_ALLOW_SIDECAR:
1217 g_object_set(GTK_CELL_RENDERER(cell),
1218 "active", fe->allow_sidecar, NULL);
1223 static gboolean filter_add_scroll(gpointer data)
1227 GtkCellRenderer *cell;
1228 GtkTreeViewColumn *column;
1231 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1232 path = gtk_tree_path_new_from_indices(rows-1, -1);
1234 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1236 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1237 cell = g_list_last(list_cells)->data;
1239 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1240 path, column, FALSE, 0.0, 0.0 );
1241 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1242 path, column, cell, TRUE);
1244 gtk_tree_path_free(path);
1245 g_list_free(list_cells);
1250 static void filter_add_cb(GtkWidget *widget, gpointer data)
1252 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1253 filter_store_populate();
1255 g_idle_add((GSourceFunc)filter_add_scroll, data);
1258 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1260 GtkWidget *filter_view = data;
1261 GtkTreeSelection *selection;
1265 if (!filter_store) return;
1266 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1267 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1268 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1271 filter_remove_entry(fe);
1273 filter_store_populate();
1276 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1280 GtkTreeViewColumn *column;
1282 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1283 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1284 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1286 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1290 gtk_tree_path_free(path);
1295 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1298 filter_add_defaults();
1300 filter_store_populate();
1302 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1305 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1307 /* no op, only so cancel button appears */
1310 static void filter_default_cb(GtkWidget *widget, gpointer data)
1314 gd = generic_dialog_new(_("Reset filters"),
1315 "reset_filter", widget, TRUE,
1316 dummy_cancel_cb, data);
1317 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1318 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1319 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1320 gtk_widget_show(gd->dialog);
1323 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1325 GtkWidget *frame = data;
1327 gtk_widget_set_sensitive(frame,
1328 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1331 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1333 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1336 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1338 file_util_trash_clear();
1341 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1345 gd = generic_dialog_new(_("Clear trash"),
1346 "clear_trash", widget, TRUE,
1347 dummy_cancel_cb, NULL);
1348 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1349 _("This will remove the trash contents."), FALSE);
1350 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1351 entry = gtk_entry_new();
1352 gtk_widget_set_can_focus(entry, FALSE);
1353 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1354 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1355 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1356 gtk_widget_show(entry);
1357 gtk_widget_show(gd->dialog);
1360 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1362 GtkWidget *pTextView;
1363 GtkTextBuffer *pTextBuffer;
1367 pTextView = GTK_WIDGET(data);
1369 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1370 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1371 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1373 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1374 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1377 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1379 GtkTextView *text_view = data;
1380 GtkTextBuffer *buffer;
1382 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1383 if (!configwindow) return;
1385 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1386 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1389 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1393 gd = generic_dialog_new(_("Reset image overlay template string"),
1394 "reset_image_overlay_template_string", widget, TRUE,
1395 dummy_cancel_cb, data);
1396 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1397 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1398 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1399 gtk_widget_show(gd->dialog);
1402 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1404 help_window_show("GuideOptionsOSD.html");
1407 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1409 #if GTK_CHECK_VERSION(3,4,0)
1412 PangoFontDescription *font_desc;
1414 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1415 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1417 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1419 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1420 font = pango_font_description_to_string(font_desc);
1421 g_free(c_options->image_overlay.font);
1422 c_options->image_overlay.font = g_strdup(font);
1426 gtk_widget_destroy(dialog);
1430 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1431 c_options->image_overlay.font = g_strdup(font);
1435 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1438 #if GTK_CHECK_VERSION(3,4,0)
1441 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1442 colour.red = options->image_overlay.text_red;
1443 colour.green = options->image_overlay.text_green;
1444 colour.blue = options->image_overlay.text_blue;
1445 colour.alpha = options->image_overlay.text_alpha;
1446 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1447 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1449 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1451 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1452 c_options->image_overlay.text_red = colour.red*255;
1453 c_options->image_overlay.text_green = colour.green*255;
1454 c_options->image_overlay.text_blue = colour.blue*255;
1455 c_options->image_overlay.text_alpha = colour.alpha*255;
1457 gtk_widget_destroy(dialog);
1460 GtkColorSelection *colorsel;
1462 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1463 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1464 colour.red = options->image_overlay.text_red*257;
1465 colour.green = options->image_overlay.text_green*257;
1466 colour.blue = options->image_overlay.text_blue*257;
1467 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1468 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1469 gtk_color_selection_set_current_color(colorsel, &colour);
1470 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1472 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1474 gtk_color_selection_get_current_color(colorsel, &colour);
1475 c_options->image_overlay.text_red = colour.red/257;
1476 c_options->image_overlay.text_green = colour.green/257;
1477 c_options->image_overlay.text_blue = colour.blue/257;
1478 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1480 gtk_widget_destroy (dialog);
1485 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1488 #if GTK_CHECK_VERSION(3,4,0)
1491 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1492 colour.red = options->image_overlay.background_red;
1493 colour.green = options->image_overlay.background_green;
1494 colour.blue = options->image_overlay.background_blue;
1495 colour.alpha = options->image_overlay.background_alpha;
1496 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1497 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1499 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1501 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1502 c_options->image_overlay.background_red = colour.red*255;
1503 c_options->image_overlay.background_green = colour.green*255;
1504 c_options->image_overlay.background_blue = colour.blue*255;
1505 c_options->image_overlay.background_alpha = colour.alpha*255;
1507 gtk_widget_destroy(dialog);
1510 GtkColorSelection *colorsel;
1512 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1513 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1514 colour.red = options->image_overlay.background_red*257;
1515 colour.green = options->image_overlay.background_green*257;
1516 colour.blue = options->image_overlay.background_blue*257;
1517 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1518 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1519 gtk_color_selection_set_current_color(colorsel, &colour);
1520 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1522 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1524 gtk_color_selection_get_current_color(colorsel, &colour);
1525 c_options->image_overlay.background_red = colour.red/257;
1526 c_options->image_overlay.background_green = colour.green/257;
1527 c_options->image_overlay.background_blue = colour.blue/257;
1528 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1530 gtk_widget_destroy(dialog);
1534 static void accel_store_populate(void)
1537 GList *groups, *actions;
1539 const gchar *accel_path;
1543 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1545 gtk_tree_store_clear(accel_store);
1546 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1548 g_assert(lw && lw->ui_manager);
1549 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1552 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1555 action = GTK_ACTION(actions->data);
1556 accel_path = gtk_action_get_accel_path(action);
1557 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1559 gchar *label, *label2, *tooltip, *accel;
1560 g_object_get(action,
1561 "tooltip", &tooltip,
1565 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1571 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1575 gtk_tree_store_append(accel_store, &iter, NULL);
1576 gtk_tree_store_set(accel_store, &iter,
1579 AE_TOOLTIP, tooltip ? tooltip : "",
1580 AE_ACCEL, accel_path,
1588 actions = actions->next;
1591 groups = groups->next;
1595 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1600 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1602 gchar *accel1 = data;
1607 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1609 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1610 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1612 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1614 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1615 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1624 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1626 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1630 GtkAccelKey old_key, key;
1631 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1633 gtk_tree_model_get_iter(model, &iter, path);
1634 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1636 /* test if the accelerator can be stored without conflicts*/
1637 gtk_accel_map_lookup_entry(accel_path, &old_key);
1639 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1640 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1641 gtk_accel_map_lookup_entry(accel_path, &key);
1643 /* restore the original for now, the key will be really changed when the changes are confirmed */
1644 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1646 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1647 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1649 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1650 gtk_tree_path_free(path);
1654 static gboolean accel_default_scroll(GtkTreeView *data)
1658 GtkTreeViewColumn *column;
1660 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1661 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1662 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1664 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1668 gtk_tree_path_free(path);
1673 static void accel_default_cb(GtkWidget *widget, gpointer data)
1675 accel_store_populate();
1677 g_idle_add((GSourceFunc)accel_default_scroll, data);
1680 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1682 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1685 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1688 gchar *accel_path, *accel;
1690 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1691 gtk_accel_map_lookup_entry(accel_path, &key);
1692 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1694 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1696 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1701 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1703 GtkTreeSelection *selection;
1705 if (!accel_store) return;
1706 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1707 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1712 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1716 GtkWidget *scrolled;
1717 GtkWidget *viewport;
1719 scrolled = gtk_scrolled_window_new(NULL, NULL);
1720 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1721 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1722 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1723 label = gtk_label_new(title);
1724 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1725 gtk_widget_show(scrolled);
1727 viewport = gtk_viewport_new(NULL, NULL);
1728 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1729 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1730 gtk_widget_show(viewport);
1732 vbox = gtk_vbox_new(FALSE, 0);
1733 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1734 gtk_widget_show(vbox);
1739 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1741 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1743 c_options->thumbnails.spec_standard =TRUE;
1744 c_options->thumbnails.cache_into_dirs = FALSE;
1748 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1750 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1752 c_options->thumbnails.spec_standard =FALSE;
1753 c_options->thumbnails.cache_into_dirs = FALSE;
1757 static void cache_local_cb(GtkWidget *widget, gpointer data)
1759 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1761 c_options->thumbnails.cache_into_dirs = TRUE;
1762 c_options->thumbnails.spec_standard =FALSE;
1766 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1767 GdkEvent *event, gpointer userdata)
1769 if (pos == GTK_ENTRY_ICON_PRIMARY)
1771 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1775 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1779 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1780 GdkEvent *event, gpointer userdata)
1782 gchar *rating_symbol;
1784 if (pos == GTK_ENTRY_ICON_PRIMARY)
1786 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1787 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1788 g_free(rating_symbol);
1792 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1793 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1794 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1798 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1799 GdkEvent *event, gpointer userdata)
1801 gchar *rating_symbol;
1803 if (pos == GTK_ENTRY_ICON_PRIMARY)
1805 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1806 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1807 g_free(rating_symbol);
1811 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1812 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1813 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1817 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1819 GtkContainer *hbox = data;
1820 GString *str = g_string_new(NULL);
1821 GtkEntry *hex_code_entry;
1822 gchar *hex_code_full;
1825 guint64 hex_value = 0;
1827 list = gtk_container_get_children(hbox);
1829 hex_code_entry = g_list_nth_data(list, 2);
1830 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1832 hex_code = g_strsplit(hex_code_full, "+", 2);
1833 if (hex_code[0] && hex_code[1])
1835 hex_value = strtoull(hex_code[1], NULL, 16);
1837 if (!hex_value || hex_value > 0x10FFFF)
1839 hex_value = 0x003F; // Unicode 'Question Mark'
1841 str = g_string_append_unichar(str, (gunichar)hex_value);
1842 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1844 g_strfreev(hex_code);
1845 g_string_free(str, TRUE);
1846 g_free(hex_code_full);
1851 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1853 guint64 star_symbol;
1855 star_symbol = star_rating_symbol_test(widget, data);
1856 c_options->star_rating.star = star_symbol;
1859 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1861 guint64 rejected_symbol;
1863 rejected_symbol = star_rating_symbol_test(widget, data);
1864 c_options->star_rating.rejected = rejected_symbol;
1867 /* general options tab */
1868 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1869 typedef struct _TZData TZData;
1873 GCancellable *cancellable;
1875 GtkWidget *progress;
1877 GFile *timezone_database_gq;
1878 gchar *timezone_database_user;
1881 static void config_tab_general(GtkWidget *notebook)
1886 GtkWidget *group_frame;
1887 GtkWidget *subgroup;
1889 GtkWidget *ct_button;
1892 gint hours, minutes, remainder;
1894 GtkWidget *star_rating_entry;
1896 gchar *rating_symbol;
1899 GNetworkMonitor *net_mon;
1900 GSocketConnectable *geeqie_org;
1901 gboolean internet_available;
1904 vbox = scrolled_notebook_page(notebook, _("General"));
1906 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1908 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1909 add_thumb_size_menu(table, 0, 0, _("Size:"));
1910 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1912 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1913 pref_label_new(hbox, _("Custom size: "));
1914 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1915 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1917 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1918 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1920 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1921 pref_checkbox_link_sensitivity(ct_button, subgroup);
1923 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1924 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1925 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1926 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1927 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1928 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1929 G_CALLBACK(cache_geeqie_cb), NULL);
1931 group_frame = pref_frame_new(subgroup, TRUE,
1932 _("Store thumbnails local to image folder (non-standard)"),
1933 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1934 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1935 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1936 G_CALLBACK(cache_local_cb), NULL);
1938 group_frame = pref_frame_new(subgroup, TRUE,
1939 _("Use standard thumbnail style and cache, shared with other applications"),
1940 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1941 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1942 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1943 G_CALLBACK(cache_standard_cb), NULL);
1945 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1946 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1948 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1950 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1951 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1953 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1954 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1955 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1957 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1958 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1961 pref_spacer(group, PREF_PAD_GROUP);
1963 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1965 c_options->star_rating.star = options->star_rating.star;
1966 c_options->star_rating.rejected = options->star_rating.rejected;
1968 str = g_string_new(NULL);
1969 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1970 pref_label_new(hbox, "Star character: ");
1971 str = g_string_append_unichar(str, options->star_rating.star);
1972 pref_label_new(hbox, g_strdup(str->str));
1973 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1974 star_rating_entry = gtk_entry_new();
1975 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1976 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1977 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1978 gtk_widget_show(star_rating_entry);
1979 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1980 G_CALLBACK(star_rating_star_test_cb), hbox);
1981 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1982 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1983 gtk_widget_show(button);
1984 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."));
1985 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1986 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1987 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1988 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1989 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1990 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1991 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1992 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1993 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1994 G_CALLBACK(star_rating_star_icon_cb),
1997 g_string_free(str, TRUE);
1998 g_free(rating_symbol);
2000 str = g_string_new(NULL);
2001 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2002 pref_label_new(hbox, "Rejected character: ");
2003 str = g_string_append_unichar(str, options->star_rating.rejected);
2004 pref_label_new(hbox, g_strdup(str->str));
2005 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2006 star_rating_entry = gtk_entry_new();
2007 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2008 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2009 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2010 gtk_widget_show(star_rating_entry);
2011 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2012 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2013 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2014 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2015 gtk_widget_show(button);
2016 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."));
2017 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2018 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2019 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2020 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2021 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2022 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2023 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2024 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2025 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2026 G_CALLBACK(star_rating_rejected_icon_cb),
2029 g_string_free(str, TRUE);
2030 g_free(rating_symbol);
2032 pref_spacer(group, PREF_PAD_GROUP);
2034 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2036 c_options->slideshow.delay = options->slideshow.delay;
2037 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2038 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2039 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2040 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2041 SLIDESHOW_SUBSECOND_PRECISION;
2043 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2045 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2047 options->slideshow.delay ? hours : 0.0,
2048 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2049 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2050 spin = pref_spin_new(hbox, ":" , NULL,
2052 options->slideshow.delay ? minutes: 0.0,
2053 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2054 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2055 spin = pref_spin_new(hbox, ":", NULL,
2056 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2057 options->slideshow.delay ? seconds : 10.0,
2058 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2059 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2061 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2062 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2064 pref_spacer(group, PREF_PAD_GROUP);
2066 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2068 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2069 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2070 pref_checkbox_new_int(group, _("Preload next image"),
2071 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2073 pref_checkbox_new_int(group, _("Refresh on file change"),
2074 options->update_on_time_change, &c_options->update_on_time_change);
2076 pref_spacer(group, PREF_PAD_GROUP);
2078 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2079 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2080 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2081 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2083 options->info_keywords.height, &c_options->info_keywords.height);
2084 pref_spin_new_int(hbox, _("Title:"), NULL,
2086 options->info_title.height, &c_options->info_title.height);
2087 pref_spin_new_int(hbox, _("Comment:"), NULL,
2089 options->info_comment.height, &c_options->info_comment.height);
2090 pref_spin_new_int(hbox, _("Rating:"), NULL,
2092 options->info_rating.height, &c_options->info_rating.height);
2094 pref_spacer(group, PREF_PAD_GROUP);
2096 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2098 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2099 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2101 pref_spacer(group, PREF_PAD_GROUP);
2103 net_mon = g_network_monitor_get_default();
2104 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2105 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2106 g_object_unref(geeqie_org);
2108 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2109 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2111 if (!internet_available)
2113 gtk_widget_set_sensitive(group, FALSE);
2116 tz = g_new0(TZData, 1);
2118 path = path_from_utf8(TIMEZONE_DATABASE);
2119 basename = g_path_get_basename(path);
2120 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2124 if (isfile(tz->timezone_database_user))
2126 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2130 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2133 if (!internet_available)
2135 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"));
2139 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"));
2141 gtk_widget_show(button);
2143 pref_spacer(group, PREF_PAD_GROUP);
2145 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2147 help_search_engine_entry = gtk_entry_new();
2148 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2149 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2150 gtk_widget_show(help_search_engine_entry);
2152 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"));
2154 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2155 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2156 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2157 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2158 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2159 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2160 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2161 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2162 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2163 G_CALLBACK(help_search_engine_entry_icon_cb),
2164 help_search_engine_entry);
2168 static void config_tab_image(GtkWidget *notebook)
2173 GtkWidget *ct_button;
2174 GtkWidget *enlargement_button;
2178 vbox = scrolled_notebook_page(notebook, _("Image"));
2180 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2182 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2183 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2186 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2187 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2190 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2191 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2193 c_options->image.zoom_increment = options->image.zoom_increment;
2194 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2195 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2196 G_CALLBACK(zoom_increment_cb), NULL);
2197 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2199 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2201 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2202 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2203 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2204 spin = pref_spin_new_int(hbox, NULL, NULL,
2206 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2207 pref_checkbox_link_sensitivity(enlargement_button, spin);
2208 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."));
2210 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2211 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2212 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2213 spin = pref_spin_new_int(hbox, NULL, NULL,
2215 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2216 pref_checkbox_link_sensitivity(ct_button, spin);
2217 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."));
2219 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2221 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2222 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2224 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2225 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2227 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2228 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2230 c_options->image.border_color = options->image.border_color;
2232 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2233 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2235 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2236 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2238 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2239 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2241 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2243 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2244 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2248 static void config_tab_windows(GtkWidget *notebook)
2254 GtkWidget *ct_button;
2257 vbox = scrolled_notebook_page(notebook, _("Windows"));
2259 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2261 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2262 options->save_window_positions, &c_options->save_window_positions);
2264 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2265 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2266 pref_checkbox_link_sensitivity(ct_button, button);
2268 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2269 options->tools_restore_state, &c_options->tools_restore_state);
2271 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2272 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2274 pref_checkbox_new_int(group, _("Show window IDs"),
2275 options->show_window_ids, &c_options->show_window_ids);
2277 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2279 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2280 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2282 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2283 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2284 options->image.limit_window_size, &c_options->image.limit_window_size);
2285 spin = pref_spin_new_int(hbox, NULL, NULL,
2287 options->image.max_window_size, &c_options->image.max_window_size);
2288 pref_checkbox_link_sensitivity(ct_button, spin);
2290 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2292 c_options->fullscreen.screen = options->fullscreen.screen;
2293 c_options->fullscreen.above = options->fullscreen.above;
2294 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2295 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2296 gtk_widget_show(hbox);
2298 pref_checkbox_new_int(group, _("Smooth image flip"),
2299 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2300 pref_checkbox_new_int(group, _("Disable screen saver"),
2301 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2304 #define PRE_FORMATTED_COLUMNS 5
2305 static void config_tab_osd(GtkWidget *notebook)
2311 GtkWidget *image_overlay_template_view;
2312 GtkWidget *scrolled;
2313 GtkWidget *scrolled_pre_formatted;
2314 GtkTextBuffer *buffer;
2316 GtkWidget *subgroup;
2318 vbox = scrolled_notebook_page(notebook, _("OSD"));
2320 image_overlay_template_view = gtk_text_view_new();
2322 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2324 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2326 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2327 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2328 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2329 gtk_widget_show(scrolled_pre_formatted);
2330 gtk_widget_show(subgroup);
2332 pref_line(group, PREF_PAD_GAP);
2334 pref_label_new(group, _("Image overlay template"));
2336 scrolled = gtk_scrolled_window_new(NULL, NULL);
2337 gtk_widget_set_size_request(scrolled, 200, 150);
2338 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2339 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2340 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2341 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2342 gtk_widget_show(scrolled);
2344 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2345 _("Extensive formatting options are shown in the Help file"));
2347 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2348 gtk_widget_show(image_overlay_template_view);
2350 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2352 #if GTK_CHECK_VERSION(3,4,0)
2353 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2354 G_CALLBACK(image_overlay_set_font_cb), notebook);
2356 button = gtk_font_button_new();
2357 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2358 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2359 g_signal_connect(G_OBJECT(button), "font-set",
2360 G_CALLBACK(image_overlay_set_font_cb),NULL);
2362 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2363 gtk_widget_show(button);
2365 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2366 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2367 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2368 gtk_widget_show(button);
2370 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2371 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2372 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2373 gtk_widget_show(button);
2374 image_overlay_set_text_colours();
2376 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2377 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2378 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2379 gtk_widget_show(button);
2381 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2382 G_CALLBACK(image_overlay_help_cb), NULL);
2383 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2384 gtk_widget_show(button);
2386 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2387 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2388 g_signal_connect(G_OBJECT(buffer), "changed",
2389 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2391 pref_line(group, PREF_PAD_GAP);
2393 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2394 hbox = gtk_hbox_new(FALSE, 0);
2395 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2396 gtk_widget_show(hbox);
2397 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2398 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2399 gtk_widget_show(label);
2400 pref_spacer(group,TRUE);
2402 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2403 hbox = gtk_hbox_new(FALSE, 0);
2404 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2405 gtk_widget_show(hbox);
2406 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2407 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2408 gtk_widget_show(label);
2409 pref_spacer(group,TRUE);
2411 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2412 hbox = gtk_hbox_new(FALSE, 0);
2413 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2414 gtk_widget_show(hbox);
2415 label = gtk_label_new(_("%path:39%"));
2416 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2417 gtk_widget_show(label);
2418 pref_spacer(group,TRUE);
2420 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2421 hbox = gtk_hbox_new(FALSE, 0);
2422 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2423 gtk_widget_show(hbox);
2424 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%"));
2425 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2426 gtk_widget_show(label);
2427 pref_spacer(group,TRUE);
2429 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2430 hbox = gtk_hbox_new(FALSE, 0);
2431 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2432 gtk_widget_show(hbox);
2433 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2434 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2435 gtk_widget_show(label);
2438 static GtkTreeModel *create_class_model(void)
2440 GtkListStore *model;
2444 /* create list store */
2445 model = gtk_list_store_new(1, G_TYPE_STRING);
2446 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2448 gtk_list_store_append(model, &iter);
2449 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2451 return GTK_TREE_MODEL (model);
2456 static void config_tab_files(GtkWidget *notebook)
2463 GtkWidget *ct_button;
2464 GtkWidget *scrolled;
2465 GtkWidget *filter_view;
2466 GtkCellRenderer *renderer;
2467 GtkTreeSelection *selection;
2468 GtkTreeViewColumn *column;
2470 vbox = scrolled_notebook_page(notebook, _("Files"));
2472 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2474 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2475 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2476 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2477 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2478 pref_checkbox_new_int(group, _("Case sensitive sort"),
2479 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2480 pref_checkbox_new_int(group, _("Natural sort order"),
2481 options->file_sort.natural, &c_options->file_sort.natural);
2482 pref_checkbox_new_int(group, _("Disable file extension checks"),
2483 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2485 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2486 options->file_filter.disable, &c_options->file_filter.disable);
2489 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2491 sidecar_ext_entry = gtk_entry_new();
2492 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2493 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2494 gtk_widget_show(sidecar_ext_entry);
2496 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2498 frame = pref_group_parent(group);
2499 g_signal_connect(G_OBJECT(ct_button), "toggled",
2500 G_CALLBACK(filter_disable_cb), frame);
2501 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2503 scrolled = gtk_scrolled_window_new(NULL, NULL);
2504 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2505 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2506 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2507 gtk_widget_show(scrolled);
2509 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2510 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2511 g_object_unref(filter_store);
2512 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2513 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2515 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2517 column = gtk_tree_view_column_new();
2518 gtk_tree_view_column_set_title(column, _("Filter"));
2519 gtk_tree_view_column_set_resizable(column, TRUE);
2521 renderer = gtk_cell_renderer_toggle_new();
2522 g_signal_connect(G_OBJECT(renderer), "toggled",
2523 G_CALLBACK(filter_store_enable_cb), filter_store);
2524 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2525 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2526 GINT_TO_POINTER(FE_ENABLE), NULL);
2528 renderer = gtk_cell_renderer_text_new();
2529 g_signal_connect(G_OBJECT(renderer), "edited",
2530 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2531 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2532 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2533 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2534 GINT_TO_POINTER(FE_EXTENSION), NULL);
2535 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2537 column = gtk_tree_view_column_new();
2538 gtk_tree_view_column_set_title(column, _("Description"));
2539 gtk_tree_view_column_set_resizable(column, TRUE);
2540 gtk_tree_view_column_set_fixed_width(column, 200);
2541 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2543 renderer = gtk_cell_renderer_text_new();
2544 g_signal_connect(G_OBJECT(renderer), "edited",
2545 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2546 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2547 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2548 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2549 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2550 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2552 column = gtk_tree_view_column_new();
2553 gtk_tree_view_column_set_title(column, _("Class"));
2554 gtk_tree_view_column_set_resizable(column, TRUE);
2555 renderer = gtk_cell_renderer_combo_new();
2556 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2557 "model", create_class_model(),
2562 g_signal_connect(G_OBJECT(renderer), "edited",
2563 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2564 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2565 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2566 GINT_TO_POINTER(FE_CLASS), NULL);
2567 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2569 column = gtk_tree_view_column_new();
2570 gtk_tree_view_column_set_title(column, _("Writable"));
2571 gtk_tree_view_column_set_resizable(column, FALSE);
2572 renderer = gtk_cell_renderer_toggle_new();
2573 g_signal_connect(G_OBJECT(renderer), "toggled",
2574 G_CALLBACK(filter_store_writable_cb), filter_store);
2575 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2576 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2577 GINT_TO_POINTER(FE_WRITABLE), NULL);
2578 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2580 column = gtk_tree_view_column_new();
2581 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2582 gtk_tree_view_column_set_resizable(column, FALSE);
2583 renderer = gtk_cell_renderer_toggle_new();
2584 g_signal_connect(G_OBJECT(renderer), "toggled",
2585 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2586 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2587 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2588 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2589 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2592 filter_store_populate();
2593 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2594 gtk_widget_show(filter_view);
2596 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2598 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2599 G_CALLBACK(filter_default_cb), filter_view);
2600 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2601 gtk_widget_show(button);
2603 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2604 G_CALLBACK(filter_remove_cb), filter_view);
2605 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2606 gtk_widget_show(button);
2608 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2609 G_CALLBACK(filter_add_cb), filter_view);
2610 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2611 gtk_widget_show(button);
2615 static void config_tab_metadata(GtkWidget *notebook)
2620 GtkWidget *ct_button;
2624 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2627 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2629 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2631 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2632 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2634 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2635 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2637 gtk_widget_set_sensitive(ct_button, FALSE);
2640 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2641 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2643 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2644 label = pref_label_new(group, text);
2645 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2646 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2649 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2651 gtk_widget_set_sensitive(group, FALSE);
2654 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2655 pref_checkbox_link_sensitivity(ct_button, hbox);
2657 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2658 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2660 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2661 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2663 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2664 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2666 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2667 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2669 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2671 gtk_widget_set_sensitive(group, FALSE);
2674 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2675 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2678 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2679 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2680 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2682 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2683 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2685 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2686 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2688 gtk_widget_set_sensitive(ct_button, FALSE);
2691 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2693 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2694 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2696 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2697 pref_checkbox_link_sensitivity(ct_button, hbox);
2699 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2700 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2702 pref_checkbox_new_int(group, _("Write metadata on image change"),
2703 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2705 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2706 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2708 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2710 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2711 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2712 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");
2717 typedef struct _KeywordFindData KeywordFindData;
2718 struct _KeywordFindData
2725 GtkWidget *button_close;
2726 GtkWidget *button_stop;
2727 GtkWidget *button_start;
2728 GtkWidget *progress;
2736 guint idle_id; /* event source id */
2739 #define KEYWORD_DIALOG_WIDTH 400
2741 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2743 GList *list_d = NULL;
2744 GList *list_f = NULL;
2748 filelist_read(dir_fd, &list_f, &list_d);
2752 filelist_read(dir_fd, &list_f, NULL);
2755 list_f = filelist_filter(list_f, FALSE);
2756 list_d = filelist_filter(list_d, TRUE);
2758 kfd->list = g_list_concat(list_f, kfd->list);
2759 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2762 static void keywords_find_reset(KeywordFindData *kfd)
2764 filelist_free(kfd->list);
2767 filelist_free(kfd->list_dir);
2768 kfd->list_dir = NULL;
2771 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2773 KeywordFindData *kfd = data;
2775 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2777 keywords_find_reset(kfd);
2778 generic_dialog_close(kfd->gd);
2782 static void keywords_find_finish(KeywordFindData *kfd)
2784 keywords_find_reset(kfd);
2786 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2787 spinner_set_interval(kfd->spinner, -1);
2789 gtk_widget_set_sensitive(kfd->group, TRUE);
2790 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2791 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2792 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2795 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2797 KeywordFindData *kfd = data;
2799 g_idle_remove_by_data(kfd);
2801 keywords_find_finish(kfd);
2804 static gboolean keywords_find_file(gpointer data)
2806 KeywordFindData *kfd = data;
2808 GtkTextBuffer *buffer;
2816 fd = kfd->list->data;
2817 kfd->list = g_list_remove(kfd->list, fd);
2819 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2820 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2824 gtk_text_buffer_get_end_iter(buffer, &iter);
2825 tmp = g_strconcat(keywords->data, "\n", NULL);
2826 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2828 keywords = keywords->next;
2831 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2832 file_data_unref(fd);
2833 string_list_free(keywords);
2837 else if (kfd->list_dir)
2841 fd = kfd->list_dir->data;
2842 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2844 keywords_find_folder(kfd, fd);
2846 file_data_unref(fd);
2851 keywords_find_finish(kfd);
2856 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2858 KeywordFindData *kfd = data;
2861 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2863 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2864 parse_out_relatives(path);
2868 warning_dialog(_("Invalid folder"),
2869 _("The specified folder can not be found."),
2870 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2876 gtk_widget_set_sensitive(kfd->group, FALSE);
2877 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2878 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2879 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2880 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2882 dir_fd = file_data_new_dir(path);
2883 keywords_find_folder(kfd, dir_fd);
2884 file_data_unref(dir_fd);
2885 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2891 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2893 KeywordFindData *kfd;
2897 kfd = g_new0(KeywordFindData, 1);
2899 kfd->gd = generic_dialog_new(_("Search for keywords"),
2900 "search_for_keywords",
2903 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2904 kfd->gd->cancel_cb = keywords_find_close_cb;
2905 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2906 keywords_find_close_cb, FALSE);
2907 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2908 keywords_find_start_cb, FALSE);
2909 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2910 keywords_find_stop_cb, FALSE);
2911 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2913 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2915 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2916 pref_spacer(hbox, PREF_PAD_INDENT);
2917 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2919 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2920 pref_label_new(hbox, _("Folder:"));
2922 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2923 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2924 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2925 gtk_widget_show(label);
2927 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2929 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2930 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2932 kfd->progress = gtk_entry_new();
2933 gtk_widget_set_can_focus(kfd->progress, FALSE);
2934 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2935 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2936 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2937 gtk_widget_show(kfd->progress);
2939 kfd->spinner = spinner_new(NULL, -1);
2940 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2941 gtk_widget_show(kfd->spinner);
2945 gtk_widget_show(kfd->gd->dialog);
2948 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2950 const gchar *path = layout_get_path(NULL);
2952 if (!path || !*path) path = homedir();
2953 keywords_find_dialog(widget, path);
2956 static void config_tab_keywords_save()
2958 GtkTextIter start, end;
2959 GtkTextBuffer *buffer;
2960 GList *kw_list = NULL;
2966 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2967 gtk_text_buffer_get_bounds(buffer, &start, &end);
2969 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2971 kw_split = strtok(buffer_text, "\n");
2972 while (kw_split != NULL)
2978 if (g_strcmp0(work->data, kw_split) == 0)
2987 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2989 kw_split = strtok(NULL, "\n");
2992 keyword_list_set(kw_list);
2994 string_list_free(kw_list);
2995 g_free(buffer_text);
2998 static void config_tab_keywords(GtkWidget *notebook)
3004 GtkWidget *scrolled;
3006 GtkTextBuffer *buffer;
3009 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3011 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3013 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3015 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3016 G_CALLBACK(keywords_find_cb), keyword_text);
3017 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3020 keyword_text = gtk_text_view_new();
3021 gtk_widget_set_size_request(keyword_text, 20, 20);
3022 scrolled = gtk_scrolled_window_new(NULL, NULL);
3023 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3024 gtk_widget_show(scrolled);
3026 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3027 gtk_widget_show(keyword_text);
3029 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3031 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3032 gtk_text_buffer_create_tag(buffer, "monospace",
3033 "family", "monospace", NULL);
3035 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3036 gtk_text_buffer_get_start_iter(buffer, &iter);
3037 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3040 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3042 GList *kwl = keyword_list_get();
3043 kwl = g_list_first(kwl);
3046 gtk_text_buffer_get_end_iter (buffer, &iter);
3047 tmp = g_strconcat(kwl->data, "\n", NULL);
3048 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3053 gtk_text_buffer_set_modified(buffer, FALSE);
3060 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3062 gint *option = data;
3064 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3068 *option = INTENT_PERCEPTUAL;
3071 *option = INTENT_RELATIVE_COLORIMETRIC;
3074 *option = INTENT_SATURATION;
3077 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3082 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3083 gint option, gint *option_c)
3090 pref_table_label(table, column, row, text, 0.0);
3092 combo = gtk_combo_box_text_new();
3094 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3095 if (option == INTENT_PERCEPTUAL) current = 0;
3096 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3097 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3098 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3099 if (option == INTENT_SATURATION) current = 2;
3100 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3101 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3103 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3105 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3107 g_signal_connect(G_OBJECT(combo), "changed",
3108 G_CALLBACK(intent_menu_cb), option_c);
3110 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3111 gtk_widget_show(combo);
3115 static void config_tab_color(GtkWidget *notebook)
3124 vbox = scrolled_notebook_page(notebook, _("Color management"));
3126 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3128 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3131 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3132 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3134 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3135 pref_label_bold(label, TRUE, FALSE);
3137 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3138 pref_label_bold(label, TRUE, FALSE);
3140 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3141 pref_label_bold(label, TRUE, FALSE);
3143 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3148 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3149 pref_table_label(table, 0, i + 1, buf, 1.0);
3152 entry = gtk_entry_new();
3153 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3154 if (options->color_profile.input_name[i])
3156 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3158 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3159 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3160 gtk_widget_show(entry);
3161 color_profile_input_name_entry[i] = entry;
3163 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3164 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3165 gtk_widget_set_size_request(entry, 160, -1);
3166 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3167 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3168 gtk_widget_show(tabcomp);
3169 color_profile_input_file_entry[i] = entry;
3172 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3174 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3176 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3177 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3179 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3181 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3182 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3183 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3184 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3185 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3187 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3189 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3191 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3193 gtk_widget_show(tabcomp);
3196 /* advanced entry tab */
3197 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3199 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3201 c_options->file_ops.use_system_trash = FALSE;
3202 c_options->file_ops.no_trash = FALSE;
3206 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3208 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3210 c_options->file_ops.use_system_trash = TRUE;
3211 c_options->file_ops.no_trash = FALSE;
3215 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3217 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3219 c_options->file_ops.no_trash = TRUE;
3223 static void config_tab_behavior(GtkWidget *notebook)
3230 GtkWidget *ct_button;
3234 GtkWidget *with_rename;
3235 GtkWidget *collections_on_top;
3237 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3239 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3241 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3242 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3243 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3244 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3245 pref_checkbox_new_int(group, _("Enable Delete key"),
3246 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3248 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3249 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3251 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3252 pref_checkbox_link_sensitivity(ct_button, hbox);
3254 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3255 pref_label_new(hbox, _("Folder:"));
3257 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3258 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3259 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3260 gtk_widget_show(tabcomp);
3262 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3263 pref_checkbox_link_sensitivity(ct_button, hbox);
3265 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3266 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3267 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3268 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3269 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3270 G_CALLBACK(safe_delete_view_cb), NULL);
3271 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3272 gtk_widget_show(button);
3274 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3275 G_CALLBACK(safe_delete_clear_cb), NULL);
3276 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3277 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3278 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3280 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3281 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3283 gtk_widget_show(button);
3285 pref_spacer(group, PREF_PAD_GROUP);
3288 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3290 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3291 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3293 pref_checkbox_new_int(group, _("In place renaming"),
3294 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3296 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3297 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3299 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3300 options->marks_save, &c_options->marks_save);
3301 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3303 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3304 options->with_rename, &c_options->with_rename);
3305 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3307 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3308 options->collections_on_top, &c_options->collections_on_top);
3309 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3311 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3312 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3314 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3315 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3317 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3318 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3320 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3321 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3323 pref_spacer(group, PREF_PAD_GROUP);
3325 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3327 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3328 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3329 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3330 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3331 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3332 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3333 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3334 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3335 pref_checkbox_new_int(group, _("Play video by left click on image"),
3336 options->image_l_click_video, &c_options->image_l_click_video);
3337 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3338 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3340 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3341 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3342 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3343 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3344 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3347 pref_spacer(group, PREF_PAD_GROUP);
3349 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3351 pref_spin_new_int(group, _("Debug level:"), NULL,
3352 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3354 pref_checkbox_new_int(group, _("Timer data"),
3355 options->log_window.timer_data, &c_options->log_window.timer_data);
3357 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3358 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3362 /* accelerators tab */
3363 static void config_tab_accelerators(GtkWidget *notebook)
3369 GtkWidget *scrolled;
3370 GtkWidget *accel_view;
3371 GtkCellRenderer *renderer;
3372 GtkTreeSelection *selection;
3373 GtkTreeViewColumn *column;
3375 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3377 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3379 scrolled = gtk_scrolled_window_new(NULL, NULL);
3380 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3381 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3382 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3383 gtk_widget_show(scrolled);
3385 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3387 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3388 g_object_unref(accel_store);
3389 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3390 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3392 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3394 renderer = gtk_cell_renderer_text_new();
3396 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3401 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3402 gtk_tree_view_column_set_resizable(column, TRUE);
3403 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3406 renderer = gtk_cell_renderer_accel_new();
3407 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3408 G_CALLBACK(accel_store_cleared_cb), accel_store);
3409 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3410 G_CALLBACK(accel_store_edited_cb), accel_store);
3413 g_object_set (renderer,
3415 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3418 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3423 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3424 gtk_tree_view_column_set_resizable(column, TRUE);
3425 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3427 renderer = gtk_cell_renderer_text_new();
3429 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3434 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3435 gtk_tree_view_column_set_resizable(column, TRUE);
3436 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3438 renderer = gtk_cell_renderer_text_new();
3440 column = gtk_tree_view_column_new_with_attributes("Accel",
3445 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3446 gtk_tree_view_column_set_resizable(column, TRUE);
3447 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3449 accel_store_populate();
3450 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3451 gtk_widget_show(accel_view);
3453 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3455 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3456 G_CALLBACK(accel_default_cb), accel_view);
3457 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3458 gtk_widget_show(button);
3460 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3461 G_CALLBACK(accel_reset_cb), accel_view);
3462 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3463 gtk_widget_show(button);
3466 /* toolbar main tab */
3467 static void config_tab_toolbar_main(GtkWidget *notebook)
3470 GtkWidget *toolbardata;
3473 lw = layout_window_list->data;
3475 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3477 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3478 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3479 gtk_widget_show(vbox);
3482 /* toolbar status tab */
3483 static void config_tab_toolbar_status(GtkWidget *notebook)
3486 GtkWidget *toolbardata;
3489 lw = layout_window_list->data;
3491 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3493 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3494 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3495 gtk_widget_show(vbox);
3499 static void config_tab_stereo(GtkWidget *notebook)
3507 GtkWidget *fs_button;
3508 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3510 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3512 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3513 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3515 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3516 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3517 pref_checkbox_new_int(box, _("Mirror left image"),
3518 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3519 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3520 pref_checkbox_new_int(box, _("Flip left image"),
3521 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3522 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3523 pref_checkbox_new_int(box, _("Mirror right image"),
3524 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3525 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3526 pref_checkbox_new_int(box, _("Flip right image"),
3527 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3528 pref_checkbox_new_int(group, _("Swap left and right images"),
3529 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3530 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3531 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3533 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3534 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3535 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3536 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3537 pref_checkbox_link_sensitivity(fs_button, box2);
3538 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3539 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3540 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3541 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3542 pref_checkbox_new_int(box, _("Mirror left image"),
3543 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3544 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3545 pref_checkbox_new_int(box, _("Flip left image"),
3546 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3547 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3548 pref_checkbox_new_int(box, _("Mirror right image"),
3549 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3550 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3551 pref_checkbox_new_int(box, _("Flip right image"),
3552 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3553 pref_checkbox_new_int(box2, _("Swap left and right images"),
3554 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3555 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3556 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3558 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3559 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3560 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3561 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3562 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3563 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3564 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3565 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3566 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3567 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3568 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3569 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3570 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3571 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3575 /* Main preferences window */
3576 static void config_window_create(void)
3578 GtkWidget *win_vbox;
3580 GtkWidget *notebook;
3582 GtkWidget *ct_button;
3584 if (!c_options) c_options = init_options(NULL);
3586 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3587 DEBUG_NAME(configwindow);
3588 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3589 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3590 G_CALLBACK(config_window_delete), NULL);
3591 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3592 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3593 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3595 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3596 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3597 gtk_widget_show(win_vbox);
3599 notebook = gtk_notebook_new();
3600 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3601 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3602 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3604 config_tab_general(notebook);
3605 config_tab_image(notebook);
3606 config_tab_osd(notebook);
3607 config_tab_windows(notebook);
3608 config_tab_accelerators(notebook);
3609 config_tab_files(notebook);
3610 config_tab_metadata(notebook);
3611 config_tab_keywords(notebook);
3612 config_tab_color(notebook);
3613 config_tab_stereo(notebook);
3614 config_tab_behavior(notebook);
3615 config_tab_toolbar_main(notebook);
3616 config_tab_toolbar_status(notebook);
3618 hbox = gtk_hbutton_box_new();
3619 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3620 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3621 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3622 gtk_widget_show(hbox);
3624 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3625 G_CALLBACK(config_window_help_cb), notebook);
3626 gtk_container_add(GTK_CONTAINER(hbox), button);
3627 gtk_widget_set_can_default(button, TRUE);
3628 gtk_widget_show(button);
3630 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3631 G_CALLBACK(config_window_ok_cb), NULL);
3632 gtk_container_add(GTK_CONTAINER(hbox), button);
3633 gtk_widget_set_can_default(button, TRUE);
3634 gtk_widget_grab_default(button);
3635 gtk_widget_show(button);
3639 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3640 G_CALLBACK(config_window_close_cb), NULL);
3641 gtk_container_add(GTK_CONTAINER(hbox), button);
3642 gtk_widget_set_can_default(button, TRUE);
3643 gtk_widget_show(button);
3645 if (!generic_dialog_get_alternative_button_order(configwindow))
3647 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3650 gtk_widget_show(notebook);
3652 gtk_widget_show(configwindow);
3656 *-----------------------------------------------------------------------------
3657 * config window show (public)
3658 *-----------------------------------------------------------------------------
3661 void show_config_window(void)
3665 gtk_window_present(GTK_WINDOW(configwindow));
3669 config_window_create();
3678 void show_about_window(LayoutWindow *lw)
3680 GdkPixbuf *pixbuf_logo;
3681 GdkPixbuf *pixbuf_icon;
3682 gchar *authors[1000];
3687 gchar *timezone_path;
3691 #define LINE_LENGTH 1000
3692 gchar line[LINE_LENGTH];
3694 copyright = g_string_new(NULL);
3695 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");
3697 path = path_from_utf8(TIMEZONE_DATABASE);
3698 basename = g_path_get_basename(path);
3699 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3700 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3702 cd = ZDOpenDatabase(timezone_path);
3705 copyright = g_string_append(copyright, ZDGetNotice(cd));
3706 ZDCloseDatabase(cd);
3710 g_free(timezone_path);
3714 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3715 fp = fopen(path, "r");
3718 while(fgets(line, LINE_LENGTH, fp))
3720 /* get rid of ending \n from fgets */
3721 line[strlen(line) - 1] = '\0';
3722 authors[i_authors] = g_strdup(line);
3725 authors[i_authors] = NULL;
3730 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3731 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3733 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3734 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3735 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3736 "title", _("About Geeqie"),
3738 "program-name", GQ_APPNAME,
3740 "logo", pixbuf_logo,
3741 "icon", pixbuf_icon,
3742 "website", GQ_WEBSITE,
3743 "website-label", "Website",
3744 "comments", comment,
3746 "translator-credits", _("translator-credits"),
3747 "wrap-license", TRUE,
3748 "license", copyright->str,
3751 g_string_free(copyright, TRUE);
3754 while(n < i_authors)
3764 static void image_overlay_set_text_colours()
3766 c_options->image_overlay.text_red = options->image_overlay.text_red;
3767 c_options->image_overlay.text_green = options->image_overlay.text_green;
3768 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3769 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3770 c_options->image_overlay.background_red = options->image_overlay.background_red;
3771 c_options->image_overlay.background_green = options->image_overlay.background_green;
3772 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3773 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3777 *-----------------------------------------------------------------------------
3778 * timezone database routines
3779 *-----------------------------------------------------------------------------
3782 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3784 GError *error = NULL;
3786 gchar *tmp_filename;
3788 if (!g_cancellable_is_cancelled(tz->cancellable))
3790 generic_dialog_close(tz->gd);
3794 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3796 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3797 move_file(tmp_filename, tz->timezone_database_user);
3798 g_free(tmp_filename);
3802 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3805 g_file_delete(tz->tmp_g_file, NULL, &error);
3806 g_object_unref(tz->tmp_g_file);
3807 tz->tmp_g_file = NULL;
3808 g_object_unref(tz->cancellable);
3809 g_object_unref(tz->timezone_database_gq);
3812 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3816 if (!g_cancellable_is_cancelled(tz->cancellable))
3818 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3822 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3826 g_cancellable_cancel(tz->cancellable);
3829 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3832 GError *error = NULL;
3833 GFileIOStream *io_stream;
3840 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3844 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3845 log_printf("Error: Download timezone database failed:\n%s", error->message);
3846 g_error_free(error);
3847 g_object_unref(tz->tmp_g_file);
3851 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3853 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3855 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3857 tz->progress = gtk_progress_bar_new();
3858 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3859 gtk_widget_show(tz->progress);
3861 gtk_widget_show(tz->gd->dialog);
3862 tz->cancellable = g_cancellable_new();
3863 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);
3865 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3868 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */