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;
424 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
426 options->marks_save = c_options->marks_save;
427 options->with_rename = c_options->with_rename;
428 options->collections_on_top = c_options->collections_on_top;
429 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
431 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
433 options->star_rating.star = c_options->star_rating.star;
434 options->star_rating.rejected = c_options->star_rating.rejected;
436 set_debug_level(debug_c);
440 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
442 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
443 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
445 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
446 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
447 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
449 options->color_profile.render_intent = c_options->color_profile.render_intent;
454 options->mouse_button_8 = c_options->mouse_button_8;
455 options->mouse_button_9 = c_options->mouse_button_9;
457 options->override_disable_gpu = c_options->override_disable_gpu;
459 config_tab_keywords_save();
461 image_options_sync();
466 layout_refresh(NULL);
469 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
471 toolbar_apply(TOOLBAR_MAIN);
472 toolbar_apply(TOOLBAR_STATUS);
476 *-----------------------------------------------------------------------------
477 * config window main button callbacks (private)
478 *-----------------------------------------------------------------------------
481 static void config_window_close_cb(GtkWidget *widget, gpointer data)
483 gtk_widget_destroy(configwindow);
488 static void config_window_help_cb(GtkWidget *widget, gpointer data)
490 GtkWidget *notebook = data;
493 static gchar *html_section[] =
495 "GuideOptionsGeneral.html",
496 "GuideOptionsImage.html",
497 "GuideOptionsOSD.html",
498 "GuideOptionsWindow.html",
499 "GuideOptionsKeyboard.html",
500 "GuideOptionsFiltering.html",
501 "GuideOptionsMetadata.html",
502 "GuideOptionsKeywords.html",
503 "GuideOptionsColor.html",
504 "GuideOptionsStereo.html",
505 "GuideOptionsBehavior.html",
506 "GuideOptionsToolbar.html",
507 "GuideOptionsToolbar.html"
510 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
511 help_window_show(html_section[i]);
514 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
516 config_window_close_cb(NULL, NULL);
520 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
523 lw = layout_window_list->data;
525 config_window_apply();
526 layout_util_sync(lw);
527 save_options(options);
528 config_window_close_cb(NULL, NULL);
532 *-----------------------------------------------------------------------------
533 * config window setup (private)
534 *-----------------------------------------------------------------------------
537 static void quality_menu_cb(GtkWidget *combo, gpointer data)
541 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
545 *option = GDK_INTERP_NEAREST;
548 *option = GDK_INTERP_TILES;
551 *option = GDK_INTERP_BILINEAR;
554 *option = GDK_INTERP_HYPER;
559 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
563 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
567 *option = DND_ACTION_ASK;
570 *option = DND_ACTION_COPY;
573 *option = DND_ACTION_MOVE;
577 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
581 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
593 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
594 guint option, guint *option_c)
601 pref_table_label(table, column, row, text, 0.0);
603 combo = gtk_combo_box_text_new();
605 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
606 if (option == GDK_INTERP_NEAREST) current = 0;
607 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
608 if (option == GDK_INTERP_TILES) current = 1;
609 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
610 if (option == GDK_INTERP_BILINEAR) current = 2;
611 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
612 if (option == GDK_INTERP_HYPER) current = 3;
614 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
616 g_signal_connect(G_OBJECT(combo), "changed",
617 G_CALLBACK(quality_menu_cb), option_c);
619 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
620 gtk_widget_show(combo);
623 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
630 pref_table_label(table, column, row, text, 0.0);
632 combo = gtk_combo_box_text_new();
634 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
635 if (option == DND_ACTION_ASK) current = 0;
636 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
637 if (option == DND_ACTION_COPY) current = 1;
638 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
639 if (option == DND_ACTION_MOVE) current = 2;
641 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
643 g_signal_connect(G_OBJECT(combo), "changed",
644 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
646 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
647 gtk_widget_show(combo);
650 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
651 gint option, gint *option_c)
658 pref_table_label(table, column, row, text, 0.0);
660 combo = gtk_combo_box_text_new();
662 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
663 if (option == PRIMARY) current = 0;
664 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
665 if (option == CLIPBOARD) current = 1;
667 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
669 g_signal_connect(G_OBJECT(combo), "changed",
670 G_CALLBACK(clipboard_selection_menu_cb), option_c);
672 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
673 gtk_widget_show(combo);
676 typedef struct _UseableMouseItems UseableMouseItems;
677 struct _UseableMouseItems
679 gchar *name; /* GtkActionEntry terminology */
684 static const UseableMouseItems useable_mouse_items[] = {
686 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
687 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
688 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
689 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
690 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
691 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
692 {"Home", N_("Home"), GTK_STOCK_HOME},
693 {"Up", N_("Up"), GTK_STOCK_GO_UP},
694 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
695 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
696 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
697 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
698 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
699 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
700 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
701 {"Search", N_("Search"), GTK_STOCK_FIND},
702 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
703 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
704 {"Copy", N_("Copy"), GTK_STOCK_COPY},
705 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
706 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
707 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
708 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
709 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
710 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
711 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
712 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
713 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
714 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
715 {"Print", N_("Print"), GTK_STOCK_PRINT},
716 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
717 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
718 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
719 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
720 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
721 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
722 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
723 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
724 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
725 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
726 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
727 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
728 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
729 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
730 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
731 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
732 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
733 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
734 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
735 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
736 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
737 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
738 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
739 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
740 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
741 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
742 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
743 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
744 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
745 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
746 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
747 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
748 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
749 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
750 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
751 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
752 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
753 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
754 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
755 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
759 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
761 gchar **option = data;
764 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
766 const UseableMouseItems *list = useable_mouse_items;
770 if (g_strcmp0(list->label, label) == 0)
778 *option = g_strdup(list->name);
782 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
783 gchar *option, gchar **option_c)
791 pref_table_label(table, column, row, text, 0.0);
793 combo = gtk_combo_box_text_new();
795 const UseableMouseItems *list = useable_mouse_items;
799 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
800 if (g_strcmp0(list->name, option) == 0)
808 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
810 g_signal_connect(G_OBJECT(combo), "changed",
811 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
813 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
814 gtk_widget_show(combo);
817 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
821 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
824 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
826 c_options->thumbnails.max_width = thumb_size_list[n].w;
827 c_options->thumbnails.max_height = thumb_size_list[n].h;
831 c_options->thumbnails.max_width = options->thumbnails.max_width;
832 c_options->thumbnails.max_height = options->thumbnails.max_height;
836 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
842 c_options->thumbnails.max_width = options->thumbnails.max_width;
843 c_options->thumbnails.max_height = options->thumbnails.max_height;
845 pref_table_label(table, column, row, text, 0.0);
847 combo = gtk_combo_box_text_new();
850 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
855 w = thumb_size_list[i].w;
856 h = thumb_size_list[i].h;
858 buf = g_strdup_printf("%d x %d", w, h);
859 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
862 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
869 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
870 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
876 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
877 g_signal_connect(G_OBJECT(combo), "changed",
878 G_CALLBACK(thumb_size_menu_cb), NULL);
880 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
881 gtk_widget_show(combo);
884 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
888 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
892 *option = PR_STEREO_NONE;
895 *option = PR_STEREO_ANAGLYPH_RC;
898 *option = PR_STEREO_ANAGLYPH_GM;
901 *option = PR_STEREO_ANAGLYPH_YB;
904 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
907 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
910 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
913 *option = PR_STEREO_ANAGLYPH_DB_RC;
916 *option = PR_STEREO_ANAGLYPH_DB_GM;
919 *option = PR_STEREO_ANAGLYPH_DB_YB;
922 *option = PR_STEREO_HORIZ;
925 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
928 *option = PR_STEREO_VERT;
931 *option = PR_STEREO_VERT | PR_STEREO_HALF;
934 *option = PR_STEREO_FIXED;
939 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
940 gint option, gint *option_c, gboolean add_fixed)
947 pref_table_label(table, column, row, text, 0.0);
949 combo = gtk_combo_box_text_new();
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
953 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
954 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
955 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
956 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
958 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
959 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
960 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
961 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
962 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
964 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
966 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
967 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
968 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
970 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
972 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
973 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
974 if (option & PR_STEREO_HORIZ)
977 if (option & PR_STEREO_HALF) current = 11;
980 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
981 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
982 if (option & PR_STEREO_VERT)
985 if (option & PR_STEREO_HALF) current = 13;
990 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
991 if (option & PR_STEREO_FIXED) current = 14;
994 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
996 g_signal_connect(G_OBJECT(combo), "changed",
997 G_CALLBACK(stereo_mode_menu_cb), option_c);
999 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1000 gtk_widget_show(combo);
1003 static void video_menu_cb(GtkWidget *combo, gpointer data)
1005 gchar **option = data;
1007 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1011 static void video_menu_populate(gpointer data, gpointer user_data)
1013 GtkWidget *combo = user_data;
1014 EditorDescription *ed = data;
1016 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1019 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1020 gchar *option, gchar **option_c)
1024 /* use lists since they are sorted */
1025 GList *eds = editor_list_get();
1029 pref_table_label(table, column, row, text, 0.0);
1031 combo = gtk_combo_box_text_new();
1032 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1033 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1035 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1037 g_signal_connect(G_OBJECT(combo), "changed",
1038 G_CALLBACK(video_menu_cb), option_c);
1040 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1041 gtk_widget_show(combo);
1044 static void filter_store_populate(void)
1048 if (!filter_store) return;
1050 gtk_list_store_clear(filter_store);
1052 work = filter_get_list();
1061 gtk_list_store_append(filter_store, &iter);
1062 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1066 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1067 gchar *new_text, gpointer data)
1069 GtkWidget *model = data;
1070 FilterEntry *fe = data;
1074 if (!new_text || strlen(new_text) < 1) return;
1076 tpath = gtk_tree_path_new_from_string(path_str);
1077 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1078 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1080 g_free(fe->extensions);
1081 fe->extensions = g_strdup(new_text);
1083 gtk_tree_path_free(tpath);
1087 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1088 gchar *new_text, gpointer data)
1090 GtkWidget *model = data;
1091 FilterEntry *fe = data;
1096 if (!new_text || !new_text[0]) return;
1098 tpath = gtk_tree_path_new_from_string(path_str);
1099 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1100 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1102 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1104 if (strcmp(new_text, _(format_class_list[i])) == 0)
1111 gtk_tree_path_free(tpath);
1115 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1116 gchar *new_text, gpointer data)
1118 GtkWidget *model = data;
1123 if (!new_text || !new_text[0]) return;
1125 tpath = gtk_tree_path_new_from_string(path_str);
1126 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1127 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1129 g_free(fe->description);
1130 fe->description = g_strdup(new_text);
1132 gtk_tree_path_free(tpath);
1135 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1136 gchar *path_str, gpointer data)
1138 GtkWidget *model = data;
1143 tpath = gtk_tree_path_new_from_string(path_str);
1144 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1145 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1147 fe->enabled = !fe->enabled;
1149 gtk_tree_path_free(tpath);
1153 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1154 gchar *path_str, gpointer data)
1156 GtkWidget *model = data;
1161 tpath = gtk_tree_path_new_from_string(path_str);
1162 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1163 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1165 fe->writable = !fe->writable;
1166 if (fe->writable) fe->allow_sidecar = FALSE;
1168 gtk_tree_path_free(tpath);
1172 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1173 gchar *path_str, gpointer data)
1175 GtkWidget *model = data;
1180 tpath = gtk_tree_path_new_from_string(path_str);
1181 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1182 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1184 fe->allow_sidecar = !fe->allow_sidecar;
1185 if (fe->allow_sidecar) fe->writable = FALSE;
1187 gtk_tree_path_free(tpath);
1191 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1192 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1196 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1198 switch (GPOINTER_TO_INT(data))
1201 g_object_set(GTK_CELL_RENDERER(cell),
1202 "active", fe->enabled, NULL);
1205 g_object_set(GTK_CELL_RENDERER(cell),
1206 "text", fe->extensions, NULL);
1208 case FE_DESCRIPTION:
1209 g_object_set(GTK_CELL_RENDERER(cell),
1210 "text", fe->description, NULL);
1213 g_object_set(GTK_CELL_RENDERER(cell),
1214 "text", _(format_class_list[fe->file_class]), NULL);
1217 g_object_set(GTK_CELL_RENDERER(cell),
1218 "active", fe->writable, NULL);
1220 case FE_ALLOW_SIDECAR:
1221 g_object_set(GTK_CELL_RENDERER(cell),
1222 "active", fe->allow_sidecar, NULL);
1227 static gboolean filter_add_scroll(gpointer data)
1231 GtkCellRenderer *cell;
1232 GtkTreeViewColumn *column;
1235 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1236 path = gtk_tree_path_new_from_indices(rows-1, -1);
1238 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1240 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1241 cell = g_list_last(list_cells)->data;
1243 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1244 path, column, FALSE, 0.0, 0.0 );
1245 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1246 path, column, cell, TRUE);
1248 gtk_tree_path_free(path);
1249 g_list_free(list_cells);
1254 static void filter_add_cb(GtkWidget *widget, gpointer data)
1256 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1257 filter_store_populate();
1259 g_idle_add((GSourceFunc)filter_add_scroll, data);
1262 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1264 GtkWidget *filter_view = data;
1265 GtkTreeSelection *selection;
1269 if (!filter_store) return;
1270 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1271 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1272 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1275 filter_remove_entry(fe);
1277 filter_store_populate();
1280 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1284 GtkTreeViewColumn *column;
1286 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1287 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1288 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1290 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1294 gtk_tree_path_free(path);
1299 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1302 filter_add_defaults();
1304 filter_store_populate();
1306 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1309 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1311 /* no op, only so cancel button appears */
1314 static void filter_default_cb(GtkWidget *widget, gpointer data)
1318 gd = generic_dialog_new(_("Reset filters"),
1319 "reset_filter", widget, TRUE,
1320 dummy_cancel_cb, data);
1321 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1322 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1323 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1324 gtk_widget_show(gd->dialog);
1327 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1329 GtkWidget *frame = data;
1331 gtk_widget_set_sensitive(frame,
1332 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1335 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1337 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1340 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1342 file_util_trash_clear();
1345 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1349 gd = generic_dialog_new(_("Clear trash"),
1350 "clear_trash", widget, TRUE,
1351 dummy_cancel_cb, NULL);
1352 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1353 _("This will remove the trash contents."), FALSE);
1354 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1355 entry = gtk_entry_new();
1356 gtk_widget_set_can_focus(entry, FALSE);
1357 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1358 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1359 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1360 gtk_widget_show(entry);
1361 gtk_widget_show(gd->dialog);
1364 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1366 GtkWidget *pTextView;
1367 GtkTextBuffer *pTextBuffer;
1371 pTextView = GTK_WIDGET(data);
1373 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1374 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1375 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1377 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1378 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1381 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1383 GtkTextView *text_view = data;
1384 GtkTextBuffer *buffer;
1386 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1387 if (!configwindow) return;
1389 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1390 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1393 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1397 gd = generic_dialog_new(_("Reset image overlay template string"),
1398 "reset_image_overlay_template_string", widget, TRUE,
1399 dummy_cancel_cb, data);
1400 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1401 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1402 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1403 gtk_widget_show(gd->dialog);
1406 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1408 help_window_show("GuideOptionsOSD.html");
1411 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1413 #if GTK_CHECK_VERSION(3,4,0)
1416 PangoFontDescription *font_desc;
1418 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1419 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1421 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1423 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1424 font = pango_font_description_to_string(font_desc);
1425 g_free(c_options->image_overlay.font);
1426 c_options->image_overlay.font = g_strdup(font);
1430 gtk_widget_destroy(dialog);
1434 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1435 c_options->image_overlay.font = g_strdup(font);
1439 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1442 #if GTK_CHECK_VERSION(3,4,0)
1445 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1446 colour.red = options->image_overlay.text_red;
1447 colour.green = options->image_overlay.text_green;
1448 colour.blue = options->image_overlay.text_blue;
1449 colour.alpha = options->image_overlay.text_alpha;
1450 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1451 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1453 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1455 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1456 c_options->image_overlay.text_red = colour.red*255;
1457 c_options->image_overlay.text_green = colour.green*255;
1458 c_options->image_overlay.text_blue = colour.blue*255;
1459 c_options->image_overlay.text_alpha = colour.alpha*255;
1461 gtk_widget_destroy(dialog);
1464 GtkColorSelection *colorsel;
1466 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1467 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1468 colour.red = options->image_overlay.text_red*257;
1469 colour.green = options->image_overlay.text_green*257;
1470 colour.blue = options->image_overlay.text_blue*257;
1471 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1472 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1473 gtk_color_selection_set_current_color(colorsel, &colour);
1474 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1476 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1478 gtk_color_selection_get_current_color(colorsel, &colour);
1479 c_options->image_overlay.text_red = colour.red/257;
1480 c_options->image_overlay.text_green = colour.green/257;
1481 c_options->image_overlay.text_blue = colour.blue/257;
1482 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1484 gtk_widget_destroy (dialog);
1489 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1492 #if GTK_CHECK_VERSION(3,4,0)
1495 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1496 colour.red = options->image_overlay.background_red;
1497 colour.green = options->image_overlay.background_green;
1498 colour.blue = options->image_overlay.background_blue;
1499 colour.alpha = options->image_overlay.background_alpha;
1500 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1501 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1503 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1505 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1506 c_options->image_overlay.background_red = colour.red*255;
1507 c_options->image_overlay.background_green = colour.green*255;
1508 c_options->image_overlay.background_blue = colour.blue*255;
1509 c_options->image_overlay.background_alpha = colour.alpha*255;
1511 gtk_widget_destroy(dialog);
1514 GtkColorSelection *colorsel;
1516 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1517 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1518 colour.red = options->image_overlay.background_red*257;
1519 colour.green = options->image_overlay.background_green*257;
1520 colour.blue = options->image_overlay.background_blue*257;
1521 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1522 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1523 gtk_color_selection_set_current_color(colorsel, &colour);
1524 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1526 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1528 gtk_color_selection_get_current_color(colorsel, &colour);
1529 c_options->image_overlay.background_red = colour.red/257;
1530 c_options->image_overlay.background_green = colour.green/257;
1531 c_options->image_overlay.background_blue = colour.blue/257;
1532 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1534 gtk_widget_destroy(dialog);
1538 static void accel_store_populate(void)
1541 GList *groups, *actions;
1543 const gchar *accel_path;
1547 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1549 gtk_tree_store_clear(accel_store);
1550 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1552 g_assert(lw && lw->ui_manager);
1553 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1556 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1559 action = GTK_ACTION(actions->data);
1560 accel_path = gtk_action_get_accel_path(action);
1561 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1563 gchar *label, *label2, *tooltip, *accel;
1564 g_object_get(action,
1565 "tooltip", &tooltip,
1569 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1575 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1579 gtk_tree_store_append(accel_store, &iter, NULL);
1580 gtk_tree_store_set(accel_store, &iter,
1583 AE_TOOLTIP, tooltip ? tooltip : "",
1584 AE_ACCEL, accel_path,
1592 actions = actions->next;
1595 groups = groups->next;
1599 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1604 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1606 gchar *accel1 = data;
1611 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1613 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1614 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1616 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1618 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1619 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1628 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1630 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1634 GtkAccelKey old_key, key;
1635 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1637 gtk_tree_model_get_iter(model, &iter, path);
1638 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1640 /* test if the accelerator can be stored without conflicts*/
1641 gtk_accel_map_lookup_entry(accel_path, &old_key);
1643 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1644 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1645 gtk_accel_map_lookup_entry(accel_path, &key);
1647 /* restore the original for now, the key will be really changed when the changes are confirmed */
1648 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1650 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1651 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1653 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1654 gtk_tree_path_free(path);
1658 static gboolean accel_default_scroll(GtkTreeView *data)
1662 GtkTreeViewColumn *column;
1664 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1665 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1666 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1668 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1672 gtk_tree_path_free(path);
1677 static void accel_default_cb(GtkWidget *widget, gpointer data)
1679 accel_store_populate();
1681 g_idle_add((GSourceFunc)accel_default_scroll, data);
1684 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1686 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1689 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1692 gchar *accel_path, *accel;
1694 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1695 gtk_accel_map_lookup_entry(accel_path, &key);
1696 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1698 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1700 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1705 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1707 GtkTreeSelection *selection;
1709 if (!accel_store) return;
1710 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1711 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1716 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1720 GtkWidget *scrolled;
1721 GtkWidget *viewport;
1723 scrolled = gtk_scrolled_window_new(NULL, NULL);
1724 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1725 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1726 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1727 label = gtk_label_new(title);
1728 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1729 gtk_widget_show(scrolled);
1731 viewport = gtk_viewport_new(NULL, NULL);
1732 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1733 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1734 gtk_widget_show(viewport);
1736 vbox = gtk_vbox_new(FALSE, 0);
1737 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1738 gtk_widget_show(vbox);
1743 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1745 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1747 c_options->thumbnails.spec_standard =TRUE;
1748 c_options->thumbnails.cache_into_dirs = FALSE;
1752 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1754 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1756 c_options->thumbnails.spec_standard =FALSE;
1757 c_options->thumbnails.cache_into_dirs = FALSE;
1761 static void cache_local_cb(GtkWidget *widget, gpointer data)
1763 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1765 c_options->thumbnails.cache_into_dirs = TRUE;
1766 c_options->thumbnails.spec_standard =FALSE;
1770 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1771 GdkEvent *event, gpointer userdata)
1773 if (pos == GTK_ENTRY_ICON_PRIMARY)
1775 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1779 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1783 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1784 GdkEvent *event, gpointer userdata)
1786 gchar *rating_symbol;
1788 if (pos == GTK_ENTRY_ICON_PRIMARY)
1790 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1791 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1792 g_free(rating_symbol);
1796 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1797 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1798 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1802 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1803 GdkEvent *event, gpointer userdata)
1805 gchar *rating_symbol;
1807 if (pos == GTK_ENTRY_ICON_PRIMARY)
1809 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1810 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1811 g_free(rating_symbol);
1815 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1816 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1817 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1821 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1823 GtkContainer *hbox = data;
1824 GString *str = g_string_new(NULL);
1825 GtkEntry *hex_code_entry;
1826 gchar *hex_code_full;
1829 guint64 hex_value = 0;
1831 list = gtk_container_get_children(hbox);
1833 hex_code_entry = g_list_nth_data(list, 2);
1834 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1836 hex_code = g_strsplit(hex_code_full, "+", 2);
1837 if (hex_code[0] && hex_code[1])
1839 hex_value = strtoull(hex_code[1], NULL, 16);
1841 if (!hex_value || hex_value > 0x10FFFF)
1843 hex_value = 0x003F; // Unicode 'Question Mark'
1845 str = g_string_append_unichar(str, (gunichar)hex_value);
1846 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1848 g_strfreev(hex_code);
1849 g_string_free(str, TRUE);
1850 g_free(hex_code_full);
1855 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1857 guint64 star_symbol;
1859 star_symbol = star_rating_symbol_test(widget, data);
1860 c_options->star_rating.star = star_symbol;
1863 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1865 guint64 rejected_symbol;
1867 rejected_symbol = star_rating_symbol_test(widget, data);
1868 c_options->star_rating.rejected = rejected_symbol;
1871 /* general options tab */
1872 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1873 typedef struct _TZData TZData;
1877 GCancellable *cancellable;
1879 GtkWidget *progress;
1881 GFile *timezone_database_gq;
1882 gchar *timezone_database_user;
1885 static void config_tab_general(GtkWidget *notebook)
1890 GtkWidget *group_frame;
1891 GtkWidget *subgroup;
1893 GtkWidget *ct_button;
1896 gint hours, minutes, remainder;
1898 GtkWidget *star_rating_entry;
1900 gchar *rating_symbol;
1903 GNetworkMonitor *net_mon;
1904 GSocketConnectable *geeqie_org;
1905 gboolean internet_available;
1908 vbox = scrolled_notebook_page(notebook, _("General"));
1910 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1912 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1913 add_thumb_size_menu(table, 0, 0, _("Size:"));
1914 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1916 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1917 pref_label_new(hbox, _("Custom size: "));
1918 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1919 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1921 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1922 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1924 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1925 pref_checkbox_link_sensitivity(ct_button, subgroup);
1927 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1928 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1929 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1930 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1931 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1932 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1933 G_CALLBACK(cache_geeqie_cb), NULL);
1935 group_frame = pref_frame_new(subgroup, TRUE,
1936 _("Store thumbnails local to image folder (non-standard)"),
1937 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1938 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1939 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1940 G_CALLBACK(cache_local_cb), NULL);
1942 group_frame = pref_frame_new(subgroup, TRUE,
1943 _("Use standard thumbnail style and cache, shared with other applications"),
1944 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1945 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1946 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1947 G_CALLBACK(cache_standard_cb), NULL);
1949 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1950 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1952 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1954 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1955 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1957 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1958 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1959 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1961 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1962 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1965 pref_spacer(group, PREF_PAD_GROUP);
1967 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1969 c_options->star_rating.star = options->star_rating.star;
1970 c_options->star_rating.rejected = options->star_rating.rejected;
1972 str = g_string_new(NULL);
1973 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1974 pref_label_new(hbox, "Star character: ");
1975 str = g_string_append_unichar(str, options->star_rating.star);
1976 pref_label_new(hbox, g_strdup(str->str));
1977 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1978 star_rating_entry = gtk_entry_new();
1979 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1980 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1981 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1982 gtk_widget_show(star_rating_entry);
1983 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1984 G_CALLBACK(star_rating_star_test_cb), hbox);
1985 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1986 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1987 gtk_widget_show(button);
1988 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."));
1989 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1990 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1991 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1992 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1993 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1994 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1995 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1996 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1997 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1998 G_CALLBACK(star_rating_star_icon_cb),
2001 g_string_free(str, TRUE);
2002 g_free(rating_symbol);
2004 str = g_string_new(NULL);
2005 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2006 pref_label_new(hbox, "Rejected character: ");
2007 str = g_string_append_unichar(str, options->star_rating.rejected);
2008 pref_label_new(hbox, g_strdup(str->str));
2009 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2010 star_rating_entry = gtk_entry_new();
2011 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2012 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2013 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2014 gtk_widget_show(star_rating_entry);
2015 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2016 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2017 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2018 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2019 gtk_widget_show(button);
2020 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."));
2021 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2022 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2023 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2024 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2025 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2026 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2027 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2028 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2029 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2030 G_CALLBACK(star_rating_rejected_icon_cb),
2033 g_string_free(str, TRUE);
2034 g_free(rating_symbol);
2036 pref_spacer(group, PREF_PAD_GROUP);
2038 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2040 c_options->slideshow.delay = options->slideshow.delay;
2041 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2042 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2043 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2044 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2045 SLIDESHOW_SUBSECOND_PRECISION;
2047 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2049 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2051 options->slideshow.delay ? hours : 0.0,
2052 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2053 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2054 spin = pref_spin_new(hbox, ":" , NULL,
2056 options->slideshow.delay ? minutes: 0.0,
2057 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2058 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2059 spin = pref_spin_new(hbox, ":", NULL,
2060 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2061 options->slideshow.delay ? seconds : 10.0,
2062 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2063 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2065 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2066 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2068 pref_spacer(group, PREF_PAD_GROUP);
2070 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2072 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2073 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2074 pref_checkbox_new_int(group, _("Preload next image"),
2075 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2077 pref_checkbox_new_int(group, _("Refresh on file change"),
2078 options->update_on_time_change, &c_options->update_on_time_change);
2081 pref_spacer(group, PREF_PAD_GROUP);
2083 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2085 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2086 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2087 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2089 pref_spacer(group, PREF_PAD_GROUP);
2091 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2092 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2093 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2094 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2096 options->info_keywords.height, &c_options->info_keywords.height);
2097 pref_spin_new_int(hbox, _("Title:"), NULL,
2099 options->info_title.height, &c_options->info_title.height);
2100 pref_spin_new_int(hbox, _("Comment:"), NULL,
2102 options->info_comment.height, &c_options->info_comment.height);
2103 pref_spin_new_int(hbox, _("Rating:"), NULL,
2105 options->info_rating.height, &c_options->info_rating.height);
2107 pref_spacer(group, PREF_PAD_GROUP);
2109 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2111 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2112 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2114 pref_spacer(group, PREF_PAD_GROUP);
2116 net_mon = g_network_monitor_get_default();
2117 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2118 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2119 g_object_unref(geeqie_org);
2121 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2122 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2124 if (!internet_available)
2126 gtk_widget_set_sensitive(group, FALSE);
2129 tz = g_new0(TZData, 1);
2131 path = path_from_utf8(TIMEZONE_DATABASE);
2132 basename = g_path_get_basename(path);
2133 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2137 if (isfile(tz->timezone_database_user))
2139 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2143 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2146 if (!internet_available)
2148 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"));
2152 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"));
2154 gtk_widget_show(button);
2156 pref_spacer(group, PREF_PAD_GROUP);
2158 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2160 help_search_engine_entry = gtk_entry_new();
2161 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2162 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2163 gtk_widget_show(help_search_engine_entry);
2165 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"));
2167 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2168 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2169 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2170 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2171 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2172 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2173 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2174 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2175 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2176 G_CALLBACK(help_search_engine_entry_icon_cb),
2177 help_search_engine_entry);
2181 static void config_tab_image(GtkWidget *notebook)
2186 GtkWidget *ct_button;
2187 GtkWidget *enlargement_button;
2190 GtkWidget *two_pass;
2191 GtkWidget *gpu_accel;
2193 vbox = scrolled_notebook_page(notebook, _("Image"));
2195 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2197 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2198 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2199 if (options->image.use_clutter_renderer)
2201 gtk_widget_set_sensitive(table, FALSE);
2205 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2206 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2207 if (options->disable_gpu && !options->override_disable_gpu)
2209 gtk_widget_set_sensitive(gpu_accel, FALSE);
2213 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2214 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2215 if (options->image.use_clutter_renderer)
2217 gtk_widget_set_sensitive(two_pass, FALSE);
2220 c_options->image.zoom_increment = options->image.zoom_increment;
2221 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2222 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2223 G_CALLBACK(zoom_increment_cb), NULL);
2224 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2226 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2228 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2229 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2230 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2231 spin = pref_spin_new_int(hbox, NULL, NULL,
2233 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2234 pref_checkbox_link_sensitivity(enlargement_button, spin);
2235 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."));
2237 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2238 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2239 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2240 spin = pref_spin_new_int(hbox, NULL, NULL,
2242 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2243 pref_checkbox_link_sensitivity(ct_button, spin);
2244 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."));
2246 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2248 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2249 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2251 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2252 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2254 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2255 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2257 c_options->image.border_color = options->image.border_color;
2259 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2260 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2262 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2263 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2265 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2266 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2268 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2270 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2271 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2275 static void config_tab_windows(GtkWidget *notebook)
2281 GtkWidget *ct_button;
2284 vbox = scrolled_notebook_page(notebook, _("Windows"));
2286 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2288 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2289 options->save_window_positions, &c_options->save_window_positions);
2291 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2292 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2293 pref_checkbox_link_sensitivity(ct_button, button);
2295 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2296 options->tools_restore_state, &c_options->tools_restore_state);
2298 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2299 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2301 pref_checkbox_new_int(group, _("Show window IDs"),
2302 options->show_window_ids, &c_options->show_window_ids);
2304 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2306 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2307 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2309 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2310 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2311 options->image.limit_window_size, &c_options->image.limit_window_size);
2312 spin = pref_spin_new_int(hbox, NULL, NULL,
2314 options->image.max_window_size, &c_options->image.max_window_size);
2315 pref_checkbox_link_sensitivity(ct_button, spin);
2317 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2319 c_options->fullscreen.screen = options->fullscreen.screen;
2320 c_options->fullscreen.above = options->fullscreen.above;
2321 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2322 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2323 gtk_widget_show(hbox);
2325 pref_checkbox_new_int(group, _("Smooth image flip"),
2326 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2327 pref_checkbox_new_int(group, _("Disable screen saver"),
2328 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2331 #define PRE_FORMATTED_COLUMNS 5
2332 static void config_tab_osd(GtkWidget *notebook)
2338 GtkWidget *image_overlay_template_view;
2339 GtkWidget *scrolled;
2340 GtkWidget *scrolled_pre_formatted;
2341 GtkTextBuffer *buffer;
2343 GtkWidget *subgroup;
2345 vbox = scrolled_notebook_page(notebook, _("OSD"));
2347 image_overlay_template_view = gtk_text_view_new();
2349 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2351 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2353 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2354 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2355 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2356 gtk_widget_show(scrolled_pre_formatted);
2357 gtk_widget_show(subgroup);
2359 pref_line(group, PREF_PAD_GAP);
2361 pref_label_new(group, _("Image overlay template"));
2363 scrolled = gtk_scrolled_window_new(NULL, NULL);
2364 gtk_widget_set_size_request(scrolled, 200, 150);
2365 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2366 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2367 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2368 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2369 gtk_widget_show(scrolled);
2371 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2372 _("Extensive formatting options are shown in the Help file"));
2374 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2375 gtk_widget_show(image_overlay_template_view);
2377 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2379 #if GTK_CHECK_VERSION(3,4,0)
2380 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2381 G_CALLBACK(image_overlay_set_font_cb), notebook);
2383 button = gtk_font_button_new();
2384 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2385 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2386 g_signal_connect(G_OBJECT(button), "font-set",
2387 G_CALLBACK(image_overlay_set_font_cb),NULL);
2389 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2390 gtk_widget_show(button);
2392 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2393 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2394 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2395 gtk_widget_show(button);
2397 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2398 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2399 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2400 gtk_widget_show(button);
2401 image_overlay_set_text_colours();
2403 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2404 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2405 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2406 gtk_widget_show(button);
2408 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2409 G_CALLBACK(image_overlay_help_cb), NULL);
2410 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2411 gtk_widget_show(button);
2413 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2414 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2415 g_signal_connect(G_OBJECT(buffer), "changed",
2416 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2418 pref_line(group, PREF_PAD_GAP);
2420 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2421 hbox = gtk_hbox_new(FALSE, 0);
2422 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2423 gtk_widget_show(hbox);
2424 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2425 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2426 gtk_widget_show(label);
2427 pref_spacer(group,TRUE);
2429 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2430 hbox = gtk_hbox_new(FALSE, 0);
2431 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2432 gtk_widget_show(hbox);
2433 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2434 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2435 gtk_widget_show(label);
2436 pref_spacer(group,TRUE);
2438 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2439 hbox = gtk_hbox_new(FALSE, 0);
2440 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2441 gtk_widget_show(hbox);
2442 label = gtk_label_new(_("%path:39%"));
2443 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2444 gtk_widget_show(label);
2445 pref_spacer(group,TRUE);
2447 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2448 hbox = gtk_hbox_new(FALSE, 0);
2449 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2450 gtk_widget_show(hbox);
2451 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%"));
2452 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2453 gtk_widget_show(label);
2454 pref_spacer(group,TRUE);
2456 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2457 hbox = gtk_hbox_new(FALSE, 0);
2458 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2459 gtk_widget_show(hbox);
2460 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2461 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2462 gtk_widget_show(label);
2465 static GtkTreeModel *create_class_model(void)
2467 GtkListStore *model;
2471 /* create list store */
2472 model = gtk_list_store_new(1, G_TYPE_STRING);
2473 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2475 gtk_list_store_append(model, &iter);
2476 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2478 return GTK_TREE_MODEL (model);
2483 static void config_tab_files(GtkWidget *notebook)
2490 GtkWidget *ct_button;
2491 GtkWidget *scrolled;
2492 GtkWidget *filter_view;
2493 GtkCellRenderer *renderer;
2494 GtkTreeSelection *selection;
2495 GtkTreeViewColumn *column;
2497 vbox = scrolled_notebook_page(notebook, _("Files"));
2499 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2501 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2502 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2503 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2504 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2505 pref_checkbox_new_int(group, _("Case sensitive sort"),
2506 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2507 pref_checkbox_new_int(group, _("Natural sort order"),
2508 options->file_sort.natural, &c_options->file_sort.natural);
2509 pref_checkbox_new_int(group, _("Disable file extension checks"),
2510 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2512 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2513 options->file_filter.disable, &c_options->file_filter.disable);
2516 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2518 sidecar_ext_entry = gtk_entry_new();
2519 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2520 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2521 gtk_widget_show(sidecar_ext_entry);
2523 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2525 frame = pref_group_parent(group);
2526 g_signal_connect(G_OBJECT(ct_button), "toggled",
2527 G_CALLBACK(filter_disable_cb), frame);
2528 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2530 scrolled = gtk_scrolled_window_new(NULL, NULL);
2531 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2532 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2533 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2534 gtk_widget_show(scrolled);
2536 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2537 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2538 g_object_unref(filter_store);
2539 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2540 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2542 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2544 column = gtk_tree_view_column_new();
2545 gtk_tree_view_column_set_title(column, _("Filter"));
2546 gtk_tree_view_column_set_resizable(column, TRUE);
2548 renderer = gtk_cell_renderer_toggle_new();
2549 g_signal_connect(G_OBJECT(renderer), "toggled",
2550 G_CALLBACK(filter_store_enable_cb), filter_store);
2551 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2552 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2553 GINT_TO_POINTER(FE_ENABLE), NULL);
2555 renderer = gtk_cell_renderer_text_new();
2556 g_signal_connect(G_OBJECT(renderer), "edited",
2557 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2558 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2559 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2560 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2561 GINT_TO_POINTER(FE_EXTENSION), NULL);
2562 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2564 column = gtk_tree_view_column_new();
2565 gtk_tree_view_column_set_title(column, _("Description"));
2566 gtk_tree_view_column_set_resizable(column, TRUE);
2567 gtk_tree_view_column_set_fixed_width(column, 200);
2568 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2570 renderer = gtk_cell_renderer_text_new();
2571 g_signal_connect(G_OBJECT(renderer), "edited",
2572 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2573 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2574 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2575 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2576 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2577 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2579 column = gtk_tree_view_column_new();
2580 gtk_tree_view_column_set_title(column, _("Class"));
2581 gtk_tree_view_column_set_resizable(column, TRUE);
2582 renderer = gtk_cell_renderer_combo_new();
2583 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2584 "model", create_class_model(),
2589 g_signal_connect(G_OBJECT(renderer), "edited",
2590 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2591 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2592 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2593 GINT_TO_POINTER(FE_CLASS), NULL);
2594 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2596 column = gtk_tree_view_column_new();
2597 gtk_tree_view_column_set_title(column, _("Writable"));
2598 gtk_tree_view_column_set_resizable(column, FALSE);
2599 renderer = gtk_cell_renderer_toggle_new();
2600 g_signal_connect(G_OBJECT(renderer), "toggled",
2601 G_CALLBACK(filter_store_writable_cb), filter_store);
2602 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2603 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2604 GINT_TO_POINTER(FE_WRITABLE), NULL);
2605 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2607 column = gtk_tree_view_column_new();
2608 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2609 gtk_tree_view_column_set_resizable(column, FALSE);
2610 renderer = gtk_cell_renderer_toggle_new();
2611 g_signal_connect(G_OBJECT(renderer), "toggled",
2612 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2613 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2614 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2615 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2616 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2619 filter_store_populate();
2620 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2621 gtk_widget_show(filter_view);
2623 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2625 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2626 G_CALLBACK(filter_default_cb), filter_view);
2627 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2628 gtk_widget_show(button);
2630 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2631 G_CALLBACK(filter_remove_cb), filter_view);
2632 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2633 gtk_widget_show(button);
2635 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2636 G_CALLBACK(filter_add_cb), filter_view);
2637 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2638 gtk_widget_show(button);
2642 static void config_tab_metadata(GtkWidget *notebook)
2647 GtkWidget *ct_button;
2651 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2654 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2656 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2658 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2659 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2661 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2662 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2664 gtk_widget_set_sensitive(ct_button, FALSE);
2667 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2668 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2670 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2671 label = pref_label_new(group, text);
2672 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2673 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2676 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2678 gtk_widget_set_sensitive(group, FALSE);
2681 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2682 pref_checkbox_link_sensitivity(ct_button, hbox);
2684 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2685 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2687 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2688 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2690 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2691 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2693 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2694 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2696 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2698 gtk_widget_set_sensitive(group, FALSE);
2701 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2702 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2705 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2706 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2707 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2709 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2710 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2712 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2713 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2715 gtk_widget_set_sensitive(ct_button, FALSE);
2718 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2720 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2721 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2723 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2724 pref_checkbox_link_sensitivity(ct_button, hbox);
2726 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2727 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2729 pref_checkbox_new_int(group, _("Write metadata on image change"),
2730 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2732 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2733 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2735 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2737 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2738 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2739 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");
2744 typedef struct _KeywordFindData KeywordFindData;
2745 struct _KeywordFindData
2752 GtkWidget *button_close;
2753 GtkWidget *button_stop;
2754 GtkWidget *button_start;
2755 GtkWidget *progress;
2763 guint idle_id; /* event source id */
2766 #define KEYWORD_DIALOG_WIDTH 400
2768 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2770 GList *list_d = NULL;
2771 GList *list_f = NULL;
2775 filelist_read(dir_fd, &list_f, &list_d);
2779 filelist_read(dir_fd, &list_f, NULL);
2782 list_f = filelist_filter(list_f, FALSE);
2783 list_d = filelist_filter(list_d, TRUE);
2785 kfd->list = g_list_concat(list_f, kfd->list);
2786 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2789 static void keywords_find_reset(KeywordFindData *kfd)
2791 filelist_free(kfd->list);
2794 filelist_free(kfd->list_dir);
2795 kfd->list_dir = NULL;
2798 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2800 KeywordFindData *kfd = data;
2802 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2804 keywords_find_reset(kfd);
2805 generic_dialog_close(kfd->gd);
2809 static void keywords_find_finish(KeywordFindData *kfd)
2811 keywords_find_reset(kfd);
2813 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2814 spinner_set_interval(kfd->spinner, -1);
2816 gtk_widget_set_sensitive(kfd->group, TRUE);
2817 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2818 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2819 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2822 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2824 KeywordFindData *kfd = data;
2826 g_idle_remove_by_data(kfd);
2828 keywords_find_finish(kfd);
2831 static gboolean keywords_find_file(gpointer data)
2833 KeywordFindData *kfd = data;
2835 GtkTextBuffer *buffer;
2843 fd = kfd->list->data;
2844 kfd->list = g_list_remove(kfd->list, fd);
2846 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2847 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2851 gtk_text_buffer_get_end_iter(buffer, &iter);
2852 tmp = g_strconcat(keywords->data, "\n", NULL);
2853 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2855 keywords = keywords->next;
2858 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2859 file_data_unref(fd);
2860 string_list_free(keywords);
2864 else if (kfd->list_dir)
2868 fd = kfd->list_dir->data;
2869 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2871 keywords_find_folder(kfd, fd);
2873 file_data_unref(fd);
2878 keywords_find_finish(kfd);
2883 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2885 KeywordFindData *kfd = data;
2888 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2890 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2891 parse_out_relatives(path);
2895 warning_dialog(_("Invalid folder"),
2896 _("The specified folder can not be found."),
2897 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2903 gtk_widget_set_sensitive(kfd->group, FALSE);
2904 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2905 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2906 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2907 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2909 dir_fd = file_data_new_dir(path);
2910 keywords_find_folder(kfd, dir_fd);
2911 file_data_unref(dir_fd);
2912 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2918 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2920 KeywordFindData *kfd;
2924 kfd = g_new0(KeywordFindData, 1);
2926 kfd->gd = generic_dialog_new(_("Search for keywords"),
2927 "search_for_keywords",
2930 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2931 kfd->gd->cancel_cb = keywords_find_close_cb;
2932 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2933 keywords_find_close_cb, FALSE);
2934 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2935 keywords_find_start_cb, FALSE);
2936 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2937 keywords_find_stop_cb, FALSE);
2938 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2940 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2942 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2943 pref_spacer(hbox, PREF_PAD_INDENT);
2944 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2946 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2947 pref_label_new(hbox, _("Folder:"));
2949 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2950 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2951 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2952 gtk_widget_show(label);
2954 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2956 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2957 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2959 kfd->progress = gtk_entry_new();
2960 gtk_widget_set_can_focus(kfd->progress, FALSE);
2961 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2962 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2963 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2964 gtk_widget_show(kfd->progress);
2966 kfd->spinner = spinner_new(NULL, -1);
2967 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2968 gtk_widget_show(kfd->spinner);
2972 gtk_widget_show(kfd->gd->dialog);
2975 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2977 const gchar *path = layout_get_path(NULL);
2979 if (!path || !*path) path = homedir();
2980 keywords_find_dialog(widget, path);
2983 static void config_tab_keywords_save()
2985 GtkTextIter start, end;
2986 GtkTextBuffer *buffer;
2987 GList *kw_list = NULL;
2993 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2994 gtk_text_buffer_get_bounds(buffer, &start, &end);
2996 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2998 kw_split = strtok(buffer_text, "\n");
2999 while (kw_split != NULL)
3005 if (g_strcmp0(work->data, kw_split) == 0)
3014 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3016 kw_split = strtok(NULL, "\n");
3019 keyword_list_set(kw_list);
3021 string_list_free(kw_list);
3022 g_free(buffer_text);
3025 static void config_tab_keywords(GtkWidget *notebook)
3031 GtkWidget *scrolled;
3033 GtkTextBuffer *buffer;
3036 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3038 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3040 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3042 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3043 G_CALLBACK(keywords_find_cb), keyword_text);
3044 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3047 keyword_text = gtk_text_view_new();
3048 gtk_widget_set_size_request(keyword_text, 20, 20);
3049 scrolled = gtk_scrolled_window_new(NULL, NULL);
3050 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3051 gtk_widget_show(scrolled);
3053 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3054 gtk_widget_show(keyword_text);
3056 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3058 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3059 gtk_text_buffer_create_tag(buffer, "monospace",
3060 "family", "monospace", NULL);
3062 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3063 gtk_text_buffer_get_start_iter(buffer, &iter);
3064 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3067 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3069 GList *kwl = keyword_list_get();
3070 kwl = g_list_first(kwl);
3073 gtk_text_buffer_get_end_iter (buffer, &iter);
3074 tmp = g_strconcat(kwl->data, "\n", NULL);
3075 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3080 gtk_text_buffer_set_modified(buffer, FALSE);
3087 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3089 gint *option = data;
3091 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3095 *option = INTENT_PERCEPTUAL;
3098 *option = INTENT_RELATIVE_COLORIMETRIC;
3101 *option = INTENT_SATURATION;
3104 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3109 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3110 gint option, gint *option_c)
3117 pref_table_label(table, column, row, text, 0.0);
3119 combo = gtk_combo_box_text_new();
3121 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3122 if (option == INTENT_PERCEPTUAL) current = 0;
3123 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3124 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3125 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3126 if (option == INTENT_SATURATION) current = 2;
3127 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3128 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3130 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3132 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3134 g_signal_connect(G_OBJECT(combo), "changed",
3135 G_CALLBACK(intent_menu_cb), option_c);
3137 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3138 gtk_widget_show(combo);
3142 static void config_tab_color(GtkWidget *notebook)
3151 vbox = scrolled_notebook_page(notebook, _("Color management"));
3153 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3155 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3158 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3159 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3161 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3162 pref_label_bold(label, TRUE, FALSE);
3164 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3165 pref_label_bold(label, TRUE, FALSE);
3167 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3168 pref_label_bold(label, TRUE, FALSE);
3170 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3175 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3176 pref_table_label(table, 0, i + 1, buf, 1.0);
3179 entry = gtk_entry_new();
3180 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3181 if (options->color_profile.input_name[i])
3183 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3185 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3186 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3187 gtk_widget_show(entry);
3188 color_profile_input_name_entry[i] = entry;
3190 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3191 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3192 gtk_widget_set_size_request(entry, 160, -1);
3193 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3194 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3195 gtk_widget_show(tabcomp);
3196 color_profile_input_file_entry[i] = entry;
3199 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3201 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3203 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3204 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3206 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3208 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3209 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3210 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3211 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3212 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3214 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3216 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3218 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3220 gtk_widget_show(tabcomp);
3223 /* advanced entry tab */
3224 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3226 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3228 c_options->file_ops.use_system_trash = FALSE;
3229 c_options->file_ops.no_trash = FALSE;
3233 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3235 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3237 c_options->file_ops.use_system_trash = TRUE;
3238 c_options->file_ops.no_trash = FALSE;
3242 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3244 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3246 c_options->file_ops.no_trash = TRUE;
3250 static void config_tab_behavior(GtkWidget *notebook)
3257 GtkWidget *ct_button;
3261 GtkWidget *with_rename;
3262 GtkWidget *collections_on_top;
3263 GtkWidget *checkbox;
3265 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3267 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3269 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3270 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3271 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3272 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3273 pref_checkbox_new_int(group, _("Enable Delete key"),
3274 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3276 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3277 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3279 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3280 pref_checkbox_link_sensitivity(ct_button, hbox);
3282 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3283 pref_label_new(hbox, _("Folder:"));
3285 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3286 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3287 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3288 gtk_widget_show(tabcomp);
3290 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3291 pref_checkbox_link_sensitivity(ct_button, hbox);
3293 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3294 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3295 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3296 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3297 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3298 G_CALLBACK(safe_delete_view_cb), NULL);
3299 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3300 gtk_widget_show(button);
3302 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3303 G_CALLBACK(safe_delete_clear_cb), NULL);
3304 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3305 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3306 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3308 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3309 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3311 gtk_widget_show(button);
3313 pref_spacer(group, PREF_PAD_GROUP);
3316 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3318 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3319 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3321 pref_checkbox_new_int(group, _("In place renaming"),
3322 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3324 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3325 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3327 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3328 options->marks_save, &c_options->marks_save);
3329 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3331 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3332 options->with_rename, &c_options->with_rename);
3333 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3335 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3336 options->collections_on_top, &c_options->collections_on_top);
3337 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3339 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3340 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3342 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3343 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3345 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3346 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3348 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3349 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3351 pref_spacer(group, PREF_PAD_GROUP);
3353 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3355 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3356 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3357 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3358 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3359 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3360 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3361 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3362 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3363 pref_checkbox_new_int(group, _("Play video by left click on image"),
3364 options->image_l_click_video, &c_options->image_l_click_video);
3365 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3366 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3368 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3369 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3370 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3371 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3372 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3374 pref_spacer(group, PREF_PAD_GROUP);
3376 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3378 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3379 options->override_disable_gpu, &c_options->override_disable_gpu);
3380 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3383 pref_spacer(group, PREF_PAD_GROUP);
3385 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3387 pref_spin_new_int(group, _("Debug level:"), NULL,
3388 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3390 pref_checkbox_new_int(group, _("Timer data"),
3391 options->log_window.timer_data, &c_options->log_window.timer_data);
3393 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3394 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3398 /* accelerators tab */
3399 static void config_tab_accelerators(GtkWidget *notebook)
3405 GtkWidget *scrolled;
3406 GtkWidget *accel_view;
3407 GtkCellRenderer *renderer;
3408 GtkTreeSelection *selection;
3409 GtkTreeViewColumn *column;
3411 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3413 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3415 scrolled = gtk_scrolled_window_new(NULL, NULL);
3416 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3417 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3418 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3419 gtk_widget_show(scrolled);
3421 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3423 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3424 g_object_unref(accel_store);
3425 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3426 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3428 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3430 renderer = gtk_cell_renderer_text_new();
3432 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3437 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3438 gtk_tree_view_column_set_resizable(column, TRUE);
3439 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3442 renderer = gtk_cell_renderer_accel_new();
3443 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3444 G_CALLBACK(accel_store_cleared_cb), accel_store);
3445 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3446 G_CALLBACK(accel_store_edited_cb), accel_store);
3449 g_object_set (renderer,
3451 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3454 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3459 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3460 gtk_tree_view_column_set_resizable(column, TRUE);
3461 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3463 renderer = gtk_cell_renderer_text_new();
3465 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3470 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3471 gtk_tree_view_column_set_resizable(column, TRUE);
3472 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3474 renderer = gtk_cell_renderer_text_new();
3476 column = gtk_tree_view_column_new_with_attributes("Accel",
3481 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3482 gtk_tree_view_column_set_resizable(column, TRUE);
3483 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3485 accel_store_populate();
3486 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3487 gtk_widget_show(accel_view);
3489 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3491 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3492 G_CALLBACK(accel_default_cb), accel_view);
3493 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3494 gtk_widget_show(button);
3496 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3497 G_CALLBACK(accel_reset_cb), accel_view);
3498 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3499 gtk_widget_show(button);
3502 /* toolbar main tab */
3503 static void config_tab_toolbar_main(GtkWidget *notebook)
3506 GtkWidget *toolbardata;
3509 lw = layout_window_list->data;
3511 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3513 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3514 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3515 gtk_widget_show(vbox);
3518 /* toolbar status tab */
3519 static void config_tab_toolbar_status(GtkWidget *notebook)
3522 GtkWidget *toolbardata;
3525 lw = layout_window_list->data;
3527 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3529 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3530 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3531 gtk_widget_show(vbox);
3535 static void config_tab_stereo(GtkWidget *notebook)
3543 GtkWidget *fs_button;
3544 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3546 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3548 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3549 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3551 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3552 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3553 pref_checkbox_new_int(box, _("Mirror left image"),
3554 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3555 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3556 pref_checkbox_new_int(box, _("Flip left image"),
3557 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3558 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3559 pref_checkbox_new_int(box, _("Mirror right image"),
3560 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3561 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3562 pref_checkbox_new_int(box, _("Flip right image"),
3563 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3564 pref_checkbox_new_int(group, _("Swap left and right images"),
3565 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3566 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3567 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3569 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3570 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3571 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3572 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3573 pref_checkbox_link_sensitivity(fs_button, box2);
3574 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3575 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3576 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3577 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3578 pref_checkbox_new_int(box, _("Mirror left image"),
3579 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3580 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3581 pref_checkbox_new_int(box, _("Flip left image"),
3582 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3583 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3584 pref_checkbox_new_int(box, _("Mirror right image"),
3585 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3586 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3587 pref_checkbox_new_int(box, _("Flip right image"),
3588 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3589 pref_checkbox_new_int(box2, _("Swap left and right images"),
3590 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3591 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3592 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3594 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3595 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3596 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3597 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3598 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3599 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3600 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3601 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3602 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3603 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3604 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3605 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3606 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3607 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3611 /* Main preferences window */
3612 static void config_window_create(void)
3614 GtkWidget *win_vbox;
3616 GtkWidget *notebook;
3618 GtkWidget *ct_button;
3620 if (!c_options) c_options = init_options(NULL);
3622 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3623 DEBUG_NAME(configwindow);
3624 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3625 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3626 G_CALLBACK(config_window_delete), NULL);
3627 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3628 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3629 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3631 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3632 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3633 gtk_widget_show(win_vbox);
3635 notebook = gtk_notebook_new();
3636 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3637 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3638 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3640 config_tab_general(notebook);
3641 config_tab_image(notebook);
3642 config_tab_osd(notebook);
3643 config_tab_windows(notebook);
3644 config_tab_accelerators(notebook);
3645 config_tab_files(notebook);
3646 config_tab_metadata(notebook);
3647 config_tab_keywords(notebook);
3648 config_tab_color(notebook);
3649 config_tab_stereo(notebook);
3650 config_tab_behavior(notebook);
3651 config_tab_toolbar_main(notebook);
3652 config_tab_toolbar_status(notebook);
3654 hbox = gtk_hbutton_box_new();
3655 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3656 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3657 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3658 gtk_widget_show(hbox);
3660 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3661 G_CALLBACK(config_window_help_cb), notebook);
3662 gtk_container_add(GTK_CONTAINER(hbox), button);
3663 gtk_widget_set_can_default(button, TRUE);
3664 gtk_widget_show(button);
3666 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3667 G_CALLBACK(config_window_ok_cb), NULL);
3668 gtk_container_add(GTK_CONTAINER(hbox), button);
3669 gtk_widget_set_can_default(button, TRUE);
3670 gtk_widget_grab_default(button);
3671 gtk_widget_show(button);
3675 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3676 G_CALLBACK(config_window_close_cb), NULL);
3677 gtk_container_add(GTK_CONTAINER(hbox), button);
3678 gtk_widget_set_can_default(button, TRUE);
3679 gtk_widget_show(button);
3681 if (!generic_dialog_get_alternative_button_order(configwindow))
3683 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3686 gtk_widget_show(notebook);
3688 gtk_widget_show(configwindow);
3692 *-----------------------------------------------------------------------------
3693 * config window show (public)
3694 *-----------------------------------------------------------------------------
3697 void show_config_window(void)
3701 gtk_window_present(GTK_WINDOW(configwindow));
3705 config_window_create();
3714 void show_about_window(LayoutWindow *lw)
3716 GdkPixbuf *pixbuf_logo;
3717 GdkPixbuf *pixbuf_icon;
3718 gchar *authors[1000];
3723 gchar *timezone_path;
3727 #define LINE_LENGTH 1000
3728 gchar line[LINE_LENGTH];
3730 copyright = g_string_new(NULL);
3731 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");
3733 path = path_from_utf8(TIMEZONE_DATABASE);
3734 basename = g_path_get_basename(path);
3735 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3736 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3738 cd = ZDOpenDatabase(timezone_path);
3741 copyright = g_string_append(copyright, ZDGetNotice(cd));
3742 ZDCloseDatabase(cd);
3746 g_free(timezone_path);
3750 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3751 fp = fopen(path, "r");
3754 while(fgets(line, LINE_LENGTH, fp))
3756 /* get rid of ending \n from fgets */
3757 line[strlen(line) - 1] = '\0';
3758 authors[i_authors] = g_strdup(line);
3761 authors[i_authors] = NULL;
3766 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3767 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3769 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3770 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3771 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3772 "title", _("About Geeqie"),
3774 "program-name", GQ_APPNAME,
3776 "logo", pixbuf_logo,
3777 "icon", pixbuf_icon,
3778 "website", GQ_WEBSITE,
3779 "website-label", "Website",
3780 "comments", comment,
3782 "translator-credits", _("translator-credits"),
3783 "wrap-license", TRUE,
3784 "license", copyright->str,
3787 g_string_free(copyright, TRUE);
3790 while(n < i_authors)
3800 static void image_overlay_set_text_colours()
3802 c_options->image_overlay.text_red = options->image_overlay.text_red;
3803 c_options->image_overlay.text_green = options->image_overlay.text_green;
3804 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3805 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3806 c_options->image_overlay.background_red = options->image_overlay.background_red;
3807 c_options->image_overlay.background_green = options->image_overlay.background_green;
3808 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3809 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3813 *-----------------------------------------------------------------------------
3814 * timezone database routines
3815 *-----------------------------------------------------------------------------
3818 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3820 GError *error = NULL;
3822 gchar *tmp_filename;
3824 if (!g_cancellable_is_cancelled(tz->cancellable))
3826 generic_dialog_close(tz->gd);
3830 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3832 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3833 move_file(tmp_filename, tz->timezone_database_user);
3834 g_free(tmp_filename);
3838 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3841 g_file_delete(tz->tmp_g_file, NULL, &error);
3842 g_object_unref(tz->tmp_g_file);
3843 tz->tmp_g_file = NULL;
3844 g_object_unref(tz->cancellable);
3845 g_object_unref(tz->timezone_database_gq);
3848 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3852 if (!g_cancellable_is_cancelled(tz->cancellable))
3854 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3858 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3862 g_cancellable_cancel(tz->cancellable);
3865 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3868 GError *error = NULL;
3869 GFileIOStream *io_stream;
3876 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3880 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3881 log_printf("Error: Download timezone database failed:\n%s", error->message);
3882 g_error_free(error);
3883 g_object_unref(tz->tmp_g_file);
3887 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3889 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3891 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3893 tz->progress = gtk_progress_bar_new();
3894 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3895 gtk_widget_show(tz->progress);
3897 gtk_widget_show(tz->gd->dialog);
3898 tz->cancellable = g_cancellable_new();
3899 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);
3901 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3904 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */