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 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
736 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
737 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
738 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
739 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
740 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
741 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
742 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
743 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
744 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
745 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
746 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
747 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
748 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
749 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
750 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
751 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
752 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
756 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
758 gchar **option = data;
761 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
763 const UseableMouseItems *list = useable_mouse_items;
767 if (g_strcmp0(list->label, label) == 0)
775 *option = g_strdup(list->name);
779 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
780 gchar *option, gchar **option_c)
788 pref_table_label(table, column, row, text, 0.0);
790 combo = gtk_combo_box_text_new();
792 const UseableMouseItems *list = useable_mouse_items;
796 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
797 if (g_strcmp0(list->name, option) == 0)
805 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
807 g_signal_connect(G_OBJECT(combo), "changed",
808 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
810 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
811 gtk_widget_show(combo);
814 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
818 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
821 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
823 c_options->thumbnails.max_width = thumb_size_list[n].w;
824 c_options->thumbnails.max_height = thumb_size_list[n].h;
828 c_options->thumbnails.max_width = options->thumbnails.max_width;
829 c_options->thumbnails.max_height = options->thumbnails.max_height;
833 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
839 c_options->thumbnails.max_width = options->thumbnails.max_width;
840 c_options->thumbnails.max_height = options->thumbnails.max_height;
842 pref_table_label(table, column, row, text, 0.0);
844 combo = gtk_combo_box_text_new();
847 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
852 w = thumb_size_list[i].w;
853 h = thumb_size_list[i].h;
855 buf = g_strdup_printf("%d x %d", w, h);
856 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
859 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
866 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
867 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
873 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
874 g_signal_connect(G_OBJECT(combo), "changed",
875 G_CALLBACK(thumb_size_menu_cb), NULL);
877 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
878 gtk_widget_show(combo);
881 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
885 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
889 *option = PR_STEREO_NONE;
892 *option = PR_STEREO_ANAGLYPH_RC;
895 *option = PR_STEREO_ANAGLYPH_GM;
898 *option = PR_STEREO_ANAGLYPH_YB;
901 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
904 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
907 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
910 *option = PR_STEREO_ANAGLYPH_DB_RC;
913 *option = PR_STEREO_ANAGLYPH_DB_GM;
916 *option = PR_STEREO_ANAGLYPH_DB_YB;
919 *option = PR_STEREO_HORIZ;
922 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
925 *option = PR_STEREO_VERT;
928 *option = PR_STEREO_VERT | PR_STEREO_HALF;
931 *option = PR_STEREO_FIXED;
936 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
937 gint option, gint *option_c, gboolean add_fixed)
944 pref_table_label(table, column, row, text, 0.0);
946 combo = gtk_combo_box_text_new();
948 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
950 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
951 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
952 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
953 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
954 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
955 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
956 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
957 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
958 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
959 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
960 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
961 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
962 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
963 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
964 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
965 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
966 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
967 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
970 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
971 if (option & PR_STEREO_HORIZ)
974 if (option & PR_STEREO_HALF) current = 11;
977 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
978 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
979 if (option & PR_STEREO_VERT)
982 if (option & PR_STEREO_HALF) current = 13;
987 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
988 if (option & PR_STEREO_FIXED) current = 14;
991 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
993 g_signal_connect(G_OBJECT(combo), "changed",
994 G_CALLBACK(stereo_mode_menu_cb), option_c);
996 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
997 gtk_widget_show(combo);
1000 static void video_menu_cb(GtkWidget *combo, gpointer data)
1002 gchar **option = data;
1004 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1008 static void video_menu_populate(gpointer data, gpointer user_data)
1010 GtkWidget *combo = user_data;
1011 EditorDescription *ed = data;
1013 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1016 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1017 gchar *option, gchar **option_c)
1021 /* use lists since they are sorted */
1022 GList *eds = editor_list_get();
1026 pref_table_label(table, column, row, text, 0.0);
1028 combo = gtk_combo_box_text_new();
1029 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1030 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1032 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1034 g_signal_connect(G_OBJECT(combo), "changed",
1035 G_CALLBACK(video_menu_cb), option_c);
1037 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1038 gtk_widget_show(combo);
1041 static void filter_store_populate(void)
1045 if (!filter_store) return;
1047 gtk_list_store_clear(filter_store);
1049 work = filter_get_list();
1058 gtk_list_store_append(filter_store, &iter);
1059 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1063 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1064 gchar *new_text, gpointer data)
1066 GtkWidget *model = data;
1067 FilterEntry *fe = data;
1071 if (!new_text || strlen(new_text) < 1) return;
1073 tpath = gtk_tree_path_new_from_string(path_str);
1074 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1075 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1077 g_free(fe->extensions);
1078 fe->extensions = g_strdup(new_text);
1080 gtk_tree_path_free(tpath);
1084 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1085 gchar *new_text, gpointer data)
1087 GtkWidget *model = data;
1088 FilterEntry *fe = data;
1093 if (!new_text || !new_text[0]) return;
1095 tpath = gtk_tree_path_new_from_string(path_str);
1096 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1097 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1099 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1101 if (strcmp(new_text, _(format_class_list[i])) == 0)
1108 gtk_tree_path_free(tpath);
1112 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1113 gchar *new_text, gpointer data)
1115 GtkWidget *model = data;
1120 if (!new_text || !new_text[0]) return;
1122 tpath = gtk_tree_path_new_from_string(path_str);
1123 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1124 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1126 g_free(fe->description);
1127 fe->description = g_strdup(new_text);
1129 gtk_tree_path_free(tpath);
1132 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1133 gchar *path_str, gpointer data)
1135 GtkWidget *model = data;
1140 tpath = gtk_tree_path_new_from_string(path_str);
1141 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1142 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1144 fe->enabled = !fe->enabled;
1146 gtk_tree_path_free(tpath);
1150 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1151 gchar *path_str, gpointer data)
1153 GtkWidget *model = data;
1158 tpath = gtk_tree_path_new_from_string(path_str);
1159 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1160 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1162 fe->writable = !fe->writable;
1163 if (fe->writable) fe->allow_sidecar = FALSE;
1165 gtk_tree_path_free(tpath);
1169 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1170 gchar *path_str, gpointer data)
1172 GtkWidget *model = data;
1177 tpath = gtk_tree_path_new_from_string(path_str);
1178 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1179 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1181 fe->allow_sidecar = !fe->allow_sidecar;
1182 if (fe->allow_sidecar) fe->writable = FALSE;
1184 gtk_tree_path_free(tpath);
1188 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1189 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1193 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1195 switch (GPOINTER_TO_INT(data))
1198 g_object_set(GTK_CELL_RENDERER(cell),
1199 "active", fe->enabled, NULL);
1202 g_object_set(GTK_CELL_RENDERER(cell),
1203 "text", fe->extensions, NULL);
1205 case FE_DESCRIPTION:
1206 g_object_set(GTK_CELL_RENDERER(cell),
1207 "text", fe->description, NULL);
1210 g_object_set(GTK_CELL_RENDERER(cell),
1211 "text", _(format_class_list[fe->file_class]), NULL);
1214 g_object_set(GTK_CELL_RENDERER(cell),
1215 "active", fe->writable, NULL);
1217 case FE_ALLOW_SIDECAR:
1218 g_object_set(GTK_CELL_RENDERER(cell),
1219 "active", fe->allow_sidecar, NULL);
1224 static gboolean filter_add_scroll(gpointer data)
1228 GtkCellRenderer *cell;
1229 GtkTreeViewColumn *column;
1232 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1233 path = gtk_tree_path_new_from_indices(rows-1, -1);
1235 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1237 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1238 cell = g_list_last(list_cells)->data;
1240 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1241 path, column, FALSE, 0.0, 0.0 );
1242 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1243 path, column, cell, TRUE);
1245 gtk_tree_path_free(path);
1246 g_list_free(list_cells);
1251 static void filter_add_cb(GtkWidget *widget, gpointer data)
1253 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1254 filter_store_populate();
1256 g_idle_add((GSourceFunc)filter_add_scroll, data);
1259 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1261 GtkWidget *filter_view = data;
1262 GtkTreeSelection *selection;
1266 if (!filter_store) return;
1267 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1268 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1269 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1272 filter_remove_entry(fe);
1274 filter_store_populate();
1277 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1281 GtkTreeViewColumn *column;
1283 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1284 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1285 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1287 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1291 gtk_tree_path_free(path);
1296 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1299 filter_add_defaults();
1301 filter_store_populate();
1303 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1306 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1308 /* no op, only so cancel button appears */
1311 static void filter_default_cb(GtkWidget *widget, gpointer data)
1315 gd = generic_dialog_new(_("Reset filters"),
1316 "reset_filter", widget, TRUE,
1317 dummy_cancel_cb, data);
1318 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1319 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1320 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1321 gtk_widget_show(gd->dialog);
1324 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1326 GtkWidget *frame = data;
1328 gtk_widget_set_sensitive(frame,
1329 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1332 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1334 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1337 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1339 file_util_trash_clear();
1342 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1346 gd = generic_dialog_new(_("Clear trash"),
1347 "clear_trash", widget, TRUE,
1348 dummy_cancel_cb, NULL);
1349 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1350 _("This will remove the trash contents."), FALSE);
1351 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1352 entry = gtk_entry_new();
1353 gtk_widget_set_can_focus(entry, FALSE);
1354 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1355 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1356 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1357 gtk_widget_show(entry);
1358 gtk_widget_show(gd->dialog);
1361 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1363 GtkWidget *pTextView;
1364 GtkTextBuffer *pTextBuffer;
1368 pTextView = GTK_WIDGET(data);
1370 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1371 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1372 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1374 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1375 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1378 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1380 GtkTextView *text_view = data;
1381 GtkTextBuffer *buffer;
1383 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1384 if (!configwindow) return;
1386 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1387 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1390 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1394 gd = generic_dialog_new(_("Reset image overlay template string"),
1395 "reset_image_overlay_template_string", widget, TRUE,
1396 dummy_cancel_cb, data);
1397 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1398 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1399 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1400 gtk_widget_show(gd->dialog);
1403 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1405 help_window_show("GuideOptionsOSD.html");
1408 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1410 #if GTK_CHECK_VERSION(3,4,0)
1413 PangoFontDescription *font_desc;
1415 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1416 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1418 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1420 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1421 font = pango_font_description_to_string(font_desc);
1422 g_free(c_options->image_overlay.font);
1423 c_options->image_overlay.font = g_strdup(font);
1427 gtk_widget_destroy(dialog);
1431 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1432 c_options->image_overlay.font = g_strdup(font);
1436 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1439 #if GTK_CHECK_VERSION(3,4,0)
1442 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1443 colour.red = options->image_overlay.text_red;
1444 colour.green = options->image_overlay.text_green;
1445 colour.blue = options->image_overlay.text_blue;
1446 colour.alpha = options->image_overlay.text_alpha;
1447 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1448 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1450 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1452 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1453 c_options->image_overlay.text_red = colour.red*255;
1454 c_options->image_overlay.text_green = colour.green*255;
1455 c_options->image_overlay.text_blue = colour.blue*255;
1456 c_options->image_overlay.text_alpha = colour.alpha*255;
1458 gtk_widget_destroy(dialog);
1461 GtkColorSelection *colorsel;
1463 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1464 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1465 colour.red = options->image_overlay.text_red*257;
1466 colour.green = options->image_overlay.text_green*257;
1467 colour.blue = options->image_overlay.text_blue*257;
1468 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1469 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1470 gtk_color_selection_set_current_color(colorsel, &colour);
1471 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1473 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1475 gtk_color_selection_get_current_color(colorsel, &colour);
1476 c_options->image_overlay.text_red = colour.red/257;
1477 c_options->image_overlay.text_green = colour.green/257;
1478 c_options->image_overlay.text_blue = colour.blue/257;
1479 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1481 gtk_widget_destroy (dialog);
1486 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1489 #if GTK_CHECK_VERSION(3,4,0)
1492 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1493 colour.red = options->image_overlay.background_red;
1494 colour.green = options->image_overlay.background_green;
1495 colour.blue = options->image_overlay.background_blue;
1496 colour.alpha = options->image_overlay.background_alpha;
1497 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1498 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1500 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1502 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1503 c_options->image_overlay.background_red = colour.red*255;
1504 c_options->image_overlay.background_green = colour.green*255;
1505 c_options->image_overlay.background_blue = colour.blue*255;
1506 c_options->image_overlay.background_alpha = colour.alpha*255;
1508 gtk_widget_destroy(dialog);
1511 GtkColorSelection *colorsel;
1513 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1514 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1515 colour.red = options->image_overlay.background_red*257;
1516 colour.green = options->image_overlay.background_green*257;
1517 colour.blue = options->image_overlay.background_blue*257;
1518 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1519 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1520 gtk_color_selection_set_current_color(colorsel, &colour);
1521 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1523 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1525 gtk_color_selection_get_current_color(colorsel, &colour);
1526 c_options->image_overlay.background_red = colour.red/257;
1527 c_options->image_overlay.background_green = colour.green/257;
1528 c_options->image_overlay.background_blue = colour.blue/257;
1529 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1531 gtk_widget_destroy(dialog);
1535 static void accel_store_populate(void)
1538 GList *groups, *actions;
1540 const gchar *accel_path;
1544 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1546 gtk_tree_store_clear(accel_store);
1547 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1549 g_assert(lw && lw->ui_manager);
1550 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1553 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1556 action = GTK_ACTION(actions->data);
1557 accel_path = gtk_action_get_accel_path(action);
1558 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1560 gchar *label, *label2, *tooltip, *accel;
1561 g_object_get(action,
1562 "tooltip", &tooltip,
1566 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1572 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1576 gtk_tree_store_append(accel_store, &iter, NULL);
1577 gtk_tree_store_set(accel_store, &iter,
1580 AE_TOOLTIP, tooltip ? tooltip : "",
1581 AE_ACCEL, accel_path,
1589 actions = actions->next;
1592 groups = groups->next;
1596 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1601 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1603 gchar *accel1 = data;
1608 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1610 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1611 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1613 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1615 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1616 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1625 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1627 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1631 GtkAccelKey old_key, key;
1632 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1634 gtk_tree_model_get_iter(model, &iter, path);
1635 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1637 /* test if the accelerator can be stored without conflicts*/
1638 gtk_accel_map_lookup_entry(accel_path, &old_key);
1640 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1641 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1642 gtk_accel_map_lookup_entry(accel_path, &key);
1644 /* restore the original for now, the key will be really changed when the changes are confirmed */
1645 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1647 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1648 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1650 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1651 gtk_tree_path_free(path);
1655 static gboolean accel_default_scroll(GtkTreeView *data)
1659 GtkTreeViewColumn *column;
1661 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1662 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1663 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1665 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1669 gtk_tree_path_free(path);
1674 static void accel_default_cb(GtkWidget *widget, gpointer data)
1676 accel_store_populate();
1678 g_idle_add((GSourceFunc)accel_default_scroll, data);
1681 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1683 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1686 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1689 gchar *accel_path, *accel;
1691 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1692 gtk_accel_map_lookup_entry(accel_path, &key);
1693 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1695 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1697 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1702 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1704 GtkTreeSelection *selection;
1706 if (!accel_store) return;
1707 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1708 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1713 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1717 GtkWidget *scrolled;
1718 GtkWidget *viewport;
1720 scrolled = gtk_scrolled_window_new(NULL, NULL);
1721 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1722 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1723 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1724 label = gtk_label_new(title);
1725 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1726 gtk_widget_show(scrolled);
1728 viewport = gtk_viewport_new(NULL, NULL);
1729 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1730 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1731 gtk_widget_show(viewport);
1733 vbox = gtk_vbox_new(FALSE, 0);
1734 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1735 gtk_widget_show(vbox);
1740 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1742 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1744 c_options->thumbnails.spec_standard =TRUE;
1745 c_options->thumbnails.cache_into_dirs = FALSE;
1749 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1751 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1753 c_options->thumbnails.spec_standard =FALSE;
1754 c_options->thumbnails.cache_into_dirs = FALSE;
1758 static void cache_local_cb(GtkWidget *widget, gpointer data)
1760 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1762 c_options->thumbnails.cache_into_dirs = TRUE;
1763 c_options->thumbnails.spec_standard =FALSE;
1767 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1768 GdkEvent *event, gpointer userdata)
1770 if (pos == GTK_ENTRY_ICON_PRIMARY)
1772 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1776 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1780 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1781 GdkEvent *event, gpointer userdata)
1783 gchar *rating_symbol;
1785 if (pos == GTK_ENTRY_ICON_PRIMARY)
1787 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1788 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1789 g_free(rating_symbol);
1793 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1794 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1795 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1799 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1800 GdkEvent *event, gpointer userdata)
1802 gchar *rating_symbol;
1804 if (pos == GTK_ENTRY_ICON_PRIMARY)
1806 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1807 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1808 g_free(rating_symbol);
1812 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1813 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1814 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1818 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1820 GtkContainer *hbox = data;
1821 GString *str = g_string_new(NULL);
1822 GtkEntry *hex_code_entry;
1823 gchar *hex_code_full;
1826 guint64 hex_value = 0;
1828 list = gtk_container_get_children(hbox);
1830 hex_code_entry = g_list_nth_data(list, 2);
1831 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1833 hex_code = g_strsplit(hex_code_full, "+", 2);
1834 if (hex_code[0] && hex_code[1])
1836 hex_value = strtoull(hex_code[1], NULL, 16);
1838 if (!hex_value || hex_value > 0x10FFFF)
1840 hex_value = 0x003F; // Unicode 'Question Mark'
1842 str = g_string_append_unichar(str, (gunichar)hex_value);
1843 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1845 g_strfreev(hex_code);
1846 g_string_free(str, TRUE);
1847 g_free(hex_code_full);
1852 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1854 guint64 star_symbol;
1856 star_symbol = star_rating_symbol_test(widget, data);
1857 c_options->star_rating.star = star_symbol;
1860 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1862 guint64 rejected_symbol;
1864 rejected_symbol = star_rating_symbol_test(widget, data);
1865 c_options->star_rating.rejected = rejected_symbol;
1868 /* general options tab */
1869 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1870 typedef struct _TZData TZData;
1874 GCancellable *cancellable;
1876 GtkWidget *progress;
1878 GFile *timezone_database_gq;
1879 gchar *timezone_database_user;
1882 static void config_tab_general(GtkWidget *notebook)
1887 GtkWidget *group_frame;
1888 GtkWidget *subgroup;
1890 GtkWidget *ct_button;
1893 gint hours, minutes, remainder;
1895 GtkWidget *star_rating_entry;
1897 gchar *rating_symbol;
1900 GNetworkMonitor *net_mon;
1901 GSocketConnectable *geeqie_org;
1902 gboolean internet_available;
1905 vbox = scrolled_notebook_page(notebook, _("General"));
1907 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1909 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1910 add_thumb_size_menu(table, 0, 0, _("Size:"));
1911 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1913 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1914 pref_label_new(hbox, _("Custom size: "));
1915 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1916 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1918 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1919 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1921 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1922 pref_checkbox_link_sensitivity(ct_button, subgroup);
1924 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1925 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1926 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1927 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1928 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1929 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1930 G_CALLBACK(cache_geeqie_cb), NULL);
1932 group_frame = pref_frame_new(subgroup, TRUE,
1933 _("Store thumbnails local to image folder (non-standard)"),
1934 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1935 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1936 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1937 G_CALLBACK(cache_local_cb), NULL);
1939 group_frame = pref_frame_new(subgroup, TRUE,
1940 _("Use standard thumbnail style and cache, shared with other applications"),
1941 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1942 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1943 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1944 G_CALLBACK(cache_standard_cb), NULL);
1946 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1947 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1949 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1951 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1952 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1954 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1955 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1956 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1958 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1959 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1962 pref_spacer(group, PREF_PAD_GROUP);
1964 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1966 c_options->star_rating.star = options->star_rating.star;
1967 c_options->star_rating.rejected = options->star_rating.rejected;
1969 str = g_string_new(NULL);
1970 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1971 pref_label_new(hbox, "Star character: ");
1972 str = g_string_append_unichar(str, options->star_rating.star);
1973 pref_label_new(hbox, g_strdup(str->str));
1974 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1975 star_rating_entry = gtk_entry_new();
1976 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1977 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1978 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1979 gtk_widget_show(star_rating_entry);
1980 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1981 G_CALLBACK(star_rating_star_test_cb), hbox);
1982 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1983 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1984 gtk_widget_show(button);
1985 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."));
1986 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1987 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1988 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1989 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1990 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1991 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1992 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1993 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1994 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1995 G_CALLBACK(star_rating_star_icon_cb),
1998 g_string_free(str, TRUE);
1999 g_free(rating_symbol);
2001 str = g_string_new(NULL);
2002 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2003 pref_label_new(hbox, "Rejected character: ");
2004 str = g_string_append_unichar(str, options->star_rating.rejected);
2005 pref_label_new(hbox, g_strdup(str->str));
2006 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2007 star_rating_entry = gtk_entry_new();
2008 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2009 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2010 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2011 gtk_widget_show(star_rating_entry);
2012 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2013 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2014 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2015 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2016 gtk_widget_show(button);
2017 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."));
2018 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2019 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2020 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2021 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2022 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2023 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2024 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2025 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2026 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2027 G_CALLBACK(star_rating_rejected_icon_cb),
2030 g_string_free(str, TRUE);
2031 g_free(rating_symbol);
2033 pref_spacer(group, PREF_PAD_GROUP);
2035 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2037 c_options->slideshow.delay = options->slideshow.delay;
2038 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2039 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2040 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2041 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2042 SLIDESHOW_SUBSECOND_PRECISION;
2044 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2046 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2048 options->slideshow.delay ? hours : 0.0,
2049 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2050 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2051 spin = pref_spin_new(hbox, ":" , NULL,
2053 options->slideshow.delay ? minutes: 0.0,
2054 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2055 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2056 spin = pref_spin_new(hbox, ":", NULL,
2057 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2058 options->slideshow.delay ? seconds : 10.0,
2059 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2060 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2062 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2063 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2065 pref_spacer(group, PREF_PAD_GROUP);
2067 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2069 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2070 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2071 pref_checkbox_new_int(group, _("Preload next image"),
2072 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2074 pref_checkbox_new_int(group, _("Refresh on file change"),
2075 options->update_on_time_change, &c_options->update_on_time_change);
2077 pref_spacer(group, PREF_PAD_GROUP);
2079 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2080 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2081 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2082 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2084 options->info_keywords.height, &c_options->info_keywords.height);
2085 pref_spin_new_int(hbox, _("Title:"), NULL,
2087 options->info_title.height, &c_options->info_title.height);
2088 pref_spin_new_int(hbox, _("Comment:"), NULL,
2090 options->info_comment.height, &c_options->info_comment.height);
2091 pref_spin_new_int(hbox, _("Rating:"), NULL,
2093 options->info_rating.height, &c_options->info_rating.height);
2095 pref_spacer(group, PREF_PAD_GROUP);
2097 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2099 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2100 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2102 pref_spacer(group, PREF_PAD_GROUP);
2104 net_mon = g_network_monitor_get_default();
2105 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2106 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2107 g_object_unref(geeqie_org);
2109 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2110 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2112 if (!internet_available)
2114 gtk_widget_set_sensitive(group, FALSE);
2117 tz = g_new0(TZData, 1);
2119 path = path_from_utf8(TIMEZONE_DATABASE);
2120 basename = g_path_get_basename(path);
2121 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2125 if (isfile(tz->timezone_database_user))
2127 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2131 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2134 if (!internet_available)
2136 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"));
2140 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"));
2142 gtk_widget_show(button);
2144 pref_spacer(group, PREF_PAD_GROUP);
2146 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2148 help_search_engine_entry = gtk_entry_new();
2149 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2150 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2151 gtk_widget_show(help_search_engine_entry);
2153 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"));
2155 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2156 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2157 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2158 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2159 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2160 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2161 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2162 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2163 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2164 G_CALLBACK(help_search_engine_entry_icon_cb),
2165 help_search_engine_entry);
2169 static void config_tab_image(GtkWidget *notebook)
2174 GtkWidget *ct_button;
2175 GtkWidget *enlargement_button;
2178 GtkWidget *two_pass;
2180 vbox = scrolled_notebook_page(notebook, _("Image"));
2182 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2184 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2185 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2186 if (options->image.use_clutter_renderer)
2188 gtk_widget_set_sensitive(table, FALSE);
2192 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2193 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2196 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2197 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2198 if (options->image.use_clutter_renderer)
2200 gtk_widget_set_sensitive(two_pass, FALSE);
2203 c_options->image.zoom_increment = options->image.zoom_increment;
2204 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2205 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2206 G_CALLBACK(zoom_increment_cb), NULL);
2207 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2209 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2211 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2212 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2213 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2214 spin = pref_spin_new_int(hbox, NULL, NULL,
2216 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2217 pref_checkbox_link_sensitivity(enlargement_button, spin);
2218 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."));
2220 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2221 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2222 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2223 spin = pref_spin_new_int(hbox, NULL, NULL,
2225 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2226 pref_checkbox_link_sensitivity(ct_button, spin);
2227 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."));
2229 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2231 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2232 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2234 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2235 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2237 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2238 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2240 c_options->image.border_color = options->image.border_color;
2242 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2243 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2245 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2246 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2248 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2249 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2251 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2253 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2254 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2258 static void config_tab_windows(GtkWidget *notebook)
2264 GtkWidget *ct_button;
2267 vbox = scrolled_notebook_page(notebook, _("Windows"));
2269 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2271 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2272 options->save_window_positions, &c_options->save_window_positions);
2274 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2275 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2276 pref_checkbox_link_sensitivity(ct_button, button);
2278 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2279 options->tools_restore_state, &c_options->tools_restore_state);
2281 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2282 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2284 pref_checkbox_new_int(group, _("Show window IDs"),
2285 options->show_window_ids, &c_options->show_window_ids);
2287 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2289 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2290 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2292 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2293 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2294 options->image.limit_window_size, &c_options->image.limit_window_size);
2295 spin = pref_spin_new_int(hbox, NULL, NULL,
2297 options->image.max_window_size, &c_options->image.max_window_size);
2298 pref_checkbox_link_sensitivity(ct_button, spin);
2300 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2302 c_options->fullscreen.screen = options->fullscreen.screen;
2303 c_options->fullscreen.above = options->fullscreen.above;
2304 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2305 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2306 gtk_widget_show(hbox);
2308 pref_checkbox_new_int(group, _("Smooth image flip"),
2309 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2310 pref_checkbox_new_int(group, _("Disable screen saver"),
2311 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2314 #define PRE_FORMATTED_COLUMNS 5
2315 static void config_tab_osd(GtkWidget *notebook)
2321 GtkWidget *image_overlay_template_view;
2322 GtkWidget *scrolled;
2323 GtkWidget *scrolled_pre_formatted;
2324 GtkTextBuffer *buffer;
2326 GtkWidget *subgroup;
2328 vbox = scrolled_notebook_page(notebook, _("OSD"));
2330 image_overlay_template_view = gtk_text_view_new();
2332 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2334 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2336 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2337 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2338 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2339 gtk_widget_show(scrolled_pre_formatted);
2340 gtk_widget_show(subgroup);
2342 pref_line(group, PREF_PAD_GAP);
2344 pref_label_new(group, _("Image overlay template"));
2346 scrolled = gtk_scrolled_window_new(NULL, NULL);
2347 gtk_widget_set_size_request(scrolled, 200, 150);
2348 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2349 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2350 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2351 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2352 gtk_widget_show(scrolled);
2354 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2355 _("Extensive formatting options are shown in the Help file"));
2357 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2358 gtk_widget_show(image_overlay_template_view);
2360 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2362 #if GTK_CHECK_VERSION(3,4,0)
2363 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2364 G_CALLBACK(image_overlay_set_font_cb), notebook);
2366 button = gtk_font_button_new();
2367 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2368 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2369 g_signal_connect(G_OBJECT(button), "font-set",
2370 G_CALLBACK(image_overlay_set_font_cb),NULL);
2372 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2373 gtk_widget_show(button);
2375 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2376 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2377 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2378 gtk_widget_show(button);
2380 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2381 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2382 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2383 gtk_widget_show(button);
2384 image_overlay_set_text_colours();
2386 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2387 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2388 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2389 gtk_widget_show(button);
2391 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2392 G_CALLBACK(image_overlay_help_cb), NULL);
2393 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2394 gtk_widget_show(button);
2396 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2397 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2398 g_signal_connect(G_OBJECT(buffer), "changed",
2399 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2401 pref_line(group, PREF_PAD_GAP);
2403 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2404 hbox = gtk_hbox_new(FALSE, 0);
2405 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2406 gtk_widget_show(hbox);
2407 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2408 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2409 gtk_widget_show(label);
2410 pref_spacer(group,TRUE);
2412 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2413 hbox = gtk_hbox_new(FALSE, 0);
2414 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2415 gtk_widget_show(hbox);
2416 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2417 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2418 gtk_widget_show(label);
2419 pref_spacer(group,TRUE);
2421 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2422 hbox = gtk_hbox_new(FALSE, 0);
2423 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2424 gtk_widget_show(hbox);
2425 label = gtk_label_new(_("%path:39%"));
2426 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2427 gtk_widget_show(label);
2428 pref_spacer(group,TRUE);
2430 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2431 hbox = gtk_hbox_new(FALSE, 0);
2432 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2433 gtk_widget_show(hbox);
2434 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%"));
2435 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2436 gtk_widget_show(label);
2437 pref_spacer(group,TRUE);
2439 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2440 hbox = gtk_hbox_new(FALSE, 0);
2441 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2442 gtk_widget_show(hbox);
2443 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2444 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2445 gtk_widget_show(label);
2448 static GtkTreeModel *create_class_model(void)
2450 GtkListStore *model;
2454 /* create list store */
2455 model = gtk_list_store_new(1, G_TYPE_STRING);
2456 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2458 gtk_list_store_append(model, &iter);
2459 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2461 return GTK_TREE_MODEL (model);
2466 static void config_tab_files(GtkWidget *notebook)
2473 GtkWidget *ct_button;
2474 GtkWidget *scrolled;
2475 GtkWidget *filter_view;
2476 GtkCellRenderer *renderer;
2477 GtkTreeSelection *selection;
2478 GtkTreeViewColumn *column;
2480 vbox = scrolled_notebook_page(notebook, _("Files"));
2482 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2484 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2485 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2486 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2487 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2488 pref_checkbox_new_int(group, _("Case sensitive sort"),
2489 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2490 pref_checkbox_new_int(group, _("Natural sort order"),
2491 options->file_sort.natural, &c_options->file_sort.natural);
2492 pref_checkbox_new_int(group, _("Disable file extension checks"),
2493 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2495 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2496 options->file_filter.disable, &c_options->file_filter.disable);
2499 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2501 sidecar_ext_entry = gtk_entry_new();
2502 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2503 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2504 gtk_widget_show(sidecar_ext_entry);
2506 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2508 frame = pref_group_parent(group);
2509 g_signal_connect(G_OBJECT(ct_button), "toggled",
2510 G_CALLBACK(filter_disable_cb), frame);
2511 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2513 scrolled = gtk_scrolled_window_new(NULL, NULL);
2514 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2515 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2516 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2517 gtk_widget_show(scrolled);
2519 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2520 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2521 g_object_unref(filter_store);
2522 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2523 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2525 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2527 column = gtk_tree_view_column_new();
2528 gtk_tree_view_column_set_title(column, _("Filter"));
2529 gtk_tree_view_column_set_resizable(column, TRUE);
2531 renderer = gtk_cell_renderer_toggle_new();
2532 g_signal_connect(G_OBJECT(renderer), "toggled",
2533 G_CALLBACK(filter_store_enable_cb), filter_store);
2534 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2535 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2536 GINT_TO_POINTER(FE_ENABLE), NULL);
2538 renderer = gtk_cell_renderer_text_new();
2539 g_signal_connect(G_OBJECT(renderer), "edited",
2540 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2541 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2542 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2543 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2544 GINT_TO_POINTER(FE_EXTENSION), NULL);
2545 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2547 column = gtk_tree_view_column_new();
2548 gtk_tree_view_column_set_title(column, _("Description"));
2549 gtk_tree_view_column_set_resizable(column, TRUE);
2550 gtk_tree_view_column_set_fixed_width(column, 200);
2551 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2553 renderer = gtk_cell_renderer_text_new();
2554 g_signal_connect(G_OBJECT(renderer), "edited",
2555 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2556 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2557 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2558 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2559 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2560 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2562 column = gtk_tree_view_column_new();
2563 gtk_tree_view_column_set_title(column, _("Class"));
2564 gtk_tree_view_column_set_resizable(column, TRUE);
2565 renderer = gtk_cell_renderer_combo_new();
2566 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2567 "model", create_class_model(),
2572 g_signal_connect(G_OBJECT(renderer), "edited",
2573 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2574 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2575 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2576 GINT_TO_POINTER(FE_CLASS), NULL);
2577 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2579 column = gtk_tree_view_column_new();
2580 gtk_tree_view_column_set_title(column, _("Writable"));
2581 gtk_tree_view_column_set_resizable(column, FALSE);
2582 renderer = gtk_cell_renderer_toggle_new();
2583 g_signal_connect(G_OBJECT(renderer), "toggled",
2584 G_CALLBACK(filter_store_writable_cb), filter_store);
2585 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2586 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2587 GINT_TO_POINTER(FE_WRITABLE), NULL);
2588 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2590 column = gtk_tree_view_column_new();
2591 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2592 gtk_tree_view_column_set_resizable(column, FALSE);
2593 renderer = gtk_cell_renderer_toggle_new();
2594 g_signal_connect(G_OBJECT(renderer), "toggled",
2595 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2596 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2597 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2598 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2599 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2602 filter_store_populate();
2603 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2604 gtk_widget_show(filter_view);
2606 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2608 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2609 G_CALLBACK(filter_default_cb), filter_view);
2610 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2611 gtk_widget_show(button);
2613 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2614 G_CALLBACK(filter_remove_cb), filter_view);
2615 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2616 gtk_widget_show(button);
2618 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2619 G_CALLBACK(filter_add_cb), filter_view);
2620 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2621 gtk_widget_show(button);
2625 static void config_tab_metadata(GtkWidget *notebook)
2630 GtkWidget *ct_button;
2634 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2637 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2639 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2641 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2642 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2644 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2645 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2647 gtk_widget_set_sensitive(ct_button, FALSE);
2650 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2651 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2653 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2654 label = pref_label_new(group, text);
2655 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2656 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2659 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2661 gtk_widget_set_sensitive(group, FALSE);
2664 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2665 pref_checkbox_link_sensitivity(ct_button, hbox);
2667 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2668 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2670 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2671 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2673 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2674 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2676 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2677 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2679 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2681 gtk_widget_set_sensitive(group, FALSE);
2684 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2685 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2688 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2689 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2690 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2692 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2693 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2695 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2696 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2698 gtk_widget_set_sensitive(ct_button, FALSE);
2701 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2703 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2704 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2706 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2707 pref_checkbox_link_sensitivity(ct_button, hbox);
2709 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2710 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2712 pref_checkbox_new_int(group, _("Write metadata on image change"),
2713 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2715 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2716 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2718 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2720 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2721 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2722 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");
2727 typedef struct _KeywordFindData KeywordFindData;
2728 struct _KeywordFindData
2735 GtkWidget *button_close;
2736 GtkWidget *button_stop;
2737 GtkWidget *button_start;
2738 GtkWidget *progress;
2746 guint idle_id; /* event source id */
2749 #define KEYWORD_DIALOG_WIDTH 400
2751 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2753 GList *list_d = NULL;
2754 GList *list_f = NULL;
2758 filelist_read(dir_fd, &list_f, &list_d);
2762 filelist_read(dir_fd, &list_f, NULL);
2765 list_f = filelist_filter(list_f, FALSE);
2766 list_d = filelist_filter(list_d, TRUE);
2768 kfd->list = g_list_concat(list_f, kfd->list);
2769 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2772 static void keywords_find_reset(KeywordFindData *kfd)
2774 filelist_free(kfd->list);
2777 filelist_free(kfd->list_dir);
2778 kfd->list_dir = NULL;
2781 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2783 KeywordFindData *kfd = data;
2785 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2787 keywords_find_reset(kfd);
2788 generic_dialog_close(kfd->gd);
2792 static void keywords_find_finish(KeywordFindData *kfd)
2794 keywords_find_reset(kfd);
2796 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2797 spinner_set_interval(kfd->spinner, -1);
2799 gtk_widget_set_sensitive(kfd->group, TRUE);
2800 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2801 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2802 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2805 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2807 KeywordFindData *kfd = data;
2809 g_idle_remove_by_data(kfd);
2811 keywords_find_finish(kfd);
2814 static gboolean keywords_find_file(gpointer data)
2816 KeywordFindData *kfd = data;
2818 GtkTextBuffer *buffer;
2826 fd = kfd->list->data;
2827 kfd->list = g_list_remove(kfd->list, fd);
2829 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2830 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2834 gtk_text_buffer_get_end_iter(buffer, &iter);
2835 tmp = g_strconcat(keywords->data, "\n", NULL);
2836 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2838 keywords = keywords->next;
2841 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2842 file_data_unref(fd);
2843 string_list_free(keywords);
2847 else if (kfd->list_dir)
2851 fd = kfd->list_dir->data;
2852 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2854 keywords_find_folder(kfd, fd);
2856 file_data_unref(fd);
2861 keywords_find_finish(kfd);
2866 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2868 KeywordFindData *kfd = data;
2871 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2873 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2874 parse_out_relatives(path);
2878 warning_dialog(_("Invalid folder"),
2879 _("The specified folder can not be found."),
2880 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2886 gtk_widget_set_sensitive(kfd->group, FALSE);
2887 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2888 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2889 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2890 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2892 dir_fd = file_data_new_dir(path);
2893 keywords_find_folder(kfd, dir_fd);
2894 file_data_unref(dir_fd);
2895 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2901 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2903 KeywordFindData *kfd;
2907 kfd = g_new0(KeywordFindData, 1);
2909 kfd->gd = generic_dialog_new(_("Search for keywords"),
2910 "search_for_keywords",
2913 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2914 kfd->gd->cancel_cb = keywords_find_close_cb;
2915 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2916 keywords_find_close_cb, FALSE);
2917 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2918 keywords_find_start_cb, FALSE);
2919 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2920 keywords_find_stop_cb, FALSE);
2921 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2923 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2925 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2926 pref_spacer(hbox, PREF_PAD_INDENT);
2927 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2929 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2930 pref_label_new(hbox, _("Folder:"));
2932 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2933 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2934 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2935 gtk_widget_show(label);
2937 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2939 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2940 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2942 kfd->progress = gtk_entry_new();
2943 gtk_widget_set_can_focus(kfd->progress, FALSE);
2944 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2945 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2946 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2947 gtk_widget_show(kfd->progress);
2949 kfd->spinner = spinner_new(NULL, -1);
2950 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2951 gtk_widget_show(kfd->spinner);
2955 gtk_widget_show(kfd->gd->dialog);
2958 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2960 const gchar *path = layout_get_path(NULL);
2962 if (!path || !*path) path = homedir();
2963 keywords_find_dialog(widget, path);
2966 static void config_tab_keywords_save()
2968 GtkTextIter start, end;
2969 GtkTextBuffer *buffer;
2970 GList *kw_list = NULL;
2976 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2977 gtk_text_buffer_get_bounds(buffer, &start, &end);
2979 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2981 kw_split = strtok(buffer_text, "\n");
2982 while (kw_split != NULL)
2988 if (g_strcmp0(work->data, kw_split) == 0)
2997 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2999 kw_split = strtok(NULL, "\n");
3002 keyword_list_set(kw_list);
3004 string_list_free(kw_list);
3005 g_free(buffer_text);
3008 static void config_tab_keywords(GtkWidget *notebook)
3014 GtkWidget *scrolled;
3016 GtkTextBuffer *buffer;
3019 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3021 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3023 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3025 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3026 G_CALLBACK(keywords_find_cb), keyword_text);
3027 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3030 keyword_text = gtk_text_view_new();
3031 gtk_widget_set_size_request(keyword_text, 20, 20);
3032 scrolled = gtk_scrolled_window_new(NULL, NULL);
3033 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3034 gtk_widget_show(scrolled);
3036 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3037 gtk_widget_show(keyword_text);
3039 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3041 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3042 gtk_text_buffer_create_tag(buffer, "monospace",
3043 "family", "monospace", NULL);
3045 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3046 gtk_text_buffer_get_start_iter(buffer, &iter);
3047 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3050 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3052 GList *kwl = keyword_list_get();
3053 kwl = g_list_first(kwl);
3056 gtk_text_buffer_get_end_iter (buffer, &iter);
3057 tmp = g_strconcat(kwl->data, "\n", NULL);
3058 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3063 gtk_text_buffer_set_modified(buffer, FALSE);
3070 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3072 gint *option = data;
3074 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3078 *option = INTENT_PERCEPTUAL;
3081 *option = INTENT_RELATIVE_COLORIMETRIC;
3084 *option = INTENT_SATURATION;
3087 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3092 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3093 gint option, gint *option_c)
3100 pref_table_label(table, column, row, text, 0.0);
3102 combo = gtk_combo_box_text_new();
3104 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3105 if (option == INTENT_PERCEPTUAL) current = 0;
3106 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3107 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3108 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3109 if (option == INTENT_SATURATION) current = 2;
3110 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3111 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3113 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3115 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3117 g_signal_connect(G_OBJECT(combo), "changed",
3118 G_CALLBACK(intent_menu_cb), option_c);
3120 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3121 gtk_widget_show(combo);
3125 static void config_tab_color(GtkWidget *notebook)
3134 vbox = scrolled_notebook_page(notebook, _("Color management"));
3136 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3138 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3141 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3142 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3144 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3145 pref_label_bold(label, TRUE, FALSE);
3147 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3148 pref_label_bold(label, TRUE, FALSE);
3150 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3151 pref_label_bold(label, TRUE, FALSE);
3153 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3158 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3159 pref_table_label(table, 0, i + 1, buf, 1.0);
3162 entry = gtk_entry_new();
3163 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3164 if (options->color_profile.input_name[i])
3166 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3168 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3169 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3170 gtk_widget_show(entry);
3171 color_profile_input_name_entry[i] = entry;
3173 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3174 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3175 gtk_widget_set_size_request(entry, 160, -1);
3176 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3177 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3178 gtk_widget_show(tabcomp);
3179 color_profile_input_file_entry[i] = entry;
3182 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3184 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3186 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3187 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3189 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3191 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3192 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3193 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3194 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3195 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3197 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3199 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3201 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3203 gtk_widget_show(tabcomp);
3206 /* advanced entry tab */
3207 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3209 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3211 c_options->file_ops.use_system_trash = FALSE;
3212 c_options->file_ops.no_trash = FALSE;
3216 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3218 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3220 c_options->file_ops.use_system_trash = TRUE;
3221 c_options->file_ops.no_trash = FALSE;
3225 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3227 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3229 c_options->file_ops.no_trash = TRUE;
3233 static void config_tab_behavior(GtkWidget *notebook)
3240 GtkWidget *ct_button;
3244 GtkWidget *with_rename;
3245 GtkWidget *collections_on_top;
3247 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3249 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3251 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3252 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3253 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3254 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3255 pref_checkbox_new_int(group, _("Enable Delete key"),
3256 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3258 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3259 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3261 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3262 pref_checkbox_link_sensitivity(ct_button, hbox);
3264 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3265 pref_label_new(hbox, _("Folder:"));
3267 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3268 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3269 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3270 gtk_widget_show(tabcomp);
3272 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3273 pref_checkbox_link_sensitivity(ct_button, hbox);
3275 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3276 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3277 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3278 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3279 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3280 G_CALLBACK(safe_delete_view_cb), NULL);
3281 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3282 gtk_widget_show(button);
3284 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3285 G_CALLBACK(safe_delete_clear_cb), NULL);
3286 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3287 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3288 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3290 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3291 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3293 gtk_widget_show(button);
3295 pref_spacer(group, PREF_PAD_GROUP);
3298 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3300 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3301 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3303 pref_checkbox_new_int(group, _("In place renaming"),
3304 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3306 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3307 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3309 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3310 options->marks_save, &c_options->marks_save);
3311 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3313 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3314 options->with_rename, &c_options->with_rename);
3315 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3317 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3318 options->collections_on_top, &c_options->collections_on_top);
3319 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3321 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3322 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3324 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3325 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3327 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3328 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3330 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3331 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3333 pref_spacer(group, PREF_PAD_GROUP);
3335 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3337 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3338 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3339 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3340 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3341 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3342 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3343 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3344 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3345 pref_checkbox_new_int(group, _("Play video by left click on image"),
3346 options->image_l_click_video, &c_options->image_l_click_video);
3347 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3348 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3350 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3351 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3352 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3353 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3354 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3357 pref_spacer(group, PREF_PAD_GROUP);
3359 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3361 pref_spin_new_int(group, _("Debug level:"), NULL,
3362 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3364 pref_checkbox_new_int(group, _("Timer data"),
3365 options->log_window.timer_data, &c_options->log_window.timer_data);
3367 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3368 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3372 /* accelerators tab */
3373 static void config_tab_accelerators(GtkWidget *notebook)
3379 GtkWidget *scrolled;
3380 GtkWidget *accel_view;
3381 GtkCellRenderer *renderer;
3382 GtkTreeSelection *selection;
3383 GtkTreeViewColumn *column;
3385 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3387 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3389 scrolled = gtk_scrolled_window_new(NULL, NULL);
3390 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3391 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3392 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3393 gtk_widget_show(scrolled);
3395 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3397 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3398 g_object_unref(accel_store);
3399 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3400 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3402 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3404 renderer = gtk_cell_renderer_text_new();
3406 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3411 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3412 gtk_tree_view_column_set_resizable(column, TRUE);
3413 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3416 renderer = gtk_cell_renderer_accel_new();
3417 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3418 G_CALLBACK(accel_store_cleared_cb), accel_store);
3419 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3420 G_CALLBACK(accel_store_edited_cb), accel_store);
3423 g_object_set (renderer,
3425 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3428 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3433 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3434 gtk_tree_view_column_set_resizable(column, TRUE);
3435 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3437 renderer = gtk_cell_renderer_text_new();
3439 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3444 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3445 gtk_tree_view_column_set_resizable(column, TRUE);
3446 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3448 renderer = gtk_cell_renderer_text_new();
3450 column = gtk_tree_view_column_new_with_attributes("Accel",
3455 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3456 gtk_tree_view_column_set_resizable(column, TRUE);
3457 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3459 accel_store_populate();
3460 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3461 gtk_widget_show(accel_view);
3463 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3465 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3466 G_CALLBACK(accel_default_cb), accel_view);
3467 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3468 gtk_widget_show(button);
3470 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3471 G_CALLBACK(accel_reset_cb), accel_view);
3472 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3473 gtk_widget_show(button);
3476 /* toolbar main tab */
3477 static void config_tab_toolbar_main(GtkWidget *notebook)
3480 GtkWidget *toolbardata;
3483 lw = layout_window_list->data;
3485 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3487 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3488 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3489 gtk_widget_show(vbox);
3492 /* toolbar status tab */
3493 static void config_tab_toolbar_status(GtkWidget *notebook)
3496 GtkWidget *toolbardata;
3499 lw = layout_window_list->data;
3501 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3503 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3504 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3505 gtk_widget_show(vbox);
3509 static void config_tab_stereo(GtkWidget *notebook)
3517 GtkWidget *fs_button;
3518 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3520 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3522 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3523 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3525 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3526 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3527 pref_checkbox_new_int(box, _("Mirror left image"),
3528 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3529 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3530 pref_checkbox_new_int(box, _("Flip left image"),
3531 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3532 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3533 pref_checkbox_new_int(box, _("Mirror right image"),
3534 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3535 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3536 pref_checkbox_new_int(box, _("Flip right image"),
3537 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3538 pref_checkbox_new_int(group, _("Swap left and right images"),
3539 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3540 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3541 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3543 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3544 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3545 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3546 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3547 pref_checkbox_link_sensitivity(fs_button, box2);
3548 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3549 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3550 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3551 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3552 pref_checkbox_new_int(box, _("Mirror left image"),
3553 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3554 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3555 pref_checkbox_new_int(box, _("Flip left image"),
3556 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3557 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3558 pref_checkbox_new_int(box, _("Mirror right image"),
3559 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3560 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3561 pref_checkbox_new_int(box, _("Flip right image"),
3562 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3563 pref_checkbox_new_int(box2, _("Swap left and right images"),
3564 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3565 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3566 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3568 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3569 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3570 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3571 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3572 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3573 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3574 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3575 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3576 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3577 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3578 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3579 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3580 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3581 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3585 /* Main preferences window */
3586 static void config_window_create(void)
3588 GtkWidget *win_vbox;
3590 GtkWidget *notebook;
3592 GtkWidget *ct_button;
3594 if (!c_options) c_options = init_options(NULL);
3596 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3597 DEBUG_NAME(configwindow);
3598 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3599 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3600 G_CALLBACK(config_window_delete), NULL);
3601 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3602 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3603 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3605 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3606 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3607 gtk_widget_show(win_vbox);
3609 notebook = gtk_notebook_new();
3610 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3611 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3612 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3614 config_tab_general(notebook);
3615 config_tab_image(notebook);
3616 config_tab_osd(notebook);
3617 config_tab_windows(notebook);
3618 config_tab_accelerators(notebook);
3619 config_tab_files(notebook);
3620 config_tab_metadata(notebook);
3621 config_tab_keywords(notebook);
3622 config_tab_color(notebook);
3623 config_tab_stereo(notebook);
3624 config_tab_behavior(notebook);
3625 config_tab_toolbar_main(notebook);
3626 config_tab_toolbar_status(notebook);
3628 hbox = gtk_hbutton_box_new();
3629 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3630 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3631 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3632 gtk_widget_show(hbox);
3634 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3635 G_CALLBACK(config_window_help_cb), notebook);
3636 gtk_container_add(GTK_CONTAINER(hbox), button);
3637 gtk_widget_set_can_default(button, TRUE);
3638 gtk_widget_show(button);
3640 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3641 G_CALLBACK(config_window_ok_cb), NULL);
3642 gtk_container_add(GTK_CONTAINER(hbox), button);
3643 gtk_widget_set_can_default(button, TRUE);
3644 gtk_widget_grab_default(button);
3645 gtk_widget_show(button);
3649 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3650 G_CALLBACK(config_window_close_cb), NULL);
3651 gtk_container_add(GTK_CONTAINER(hbox), button);
3652 gtk_widget_set_can_default(button, TRUE);
3653 gtk_widget_show(button);
3655 if (!generic_dialog_get_alternative_button_order(configwindow))
3657 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3660 gtk_widget_show(notebook);
3662 gtk_widget_show(configwindow);
3666 *-----------------------------------------------------------------------------
3667 * config window show (public)
3668 *-----------------------------------------------------------------------------
3671 void show_config_window(void)
3675 gtk_window_present(GTK_WINDOW(configwindow));
3679 config_window_create();
3688 void show_about_window(LayoutWindow *lw)
3690 GdkPixbuf *pixbuf_logo;
3691 GdkPixbuf *pixbuf_icon;
3692 gchar *authors[1000];
3697 gchar *timezone_path;
3701 #define LINE_LENGTH 1000
3702 gchar line[LINE_LENGTH];
3704 copyright = g_string_new(NULL);
3705 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");
3707 path = path_from_utf8(TIMEZONE_DATABASE);
3708 basename = g_path_get_basename(path);
3709 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3710 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3712 cd = ZDOpenDatabase(timezone_path);
3715 copyright = g_string_append(copyright, ZDGetNotice(cd));
3716 ZDCloseDatabase(cd);
3720 g_free(timezone_path);
3724 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3725 fp = fopen(path, "r");
3728 while(fgets(line, LINE_LENGTH, fp))
3730 /* get rid of ending \n from fgets */
3731 line[strlen(line) - 1] = '\0';
3732 authors[i_authors] = g_strdup(line);
3735 authors[i_authors] = NULL;
3740 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3741 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3743 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3744 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3745 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3746 "title", _("About Geeqie"),
3748 "program-name", GQ_APPNAME,
3750 "logo", pixbuf_logo,
3751 "icon", pixbuf_icon,
3752 "website", GQ_WEBSITE,
3753 "website-label", "Website",
3754 "comments", comment,
3756 "translator-credits", _("translator-credits"),
3757 "wrap-license", TRUE,
3758 "license", copyright->str,
3761 g_string_free(copyright, TRUE);
3764 while(n < i_authors)
3774 static void image_overlay_set_text_colours()
3776 c_options->image_overlay.text_red = options->image_overlay.text_red;
3777 c_options->image_overlay.text_green = options->image_overlay.text_green;
3778 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3779 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3780 c_options->image_overlay.background_red = options->image_overlay.background_red;
3781 c_options->image_overlay.background_green = options->image_overlay.background_green;
3782 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3783 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3787 *-----------------------------------------------------------------------------
3788 * timezone database routines
3789 *-----------------------------------------------------------------------------
3792 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3794 GError *error = NULL;
3796 gchar *tmp_filename;
3798 if (!g_cancellable_is_cancelled(tz->cancellable))
3800 generic_dialog_close(tz->gd);
3804 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3806 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3807 move_file(tmp_filename, tz->timezone_database_user);
3808 g_free(tmp_filename);
3812 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3815 g_file_delete(tz->tmp_g_file, NULL, &error);
3816 g_object_unref(tz->tmp_g_file);
3817 tz->tmp_g_file = NULL;
3818 g_object_unref(tz->cancellable);
3819 g_object_unref(tz->timezone_database_gq);
3822 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3826 if (!g_cancellable_is_cancelled(tz->cancellable))
3828 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3832 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3836 g_cancellable_cancel(tz->cancellable);
3839 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3842 GError *error = NULL;
3843 GFileIOStream *io_stream;
3850 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3854 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3855 log_printf("Error: Download timezone database failed:\n%s", error->message);
3856 g_error_free(error);
3857 g_object_unref(tz->tmp_g_file);
3861 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3863 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3865 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3867 tz->progress = gtk_progress_bar_new();
3868 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3869 gtk_widget_show(tz->progress);
3871 gtk_widget_show(tz->gd->dialog);
3872 tz->cancellable = g_cancellable_new();
3873 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);
3875 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3878 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */