2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
381 options->dnd_default_action = c_options->dnd_default_action;
383 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
384 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
385 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
386 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
387 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
388 options->metadata.confirm_write = c_options->metadata.confirm_write;
389 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
390 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
391 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
392 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
393 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
394 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
395 options->metadata.write_orientation = c_options->metadata.write_orientation;
396 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
397 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
398 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
399 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
400 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
401 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
402 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
403 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
411 options->stereo.fixed_w = c_options->stereo.fixed_w;
412 options->stereo.fixed_h = c_options->stereo.fixed_h;
413 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
414 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
415 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
416 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
418 options->info_keywords.height = c_options->info_keywords.height;
419 options->info_title.height = c_options->info_title.height;
420 options->info_comment.height = c_options->info_comment.height;
421 options->info_rating.height = c_options->info_rating.height;
423 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
425 options->marks_save = c_options->marks_save;
426 options->with_rename = c_options->with_rename;
427 options->collections_on_top = c_options->collections_on_top;
428 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
430 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
432 options->star_rating.star = c_options->star_rating.star;
433 options->star_rating.rejected = c_options->star_rating.rejected;
435 set_debug_level(debug_c);
439 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
441 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
442 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
444 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
445 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
446 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
448 options->color_profile.render_intent = c_options->color_profile.render_intent;
453 options->mouse_button_8 = c_options->mouse_button_8;
454 options->mouse_button_9 = c_options->mouse_button_9;
456 config_tab_keywords_save();
458 image_options_sync();
463 layout_refresh(NULL);
466 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
468 toolbar_apply(TOOLBAR_MAIN);
469 toolbar_apply(TOOLBAR_STATUS);
473 *-----------------------------------------------------------------------------
474 * config window main button callbacks (private)
475 *-----------------------------------------------------------------------------
478 static void config_window_close_cb(GtkWidget *widget, gpointer data)
480 gtk_widget_destroy(configwindow);
485 static void config_window_help_cb(GtkWidget *widget, gpointer data)
487 GtkWidget *notebook = data;
490 static gchar *html_section[] =
492 "GuideOptionsGeneral.html",
493 "GuideOptionsImage.html",
494 "GuideOptionsOSD.html",
495 "GuideOptionsWindow.html",
496 "GuideOptionsKeyboard.html",
497 "GuideOptionsFiltering.html",
498 "GuideOptionsMetadata.html",
499 "GuideOptionsKeywords.html",
500 "GuideOptionsColor.html",
501 "GuideOptionsStereo.html",
502 "GuideOptionsBehavior.html",
503 "GuideOptionsToolbar.html",
504 "GuideOptionsToolbar.html"
507 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
508 help_window_show(html_section[i]);
511 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
513 config_window_close_cb(NULL, NULL);
517 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
520 lw = layout_window_list->data;
522 config_window_apply();
523 layout_util_sync(lw);
524 save_options(options);
525 config_window_close_cb(NULL, NULL);
529 *-----------------------------------------------------------------------------
530 * config window setup (private)
531 *-----------------------------------------------------------------------------
534 static void quality_menu_cb(GtkWidget *combo, gpointer data)
538 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
542 *option = GDK_INTERP_NEAREST;
545 *option = GDK_INTERP_TILES;
548 *option = GDK_INTERP_BILINEAR;
551 *option = GDK_INTERP_HYPER;
556 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
560 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
564 *option = DND_ACTION_ASK;
567 *option = DND_ACTION_COPY;
570 *option = DND_ACTION_MOVE;
574 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
578 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
590 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
591 guint option, guint *option_c)
598 pref_table_label(table, column, row, text, 0.0);
600 combo = gtk_combo_box_text_new();
602 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
603 if (option == GDK_INTERP_NEAREST) current = 0;
604 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
605 if (option == GDK_INTERP_TILES) current = 1;
606 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
607 if (option == GDK_INTERP_BILINEAR) current = 2;
608 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
609 if (option == GDK_INTERP_HYPER) current = 3;
611 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
613 g_signal_connect(G_OBJECT(combo), "changed",
614 G_CALLBACK(quality_menu_cb), option_c);
616 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
617 gtk_widget_show(combo);
620 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
627 pref_table_label(table, column, row, text, 0.0);
629 combo = gtk_combo_box_text_new();
631 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
632 if (option == DND_ACTION_ASK) current = 0;
633 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
634 if (option == DND_ACTION_COPY) current = 1;
635 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
636 if (option == DND_ACTION_MOVE) current = 2;
638 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
640 g_signal_connect(G_OBJECT(combo), "changed",
641 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
643 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
644 gtk_widget_show(combo);
647 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
648 gint option, gint *option_c)
655 pref_table_label(table, column, row, text, 0.0);
657 combo = gtk_combo_box_text_new();
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
660 if (option == PRIMARY) current = 0;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
662 if (option == CLIPBOARD) current = 1;
664 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(clipboard_selection_menu_cb), option_c);
669 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
670 gtk_widget_show(combo);
673 typedef struct _UseableMouseItems UseableMouseItems;
674 struct _UseableMouseItems
676 gchar *name; /* GtkActionEntry terminology */
681 static const UseableMouseItems useable_mouse_items[] = {
683 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
684 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
685 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
686 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
687 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
688 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
689 {"Home", N_("Home"), GTK_STOCK_HOME},
690 {"Up", N_("Up"), GTK_STOCK_GO_UP},
691 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
692 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
693 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
694 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
695 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
696 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
697 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
698 {"Search", N_("Search"), GTK_STOCK_FIND},
699 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
700 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
701 {"Copy", N_("Copy"), GTK_STOCK_COPY},
702 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
703 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
704 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
705 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
706 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
707 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
708 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
709 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
710 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
711 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
712 {"Print", N_("Print"), GTK_STOCK_PRINT},
713 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
714 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
715 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
716 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
717 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
718 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
719 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
720 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
721 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
722 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
723 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
724 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
725 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
726 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
727 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
728 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
729 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
730 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
731 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
732 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
733 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
734 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
735 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
736 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
737 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
738 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
739 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
740 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
741 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
742 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
743 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
744 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
745 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
746 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
747 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
748 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
749 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
750 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
751 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
755 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
757 gchar **option = data;
760 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
762 const UseableMouseItems *list = useable_mouse_items;
766 if (g_strcmp0(list->label, label) == 0)
774 *option = g_strdup(list->name);
778 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
779 gchar *option, gchar **option_c)
787 pref_table_label(table, column, row, text, 0.0);
789 combo = gtk_combo_box_text_new();
791 const UseableMouseItems *list = useable_mouse_items;
795 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
796 if (g_strcmp0(list->name, option) == 0)
804 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
806 g_signal_connect(G_OBJECT(combo), "changed",
807 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
809 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
810 gtk_widget_show(combo);
813 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
817 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
820 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
822 c_options->thumbnails.max_width = thumb_size_list[n].w;
823 c_options->thumbnails.max_height = thumb_size_list[n].h;
827 c_options->thumbnails.max_width = options->thumbnails.max_width;
828 c_options->thumbnails.max_height = options->thumbnails.max_height;
832 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
838 c_options->thumbnails.max_width = options->thumbnails.max_width;
839 c_options->thumbnails.max_height = options->thumbnails.max_height;
841 pref_table_label(table, column, row, text, 0.0);
843 combo = gtk_combo_box_text_new();
846 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
851 w = thumb_size_list[i].w;
852 h = thumb_size_list[i].h;
854 buf = g_strdup_printf("%d x %d", w, h);
855 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
858 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
865 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
866 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
872 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
873 g_signal_connect(G_OBJECT(combo), "changed",
874 G_CALLBACK(thumb_size_menu_cb), NULL);
876 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
877 gtk_widget_show(combo);
880 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
884 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
888 *option = PR_STEREO_NONE;
891 *option = PR_STEREO_ANAGLYPH_RC;
894 *option = PR_STEREO_ANAGLYPH_GM;
897 *option = PR_STEREO_ANAGLYPH_YB;
900 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
903 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
906 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
909 *option = PR_STEREO_ANAGLYPH_DB_RC;
912 *option = PR_STEREO_ANAGLYPH_DB_GM;
915 *option = PR_STEREO_ANAGLYPH_DB_YB;
918 *option = PR_STEREO_HORIZ;
921 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
924 *option = PR_STEREO_VERT;
927 *option = PR_STEREO_VERT | PR_STEREO_HALF;
930 *option = PR_STEREO_FIXED;
935 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
936 gint option, gint *option_c, gboolean add_fixed)
943 pref_table_label(table, column, row, text, 0.0);
945 combo = gtk_combo_box_text_new();
947 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
949 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
950 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
952 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
953 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
954 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
955 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
956 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
958 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
959 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
960 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
961 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
962 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
964 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
966 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
968 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
970 if (option & PR_STEREO_HORIZ)
973 if (option & PR_STEREO_HALF) current = 11;
976 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
977 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
978 if (option & PR_STEREO_VERT)
981 if (option & PR_STEREO_HALF) current = 13;
986 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
987 if (option & PR_STEREO_FIXED) current = 14;
990 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
992 g_signal_connect(G_OBJECT(combo), "changed",
993 G_CALLBACK(stereo_mode_menu_cb), option_c);
995 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
996 gtk_widget_show(combo);
999 static void video_menu_cb(GtkWidget *combo, gpointer data)
1001 gchar **option = data;
1003 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1007 static void video_menu_populate(gpointer data, gpointer user_data)
1009 GtkWidget *combo = user_data;
1010 EditorDescription *ed = data;
1012 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1015 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1016 gchar *option, gchar **option_c)
1020 /* use lists since they are sorted */
1021 GList *eds = editor_list_get();
1025 pref_table_label(table, column, row, text, 0.0);
1027 combo = gtk_combo_box_text_new();
1028 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1029 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1031 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1033 g_signal_connect(G_OBJECT(combo), "changed",
1034 G_CALLBACK(video_menu_cb), option_c);
1036 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1037 gtk_widget_show(combo);
1040 static void filter_store_populate(void)
1044 if (!filter_store) return;
1046 gtk_list_store_clear(filter_store);
1048 work = filter_get_list();
1057 gtk_list_store_append(filter_store, &iter);
1058 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1062 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1063 gchar *new_text, gpointer data)
1065 GtkWidget *model = data;
1066 FilterEntry *fe = data;
1070 if (!new_text || strlen(new_text) < 1) return;
1072 tpath = gtk_tree_path_new_from_string(path_str);
1073 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1074 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1076 g_free(fe->extensions);
1077 fe->extensions = g_strdup(new_text);
1079 gtk_tree_path_free(tpath);
1083 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1084 gchar *new_text, gpointer data)
1086 GtkWidget *model = data;
1087 FilterEntry *fe = data;
1092 if (!new_text || !new_text[0]) return;
1094 tpath = gtk_tree_path_new_from_string(path_str);
1095 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1096 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1098 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1100 if (strcmp(new_text, _(format_class_list[i])) == 0)
1107 gtk_tree_path_free(tpath);
1111 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1112 gchar *new_text, gpointer data)
1114 GtkWidget *model = data;
1119 if (!new_text || !new_text[0]) return;
1121 tpath = gtk_tree_path_new_from_string(path_str);
1122 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1123 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1125 g_free(fe->description);
1126 fe->description = g_strdup(new_text);
1128 gtk_tree_path_free(tpath);
1131 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1132 gchar *path_str, gpointer data)
1134 GtkWidget *model = data;
1139 tpath = gtk_tree_path_new_from_string(path_str);
1140 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1141 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1143 fe->enabled = !fe->enabled;
1145 gtk_tree_path_free(tpath);
1149 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1150 gchar *path_str, gpointer data)
1152 GtkWidget *model = data;
1157 tpath = gtk_tree_path_new_from_string(path_str);
1158 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1159 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1161 fe->writable = !fe->writable;
1162 if (fe->writable) fe->allow_sidecar = FALSE;
1164 gtk_tree_path_free(tpath);
1168 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1169 gchar *path_str, gpointer data)
1171 GtkWidget *model = data;
1176 tpath = gtk_tree_path_new_from_string(path_str);
1177 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1178 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1180 fe->allow_sidecar = !fe->allow_sidecar;
1181 if (fe->allow_sidecar) fe->writable = FALSE;
1183 gtk_tree_path_free(tpath);
1187 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1188 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1192 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1194 switch (GPOINTER_TO_INT(data))
1197 g_object_set(GTK_CELL_RENDERER(cell),
1198 "active", fe->enabled, NULL);
1201 g_object_set(GTK_CELL_RENDERER(cell),
1202 "text", fe->extensions, NULL);
1204 case FE_DESCRIPTION:
1205 g_object_set(GTK_CELL_RENDERER(cell),
1206 "text", fe->description, NULL);
1209 g_object_set(GTK_CELL_RENDERER(cell),
1210 "text", _(format_class_list[fe->file_class]), NULL);
1213 g_object_set(GTK_CELL_RENDERER(cell),
1214 "active", fe->writable, NULL);
1216 case FE_ALLOW_SIDECAR:
1217 g_object_set(GTK_CELL_RENDERER(cell),
1218 "active", fe->allow_sidecar, NULL);
1223 static gboolean filter_add_scroll(gpointer data)
1227 GtkCellRenderer *cell;
1228 GtkTreeViewColumn *column;
1233 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1234 path = gtk_tree_path_new_from_indices(rows-1, -1);
1236 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1238 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1239 cell = g_list_last(list_cells)->data;
1241 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1242 path, column, FALSE, 0.0, 0.0 );
1243 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1244 path, column, cell, TRUE);
1246 gtk_tree_path_free(path);
1247 g_list_free(list_cells);
1252 static void filter_add_cb(GtkWidget *widget, gpointer data)
1254 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1255 filter_store_populate();
1257 g_idle_add((GSourceFunc)filter_add_scroll, data);
1260 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1262 GtkWidget *filter_view = data;
1263 GtkTreeSelection *selection;
1267 if (!filter_store) return;
1268 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1269 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1270 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1273 filter_remove_entry(fe);
1275 filter_store_populate();
1278 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1282 GtkTreeViewColumn *column;
1284 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1285 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1286 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1288 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1292 gtk_tree_path_free(path);
1297 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1300 filter_add_defaults();
1302 filter_store_populate();
1304 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1307 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1309 /* no op, only so cancel button appears */
1312 static void filter_default_cb(GtkWidget *widget, gpointer data)
1316 gd = generic_dialog_new(_("Reset filters"),
1317 "reset_filter", widget, TRUE,
1318 dummy_cancel_cb, data);
1319 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1320 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1321 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1322 gtk_widget_show(gd->dialog);
1325 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1327 GtkWidget *frame = data;
1329 gtk_widget_set_sensitive(frame,
1330 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1333 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1335 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1338 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1340 file_util_trash_clear();
1343 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1347 gd = generic_dialog_new(_("Clear trash"),
1348 "clear_trash", widget, TRUE,
1349 dummy_cancel_cb, NULL);
1350 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1351 _("This will remove the trash contents."), FALSE);
1352 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1353 entry = gtk_entry_new();
1354 gtk_widget_set_can_focus(entry, FALSE);
1355 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1356 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1357 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1358 gtk_widget_show(entry);
1359 gtk_widget_show(gd->dialog);
1362 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1364 GtkWidget *pTextView;
1365 GtkTextBuffer *pTextBuffer;
1369 pTextView = GTK_WIDGET(data);
1371 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1372 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1373 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1375 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1376 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1379 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1381 GtkTextView *text_view = data;
1382 GtkTextBuffer *buffer;
1384 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1385 if (!configwindow) return;
1387 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1388 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1391 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1395 gd = generic_dialog_new(_("Reset image overlay template string"),
1396 "reset_image_overlay_template_string", widget, TRUE,
1397 dummy_cancel_cb, data);
1398 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1399 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1400 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1401 gtk_widget_show(gd->dialog);
1404 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1406 help_window_show("GuideOptionsOSD.html");
1409 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1411 #if GTK_CHECK_VERSION(3,4,0)
1414 PangoFontDescription *font_desc;
1416 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1417 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1419 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1421 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1422 font = pango_font_description_to_string(font_desc);
1423 g_free(c_options->image_overlay.font);
1424 c_options->image_overlay.font = g_strdup(font);
1428 gtk_widget_destroy(dialog);
1432 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1433 c_options->image_overlay.font = g_strdup(font);
1437 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1440 #if GTK_CHECK_VERSION(3,4,0)
1443 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1444 colour.red = options->image_overlay.text_red;
1445 colour.green = options->image_overlay.text_green;
1446 colour.blue = options->image_overlay.text_blue;
1447 colour.alpha = options->image_overlay.text_alpha;
1448 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1449 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1451 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1453 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1454 c_options->image_overlay.text_red = colour.red*255;
1455 c_options->image_overlay.text_green = colour.green*255;
1456 c_options->image_overlay.text_blue = colour.blue*255;
1457 c_options->image_overlay.text_alpha = colour.alpha*255;
1459 gtk_widget_destroy(dialog);
1462 GtkColorSelection *colorsel;
1464 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1465 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1466 colour.red = options->image_overlay.text_red*257;
1467 colour.green = options->image_overlay.text_green*257;
1468 colour.blue = options->image_overlay.text_blue*257;
1469 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1470 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1471 gtk_color_selection_set_current_color(colorsel, &colour);
1472 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1474 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1476 gtk_color_selection_get_current_color(colorsel, &colour);
1477 c_options->image_overlay.text_red = colour.red/257;
1478 c_options->image_overlay.text_green = colour.green/257;
1479 c_options->image_overlay.text_blue = colour.blue/257;
1480 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1482 gtk_widget_destroy (dialog);
1487 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1490 #if GTK_CHECK_VERSION(3,4,0)
1493 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1494 colour.red = options->image_overlay.background_red;
1495 colour.green = options->image_overlay.background_green;
1496 colour.blue = options->image_overlay.background_blue;
1497 colour.alpha = options->image_overlay.background_alpha;
1498 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1499 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1501 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1503 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1504 c_options->image_overlay.background_red = colour.red*255;
1505 c_options->image_overlay.background_green = colour.green*255;
1506 c_options->image_overlay.background_blue = colour.blue*255;
1507 c_options->image_overlay.background_alpha = colour.alpha*255;
1509 gtk_widget_destroy(dialog);
1512 GtkColorSelection *colorsel;
1514 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1515 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1516 colour.red = options->image_overlay.background_red*257;
1517 colour.green = options->image_overlay.background_green*257;
1518 colour.blue = options->image_overlay.background_blue*257;
1519 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1520 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1521 gtk_color_selection_set_current_color(colorsel, &colour);
1522 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1524 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1526 gtk_color_selection_get_current_color(colorsel, &colour);
1527 c_options->image_overlay.background_red = colour.red/257;
1528 c_options->image_overlay.background_green = colour.green/257;
1529 c_options->image_overlay.background_blue = colour.blue/257;
1530 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1532 gtk_widget_destroy(dialog);
1536 static void accel_store_populate(void)
1539 GList *groups, *actions;
1541 const gchar *accel_path;
1545 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1547 gtk_tree_store_clear(accel_store);
1548 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1550 g_assert(lw && lw->ui_manager);
1551 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1554 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1557 action = GTK_ACTION(actions->data);
1558 accel_path = gtk_action_get_accel_path(action);
1559 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1561 gchar *label, *label2, *tooltip, *accel;
1562 g_object_get(action,
1563 "tooltip", &tooltip,
1567 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1573 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1577 gtk_tree_store_append(accel_store, &iter, NULL);
1578 gtk_tree_store_set(accel_store, &iter,
1581 AE_TOOLTIP, tooltip ? tooltip : "",
1582 AE_ACCEL, accel_path,
1590 actions = actions->next;
1593 groups = groups->next;
1597 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1602 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1604 gchar *accel1 = data;
1609 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1611 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1612 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1614 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1616 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1617 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1626 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1628 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1632 GtkAccelKey old_key, key;
1633 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1635 gtk_tree_model_get_iter(model, &iter, path);
1636 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1638 /* test if the accelerator can be stored without conflicts*/
1639 gtk_accel_map_lookup_entry(accel_path, &old_key);
1641 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1642 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1643 gtk_accel_map_lookup_entry(accel_path, &key);
1645 /* restore the original for now, the key will be really changed when the changes are confirmed */
1646 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1648 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1649 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1651 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1652 gtk_tree_path_free(path);
1656 static gboolean accel_default_scroll(GtkTreeView *data)
1660 GtkTreeViewColumn *column;
1662 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1663 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1664 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1666 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1670 gtk_tree_path_free(path);
1675 static void accel_default_cb(GtkWidget *widget, gpointer data)
1677 accel_store_populate();
1679 g_idle_add((GSourceFunc)accel_default_scroll, data);
1682 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1684 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1687 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1690 gchar *accel_path, *accel;
1692 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1693 gtk_accel_map_lookup_entry(accel_path, &key);
1694 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1696 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1698 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1703 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1705 GtkTreeSelection *selection;
1707 if (!accel_store) return;
1708 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1709 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1714 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1718 GtkWidget *scrolled;
1719 GtkWidget *viewport;
1721 scrolled = gtk_scrolled_window_new(NULL, NULL);
1722 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1723 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1724 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1725 label = gtk_label_new(title);
1726 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1727 gtk_widget_show(scrolled);
1729 viewport = gtk_viewport_new(NULL, NULL);
1730 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1731 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1732 gtk_widget_show(viewport);
1734 vbox = gtk_vbox_new(FALSE, 0);
1735 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1736 gtk_widget_show(vbox);
1741 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1743 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1745 c_options->thumbnails.spec_standard =TRUE;
1746 c_options->thumbnails.cache_into_dirs = FALSE;
1750 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1752 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1754 c_options->thumbnails.spec_standard =FALSE;
1755 c_options->thumbnails.cache_into_dirs = FALSE;
1759 static void cache_local_cb(GtkWidget *widget, gpointer data)
1761 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1763 c_options->thumbnails.cache_into_dirs = TRUE;
1764 c_options->thumbnails.spec_standard =FALSE;
1768 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1769 GdkEvent *event, gpointer userdata)
1771 if (pos == GTK_ENTRY_ICON_PRIMARY)
1773 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1777 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1781 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1782 GdkEvent *event, gpointer userdata)
1784 gchar *rating_symbol;
1786 if (pos == GTK_ENTRY_ICON_PRIMARY)
1788 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1789 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1790 g_free(rating_symbol);
1794 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1795 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1796 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1800 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1801 GdkEvent *event, gpointer userdata)
1803 gchar *rating_symbol;
1805 if (pos == GTK_ENTRY_ICON_PRIMARY)
1807 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1808 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1809 g_free(rating_symbol);
1813 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1814 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1815 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1819 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1821 GtkContainer *hbox = data;
1822 GString *str = g_string_new(NULL);
1823 GtkEntry *hex_code_entry;
1824 gchar *hex_code_full;
1827 guint64 hex_value = 0;
1829 list = gtk_container_get_children(hbox);
1831 hex_code_entry = g_list_nth_data(list, 2);
1832 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1834 hex_code = g_strsplit(hex_code_full, "+", 2);
1835 if (hex_code[0] && hex_code[1])
1837 hex_value = strtoull(hex_code[1], NULL, 16);
1839 if (!hex_value || hex_value > 0x10FFFF)
1841 hex_value = 0x003F; // Unicode 'Question Mark'
1843 str = g_string_append_unichar(str, (gunichar)hex_value);
1844 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1846 g_strfreev(hex_code);
1847 g_string_free(str, TRUE);
1848 g_free(hex_code_full);
1853 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1855 guint64 star_symbol;
1857 star_symbol = star_rating_symbol_test(widget, data);
1858 c_options->star_rating.star = star_symbol;
1861 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1863 guint64 rejected_symbol;
1865 rejected_symbol = star_rating_symbol_test(widget, data);
1866 c_options->star_rating.rejected = rejected_symbol;
1869 /* general options tab */
1870 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1871 typedef struct _TZData TZData;
1875 GCancellable *cancellable;
1877 GtkWidget *progress;
1879 GFile *timezone_database_gq;
1880 gchar *timezone_database_user;
1883 static void config_tab_general(GtkWidget *notebook)
1888 GtkWidget *group_frame;
1889 GtkWidget *subgroup;
1891 GtkWidget *ct_button;
1894 gint hours, minutes, remainder;
1896 GtkWidget *star_rating_entry;
1898 gchar *rating_symbol;
1901 GNetworkMonitor *net_mon;
1902 GSocketConnectable *geeqie_org;
1903 gboolean internet_available;
1906 vbox = scrolled_notebook_page(notebook, _("General"));
1908 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1910 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1911 add_thumb_size_menu(table, 0, 0, _("Size:"));
1912 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1914 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1915 pref_label_new(hbox, _("Custom size: "));
1916 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1917 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1919 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1920 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1922 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1923 pref_checkbox_link_sensitivity(ct_button, subgroup);
1925 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1926 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1927 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1928 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1929 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1930 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1931 G_CALLBACK(cache_geeqie_cb), NULL);
1933 group_frame = pref_frame_new(subgroup, TRUE,
1934 _("Store thumbnails local to image folder (non-standard)"),
1935 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1936 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1937 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1938 G_CALLBACK(cache_local_cb), NULL);
1940 group_frame = pref_frame_new(subgroup, TRUE,
1941 _("Use standard thumbnail style and cache, shared with other applications"),
1942 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1943 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1944 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1945 G_CALLBACK(cache_standard_cb), NULL);
1947 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1948 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1950 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1952 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1953 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1955 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1956 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1957 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1959 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1960 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1963 pref_spacer(group, PREF_PAD_GROUP);
1965 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1967 c_options->star_rating.star = options->star_rating.star;
1968 c_options->star_rating.rejected = options->star_rating.rejected;
1970 str = g_string_new(NULL);
1971 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1972 pref_label_new(hbox, "Star character: ");
1973 str = g_string_append_unichar(str, options->star_rating.star);
1974 pref_label_new(hbox, g_strdup(str->str));
1975 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1976 star_rating_entry = gtk_entry_new();
1977 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1978 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1979 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1980 gtk_widget_show(star_rating_entry);
1981 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1982 G_CALLBACK(star_rating_star_test_cb), hbox);
1983 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1984 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1985 gtk_widget_show(button);
1986 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."));
1987 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1988 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1989 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1990 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1991 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1992 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1993 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1994 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1995 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1996 G_CALLBACK(star_rating_star_icon_cb),
1999 g_string_free(str, TRUE);
2000 g_free(rating_symbol);
2002 str = g_string_new(NULL);
2003 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2004 pref_label_new(hbox, "Rejected character: ");
2005 str = g_string_append_unichar(str, options->star_rating.rejected);
2006 pref_label_new(hbox, g_strdup(str->str));
2007 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2008 star_rating_entry = gtk_entry_new();
2009 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2010 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2011 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2012 gtk_widget_show(star_rating_entry);
2013 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2014 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2015 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2016 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2017 gtk_widget_show(button);
2018 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."));
2019 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2020 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2021 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2022 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2023 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2024 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2025 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2026 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2027 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2028 G_CALLBACK(star_rating_rejected_icon_cb),
2031 g_string_free(str, TRUE);
2032 g_free(rating_symbol);
2034 pref_spacer(group, PREF_PAD_GROUP);
2036 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2038 c_options->slideshow.delay = options->slideshow.delay;
2039 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2040 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2041 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2042 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2043 SLIDESHOW_SUBSECOND_PRECISION;
2045 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2047 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2049 options->slideshow.delay ? hours : 0.0,
2050 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2051 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2052 spin = pref_spin_new(hbox, ":" , NULL,
2054 options->slideshow.delay ? minutes: 0.0,
2055 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2056 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2057 spin = pref_spin_new(hbox, ":", NULL,
2058 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2059 options->slideshow.delay ? seconds : 10.0,
2060 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2061 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2063 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2064 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2066 pref_spacer(group, PREF_PAD_GROUP);
2068 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2070 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2071 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2072 pref_checkbox_new_int(group, _("Preload next image"),
2073 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2075 pref_checkbox_new_int(group, _("Refresh on file change"),
2076 options->update_on_time_change, &c_options->update_on_time_change);
2078 pref_spacer(group, PREF_PAD_GROUP);
2080 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2081 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2082 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2083 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2085 options->info_keywords.height, &c_options->info_keywords.height);
2086 pref_spin_new_int(hbox, _("Title:"), NULL,
2088 options->info_title.height, &c_options->info_title.height);
2089 pref_spin_new_int(hbox, _("Comment:"), NULL,
2091 options->info_comment.height, &c_options->info_comment.height);
2092 pref_spin_new_int(hbox, _("Rating:"), NULL,
2094 options->info_rating.height, &c_options->info_rating.height);
2096 pref_spacer(group, PREF_PAD_GROUP);
2098 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2100 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2101 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2103 pref_spacer(group, PREF_PAD_GROUP);
2105 net_mon = g_network_monitor_get_default();
2106 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2107 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2108 g_object_unref(geeqie_org);
2110 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2111 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2113 if (!internet_available)
2115 gtk_widget_set_sensitive(group, FALSE);
2118 tz = g_new0(TZData, 1);
2120 path = path_from_utf8(TIMEZONE_DATABASE);
2121 basename = g_path_get_basename(path);
2122 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2126 if (isfile(tz->timezone_database_user))
2128 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2132 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2135 if (!internet_available)
2137 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"));
2141 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"));
2143 gtk_widget_show(button);
2145 pref_spacer(group, PREF_PAD_GROUP);
2147 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2149 help_search_engine_entry = gtk_entry_new();
2150 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2151 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2152 gtk_widget_show(help_search_engine_entry);
2154 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"));
2156 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2157 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2158 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2159 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2160 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2161 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2162 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2163 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2164 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2165 G_CALLBACK(help_search_engine_entry_icon_cb),
2166 help_search_engine_entry);
2170 static void config_tab_image(GtkWidget *notebook)
2175 GtkWidget *ct_button;
2176 GtkWidget *enlargement_button;
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);
2188 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2189 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2192 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2193 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2195 c_options->image.zoom_increment = options->image.zoom_increment;
2196 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2197 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2198 G_CALLBACK(zoom_increment_cb), NULL);
2199 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2201 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2203 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2204 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2205 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2206 spin = pref_spin_new_int(hbox, NULL, NULL,
2208 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2209 pref_checkbox_link_sensitivity(enlargement_button, spin);
2210 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."));
2212 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2213 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2214 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2215 spin = pref_spin_new_int(hbox, NULL, NULL,
2217 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2218 pref_checkbox_link_sensitivity(ct_button, spin);
2219 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."));
2221 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2223 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2224 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2226 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2227 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2229 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2230 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2232 c_options->image.border_color = options->image.border_color;
2234 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2235 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2237 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2238 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2240 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2241 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2243 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2245 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2246 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2250 static void config_tab_windows(GtkWidget *notebook)
2256 GtkWidget *ct_button;
2259 vbox = scrolled_notebook_page(notebook, _("Windows"));
2261 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2263 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2264 options->save_window_positions, &c_options->save_window_positions);
2266 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2267 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2268 pref_checkbox_link_sensitivity(ct_button, button);
2270 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2271 options->tools_restore_state, &c_options->tools_restore_state);
2273 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2274 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2276 pref_checkbox_new_int(group, _("Show window IDs"),
2277 options->show_window_ids, &c_options->show_window_ids);
2279 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2281 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2282 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2284 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2285 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2286 options->image.limit_window_size, &c_options->image.limit_window_size);
2287 spin = pref_spin_new_int(hbox, NULL, NULL,
2289 options->image.max_window_size, &c_options->image.max_window_size);
2290 pref_checkbox_link_sensitivity(ct_button, spin);
2292 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2294 c_options->fullscreen.screen = options->fullscreen.screen;
2295 c_options->fullscreen.above = options->fullscreen.above;
2296 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2297 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2298 gtk_widget_show(hbox);
2300 pref_checkbox_new_int(group, _("Smooth image flip"),
2301 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2302 pref_checkbox_new_int(group, _("Disable screen saver"),
2303 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2306 #define PRE_FORMATTED_COLUMNS 5
2307 static void config_tab_osd(GtkWidget *notebook)
2311 GtkWidget *vbox_buttons;
2314 GtkWidget *image_overlay_template_view;
2315 GtkWidget *scrolled;
2316 GtkWidget *scrolled_pre_formatted;
2317 GtkTextBuffer *buffer;
2319 GtkWidget * subgroup;
2324 vbox = scrolled_notebook_page(notebook, _("OSD"));
2326 image_overlay_template_view = gtk_text_view_new();
2328 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2330 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2332 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2333 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2334 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2335 gtk_widget_show(scrolled_pre_formatted);
2336 gtk_widget_show(subgroup);
2338 pref_line(group, PREF_PAD_GAP);
2340 pref_label_new(group, _("Image overlay template"));
2342 scrolled = gtk_scrolled_window_new(NULL, NULL);
2343 gtk_widget_set_size_request(scrolled, 200, 150);
2344 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2345 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2346 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2347 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2348 gtk_widget_show(scrolled);
2350 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2351 _("Extensive formatting options are shown in the Help file"));
2353 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2354 gtk_widget_show(image_overlay_template_view);
2356 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2358 #if GTK_CHECK_VERSION(3,4,0)
2359 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2360 G_CALLBACK(image_overlay_set_font_cb), notebook);
2362 button = gtk_font_button_new();
2363 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2364 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2365 g_signal_connect(G_OBJECT(button), "font-set",
2366 G_CALLBACK(image_overlay_set_font_cb),NULL);
2368 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2369 gtk_widget_show(button);
2371 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2372 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2373 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2374 gtk_widget_show(button);
2376 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2377 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2378 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2379 gtk_widget_show(button);
2380 image_overlay_set_text_colours();
2382 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2383 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2384 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2385 gtk_widget_show(button);
2387 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2388 G_CALLBACK(image_overlay_help_cb), NULL);
2389 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2390 gtk_widget_show(button);
2392 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2393 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2394 g_signal_connect(G_OBJECT(buffer), "changed",
2395 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2397 pref_line(group, PREF_PAD_GAP);
2399 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2400 hbox = gtk_hbox_new(FALSE, 0);
2401 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2402 gtk_widget_show(hbox);
2403 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2404 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2405 gtk_widget_show(label);
2406 pref_spacer(group,TRUE);
2408 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2409 hbox = gtk_hbox_new(FALSE, 0);
2410 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2411 gtk_widget_show(hbox);
2412 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2413 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2414 gtk_widget_show(label);
2415 pref_spacer(group,TRUE);
2417 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2418 hbox = gtk_hbox_new(FALSE, 0);
2419 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2420 gtk_widget_show(hbox);
2421 label = gtk_label_new(_("%path:39%"));
2422 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2423 gtk_widget_show(label);
2424 pref_spacer(group,TRUE);
2426 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2427 hbox = gtk_hbox_new(FALSE, 0);
2428 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2429 gtk_widget_show(hbox);
2430 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%"));
2431 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2432 gtk_widget_show(label);
2433 pref_spacer(group,TRUE);
2435 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2436 hbox = gtk_hbox_new(FALSE, 0);
2437 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2438 gtk_widget_show(hbox);
2439 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2440 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2441 gtk_widget_show(label);
2444 static GtkTreeModel *create_class_model(void)
2446 GtkListStore *model;
2450 /* create list store */
2451 model = gtk_list_store_new(1, G_TYPE_STRING);
2452 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2454 gtk_list_store_append(model, &iter);
2455 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2457 return GTK_TREE_MODEL (model);
2462 static void config_tab_files(GtkWidget *notebook)
2469 GtkWidget *ct_button;
2470 GtkWidget *scrolled;
2471 GtkWidget *filter_view;
2472 GtkCellRenderer *renderer;
2473 GtkTreeSelection *selection;
2474 GtkTreeViewColumn *column;
2476 vbox = scrolled_notebook_page(notebook, _("Files"));
2478 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2480 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2481 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2482 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2483 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2484 pref_checkbox_new_int(group, _("Case sensitive sort"),
2485 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2486 pref_checkbox_new_int(group, _("Natural sort order"),
2487 options->file_sort.natural, &c_options->file_sort.natural);
2488 pref_checkbox_new_int(group, _("Disable file extension checks"),
2489 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2491 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2492 options->file_filter.disable, &c_options->file_filter.disable);
2495 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2497 sidecar_ext_entry = gtk_entry_new();
2498 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2499 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2500 gtk_widget_show(sidecar_ext_entry);
2502 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2504 frame = pref_group_parent(group);
2505 g_signal_connect(G_OBJECT(ct_button), "toggled",
2506 G_CALLBACK(filter_disable_cb), frame);
2507 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2509 scrolled = gtk_scrolled_window_new(NULL, NULL);
2510 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2511 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2512 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2513 gtk_widget_show(scrolled);
2515 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2516 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2517 g_object_unref(filter_store);
2518 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2519 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2521 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2523 column = gtk_tree_view_column_new();
2524 gtk_tree_view_column_set_title(column, _("Filter"));
2525 gtk_tree_view_column_set_resizable(column, TRUE);
2527 renderer = gtk_cell_renderer_toggle_new();
2528 g_signal_connect(G_OBJECT(renderer), "toggled",
2529 G_CALLBACK(filter_store_enable_cb), filter_store);
2530 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2531 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2532 GINT_TO_POINTER(FE_ENABLE), NULL);
2534 renderer = gtk_cell_renderer_text_new();
2535 g_signal_connect(G_OBJECT(renderer), "edited",
2536 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2537 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2538 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2539 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2540 GINT_TO_POINTER(FE_EXTENSION), NULL);
2541 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2543 column = gtk_tree_view_column_new();
2544 gtk_tree_view_column_set_title(column, _("Description"));
2545 gtk_tree_view_column_set_resizable(column, TRUE);
2546 gtk_tree_view_column_set_fixed_width(column, 200);
2547 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2549 renderer = gtk_cell_renderer_text_new();
2550 g_signal_connect(G_OBJECT(renderer), "edited",
2551 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2552 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2553 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2554 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2555 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2556 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2558 column = gtk_tree_view_column_new();
2559 gtk_tree_view_column_set_title(column, _("Class"));
2560 gtk_tree_view_column_set_resizable(column, TRUE);
2561 renderer = gtk_cell_renderer_combo_new();
2562 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2563 "model", create_class_model(),
2568 g_signal_connect(G_OBJECT(renderer), "edited",
2569 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2570 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2571 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2572 GINT_TO_POINTER(FE_CLASS), NULL);
2573 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2575 column = gtk_tree_view_column_new();
2576 gtk_tree_view_column_set_title(column, _("Writable"));
2577 gtk_tree_view_column_set_resizable(column, FALSE);
2578 renderer = gtk_cell_renderer_toggle_new();
2579 g_signal_connect(G_OBJECT(renderer), "toggled",
2580 G_CALLBACK(filter_store_writable_cb), filter_store);
2581 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2582 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2583 GINT_TO_POINTER(FE_WRITABLE), NULL);
2584 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2586 column = gtk_tree_view_column_new();
2587 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2588 gtk_tree_view_column_set_resizable(column, FALSE);
2589 renderer = gtk_cell_renderer_toggle_new();
2590 g_signal_connect(G_OBJECT(renderer), "toggled",
2591 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2592 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2593 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2594 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2595 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2598 filter_store_populate();
2599 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2600 gtk_widget_show(filter_view);
2602 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2604 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2605 G_CALLBACK(filter_default_cb), filter_view);
2606 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2607 gtk_widget_show(button);
2609 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2610 G_CALLBACK(filter_remove_cb), filter_view);
2611 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2612 gtk_widget_show(button);
2614 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2615 G_CALLBACK(filter_add_cb), filter_view);
2616 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2617 gtk_widget_show(button);
2621 static void config_tab_metadata(GtkWidget *notebook)
2626 GtkWidget *ct_button;
2630 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2633 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2635 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2637 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2638 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2640 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2641 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2643 gtk_widget_set_sensitive(ct_button, FALSE);
2646 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2647 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2649 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2650 label = pref_label_new(group, text);
2651 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2652 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2655 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2657 gtk_widget_set_sensitive(group, FALSE);
2660 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2661 pref_checkbox_link_sensitivity(ct_button, hbox);
2663 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2664 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2666 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2667 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2669 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2670 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2672 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2673 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2675 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2677 gtk_widget_set_sensitive(group, FALSE);
2680 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2681 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2684 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2685 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2686 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2688 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2689 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2691 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2692 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2694 gtk_widget_set_sensitive(ct_button, FALSE);
2697 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2699 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2700 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2702 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2703 pref_checkbox_link_sensitivity(ct_button, hbox);
2705 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2706 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2708 pref_checkbox_new_int(group, _("Write metadata on image change"),
2709 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2711 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2712 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2714 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2716 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2717 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2718 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");
2723 typedef struct _KeywordFindData KeywordFindData;
2724 struct _KeywordFindData
2731 GtkWidget *button_close;
2732 GtkWidget *button_stop;
2733 GtkWidget *button_start;
2734 GtkWidget *progress;
2742 guint idle_id; /* event source id */
2745 #define KEYWORD_DIALOG_WIDTH 400
2747 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2749 GList *list_d = NULL;
2750 GList *list_f = NULL;
2754 filelist_read(dir_fd, &list_f, &list_d);
2758 filelist_read(dir_fd, &list_f, NULL);
2761 list_f = filelist_filter(list_f, FALSE);
2762 list_d = filelist_filter(list_d, TRUE);
2764 kfd->list = g_list_concat(list_f, kfd->list);
2765 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2768 static void keywords_find_reset(KeywordFindData *kfd)
2770 filelist_free(kfd->list);
2773 filelist_free(kfd->list_dir);
2774 kfd->list_dir = NULL;
2777 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2779 KeywordFindData *kfd = data;
2781 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2783 keywords_find_reset(kfd);
2784 generic_dialog_close(kfd->gd);
2788 static void keywords_find_finish(KeywordFindData *kfd)
2790 keywords_find_reset(kfd);
2792 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2793 spinner_set_interval(kfd->spinner, -1);
2795 gtk_widget_set_sensitive(kfd->group, TRUE);
2796 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2797 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2798 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2801 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2803 KeywordFindData *kfd = data;
2805 g_idle_remove_by_data(kfd);
2807 keywords_find_finish(kfd);
2810 static gboolean keywords_find_file(gpointer data)
2812 KeywordFindData *kfd = data;
2814 GtkTextBuffer *buffer;
2822 fd = kfd->list->data;
2823 kfd->list = g_list_remove(kfd->list, fd);
2825 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2826 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2830 gtk_text_buffer_get_end_iter(buffer, &iter);
2831 tmp = g_strconcat(keywords->data, "\n", NULL);
2832 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2834 keywords = keywords->next;
2837 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2838 file_data_unref(fd);
2839 string_list_free(keywords);
2843 else if (kfd->list_dir)
2847 fd = kfd->list_dir->data;
2848 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2850 keywords_find_folder(kfd, fd);
2852 file_data_unref(fd);
2857 keywords_find_finish(kfd);
2862 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2864 KeywordFindData *kfd = data;
2867 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2869 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2870 parse_out_relatives(path);
2874 warning_dialog(_("Invalid folder"),
2875 _("The specified folder can not be found."),
2876 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2882 gtk_widget_set_sensitive(kfd->group, FALSE);
2883 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2884 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2885 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2886 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2888 dir_fd = file_data_new_dir(path);
2889 keywords_find_folder(kfd, dir_fd);
2890 file_data_unref(dir_fd);
2891 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2897 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2899 KeywordFindData *kfd;
2903 kfd = g_new0(KeywordFindData, 1);
2905 kfd->gd = generic_dialog_new(_("Search for keywords"),
2906 "search_for_keywords",
2909 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2910 kfd->gd->cancel_cb = keywords_find_close_cb;
2911 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2912 keywords_find_close_cb, FALSE);
2913 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2914 keywords_find_start_cb, FALSE);
2915 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2916 keywords_find_stop_cb, FALSE);
2917 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2919 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2921 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2922 pref_spacer(hbox, PREF_PAD_INDENT);
2923 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2925 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2926 pref_label_new(hbox, _("Folder:"));
2928 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2929 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2930 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2931 gtk_widget_show(label);
2933 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2935 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2936 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2938 kfd->progress = gtk_entry_new();
2939 gtk_widget_set_can_focus(kfd->progress, FALSE);
2940 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2941 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2942 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2943 gtk_widget_show(kfd->progress);
2945 kfd->spinner = spinner_new(NULL, -1);
2946 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2947 gtk_widget_show(kfd->spinner);
2951 gtk_widget_show(kfd->gd->dialog);
2954 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2956 const gchar *path = layout_get_path(NULL);
2958 if (!path || !*path) path = homedir();
2959 keywords_find_dialog(widget, path);
2962 static void config_tab_keywords_save()
2964 GtkTextIter start, end;
2965 GtkTextBuffer *buffer;
2966 GList *kw_list = NULL;
2972 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2973 gtk_text_buffer_get_bounds(buffer, &start, &end);
2975 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2977 kw_split = strtok(buffer_text, "\n");
2978 while (kw_split != NULL)
2984 if (g_strcmp0(work->data, kw_split) == 0)
2993 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2995 kw_split = strtok(NULL, "\n");
2998 keyword_list_set(kw_list);
3000 string_list_free(kw_list);
3001 g_free(buffer_text);
3004 static void config_tab_keywords(GtkWidget *notebook)
3010 GtkWidget *scrolled;
3012 GtkTextBuffer *buffer;
3015 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3017 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3019 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3021 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3022 G_CALLBACK(keywords_find_cb), keyword_text);
3023 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3026 keyword_text = gtk_text_view_new();
3027 gtk_widget_set_size_request(keyword_text, 20, 20);
3028 scrolled = gtk_scrolled_window_new(NULL, NULL);
3029 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3030 gtk_widget_show(scrolled);
3032 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3033 gtk_widget_show(keyword_text);
3035 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3037 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3038 gtk_text_buffer_create_tag(buffer, "monospace",
3039 "family", "monospace", NULL);
3041 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3042 gtk_text_buffer_get_start_iter(buffer, &iter);
3043 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3046 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3048 GList *kwl = keyword_list_get();
3049 kwl = g_list_first(kwl);
3052 gtk_text_buffer_get_end_iter (buffer, &iter);
3053 tmp = g_strconcat(kwl->data, "\n", NULL);
3054 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3059 gtk_text_buffer_set_modified(buffer, FALSE);
3066 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3068 gint *option = data;
3070 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3074 *option = INTENT_PERCEPTUAL;
3077 *option = INTENT_RELATIVE_COLORIMETRIC;
3080 *option = INTENT_SATURATION;
3083 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3088 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3089 gint option, gint *option_c)
3096 pref_table_label(table, column, row, text, 0.0);
3098 combo = gtk_combo_box_text_new();
3100 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3101 if (option == INTENT_PERCEPTUAL) current = 0;
3102 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3103 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3104 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3105 if (option == INTENT_SATURATION) current = 2;
3106 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3107 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3109 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3111 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3113 g_signal_connect(G_OBJECT(combo), "changed",
3114 G_CALLBACK(intent_menu_cb), option_c);
3116 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3117 gtk_widget_show(combo);
3121 static void config_tab_color(GtkWidget *notebook)
3130 vbox = scrolled_notebook_page(notebook, _("Color management"));
3132 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3134 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3137 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3138 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3140 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3141 pref_label_bold(label, TRUE, FALSE);
3143 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3144 pref_label_bold(label, TRUE, FALSE);
3146 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3147 pref_label_bold(label, TRUE, FALSE);
3149 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3154 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3155 pref_table_label(table, 0, i + 1, buf, 1.0);
3158 entry = gtk_entry_new();
3159 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3160 if (options->color_profile.input_name[i])
3162 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3164 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3165 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3166 gtk_widget_show(entry);
3167 color_profile_input_name_entry[i] = entry;
3169 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3170 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3171 gtk_widget_set_size_request(entry, 160, -1);
3172 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3173 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3174 gtk_widget_show(tabcomp);
3175 color_profile_input_file_entry[i] = entry;
3178 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3180 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3182 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3183 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3185 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3187 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3188 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3189 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3190 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3191 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3193 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3195 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3197 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3199 gtk_widget_show(tabcomp);
3202 /* advanced entry tab */
3203 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3205 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3207 c_options->file_ops.use_system_trash = FALSE;
3208 c_options->file_ops.no_trash = FALSE;
3212 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3214 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3216 c_options->file_ops.use_system_trash = TRUE;
3217 c_options->file_ops.no_trash = FALSE;
3221 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3223 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3225 c_options->file_ops.no_trash = TRUE;
3229 static void config_tab_behavior(GtkWidget *notebook)
3236 GtkWidget *ct_button;
3240 GtkWidget *with_rename;
3241 GtkWidget *collections_on_top;
3243 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3245 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3247 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3248 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3249 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3250 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3251 pref_checkbox_new_int(group, _("Enable Delete key"),
3252 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3254 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3255 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3257 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3258 pref_checkbox_link_sensitivity(ct_button, hbox);
3260 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3261 pref_label_new(hbox, _("Folder:"));
3263 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3264 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3265 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3266 gtk_widget_show(tabcomp);
3268 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3269 pref_checkbox_link_sensitivity(ct_button, hbox);
3271 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3272 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3273 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3274 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3275 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3276 G_CALLBACK(safe_delete_view_cb), NULL);
3277 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3278 gtk_widget_show(button);
3280 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3281 G_CALLBACK(safe_delete_clear_cb), NULL);
3282 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3283 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3284 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3286 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3287 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3289 gtk_widget_show(button);
3291 pref_spacer(group, PREF_PAD_GROUP);
3294 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3296 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3297 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3299 pref_checkbox_new_int(group, _("In place renaming"),
3300 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3302 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3303 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3305 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3306 options->marks_save, &c_options->marks_save);
3307 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3309 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3310 options->with_rename, &c_options->with_rename);
3311 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3313 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3314 options->collections_on_top, &c_options->collections_on_top);
3315 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3317 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3318 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3320 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3321 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3323 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3324 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3326 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3327 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3329 pref_spacer(group, PREF_PAD_GROUP);
3331 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3333 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3334 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3335 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3336 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3337 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3338 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3339 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3340 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3341 pref_checkbox_new_int(group, _("Play video by left click on image"),
3342 options->image_l_click_video, &c_options->image_l_click_video);
3343 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3344 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3346 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3347 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3348 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3349 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3350 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3353 pref_spacer(group, PREF_PAD_GROUP);
3355 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3357 pref_spin_new_int(group, _("Debug level:"), NULL,
3358 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3360 pref_checkbox_new_int(group, _("Timer data"),
3361 options->log_window.timer_data, &c_options->log_window.timer_data);
3363 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3364 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3368 /* accelerators tab */
3369 static void config_tab_accelerators(GtkWidget *notebook)
3375 GtkWidget *scrolled;
3376 GtkWidget *accel_view;
3377 GtkCellRenderer *renderer;
3378 GtkTreeSelection *selection;
3379 GtkTreeViewColumn *column;
3381 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3383 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3385 scrolled = gtk_scrolled_window_new(NULL, NULL);
3386 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3387 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3388 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3389 gtk_widget_show(scrolled);
3391 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3393 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3394 g_object_unref(accel_store);
3395 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3396 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3398 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3400 renderer = gtk_cell_renderer_text_new();
3402 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3407 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3408 gtk_tree_view_column_set_resizable(column, TRUE);
3409 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3412 renderer = gtk_cell_renderer_accel_new();
3413 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3414 G_CALLBACK(accel_store_cleared_cb), accel_store);
3415 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3416 G_CALLBACK(accel_store_edited_cb), accel_store);
3419 g_object_set (renderer,
3421 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3424 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3429 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3430 gtk_tree_view_column_set_resizable(column, TRUE);
3431 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3433 renderer = gtk_cell_renderer_text_new();
3435 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3440 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3441 gtk_tree_view_column_set_resizable(column, TRUE);
3442 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3444 renderer = gtk_cell_renderer_text_new();
3446 column = gtk_tree_view_column_new_with_attributes("Accel",
3451 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3452 gtk_tree_view_column_set_resizable(column, TRUE);
3453 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3455 accel_store_populate();
3456 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3457 gtk_widget_show(accel_view);
3459 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3461 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3462 G_CALLBACK(accel_default_cb), accel_view);
3463 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3464 gtk_widget_show(button);
3466 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3467 G_CALLBACK(accel_reset_cb), accel_view);
3468 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3469 gtk_widget_show(button);
3472 /* toolbar main tab */
3473 static void config_tab_toolbar_main(GtkWidget *notebook)
3476 GtkWidget *toolbardata;
3479 lw = layout_window_list->data;
3481 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3483 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3484 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3485 gtk_widget_show(vbox);
3488 /* toolbar status tab */
3489 static void config_tab_toolbar_status(GtkWidget *notebook)
3492 GtkWidget *toolbardata;
3495 lw = layout_window_list->data;
3497 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3499 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3500 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3501 gtk_widget_show(vbox);
3505 static void config_tab_stereo(GtkWidget *notebook)
3513 GtkWidget *fs_button;
3514 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3516 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3518 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3519 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3521 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3522 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3523 pref_checkbox_new_int(box, _("Mirror left image"),
3524 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3525 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3526 pref_checkbox_new_int(box, _("Flip left image"),
3527 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3528 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3529 pref_checkbox_new_int(box, _("Mirror right image"),
3530 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3531 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3532 pref_checkbox_new_int(box, _("Flip right image"),
3533 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3534 pref_checkbox_new_int(group, _("Swap left and right images"),
3535 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3536 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3537 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3539 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3540 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3541 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3542 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3543 pref_checkbox_link_sensitivity(fs_button, box2);
3544 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3545 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3546 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3547 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3548 pref_checkbox_new_int(box, _("Mirror left image"),
3549 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3550 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3551 pref_checkbox_new_int(box, _("Flip left image"),
3552 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3553 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3554 pref_checkbox_new_int(box, _("Mirror right image"),
3555 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3556 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3557 pref_checkbox_new_int(box, _("Flip right image"),
3558 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3559 pref_checkbox_new_int(box2, _("Swap left and right images"),
3560 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3561 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3562 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3564 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3565 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3566 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3567 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3568 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3569 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3570 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3571 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3572 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3573 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3574 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3575 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3576 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3577 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3581 /* Main preferences window */
3582 static void config_window_create(void)
3584 GtkWidget *win_vbox;
3586 GtkWidget *notebook;
3588 GtkWidget *ct_button;
3590 if (!c_options) c_options = init_options(NULL);
3592 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3593 DEBUG_NAME(configwindow);
3594 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3595 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3596 G_CALLBACK(config_window_delete), NULL);
3597 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3598 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3599 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3601 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3602 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3603 gtk_widget_show(win_vbox);
3605 notebook = gtk_notebook_new();
3606 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3607 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3608 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3610 config_tab_general(notebook);
3611 config_tab_image(notebook);
3612 config_tab_osd(notebook);
3613 config_tab_windows(notebook);
3614 config_tab_accelerators(notebook);
3615 config_tab_files(notebook);
3616 config_tab_metadata(notebook);
3617 config_tab_keywords(notebook);
3618 config_tab_color(notebook);
3619 config_tab_stereo(notebook);
3620 config_tab_behavior(notebook);
3621 config_tab_toolbar_main(notebook);
3622 config_tab_toolbar_status(notebook);
3624 hbox = gtk_hbutton_box_new();
3625 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3626 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3627 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3628 gtk_widget_show(hbox);
3630 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3631 G_CALLBACK(config_window_help_cb), notebook);
3632 gtk_container_add(GTK_CONTAINER(hbox), button);
3633 gtk_widget_set_can_default(button, TRUE);
3634 gtk_widget_show(button);
3636 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3637 G_CALLBACK(config_window_ok_cb), NULL);
3638 gtk_container_add(GTK_CONTAINER(hbox), button);
3639 gtk_widget_set_can_default(button, TRUE);
3640 gtk_widget_grab_default(button);
3641 gtk_widget_show(button);
3645 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3646 G_CALLBACK(config_window_close_cb), NULL);
3647 gtk_container_add(GTK_CONTAINER(hbox), button);
3648 gtk_widget_set_can_default(button, TRUE);
3649 gtk_widget_show(button);
3651 if (!generic_dialog_get_alternative_button_order(configwindow))
3653 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3656 gtk_widget_show(notebook);
3658 gtk_widget_show(configwindow);
3662 *-----------------------------------------------------------------------------
3663 * config window show (public)
3664 *-----------------------------------------------------------------------------
3667 void show_config_window(void)
3671 gtk_window_present(GTK_WINDOW(configwindow));
3675 config_window_create();
3684 void show_about_window(LayoutWindow *lw)
3686 GdkPixbuf *pixbuf_logo;
3687 GdkPixbuf *pixbuf_icon;
3688 gchar *authors[1000];
3693 gchar *timezone_path;
3697 #define LINE_LENGTH 1000
3698 gchar line[LINE_LENGTH];
3700 copyright = g_string_new(NULL);
3701 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");
3703 path = path_from_utf8(TIMEZONE_DATABASE);
3704 basename = g_path_get_basename(path);
3705 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3706 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3708 cd = ZDOpenDatabase(timezone_path);
3711 copyright = g_string_append(copyright, ZDGetNotice(cd));
3712 ZDCloseDatabase(cd);
3716 g_free(timezone_path);
3720 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3721 fp = fopen(path, "r");
3724 while(fgets(line, LINE_LENGTH, fp))
3726 /* get rid of ending \n from fgets */
3727 line[strlen(line) - 1] = '\0';
3728 authors[i_authors] = g_strdup(line);
3731 authors[i_authors] = NULL;
3736 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3737 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3739 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3740 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3741 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3742 "title", _("About Geeqie"),
3744 "program-name", GQ_APPNAME,
3746 "logo", pixbuf_logo,
3747 "icon", pixbuf_icon,
3748 "website", GQ_WEBSITE,
3749 "website-label", "Website",
3750 "comments", comment,
3752 "translator-credits", _("translator-credits"),
3753 "wrap-license", TRUE,
3754 "license", copyright->str,
3757 g_string_free(copyright, TRUE);
3760 while(n < i_authors)
3770 static void image_overlay_set_text_colours()
3772 c_options->image_overlay.text_red = options->image_overlay.text_red;
3773 c_options->image_overlay.text_green = options->image_overlay.text_green;
3774 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3775 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3776 c_options->image_overlay.background_red = options->image_overlay.background_red;
3777 c_options->image_overlay.background_green = options->image_overlay.background_green;
3778 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3779 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3783 *-----------------------------------------------------------------------------
3784 * timezone database routines
3785 *-----------------------------------------------------------------------------
3788 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3790 GError *error = NULL;
3792 gchar *tmp_filename;
3794 if (!g_cancellable_is_cancelled(tz->cancellable))
3796 generic_dialog_close(tz->gd);
3800 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3802 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3803 move_file(tmp_filename, tz->timezone_database_user);
3804 g_free(tmp_filename);
3808 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3811 g_file_delete(tz->tmp_g_file, NULL, &error);
3812 g_object_unref(tz->tmp_g_file);
3813 tz->tmp_g_file = NULL;
3814 g_object_unref(tz->cancellable);
3815 g_object_unref(tz->timezone_database_gq);
3818 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3822 if (!g_cancellable_is_cancelled(tz->cancellable))
3824 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3828 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3831 GError *error = NULL;
3833 g_cancellable_cancel(tz->cancellable);
3836 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3839 GError *error = NULL;
3840 GFileIOStream *io_stream;
3847 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3851 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3852 log_printf("Error: Download timezone database failed:\n%s", error->message);
3853 g_error_free(error);
3854 g_object_unref(tz->tmp_g_file);
3858 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3860 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3862 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3864 tz->progress = gtk_progress_bar_new();
3865 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3866 gtk_widget_show(tz->progress);
3868 gtk_widget_show(tz->gd->dialog);
3869 tz->cancellable = g_cancellable_new();
3870 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);
3872 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3875 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */