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)
248 gboolean refresh = FALSE;
253 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
255 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
256 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
257 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
258 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
259 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
260 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
261 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
263 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
264 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
265 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
266 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
267 options->file_ops.no_trash = c_options->file_ops.no_trash;
268 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
269 options->tools_restore_state = c_options->tools_restore_state;
270 options->save_window_positions = c_options->save_window_positions;
271 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
272 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
273 options->show_window_ids = c_options->show_window_ids;
274 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
275 options->image.zoom_2pass = c_options->image.zoom_2pass;
276 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
277 options->image.limit_window_size = c_options->image.limit_window_size;
278 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
279 options->image.max_window_size = c_options->image.max_window_size;
280 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
281 options->image.max_autofit_size = c_options->image.max_autofit_size;
282 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
283 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
284 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
285 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
287 if (options->thumbnails.max_width != c_options->thumbnails.max_width
288 || options->thumbnails.max_height != c_options->thumbnails.max_height
289 || options->thumbnails.quality != c_options->thumbnails.quality)
291 thumb_format_changed = TRUE;
293 options->thumbnails.max_width = c_options->thumbnails.max_width;
294 options->thumbnails.max_height = c_options->thumbnails.max_height;
295 options->thumbnails.quality = c_options->thumbnails.quality;
297 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
298 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
299 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
300 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
301 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
302 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
303 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
304 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
305 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
306 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
307 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
308 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
310 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
311 options->file_sort.natural = c_options->file_sort.natural;
312 options->file_filter.disable = c_options->file_filter.disable;
314 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
315 sidecar_ext_parse(options->sidecar.ext);
317 options->slideshow.random = c_options->slideshow.random;
318 options->slideshow.repeat = c_options->slideshow.repeat;
319 options->slideshow.delay = c_options->slideshow.delay;
321 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
322 options->image_lm_click_nav = c_options->image_lm_click_nav;
323 options->image_l_click_video = c_options->image_l_click_video;
324 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
326 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
328 options->image.tile_cache_max = c_options->image.tile_cache_max;
329 options->image.image_cache_max = c_options->image.image_cache_max;
331 options->image.zoom_quality = c_options->image.zoom_quality;
333 options->image.zoom_increment = c_options->image.zoom_increment;
335 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
338 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
339 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
340 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
342 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
343 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
344 options->image.border_color = c_options->image.border_color;
345 layout_colors_update();
346 view_window_colors_update();
349 options->image.alpha_color_1 = c_options->image.alpha_color_1;
350 options->image.alpha_color_2 = c_options->image.alpha_color_2;
352 options->fullscreen.screen = c_options->fullscreen.screen;
353 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
354 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
355 options->fullscreen.above = c_options->fullscreen.above;
356 if (c_options->image_overlay.template_string)
357 set_image_overlay_template_string(&options->image_overlay.template_string,
358 c_options->image_overlay.template_string);
359 if (c_options->image_overlay.font)
360 set_image_overlay_font_string(&options->image_overlay.font,
361 c_options->image_overlay.font);
362 options->image_overlay.text_red = c_options->image_overlay.text_red;
363 options->image_overlay.text_green = c_options->image_overlay.text_green;
364 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
365 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
366 options->image_overlay.background_red = c_options->image_overlay.background_red;
367 options->image_overlay.background_green = c_options->image_overlay.background_green;
368 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
369 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
370 options->update_on_time_change = c_options->update_on_time_change;
371 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
373 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
374 options->rot_invariant_sim = c_options->rot_invariant_sim;
376 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
378 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
380 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
381 options->dnd_icon_size = c_options->dnd_icon_size;
382 options->clipboard_selection = c_options->clipboard_selection;
383 options->dnd_default_action = c_options->dnd_default_action;
385 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
386 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
387 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
388 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
389 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
390 options->metadata.confirm_write = c_options->metadata.confirm_write;
391 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
392 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
393 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
394 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
395 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
396 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
397 options->metadata.write_orientation = c_options->metadata.write_orientation;
398 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
399 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
400 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
401 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
402 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
403 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
404 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
405 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
406 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
407 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
408 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
409 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
410 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
411 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
412 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
413 options->stereo.fixed_w = c_options->stereo.fixed_w;
414 options->stereo.fixed_h = c_options->stereo.fixed_h;
415 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
416 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
417 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
418 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
420 options->info_keywords.height = c_options->info_keywords.height;
421 options->info_title.height = c_options->info_title.height;
422 options->info_comment.height = c_options->info_comment.height;
423 options->info_rating.height = c_options->info_rating.height;
425 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
426 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
428 options->marks_save = c_options->marks_save;
429 options->with_rename = c_options->with_rename;
430 options->collections_on_top = c_options->collections_on_top;
431 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
433 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
435 options->star_rating.star = c_options->star_rating.star;
436 options->star_rating.rejected = c_options->star_rating.rejected;
438 set_debug_level(debug_c);
442 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
444 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
445 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
447 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
448 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
449 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
451 options->color_profile.render_intent = c_options->color_profile.render_intent;
456 options->mouse_button_8 = c_options->mouse_button_8;
457 options->mouse_button_9 = c_options->mouse_button_9;
459 options->override_disable_gpu = c_options->override_disable_gpu;
461 config_tab_keywords_save();
463 image_options_sync();
468 layout_refresh(NULL);
471 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
473 toolbar_apply(TOOLBAR_MAIN);
474 toolbar_apply(TOOLBAR_STATUS);
478 *-----------------------------------------------------------------------------
479 * config window main button callbacks (private)
480 *-----------------------------------------------------------------------------
483 static void config_window_close_cb(GtkWidget *widget, gpointer data)
485 gtk_widget_destroy(configwindow);
490 static void config_window_help_cb(GtkWidget *widget, gpointer data)
492 GtkWidget *notebook = data;
495 static gchar *html_section[] =
497 "GuideOptionsGeneral.html",
498 "GuideOptionsImage.html",
499 "GuideOptionsOSD.html",
500 "GuideOptionsWindow.html",
501 "GuideOptionsKeyboard.html",
502 "GuideOptionsFiltering.html",
503 "GuideOptionsMetadata.html",
504 "GuideOptionsKeywords.html",
505 "GuideOptionsColor.html",
506 "GuideOptionsStereo.html",
507 "GuideOptionsBehavior.html",
508 "GuideOptionsToolbar.html",
509 "GuideOptionsToolbar.html"
512 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
513 help_window_show(html_section[i]);
516 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
518 config_window_close_cb(NULL, NULL);
522 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
525 lw = layout_window_list->data;
527 config_window_apply();
528 layout_util_sync(lw);
529 save_options(options);
530 config_window_close_cb(NULL, NULL);
534 *-----------------------------------------------------------------------------
535 * config window setup (private)
536 *-----------------------------------------------------------------------------
539 static void quality_menu_cb(GtkWidget *combo, gpointer data)
543 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
547 *option = GDK_INTERP_NEAREST;
550 *option = GDK_INTERP_TILES;
553 *option = GDK_INTERP_BILINEAR;
558 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
562 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
566 *option = DND_ACTION_ASK;
569 *option = DND_ACTION_COPY;
572 *option = DND_ACTION_MOVE;
576 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
580 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
592 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
593 guint option, guint *option_c)
600 pref_table_label(table, column, row, text, 0.0);
602 combo = gtk_combo_box_text_new();
604 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
605 if (option == GDK_INTERP_NEAREST) current = 0;
606 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
607 if (option == GDK_INTERP_TILES) current = 1;
608 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
609 if (option == GDK_INTERP_BILINEAR) current = 2;
611 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
613 g_signal_connect(G_OBJECT(combo), "changed",
614 G_CALLBACK(quality_menu_cb), option_c);
616 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
617 gtk_widget_show(combo);
620 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
627 pref_table_label(table, column, row, text, 0.0);
629 combo = gtk_combo_box_text_new();
631 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
632 if (option == DND_ACTION_ASK) current = 0;
633 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
634 if (option == DND_ACTION_COPY) current = 1;
635 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
636 if (option == DND_ACTION_MOVE) current = 2;
638 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
640 g_signal_connect(G_OBJECT(combo), "changed",
641 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
643 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
644 gtk_widget_show(combo);
647 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
648 gint option, gint *option_c)
655 pref_table_label(table, column, row, text, 0.0);
657 combo = gtk_combo_box_text_new();
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
660 if (option == PRIMARY) current = 0;
661 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
662 if (option == CLIPBOARD) current = 1;
664 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
666 g_signal_connect(G_OBJECT(combo), "changed",
667 G_CALLBACK(clipboard_selection_menu_cb), option_c);
669 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
670 gtk_widget_show(combo);
673 typedef struct _UseableMouseItems UseableMouseItems;
674 struct _UseableMouseItems
676 gchar *name; /* GtkActionEntry terminology */
681 static const UseableMouseItems useable_mouse_items[] = {
683 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
684 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
685 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
686 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
687 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
688 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
689 {"Home", N_("Home"), GTK_STOCK_HOME},
690 {"Up", N_("Up"), GTK_STOCK_GO_UP},
691 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
692 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
693 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
694 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
695 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
696 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
697 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
698 {"Search", N_("Search"), GTK_STOCK_FIND},
699 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
700 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
701 {"Copy", N_("Copy"), GTK_STOCK_COPY},
702 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
703 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
704 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
705 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
706 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
707 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
708 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
709 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
710 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
711 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
712 {"Print", N_("Print"), GTK_STOCK_PRINT},
713 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
714 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
715 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
716 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
717 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
718 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
719 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
720 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
721 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
722 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
723 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
724 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
725 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
726 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
727 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
728 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
729 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
730 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
731 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
732 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
733 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
734 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
735 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
736 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
737 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
738 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
739 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
740 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
741 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
742 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
743 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
744 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
745 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
746 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
747 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
748 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
749 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
750 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
751 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
752 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
756 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
758 gchar **option = data;
761 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
763 const UseableMouseItems *list = useable_mouse_items;
767 if (g_strcmp0(list->label, label) == 0)
775 *option = g_strdup(list->name);
779 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
780 gchar *option, gchar **option_c)
788 pref_table_label(table, column, row, text, 0.0);
790 combo = gtk_combo_box_text_new();
792 const UseableMouseItems *list = useable_mouse_items;
796 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
797 if (g_strcmp0(list->name, option) == 0)
805 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
807 g_signal_connect(G_OBJECT(combo), "changed",
808 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
810 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
811 gtk_widget_show(combo);
814 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
818 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
821 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
823 c_options->thumbnails.max_width = thumb_size_list[n].w;
824 c_options->thumbnails.max_height = thumb_size_list[n].h;
828 c_options->thumbnails.max_width = options->thumbnails.max_width;
829 c_options->thumbnails.max_height = options->thumbnails.max_height;
833 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
839 c_options->thumbnails.max_width = options->thumbnails.max_width;
840 c_options->thumbnails.max_height = options->thumbnails.max_height;
842 pref_table_label(table, column, row, text, 0.0);
844 combo = gtk_combo_box_text_new();
847 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
852 w = thumb_size_list[i].w;
853 h = thumb_size_list[i].h;
855 buf = g_strdup_printf("%d x %d", w, h);
856 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
859 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
866 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
867 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
873 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
874 g_signal_connect(G_OBJECT(combo), "changed",
875 G_CALLBACK(thumb_size_menu_cb), NULL);
877 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
878 gtk_widget_show(combo);
881 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
885 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
889 *option = PR_STEREO_NONE;
892 *option = PR_STEREO_ANAGLYPH_RC;
895 *option = PR_STEREO_ANAGLYPH_GM;
898 *option = PR_STEREO_ANAGLYPH_YB;
901 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
904 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
907 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
910 *option = PR_STEREO_ANAGLYPH_DB_RC;
913 *option = PR_STEREO_ANAGLYPH_DB_GM;
916 *option = PR_STEREO_ANAGLYPH_DB_YB;
919 *option = PR_STEREO_HORIZ;
922 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
925 *option = PR_STEREO_VERT;
928 *option = PR_STEREO_VERT | PR_STEREO_HALF;
931 *option = PR_STEREO_FIXED;
936 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
937 gint option, gint *option_c, gboolean add_fixed)
944 pref_table_label(table, column, row, text, 0.0);
946 combo = gtk_combo_box_text_new();
948 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
950 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
951 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
952 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
953 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
954 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
955 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
956 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
957 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
958 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
959 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
960 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
961 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
962 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
963 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
964 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
965 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
966 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
967 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
970 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
971 if (option & PR_STEREO_HORIZ)
974 if (option & PR_STEREO_HALF) current = 11;
977 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
978 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
979 if (option & PR_STEREO_VERT)
982 if (option & PR_STEREO_HALF) current = 13;
987 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
988 if (option & PR_STEREO_FIXED) current = 14;
991 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
993 g_signal_connect(G_OBJECT(combo), "changed",
994 G_CALLBACK(stereo_mode_menu_cb), option_c);
996 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
997 gtk_widget_show(combo);
1000 static void video_menu_cb(GtkWidget *combo, gpointer data)
1002 gchar **option = data;
1004 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1008 static void video_menu_populate(gpointer data, gpointer user_data)
1010 GtkWidget *combo = user_data;
1011 EditorDescription *ed = data;
1013 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1016 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1017 gchar *option, gchar **option_c)
1021 /* use lists since they are sorted */
1022 GList *eds = editor_list_get();
1026 pref_table_label(table, column, row, text, 0.0);
1028 combo = gtk_combo_box_text_new();
1029 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1030 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1032 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1034 g_signal_connect(G_OBJECT(combo), "changed",
1035 G_CALLBACK(video_menu_cb), option_c);
1037 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1038 gtk_widget_show(combo);
1041 static void filter_store_populate(void)
1045 if (!filter_store) return;
1047 gtk_list_store_clear(filter_store);
1049 work = filter_get_list();
1058 gtk_list_store_append(filter_store, &iter);
1059 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1063 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1064 gchar *new_text, gpointer data)
1066 GtkWidget *model = data;
1067 FilterEntry *fe = data;
1071 if (!new_text || strlen(new_text) < 1) return;
1073 tpath = gtk_tree_path_new_from_string(path_str);
1074 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1075 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1077 g_free(fe->extensions);
1078 fe->extensions = g_strdup(new_text);
1080 gtk_tree_path_free(tpath);
1084 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1085 gchar *new_text, gpointer data)
1087 GtkWidget *model = data;
1088 FilterEntry *fe = data;
1093 if (!new_text || !new_text[0]) return;
1095 tpath = gtk_tree_path_new_from_string(path_str);
1096 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1097 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1099 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1101 if (strcmp(new_text, _(format_class_list[i])) == 0)
1108 gtk_tree_path_free(tpath);
1112 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1113 gchar *new_text, gpointer data)
1115 GtkWidget *model = data;
1120 if (!new_text || !new_text[0]) return;
1122 tpath = gtk_tree_path_new_from_string(path_str);
1123 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1124 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1126 g_free(fe->description);
1127 fe->description = g_strdup(new_text);
1129 gtk_tree_path_free(tpath);
1132 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1133 gchar *path_str, gpointer data)
1135 GtkWidget *model = data;
1140 tpath = gtk_tree_path_new_from_string(path_str);
1141 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1142 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1144 fe->enabled = !fe->enabled;
1146 gtk_tree_path_free(tpath);
1150 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1151 gchar *path_str, gpointer data)
1153 GtkWidget *model = data;
1158 tpath = gtk_tree_path_new_from_string(path_str);
1159 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1160 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1162 fe->writable = !fe->writable;
1163 if (fe->writable) fe->allow_sidecar = FALSE;
1165 gtk_tree_path_free(tpath);
1169 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1170 gchar *path_str, gpointer data)
1172 GtkWidget *model = data;
1177 tpath = gtk_tree_path_new_from_string(path_str);
1178 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1179 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1181 fe->allow_sidecar = !fe->allow_sidecar;
1182 if (fe->allow_sidecar) fe->writable = FALSE;
1184 gtk_tree_path_free(tpath);
1188 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1189 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1193 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1195 switch (GPOINTER_TO_INT(data))
1198 g_object_set(GTK_CELL_RENDERER(cell),
1199 "active", fe->enabled, NULL);
1202 g_object_set(GTK_CELL_RENDERER(cell),
1203 "text", fe->extensions, NULL);
1205 case FE_DESCRIPTION:
1206 g_object_set(GTK_CELL_RENDERER(cell),
1207 "text", fe->description, NULL);
1210 g_object_set(GTK_CELL_RENDERER(cell),
1211 "text", _(format_class_list[fe->file_class]), NULL);
1214 g_object_set(GTK_CELL_RENDERER(cell),
1215 "active", fe->writable, NULL);
1217 case FE_ALLOW_SIDECAR:
1218 g_object_set(GTK_CELL_RENDERER(cell),
1219 "active", fe->allow_sidecar, NULL);
1224 static gboolean filter_add_scroll(gpointer data)
1228 GtkCellRenderer *cell;
1229 GtkTreeViewColumn *column;
1232 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1233 path = gtk_tree_path_new_from_indices(rows-1, -1);
1235 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1237 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1238 cell = g_list_last(list_cells)->data;
1240 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1241 path, column, FALSE, 0.0, 0.0 );
1242 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1243 path, column, cell, TRUE);
1245 gtk_tree_path_free(path);
1246 g_list_free(list_cells);
1251 static void filter_add_cb(GtkWidget *widget, gpointer data)
1253 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1254 filter_store_populate();
1256 g_idle_add((GSourceFunc)filter_add_scroll, data);
1259 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1261 GtkWidget *filter_view = data;
1262 GtkTreeSelection *selection;
1266 if (!filter_store) return;
1267 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1268 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1269 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1272 filter_remove_entry(fe);
1274 filter_store_populate();
1277 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1281 GtkTreeViewColumn *column;
1283 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1284 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1285 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1287 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1291 gtk_tree_path_free(path);
1296 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1299 filter_add_defaults();
1301 filter_store_populate();
1303 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1306 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1308 /* no op, only so cancel button appears */
1311 static void filter_default_cb(GtkWidget *widget, gpointer data)
1315 gd = generic_dialog_new(_("Reset filters"),
1316 "reset_filter", widget, TRUE,
1317 dummy_cancel_cb, data);
1318 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1319 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1320 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1321 gtk_widget_show(gd->dialog);
1324 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1326 GtkWidget *frame = data;
1328 gtk_widget_set_sensitive(frame,
1329 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1332 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1334 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1337 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1339 file_util_trash_clear();
1342 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1346 gd = generic_dialog_new(_("Clear trash"),
1347 "clear_trash", widget, TRUE,
1348 dummy_cancel_cb, NULL);
1349 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1350 _("This will remove the trash contents."), FALSE);
1351 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1352 entry = gtk_entry_new();
1353 gtk_widget_set_can_focus(entry, FALSE);
1354 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1355 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1356 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1357 gtk_widget_show(entry);
1358 gtk_widget_show(gd->dialog);
1361 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1363 GtkWidget *pTextView;
1364 GtkTextBuffer *pTextBuffer;
1368 pTextView = GTK_WIDGET(data);
1370 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1371 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1372 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1374 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1375 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1378 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1380 GtkTextView *text_view = data;
1381 GtkTextBuffer *buffer;
1383 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1384 if (!configwindow) return;
1386 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1387 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1390 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1394 gd = generic_dialog_new(_("Reset image overlay template string"),
1395 "reset_image_overlay_template_string", widget, TRUE,
1396 dummy_cancel_cb, data);
1397 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1398 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1399 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1400 gtk_widget_show(gd->dialog);
1403 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1405 help_window_show("GuideOptionsOSD.html");
1408 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1410 #if GTK_CHECK_VERSION(3,4,0)
1413 PangoFontDescription *font_desc;
1415 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1416 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1418 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1420 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1421 font = pango_font_description_to_string(font_desc);
1422 g_free(c_options->image_overlay.font);
1423 c_options->image_overlay.font = g_strdup(font);
1427 gtk_widget_destroy(dialog);
1431 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1432 c_options->image_overlay.font = g_strdup(font);
1436 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1439 #if GTK_CHECK_VERSION(3,4,0)
1442 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1443 colour.red = options->image_overlay.text_red;
1444 colour.green = options->image_overlay.text_green;
1445 colour.blue = options->image_overlay.text_blue;
1446 colour.alpha = options->image_overlay.text_alpha;
1447 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1448 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1450 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1452 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1453 c_options->image_overlay.text_red = colour.red*255;
1454 c_options->image_overlay.text_green = colour.green*255;
1455 c_options->image_overlay.text_blue = colour.blue*255;
1456 c_options->image_overlay.text_alpha = colour.alpha*255;
1458 gtk_widget_destroy(dialog);
1461 GtkColorSelection *colorsel;
1463 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1464 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1465 colour.red = options->image_overlay.text_red*257;
1466 colour.green = options->image_overlay.text_green*257;
1467 colour.blue = options->image_overlay.text_blue*257;
1468 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1469 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1470 gtk_color_selection_set_current_color(colorsel, &colour);
1471 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1473 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1475 gtk_color_selection_get_current_color(colorsel, &colour);
1476 c_options->image_overlay.text_red = colour.red/257;
1477 c_options->image_overlay.text_green = colour.green/257;
1478 c_options->image_overlay.text_blue = colour.blue/257;
1479 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1481 gtk_widget_destroy (dialog);
1486 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1489 #if GTK_CHECK_VERSION(3,4,0)
1492 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1493 colour.red = options->image_overlay.background_red;
1494 colour.green = options->image_overlay.background_green;
1495 colour.blue = options->image_overlay.background_blue;
1496 colour.alpha = options->image_overlay.background_alpha;
1497 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1498 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1500 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1502 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1503 c_options->image_overlay.background_red = colour.red*255;
1504 c_options->image_overlay.background_green = colour.green*255;
1505 c_options->image_overlay.background_blue = colour.blue*255;
1506 c_options->image_overlay.background_alpha = colour.alpha*255;
1508 gtk_widget_destroy(dialog);
1511 GtkColorSelection *colorsel;
1513 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1514 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1515 colour.red = options->image_overlay.background_red*257;
1516 colour.green = options->image_overlay.background_green*257;
1517 colour.blue = options->image_overlay.background_blue*257;
1518 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1519 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1520 gtk_color_selection_set_current_color(colorsel, &colour);
1521 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1523 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1525 gtk_color_selection_get_current_color(colorsel, &colour);
1526 c_options->image_overlay.background_red = colour.red/257;
1527 c_options->image_overlay.background_green = colour.green/257;
1528 c_options->image_overlay.background_blue = colour.blue/257;
1529 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1531 gtk_widget_destroy(dialog);
1535 static void accel_store_populate(void)
1538 GList *groups, *actions;
1540 const gchar *accel_path;
1544 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1546 gtk_tree_store_clear(accel_store);
1547 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1549 g_assert(lw && lw->ui_manager);
1550 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1553 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1556 action = GTK_ACTION(actions->data);
1557 accel_path = gtk_action_get_accel_path(action);
1558 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1560 gchar *label, *label2, *tooltip, *accel;
1561 g_object_get(action,
1562 "tooltip", &tooltip,
1566 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1572 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1576 gtk_tree_store_append(accel_store, &iter, NULL);
1577 gtk_tree_store_set(accel_store, &iter,
1580 AE_TOOLTIP, tooltip ? tooltip : "",
1581 AE_ACCEL, accel_path,
1589 actions = actions->next;
1592 groups = groups->next;
1596 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1601 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1603 gchar *accel1 = data;
1608 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1610 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1611 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1613 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1615 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1616 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1625 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1627 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1631 GtkAccelKey old_key, key;
1632 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1634 gtk_tree_model_get_iter(model, &iter, path);
1635 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1637 /* test if the accelerator can be stored without conflicts*/
1638 gtk_accel_map_lookup_entry(accel_path, &old_key);
1640 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1641 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1642 gtk_accel_map_lookup_entry(accel_path, &key);
1644 /* restore the original for now, the key will be really changed when the changes are confirmed */
1645 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1647 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1648 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1650 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1651 gtk_tree_path_free(path);
1655 static gboolean accel_default_scroll(GtkTreeView *data)
1659 GtkTreeViewColumn *column;
1661 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1662 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1663 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1665 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1669 gtk_tree_path_free(path);
1674 static void accel_default_cb(GtkWidget *widget, gpointer data)
1676 accel_store_populate();
1678 g_idle_add((GSourceFunc)accel_default_scroll, data);
1681 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1683 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1686 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1689 gchar *accel_path, *accel;
1691 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1692 gtk_accel_map_lookup_entry(accel_path, &key);
1693 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1695 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1697 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1702 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1704 GtkTreeSelection *selection;
1706 if (!accel_store) return;
1707 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1708 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1713 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1717 GtkWidget *scrolled;
1718 GtkWidget *viewport;
1720 scrolled = gtk_scrolled_window_new(NULL, NULL);
1721 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1722 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1723 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1724 label = gtk_label_new(title);
1725 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1726 gtk_widget_show(scrolled);
1728 viewport = gtk_viewport_new(NULL, NULL);
1729 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1730 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1731 gtk_widget_show(viewport);
1733 vbox = gtk_vbox_new(FALSE, 0);
1734 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1735 gtk_widget_show(vbox);
1740 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1742 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1744 c_options->thumbnails.spec_standard =TRUE;
1745 c_options->thumbnails.cache_into_dirs = FALSE;
1749 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1751 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1753 c_options->thumbnails.spec_standard =FALSE;
1754 c_options->thumbnails.cache_into_dirs = FALSE;
1758 static void cache_local_cb(GtkWidget *widget, gpointer data)
1760 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1762 c_options->thumbnails.cache_into_dirs = TRUE;
1763 c_options->thumbnails.spec_standard =FALSE;
1767 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1768 GdkEvent *event, gpointer userdata)
1770 if (pos == GTK_ENTRY_ICON_PRIMARY)
1772 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1776 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1780 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1781 GdkEvent *event, gpointer userdata)
1783 gchar *rating_symbol;
1785 if (pos == GTK_ENTRY_ICON_PRIMARY)
1787 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1788 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1789 g_free(rating_symbol);
1793 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1794 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1795 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1799 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1800 GdkEvent *event, gpointer userdata)
1802 gchar *rating_symbol;
1804 if (pos == GTK_ENTRY_ICON_PRIMARY)
1806 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1807 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1808 g_free(rating_symbol);
1812 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1813 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1814 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1818 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1820 GtkContainer *hbox = data;
1821 GString *str = g_string_new(NULL);
1822 GtkEntry *hex_code_entry;
1823 gchar *hex_code_full;
1826 guint64 hex_value = 0;
1828 list = gtk_container_get_children(hbox);
1830 hex_code_entry = g_list_nth_data(list, 2);
1831 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1833 hex_code = g_strsplit(hex_code_full, "+", 2);
1834 if (hex_code[0] && hex_code[1])
1836 hex_value = strtoull(hex_code[1], NULL, 16);
1838 if (!hex_value || hex_value > 0x10FFFF)
1840 hex_value = 0x003F; // Unicode 'Question Mark'
1842 str = g_string_append_unichar(str, (gunichar)hex_value);
1843 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1845 g_strfreev(hex_code);
1846 g_string_free(str, TRUE);
1847 g_free(hex_code_full);
1852 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1854 guint64 star_symbol;
1856 star_symbol = star_rating_symbol_test(widget, data);
1857 c_options->star_rating.star = star_symbol;
1860 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1862 guint64 rejected_symbol;
1864 rejected_symbol = star_rating_symbol_test(widget, data);
1865 c_options->star_rating.rejected = rejected_symbol;
1868 /* general options tab */
1869 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1870 typedef struct _TZData TZData;
1874 GCancellable *cancellable;
1876 GtkWidget *progress;
1878 GFile *timezone_database_gq;
1879 gchar *timezone_database_user;
1882 static void config_tab_general(GtkWidget *notebook)
1887 GtkWidget *group_frame;
1888 GtkWidget *subgroup;
1890 GtkWidget *ct_button;
1893 gint hours, minutes, remainder;
1895 GtkWidget *star_rating_entry;
1897 gchar *rating_symbol;
1900 GNetworkMonitor *net_mon;
1901 GSocketConnectable *geeqie_org;
1902 gboolean internet_available;
1905 vbox = scrolled_notebook_page(notebook, _("General"));
1907 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1909 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1910 add_thumb_size_menu(table, 0, 0, _("Size:"));
1911 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1913 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1914 pref_label_new(hbox, _("Custom size: "));
1915 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1916 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1918 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1919 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1921 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1922 pref_checkbox_link_sensitivity(ct_button, subgroup);
1924 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1925 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1926 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1927 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1928 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1929 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1930 G_CALLBACK(cache_geeqie_cb), NULL);
1932 group_frame = pref_frame_new(subgroup, TRUE,
1933 _("Store thumbnails local to image folder (non-standard)"),
1934 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1935 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1936 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1937 G_CALLBACK(cache_local_cb), NULL);
1939 group_frame = pref_frame_new(subgroup, TRUE,
1940 _("Use standard thumbnail style and cache, shared with other applications"),
1941 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1942 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1943 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1944 G_CALLBACK(cache_standard_cb), NULL);
1946 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1947 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1949 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1951 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1952 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1954 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1955 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1956 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1958 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1959 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1962 pref_spacer(group, PREF_PAD_GROUP);
1964 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1966 c_options->star_rating.star = options->star_rating.star;
1967 c_options->star_rating.rejected = options->star_rating.rejected;
1969 str = g_string_new(NULL);
1970 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1971 pref_label_new(hbox, "Star character: ");
1972 str = g_string_append_unichar(str, options->star_rating.star);
1973 pref_label_new(hbox, g_strdup(str->str));
1974 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1975 star_rating_entry = gtk_entry_new();
1976 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1977 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1978 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1979 gtk_widget_show(star_rating_entry);
1980 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1981 G_CALLBACK(star_rating_star_test_cb), hbox);
1982 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1983 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1984 gtk_widget_show(button);
1985 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
1986 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1987 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1988 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1989 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1990 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1991 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1992 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1993 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1994 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1995 G_CALLBACK(star_rating_star_icon_cb),
1998 g_string_free(str, TRUE);
1999 g_free(rating_symbol);
2001 str = g_string_new(NULL);
2002 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2003 pref_label_new(hbox, "Rejected character: ");
2004 str = g_string_append_unichar(str, options->star_rating.rejected);
2005 pref_label_new(hbox, g_strdup(str->str));
2006 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2007 star_rating_entry = gtk_entry_new();
2008 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2009 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2010 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2011 gtk_widget_show(star_rating_entry);
2012 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2013 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2014 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2015 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2016 gtk_widget_show(button);
2017 gtk_widget_set_tooltip_text(star_rating_entry, _("Hexadecimal representation of a Unicode character. A list of all Unicode characters may be found on the Internet."));
2018 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2019 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2020 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2021 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2022 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2023 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2024 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2025 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2026 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2027 G_CALLBACK(star_rating_rejected_icon_cb),
2030 g_string_free(str, TRUE);
2031 g_free(rating_symbol);
2033 pref_spacer(group, PREF_PAD_GROUP);
2035 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2037 c_options->slideshow.delay = options->slideshow.delay;
2038 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2039 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2040 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2041 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2042 SLIDESHOW_SUBSECOND_PRECISION;
2044 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2046 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2048 options->slideshow.delay ? hours : 0.0,
2049 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2050 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2051 spin = pref_spin_new(hbox, ":" , NULL,
2053 options->slideshow.delay ? minutes: 0.0,
2054 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2055 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2056 spin = pref_spin_new(hbox, ":", NULL,
2057 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2058 options->slideshow.delay ? seconds : 10.0,
2059 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2060 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2062 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2063 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2065 pref_spacer(group, PREF_PAD_GROUP);
2067 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2069 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2070 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2071 pref_checkbox_new_int(group, _("Preload next image"),
2072 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2074 pref_checkbox_new_int(group, _("Refresh on file change"),
2075 options->update_on_time_change, &c_options->update_on_time_change);
2078 pref_spacer(group, PREF_PAD_GROUP);
2080 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2082 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2083 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2084 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2086 pref_spacer(group, PREF_PAD_GROUP);
2088 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2089 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2090 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2091 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2093 options->info_keywords.height, &c_options->info_keywords.height);
2094 pref_spin_new_int(hbox, _("Title:"), NULL,
2096 options->info_title.height, &c_options->info_title.height);
2097 pref_spin_new_int(hbox, _("Comment:"), NULL,
2099 options->info_comment.height, &c_options->info_comment.height);
2100 pref_spin_new_int(hbox, _("Rating:"), NULL,
2102 options->info_rating.height, &c_options->info_rating.height);
2104 pref_spacer(group, PREF_PAD_GROUP);
2106 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2108 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2109 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2111 pref_spacer(group, PREF_PAD_GROUP);
2113 net_mon = g_network_monitor_get_default();
2114 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2115 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2116 g_object_unref(geeqie_org);
2118 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2119 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2121 if (!internet_available)
2123 gtk_widget_set_sensitive(group, FALSE);
2126 tz = g_new0(TZData, 1);
2128 path = path_from_utf8(TIMEZONE_DATABASE);
2129 basename = g_path_get_basename(path);
2130 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2134 if (isfile(tz->timezone_database_user))
2136 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2140 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2143 if (!internet_available)
2145 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"));
2149 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"));
2151 gtk_widget_show(button);
2153 pref_spacer(group, PREF_PAD_GROUP);
2155 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2157 help_search_engine_entry = gtk_entry_new();
2158 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2159 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2160 gtk_widget_show(help_search_engine_entry);
2162 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"));
2164 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2165 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2166 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2167 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2168 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2169 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2170 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2171 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2172 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2173 G_CALLBACK(help_search_engine_entry_icon_cb),
2174 help_search_engine_entry);
2178 static void config_tab_image(GtkWidget *notebook)
2183 GtkWidget *ct_button;
2184 GtkWidget *enlargement_button;
2187 GtkWidget *two_pass;
2189 GtkWidget *gpu_accel;
2192 vbox = scrolled_notebook_page(notebook, _("Image"));
2194 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2196 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2197 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2198 if (options->image.use_clutter_renderer && !options->disable_gpu)
2200 gtk_widget_set_sensitive(table, FALSE);
2204 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2205 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2206 if (options->disable_gpu && !options->override_disable_gpu)
2208 gtk_widget_set_sensitive(gpu_accel, FALSE);
2212 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2213 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2214 if (options->image.use_clutter_renderer && !options->disable_gpu)
2216 gtk_widget_set_sensitive(two_pass, FALSE);
2219 c_options->image.zoom_increment = options->image.zoom_increment;
2220 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2221 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2222 G_CALLBACK(zoom_increment_cb), NULL);
2223 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2225 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2227 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2228 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2229 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2230 spin = pref_spin_new_int(hbox, NULL, NULL,
2232 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2233 pref_checkbox_link_sensitivity(enlargement_button, spin);
2234 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."));
2236 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2237 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2238 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2239 spin = pref_spin_new_int(hbox, NULL, NULL,
2241 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2242 pref_checkbox_link_sensitivity(ct_button, spin);
2243 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."));
2245 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2247 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2248 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2250 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2251 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2253 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2254 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2256 c_options->image.border_color = options->image.border_color;
2258 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2259 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2261 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2262 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2264 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2265 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2267 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2269 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2270 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2274 static void config_tab_windows(GtkWidget *notebook)
2280 GtkWidget *ct_button;
2283 vbox = scrolled_notebook_page(notebook, _("Windows"));
2285 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2287 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2288 options->save_window_positions, &c_options->save_window_positions);
2290 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2291 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2292 pref_checkbox_link_sensitivity(ct_button, button);
2294 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2295 options->tools_restore_state, &c_options->tools_restore_state);
2297 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2298 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2300 pref_checkbox_new_int(group, _("Show window IDs"),
2301 options->show_window_ids, &c_options->show_window_ids);
2303 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2305 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2306 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2308 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2309 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2310 options->image.limit_window_size, &c_options->image.limit_window_size);
2311 spin = pref_spin_new_int(hbox, NULL, NULL,
2313 options->image.max_window_size, &c_options->image.max_window_size);
2314 pref_checkbox_link_sensitivity(ct_button, spin);
2316 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2318 c_options->fullscreen.screen = options->fullscreen.screen;
2319 c_options->fullscreen.above = options->fullscreen.above;
2320 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2321 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2322 gtk_widget_show(hbox);
2324 pref_checkbox_new_int(group, _("Smooth image flip"),
2325 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2326 pref_checkbox_new_int(group, _("Disable screen saver"),
2327 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2330 #define PRE_FORMATTED_COLUMNS 5
2331 static void config_tab_osd(GtkWidget *notebook)
2337 GtkWidget *image_overlay_template_view;
2338 GtkWidget *scrolled;
2339 GtkWidget *scrolled_pre_formatted;
2340 GtkTextBuffer *buffer;
2342 GtkWidget *subgroup;
2344 vbox = scrolled_notebook_page(notebook, _("OSD"));
2346 image_overlay_template_view = gtk_text_view_new();
2348 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2350 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2352 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2353 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2354 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2355 gtk_widget_show(scrolled_pre_formatted);
2356 gtk_widget_show(subgroup);
2358 pref_line(group, PREF_PAD_GAP);
2360 pref_label_new(group, _("Image overlay template"));
2362 scrolled = gtk_scrolled_window_new(NULL, NULL);
2363 gtk_widget_set_size_request(scrolled, 200, 150);
2364 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2365 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2366 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2367 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2368 gtk_widget_show(scrolled);
2370 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2371 _("Extensive formatting options are shown in the Help file"));
2373 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2374 gtk_widget_show(image_overlay_template_view);
2376 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2378 #if GTK_CHECK_VERSION(3,4,0)
2379 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2380 G_CALLBACK(image_overlay_set_font_cb), notebook);
2382 button = gtk_font_button_new();
2383 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2384 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2385 g_signal_connect(G_OBJECT(button), "font-set",
2386 G_CALLBACK(image_overlay_set_font_cb),NULL);
2388 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2389 gtk_widget_show(button);
2391 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2392 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2393 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2394 gtk_widget_show(button);
2396 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2397 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2398 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2399 gtk_widget_show(button);
2400 image_overlay_set_text_colours();
2402 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2403 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2404 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2405 gtk_widget_show(button);
2407 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2408 G_CALLBACK(image_overlay_help_cb), NULL);
2409 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2410 gtk_widget_show(button);
2412 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2413 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2414 g_signal_connect(G_OBJECT(buffer), "changed",
2415 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2417 pref_line(group, PREF_PAD_GAP);
2419 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2420 hbox = gtk_hbox_new(FALSE, 0);
2421 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2422 gtk_widget_show(hbox);
2423 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2424 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2425 gtk_widget_show(label);
2426 pref_spacer(group,TRUE);
2428 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2429 hbox = gtk_hbox_new(FALSE, 0);
2430 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2431 gtk_widget_show(hbox);
2432 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2433 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2434 gtk_widget_show(label);
2435 pref_spacer(group,TRUE);
2437 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2438 hbox = gtk_hbox_new(FALSE, 0);
2439 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2440 gtk_widget_show(hbox);
2441 label = gtk_label_new(_("%path:39%"));
2442 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2443 gtk_widget_show(label);
2444 pref_spacer(group,TRUE);
2446 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2447 hbox = gtk_hbox_new(FALSE, 0);
2448 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2449 gtk_widget_show(hbox);
2450 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%"));
2451 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2452 gtk_widget_show(label);
2453 pref_spacer(group,TRUE);
2455 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2456 hbox = gtk_hbox_new(FALSE, 0);
2457 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2458 gtk_widget_show(hbox);
2459 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2460 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2461 gtk_widget_show(label);
2464 static GtkTreeModel *create_class_model(void)
2466 GtkListStore *model;
2470 /* create list store */
2471 model = gtk_list_store_new(1, G_TYPE_STRING);
2472 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2474 gtk_list_store_append(model, &iter);
2475 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2477 return GTK_TREE_MODEL (model);
2482 static void config_tab_files(GtkWidget *notebook)
2489 GtkWidget *ct_button;
2490 GtkWidget *scrolled;
2491 GtkWidget *filter_view;
2492 GtkCellRenderer *renderer;
2493 GtkTreeSelection *selection;
2494 GtkTreeViewColumn *column;
2496 vbox = scrolled_notebook_page(notebook, _("Files"));
2498 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2500 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2501 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2502 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2503 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2504 pref_checkbox_new_int(group, _("Case sensitive sort"),
2505 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2506 pref_checkbox_new_int(group, _("Natural sort order"),
2507 options->file_sort.natural, &c_options->file_sort.natural);
2508 pref_checkbox_new_int(group, _("Disable file extension checks"),
2509 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2511 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2512 options->file_filter.disable, &c_options->file_filter.disable);
2515 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2517 sidecar_ext_entry = gtk_entry_new();
2518 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2519 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2520 gtk_widget_show(sidecar_ext_entry);
2522 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2524 frame = pref_group_parent(group);
2525 g_signal_connect(G_OBJECT(ct_button), "toggled",
2526 G_CALLBACK(filter_disable_cb), frame);
2527 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2529 scrolled = gtk_scrolled_window_new(NULL, NULL);
2530 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2531 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2532 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2533 gtk_widget_show(scrolled);
2535 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2536 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2537 g_object_unref(filter_store);
2538 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2539 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2541 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2543 column = gtk_tree_view_column_new();
2544 gtk_tree_view_column_set_title(column, _("Filter"));
2545 gtk_tree_view_column_set_resizable(column, TRUE);
2547 renderer = gtk_cell_renderer_toggle_new();
2548 g_signal_connect(G_OBJECT(renderer), "toggled",
2549 G_CALLBACK(filter_store_enable_cb), filter_store);
2550 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2551 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2552 GINT_TO_POINTER(FE_ENABLE), NULL);
2554 renderer = gtk_cell_renderer_text_new();
2555 g_signal_connect(G_OBJECT(renderer), "edited",
2556 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2557 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2558 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2559 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2560 GINT_TO_POINTER(FE_EXTENSION), NULL);
2561 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2563 column = gtk_tree_view_column_new();
2564 gtk_tree_view_column_set_title(column, _("Description"));
2565 gtk_tree_view_column_set_resizable(column, TRUE);
2566 gtk_tree_view_column_set_fixed_width(column, 200);
2567 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2569 renderer = gtk_cell_renderer_text_new();
2570 g_signal_connect(G_OBJECT(renderer), "edited",
2571 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2572 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2573 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2574 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2575 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2576 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2578 column = gtk_tree_view_column_new();
2579 gtk_tree_view_column_set_title(column, _("Class"));
2580 gtk_tree_view_column_set_resizable(column, TRUE);
2581 renderer = gtk_cell_renderer_combo_new();
2582 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2583 "model", create_class_model(),
2588 g_signal_connect(G_OBJECT(renderer), "edited",
2589 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2590 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2591 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2592 GINT_TO_POINTER(FE_CLASS), NULL);
2593 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2595 column = gtk_tree_view_column_new();
2596 gtk_tree_view_column_set_title(column, _("Writable"));
2597 gtk_tree_view_column_set_resizable(column, FALSE);
2598 renderer = gtk_cell_renderer_toggle_new();
2599 g_signal_connect(G_OBJECT(renderer), "toggled",
2600 G_CALLBACK(filter_store_writable_cb), filter_store);
2601 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2602 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2603 GINT_TO_POINTER(FE_WRITABLE), NULL);
2604 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2606 column = gtk_tree_view_column_new();
2607 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2608 gtk_tree_view_column_set_resizable(column, FALSE);
2609 renderer = gtk_cell_renderer_toggle_new();
2610 g_signal_connect(G_OBJECT(renderer), "toggled",
2611 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2612 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2613 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2614 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2615 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2618 filter_store_populate();
2619 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2620 gtk_widget_show(filter_view);
2622 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2624 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2625 G_CALLBACK(filter_default_cb), filter_view);
2626 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2627 gtk_widget_show(button);
2629 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2630 G_CALLBACK(filter_remove_cb), filter_view);
2631 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2632 gtk_widget_show(button);
2634 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2635 G_CALLBACK(filter_add_cb), filter_view);
2636 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2637 gtk_widget_show(button);
2641 static void config_tab_metadata(GtkWidget *notebook)
2646 GtkWidget *ct_button;
2650 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2653 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2655 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2657 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2658 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2660 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2661 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2663 gtk_widget_set_sensitive(ct_button, FALSE);
2666 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2667 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2669 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2670 label = pref_label_new(group, text);
2671 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2672 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2675 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2677 gtk_widget_set_sensitive(group, FALSE);
2680 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2681 pref_checkbox_link_sensitivity(ct_button, hbox);
2683 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2684 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2686 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2687 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2689 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2690 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2692 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2693 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2695 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2697 gtk_widget_set_sensitive(group, FALSE);
2700 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2701 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2704 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2705 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2706 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2708 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2709 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2711 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2712 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2714 gtk_widget_set_sensitive(ct_button, FALSE);
2717 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2719 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2720 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2722 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2723 pref_checkbox_link_sensitivity(ct_button, hbox);
2725 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2726 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2728 pref_checkbox_new_int(group, _("Write metadata on image change"),
2729 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2731 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2732 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2734 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2736 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2737 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2738 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");
2743 typedef struct _KeywordFindData KeywordFindData;
2744 struct _KeywordFindData
2751 GtkWidget *button_close;
2752 GtkWidget *button_stop;
2753 GtkWidget *button_start;
2754 GtkWidget *progress;
2762 guint idle_id; /* event source id */
2765 #define KEYWORD_DIALOG_WIDTH 400
2767 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2769 GList *list_d = NULL;
2770 GList *list_f = NULL;
2774 filelist_read(dir_fd, &list_f, &list_d);
2778 filelist_read(dir_fd, &list_f, NULL);
2781 list_f = filelist_filter(list_f, FALSE);
2782 list_d = filelist_filter(list_d, TRUE);
2784 kfd->list = g_list_concat(list_f, kfd->list);
2785 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2788 static void keywords_find_reset(KeywordFindData *kfd)
2790 filelist_free(kfd->list);
2793 filelist_free(kfd->list_dir);
2794 kfd->list_dir = NULL;
2797 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2799 KeywordFindData *kfd = data;
2801 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2803 keywords_find_reset(kfd);
2804 generic_dialog_close(kfd->gd);
2808 static void keywords_find_finish(KeywordFindData *kfd)
2810 keywords_find_reset(kfd);
2812 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2813 spinner_set_interval(kfd->spinner, -1);
2815 gtk_widget_set_sensitive(kfd->group, TRUE);
2816 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2817 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2818 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2821 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2823 KeywordFindData *kfd = data;
2825 g_idle_remove_by_data(kfd);
2827 keywords_find_finish(kfd);
2830 static gboolean keywords_find_file(gpointer data)
2832 KeywordFindData *kfd = data;
2834 GtkTextBuffer *buffer;
2842 fd = kfd->list->data;
2843 kfd->list = g_list_remove(kfd->list, fd);
2845 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2846 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2850 gtk_text_buffer_get_end_iter(buffer, &iter);
2851 tmp = g_strconcat(keywords->data, "\n", NULL);
2852 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2854 keywords = keywords->next;
2857 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2858 file_data_unref(fd);
2859 string_list_free(keywords);
2863 else if (kfd->list_dir)
2867 fd = kfd->list_dir->data;
2868 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2870 keywords_find_folder(kfd, fd);
2872 file_data_unref(fd);
2877 keywords_find_finish(kfd);
2882 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2884 KeywordFindData *kfd = data;
2887 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2889 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2890 parse_out_relatives(path);
2894 warning_dialog(_("Invalid folder"),
2895 _("The specified folder can not be found."),
2896 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2902 gtk_widget_set_sensitive(kfd->group, FALSE);
2903 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2904 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2905 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2906 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2908 dir_fd = file_data_new_dir(path);
2909 keywords_find_folder(kfd, dir_fd);
2910 file_data_unref(dir_fd);
2911 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2917 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2919 KeywordFindData *kfd;
2923 kfd = g_new0(KeywordFindData, 1);
2925 kfd->gd = generic_dialog_new(_("Search for keywords"),
2926 "search_for_keywords",
2929 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2930 kfd->gd->cancel_cb = keywords_find_close_cb;
2931 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2932 keywords_find_close_cb, FALSE);
2933 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2934 keywords_find_start_cb, FALSE);
2935 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2936 keywords_find_stop_cb, FALSE);
2937 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2939 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2941 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2942 pref_spacer(hbox, PREF_PAD_INDENT);
2943 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2945 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2946 pref_label_new(hbox, _("Folder:"));
2948 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2949 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2950 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2951 gtk_widget_show(label);
2953 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2955 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2956 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2958 kfd->progress = gtk_entry_new();
2959 gtk_widget_set_can_focus(kfd->progress, FALSE);
2960 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2961 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2962 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2963 gtk_widget_show(kfd->progress);
2965 kfd->spinner = spinner_new(NULL, -1);
2966 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2967 gtk_widget_show(kfd->spinner);
2971 gtk_widget_show(kfd->gd->dialog);
2974 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2976 const gchar *path = layout_get_path(NULL);
2978 if (!path || !*path) path = homedir();
2979 keywords_find_dialog(widget, path);
2982 static void config_tab_keywords_save()
2984 GtkTextIter start, end;
2985 GtkTextBuffer *buffer;
2986 GList *kw_list = NULL;
2992 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2993 gtk_text_buffer_get_bounds(buffer, &start, &end);
2995 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2997 kw_split = strtok(buffer_text, "\n");
2998 while (kw_split != NULL)
3004 if (g_strcmp0(work->data, kw_split) == 0)
3013 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3015 kw_split = strtok(NULL, "\n");
3018 keyword_list_set(kw_list);
3020 string_list_free(kw_list);
3021 g_free(buffer_text);
3024 static void config_tab_keywords(GtkWidget *notebook)
3030 GtkWidget *scrolled;
3032 GtkTextBuffer *buffer;
3035 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3037 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3039 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3041 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3042 G_CALLBACK(keywords_find_cb), keyword_text);
3043 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3046 keyword_text = gtk_text_view_new();
3047 gtk_widget_set_size_request(keyword_text, 20, 20);
3048 scrolled = gtk_scrolled_window_new(NULL, NULL);
3049 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3050 gtk_widget_show(scrolled);
3052 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3053 gtk_widget_show(keyword_text);
3055 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3057 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3058 gtk_text_buffer_create_tag(buffer, "monospace",
3059 "family", "monospace", NULL);
3061 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3062 gtk_text_buffer_get_start_iter(buffer, &iter);
3063 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3066 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3068 GList *kwl = keyword_list_get();
3069 kwl = g_list_first(kwl);
3072 gtk_text_buffer_get_end_iter (buffer, &iter);
3073 tmp = g_strconcat(kwl->data, "\n", NULL);
3074 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3079 gtk_text_buffer_set_modified(buffer, FALSE);
3086 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3088 gint *option = data;
3090 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3094 *option = INTENT_PERCEPTUAL;
3097 *option = INTENT_RELATIVE_COLORIMETRIC;
3100 *option = INTENT_SATURATION;
3103 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3108 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3109 gint option, gint *option_c)
3116 pref_table_label(table, column, row, text, 0.0);
3118 combo = gtk_combo_box_text_new();
3120 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3121 if (option == INTENT_PERCEPTUAL) current = 0;
3122 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3123 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3124 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3125 if (option == INTENT_SATURATION) current = 2;
3126 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3127 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3129 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3131 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3133 g_signal_connect(G_OBJECT(combo), "changed",
3134 G_CALLBACK(intent_menu_cb), option_c);
3136 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3137 gtk_widget_show(combo);
3141 static void config_tab_color(GtkWidget *notebook)
3150 vbox = scrolled_notebook_page(notebook, _("Color management"));
3152 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3154 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3157 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3158 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3160 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3161 pref_label_bold(label, TRUE, FALSE);
3163 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3164 pref_label_bold(label, TRUE, FALSE);
3166 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3167 pref_label_bold(label, TRUE, FALSE);
3169 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3174 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3175 pref_table_label(table, 0, i + 1, buf, 1.0);
3178 entry = gtk_entry_new();
3179 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3180 if (options->color_profile.input_name[i])
3182 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3184 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3185 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3186 gtk_widget_show(entry);
3187 color_profile_input_name_entry[i] = entry;
3189 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3190 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3191 gtk_widget_set_size_request(entry, 160, -1);
3192 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3193 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3194 gtk_widget_show(tabcomp);
3195 color_profile_input_file_entry[i] = entry;
3198 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3200 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3202 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3203 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3205 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3207 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3208 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3209 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3210 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3211 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3213 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3215 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3217 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3219 gtk_widget_show(tabcomp);
3222 /* advanced entry tab */
3223 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3225 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3227 c_options->file_ops.use_system_trash = FALSE;
3228 c_options->file_ops.no_trash = FALSE;
3232 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3234 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3236 c_options->file_ops.use_system_trash = TRUE;
3237 c_options->file_ops.no_trash = FALSE;
3241 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3243 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3245 c_options->file_ops.no_trash = TRUE;
3249 static void config_tab_behavior(GtkWidget *notebook)
3256 GtkWidget *ct_button;
3260 GtkWidget *with_rename;
3261 GtkWidget *collections_on_top;
3262 GtkWidget *checkbox;
3264 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3266 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3268 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3269 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3270 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3271 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3272 pref_checkbox_new_int(group, _("Enable Delete key"),
3273 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3275 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3276 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3278 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3279 pref_checkbox_link_sensitivity(ct_button, hbox);
3281 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3282 pref_label_new(hbox, _("Folder:"));
3284 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3285 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3286 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3287 gtk_widget_show(tabcomp);
3289 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3290 pref_checkbox_link_sensitivity(ct_button, hbox);
3292 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3293 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3294 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3295 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3296 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3297 G_CALLBACK(safe_delete_view_cb), NULL);
3298 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3299 gtk_widget_show(button);
3301 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3302 G_CALLBACK(safe_delete_clear_cb), NULL);
3303 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3304 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3305 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3307 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3308 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3310 gtk_widget_show(button);
3312 pref_spacer(group, PREF_PAD_GROUP);
3315 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3317 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3318 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3320 pref_checkbox_new_int(group, _("In place renaming"),
3321 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3323 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3324 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3326 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3327 options->marks_save, &c_options->marks_save);
3328 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3330 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3331 options->with_rename, &c_options->with_rename);
3332 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3334 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3335 options->collections_on_top, &c_options->collections_on_top);
3336 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3338 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3339 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3341 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3342 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3344 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3345 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3347 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3348 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3350 pref_spacer(group, PREF_PAD_GROUP);
3352 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3354 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3355 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3356 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3357 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3358 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3359 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3360 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3361 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3362 pref_checkbox_new_int(group, _("Play video by left click on image"),
3363 options->image_l_click_video, &c_options->image_l_click_video);
3364 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3365 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3367 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3368 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3369 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3370 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3371 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3373 pref_spacer(group, PREF_PAD_GROUP);
3375 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3377 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3378 options->override_disable_gpu, &c_options->override_disable_gpu);
3379 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3382 pref_spacer(group, PREF_PAD_GROUP);
3384 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3386 pref_spin_new_int(group, _("Debug level:"), NULL,
3387 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3389 pref_checkbox_new_int(group, _("Timer data"),
3390 options->log_window.timer_data, &c_options->log_window.timer_data);
3392 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3393 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3397 /* accelerators tab */
3398 static void config_tab_accelerators(GtkWidget *notebook)
3404 GtkWidget *scrolled;
3405 GtkWidget *accel_view;
3406 GtkCellRenderer *renderer;
3407 GtkTreeSelection *selection;
3408 GtkTreeViewColumn *column;
3410 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3412 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3414 scrolled = gtk_scrolled_window_new(NULL, NULL);
3415 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3416 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3417 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3418 gtk_widget_show(scrolled);
3420 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3422 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3423 g_object_unref(accel_store);
3424 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3425 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3427 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3429 renderer = gtk_cell_renderer_text_new();
3431 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3436 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3437 gtk_tree_view_column_set_resizable(column, TRUE);
3438 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3441 renderer = gtk_cell_renderer_accel_new();
3442 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3443 G_CALLBACK(accel_store_cleared_cb), accel_store);
3444 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3445 G_CALLBACK(accel_store_edited_cb), accel_store);
3448 g_object_set (renderer,
3450 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3453 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3458 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3459 gtk_tree_view_column_set_resizable(column, TRUE);
3460 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3462 renderer = gtk_cell_renderer_text_new();
3464 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3469 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3470 gtk_tree_view_column_set_resizable(column, TRUE);
3471 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3473 renderer = gtk_cell_renderer_text_new();
3475 column = gtk_tree_view_column_new_with_attributes("Accel",
3480 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3481 gtk_tree_view_column_set_resizable(column, TRUE);
3482 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3484 accel_store_populate();
3485 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3486 gtk_widget_show(accel_view);
3488 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3490 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3491 G_CALLBACK(accel_default_cb), accel_view);
3492 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3493 gtk_widget_show(button);
3495 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3496 G_CALLBACK(accel_reset_cb), accel_view);
3497 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3498 gtk_widget_show(button);
3501 /* toolbar main tab */
3502 static void config_tab_toolbar_main(GtkWidget *notebook)
3505 GtkWidget *toolbardata;
3508 lw = layout_window_list->data;
3510 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3512 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3513 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3514 gtk_widget_show(vbox);
3517 /* toolbar status tab */
3518 static void config_tab_toolbar_status(GtkWidget *notebook)
3521 GtkWidget *toolbardata;
3524 lw = layout_window_list->data;
3526 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3528 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3529 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3530 gtk_widget_show(vbox);
3534 static void config_tab_stereo(GtkWidget *notebook)
3542 GtkWidget *fs_button;
3543 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3545 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3547 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3548 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3550 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3551 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3552 pref_checkbox_new_int(box, _("Mirror left image"),
3553 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3554 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3555 pref_checkbox_new_int(box, _("Flip left image"),
3556 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3557 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3558 pref_checkbox_new_int(box, _("Mirror right image"),
3559 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3560 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3561 pref_checkbox_new_int(box, _("Flip right image"),
3562 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3563 pref_checkbox_new_int(group, _("Swap left and right images"),
3564 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3565 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3566 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3568 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3569 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3570 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3571 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3572 pref_checkbox_link_sensitivity(fs_button, box2);
3573 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3574 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3575 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3576 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3577 pref_checkbox_new_int(box, _("Mirror left image"),
3578 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3579 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3580 pref_checkbox_new_int(box, _("Flip left image"),
3581 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3582 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3583 pref_checkbox_new_int(box, _("Mirror right image"),
3584 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3585 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3586 pref_checkbox_new_int(box, _("Flip right image"),
3587 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3588 pref_checkbox_new_int(box2, _("Swap left and right images"),
3589 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3590 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3591 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3593 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3594 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3595 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3596 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3597 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3598 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3599 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3600 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3601 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3602 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3603 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3604 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3605 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3606 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3610 /* Main preferences window */
3611 static void config_window_create(void)
3613 GtkWidget *win_vbox;
3615 GtkWidget *notebook;
3617 GtkWidget *ct_button;
3619 if (!c_options) c_options = init_options(NULL);
3621 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3622 DEBUG_NAME(configwindow);
3623 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3624 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3625 G_CALLBACK(config_window_delete), NULL);
3626 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3627 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3628 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3630 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3631 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3632 gtk_widget_show(win_vbox);
3634 notebook = gtk_notebook_new();
3635 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3636 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3637 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3639 config_tab_general(notebook);
3640 config_tab_image(notebook);
3641 config_tab_osd(notebook);
3642 config_tab_windows(notebook);
3643 config_tab_accelerators(notebook);
3644 config_tab_files(notebook);
3645 config_tab_metadata(notebook);
3646 config_tab_keywords(notebook);
3647 config_tab_color(notebook);
3648 config_tab_stereo(notebook);
3649 config_tab_behavior(notebook);
3650 config_tab_toolbar_main(notebook);
3651 config_tab_toolbar_status(notebook);
3653 hbox = gtk_hbutton_box_new();
3654 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3655 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3656 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3657 gtk_widget_show(hbox);
3659 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3660 G_CALLBACK(config_window_help_cb), notebook);
3661 gtk_container_add(GTK_CONTAINER(hbox), button);
3662 gtk_widget_set_can_default(button, TRUE);
3663 gtk_widget_show(button);
3665 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3666 G_CALLBACK(config_window_ok_cb), NULL);
3667 gtk_container_add(GTK_CONTAINER(hbox), button);
3668 gtk_widget_set_can_default(button, TRUE);
3669 gtk_widget_grab_default(button);
3670 gtk_widget_show(button);
3674 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3675 G_CALLBACK(config_window_close_cb), NULL);
3676 gtk_container_add(GTK_CONTAINER(hbox), button);
3677 gtk_widget_set_can_default(button, TRUE);
3678 gtk_widget_show(button);
3680 if (!generic_dialog_get_alternative_button_order(configwindow))
3682 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3685 gtk_widget_show(notebook);
3687 gtk_widget_show(configwindow);
3691 *-----------------------------------------------------------------------------
3692 * config window show (public)
3693 *-----------------------------------------------------------------------------
3696 void show_config_window(void)
3700 gtk_window_present(GTK_WINDOW(configwindow));
3704 config_window_create();
3713 void show_about_window(LayoutWindow *lw)
3715 GdkPixbuf *pixbuf_logo;
3716 GdkPixbuf *pixbuf_icon;
3717 gchar *authors[1000];
3722 gchar *timezone_path;
3726 #define LINE_LENGTH 1000
3727 gchar line[LINE_LENGTH];
3729 copyright = g_string_new(NULL);
3730 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");
3732 path = path_from_utf8(TIMEZONE_DATABASE);
3733 basename = g_path_get_basename(path);
3734 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3735 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3737 cd = ZDOpenDatabase(timezone_path);
3740 copyright = g_string_append(copyright, ZDGetNotice(cd));
3741 ZDCloseDatabase(cd);
3745 g_free(timezone_path);
3749 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3750 fp = fopen(path, "r");
3753 while(fgets(line, LINE_LENGTH, fp))
3755 /* get rid of ending \n from fgets */
3756 line[strlen(line) - 1] = '\0';
3757 authors[i_authors] = g_strdup(line);
3760 authors[i_authors] = NULL;
3765 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3766 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3768 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3769 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3770 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3771 "title", _("About Geeqie"),
3773 "program-name", GQ_APPNAME,
3775 "logo", pixbuf_logo,
3776 "icon", pixbuf_icon,
3777 "website", GQ_WEBSITE,
3778 "website-label", "Website",
3779 "comments", comment,
3781 "translator-credits", _("translator-credits"),
3782 "wrap-license", TRUE,
3783 "license", copyright->str,
3786 g_string_free(copyright, TRUE);
3789 while(n < i_authors)
3799 static void image_overlay_set_text_colours()
3801 c_options->image_overlay.text_red = options->image_overlay.text_red;
3802 c_options->image_overlay.text_green = options->image_overlay.text_green;
3803 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3804 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3805 c_options->image_overlay.background_red = options->image_overlay.background_red;
3806 c_options->image_overlay.background_green = options->image_overlay.background_green;
3807 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3808 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3812 *-----------------------------------------------------------------------------
3813 * timezone database routines
3814 *-----------------------------------------------------------------------------
3817 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3819 GError *error = NULL;
3821 gchar *tmp_filename;
3823 if (!g_cancellable_is_cancelled(tz->cancellable))
3825 generic_dialog_close(tz->gd);
3829 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3831 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3832 move_file(tmp_filename, tz->timezone_database_user);
3833 g_free(tmp_filename);
3837 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3840 g_file_delete(tz->tmp_g_file, NULL, &error);
3841 g_object_unref(tz->tmp_g_file);
3842 tz->tmp_g_file = NULL;
3843 g_object_unref(tz->cancellable);
3844 g_object_unref(tz->timezone_database_gq);
3847 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3851 if (!g_cancellable_is_cancelled(tz->cancellable))
3853 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3857 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3861 g_cancellable_cancel(tz->cancellable);
3864 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3867 GError *error = NULL;
3868 GFileIOStream *io_stream;
3875 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3879 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3880 log_printf("Error: Download timezone database failed:\n%s", error->message);
3881 g_error_free(error);
3882 g_object_unref(tz->tmp_g_file);
3886 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3888 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3890 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3892 tz->progress = gtk_progress_bar_new();
3893 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3894 gtk_widget_show(tz->progress);
3896 gtk_widget_show(tz->gd->dialog);
3897 tz->cancellable = g_cancellable_new();
3898 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);
3900 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3903 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */