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[] = {
124 /* config memory values */
125 static ConfOptions *c_options = NULL;
132 static GtkWidget *configwindow = NULL;
133 static GtkListStore *filter_store = NULL;
134 static GtkTreeStore *accel_store = NULL;
136 static GtkWidget *safe_delete_path_entry;
138 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_screen_file_entry;
142 static GtkWidget *sidecar_ext_entry;
143 static GtkWidget *help_search_engine_entry;
146 #define CONFIG_WINDOW_DEF_WIDTH 700
147 #define CONFIG_WINDOW_DEF_HEIGHT 600
150 *-----------------------------------------------------------------------------
151 * option widget callbacks (private)
152 *-----------------------------------------------------------------------------
155 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
157 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
160 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
162 gint mins_secs_tenths, delay;
164 mins_secs_tenths = c_options->slideshow.delay %
165 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
167 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
168 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
171 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
172 SLIDESHOW_SUBSECOND_PRECISION;
175 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
177 gint hours, secs_tenths, delay;
179 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
180 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
182 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
183 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
184 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
186 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
187 SLIDESHOW_SUBSECOND_PRECISION;
190 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
192 gint hours_mins, delay;
194 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
196 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
197 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
198 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
200 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
201 SLIDESHOW_SUBSECOND_PRECISION;
205 *-----------------------------------------------------------------------------
206 * sync progam to config window routine (private)
207 *-----------------------------------------------------------------------------
210 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
216 buf = gtk_entry_get_text(GTK_ENTRY(entry));
217 if (buf && strlen(buf) > 0)
222 *option = g_strdup(buf);
227 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
229 gchar *accel_path, *accel;
231 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
233 if (accel_path && accel_path[0])
236 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
237 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
247 static void config_window_apply(void)
250 gboolean refresh = FALSE;
252 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
254 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
255 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
256 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
257 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
258 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
259 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
260 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
262 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
263 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
264 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
265 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
266 options->file_ops.no_trash = c_options->file_ops.no_trash;
267 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
268 options->tools_restore_state = c_options->tools_restore_state;
269 options->save_window_positions = c_options->save_window_positions;
270 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
271 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
272 options->show_window_ids = c_options->show_window_ids;
273 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
274 options->image.zoom_2pass = c_options->image.zoom_2pass;
275 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
276 options->image.limit_window_size = c_options->image.limit_window_size;
277 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
278 options->image.max_window_size = c_options->image.max_window_size;
279 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
280 options->image.max_autofit_size = c_options->image.max_autofit_size;
281 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
282 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
283 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
284 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
286 if (options->thumbnails.max_width != c_options->thumbnails.max_width
287 || options->thumbnails.max_height != c_options->thumbnails.max_height
288 || options->thumbnails.quality != c_options->thumbnails.quality)
290 thumb_format_changed = TRUE;
292 options->thumbnails.max_width = c_options->thumbnails.max_width;
293 options->thumbnails.max_height = c_options->thumbnails.max_height;
294 options->thumbnails.quality = c_options->thumbnails.quality;
296 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
297 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
298 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
299 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
300 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
301 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
302 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
303 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
304 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
305 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
306 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
307 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
309 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
310 options->file_sort.natural = c_options->file_sort.natural;
311 options->file_filter.disable = c_options->file_filter.disable;
313 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
314 sidecar_ext_parse(options->sidecar.ext);
316 options->slideshow.random = c_options->slideshow.random;
317 options->slideshow.repeat = c_options->slideshow.repeat;
318 options->slideshow.delay = c_options->slideshow.delay;
320 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
321 options->image_lm_click_nav = c_options->image_lm_click_nav;
322 options->image_l_click_video = c_options->image_l_click_video;
323 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
325 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
327 options->image.tile_cache_max = c_options->image.tile_cache_max;
328 options->image.image_cache_max = c_options->image.image_cache_max;
330 options->image.zoom_quality = c_options->image.zoom_quality;
332 options->image.zoom_increment = c_options->image.zoom_increment;
334 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
337 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
338 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
339 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
341 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
342 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
343 options->image.border_color = c_options->image.border_color;
344 layout_colors_update();
345 view_window_colors_update();
348 options->image.alpha_color_1 = c_options->image.alpha_color_1;
349 options->image.alpha_color_2 = c_options->image.alpha_color_2;
351 options->fullscreen.screen = c_options->fullscreen.screen;
352 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
353 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
354 options->fullscreen.above = c_options->fullscreen.above;
355 if (c_options->image_overlay.template_string)
356 set_image_overlay_template_string(&options->image_overlay.template_string,
357 c_options->image_overlay.template_string);
358 if (c_options->image_overlay.font)
359 set_image_overlay_font_string(&options->image_overlay.font,
360 c_options->image_overlay.font);
361 options->image_overlay.text_red = c_options->image_overlay.text_red;
362 options->image_overlay.text_green = c_options->image_overlay.text_green;
363 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
364 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
365 options->image_overlay.background_red = c_options->image_overlay.background_red;
366 options->image_overlay.background_green = c_options->image_overlay.background_green;
367 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
368 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
369 options->update_on_time_change = c_options->update_on_time_change;
370 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
372 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
373 options->rot_invariant_sim = c_options->rot_invariant_sim;
375 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
377 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
379 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
380 options->dnd_icon_size = c_options->dnd_icon_size;
381 options->clipboard_selection = c_options->clipboard_selection;
383 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
384 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
385 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
386 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
387 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
388 options->metadata.confirm_write = c_options->metadata.confirm_write;
389 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
390 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
391 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
392 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
393 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
394 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
395 options->metadata.write_orientation = c_options->metadata.write_orientation;
396 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
397 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
398 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
399 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
400 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
401 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
402 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
403 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
411 options->stereo.fixed_w = c_options->stereo.fixed_w;
412 options->stereo.fixed_h = c_options->stereo.fixed_h;
413 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
414 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
415 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
416 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
418 options->info_keywords.height = c_options->info_keywords.height;
419 options->info_title.height = c_options->info_title.height;
420 options->info_comment.height = c_options->info_comment.height;
421 options->info_rating.height = c_options->info_rating.height;
423 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
425 options->marks_save = c_options->marks_save;
426 options->with_rename = c_options->with_rename;
427 options->collections_on_top = c_options->collections_on_top;
428 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
430 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
432 options->star_rating.star = c_options->star_rating.star;
433 options->star_rating.rejected = c_options->star_rating.rejected;
435 set_debug_level(debug_c);
439 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
441 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
442 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
444 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
445 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
446 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
448 options->color_profile.render_intent = c_options->color_profile.render_intent;
453 options->mouse_button_8 = c_options->mouse_button_8;
454 options->mouse_button_9 = c_options->mouse_button_9;
456 config_tab_keywords_save();
458 image_options_sync();
463 layout_refresh(NULL);
466 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
468 toolbar_apply(TOOLBAR_MAIN);
469 toolbar_apply(TOOLBAR_STATUS);
473 *-----------------------------------------------------------------------------
474 * config window main button callbacks (private)
475 *-----------------------------------------------------------------------------
478 static void config_window_close_cb(GtkWidget *widget, gpointer data)
480 gtk_widget_destroy(configwindow);
485 static void config_window_help_cb(GtkWidget *widget, gpointer data)
487 GtkWidget *notebook = data;
490 static gchar *html_section[] =
492 "GuideOptionsGeneral.html",
493 "GuideOptionsImage.html",
494 "GuideOptionsOSD.html",
495 "GuideOptionsWindow.html",
496 "GuideOptionsKeyboard.html",
497 "GuideOptionsFiltering.html",
498 "GuideOptionsMetadata.html",
499 "GuideOptionsKeywords.html",
500 "GuideOptionsColor.html",
501 "GuideOptionsStereo.html",
502 "GuideOptionsBehavior.html",
503 "GuideOptionsToolbar.html"
506 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
507 help_window_show(html_section[i]);
510 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
512 config_window_close_cb(NULL, NULL);
516 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
518 config_window_apply();
519 config_window_close_cb(NULL, NULL);
522 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
525 lw = layout_window_list->data;
527 config_window_apply();
528 layout_util_sync(lw);
531 static void config_window_save_cb(GtkWidget *widget, gpointer data)
533 config_window_apply();
534 save_options(options);
538 *-----------------------------------------------------------------------------
539 * config window setup (private)
540 *-----------------------------------------------------------------------------
543 static void quality_menu_cb(GtkWidget *combo, gpointer data)
547 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
551 *option = GDK_INTERP_NEAREST;
554 *option = GDK_INTERP_TILES;
557 *option = GDK_INTERP_BILINEAR;
560 *option = GDK_INTERP_HYPER;
565 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
569 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
581 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
582 guint option, guint *option_c)
589 pref_table_label(table, column, row, text, 0.0);
591 combo = gtk_combo_box_text_new();
593 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
594 if (option == GDK_INTERP_NEAREST) current = 0;
595 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
596 if (option == GDK_INTERP_TILES) current = 1;
597 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
598 if (option == GDK_INTERP_BILINEAR) current = 2;
599 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
600 if (option == GDK_INTERP_HYPER) current = 3;
602 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
604 g_signal_connect(G_OBJECT(combo), "changed",
605 G_CALLBACK(quality_menu_cb), option_c);
607 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
608 GTK_EXPAND | GTK_FILL, 0, 0, 0);
609 gtk_widget_show(combo);
612 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
613 gint option, gint *option_c)
620 pref_table_label(table, column, row, text, 0.0);
622 combo = gtk_combo_box_text_new();
624 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
625 if (option == PRIMARY) current = 0;
626 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
627 if (option == CLIPBOARD) current = 1;
629 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
631 g_signal_connect(G_OBJECT(combo), "changed",
632 G_CALLBACK(clipboard_selection_menu_cb), option_c);
634 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
635 GTK_EXPAND | GTK_FILL, 0, 0, 0);
636 gtk_widget_show(combo);
639 typedef struct _UseableMouseItems UseableMouseItems;
640 struct _UseableMouseItems
642 gchar *name; /* GtkActionEntry terminology */
647 static const UseableMouseItems useable_mouse_items[] = {
649 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
650 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
651 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
652 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
653 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
654 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
655 {"Home", N_("Home"), GTK_STOCK_HOME},
656 {"Up", N_("Up"), GTK_STOCK_GO_UP},
657 {"NextPage", N_("Next Page"), PIXBUF_INLINE_ICON_NEXT_PAGE},
658 {"PrevPage", N_("Previous Page"), PIXBUF_INLINE_ICON_PREVIOUS_PAGE},
659 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
660 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
661 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
662 {"Search", N_("Search"), GTK_STOCK_FIND},
663 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
664 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
665 {"Copy", N_("Copy"), GTK_STOCK_COPY},
666 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
667 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
668 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
669 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
670 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
671 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
672 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
673 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
674 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
675 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
676 {"Print", N_("Print"), GTK_STOCK_PRINT},
677 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
678 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
679 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
680 {"RotateCW", N_("Rotate clockwise"), PIXBUF_INLINE_ICON_CW},
681 {"RotateCCW", N_("Rotate counterclockwise"), PIXBUF_INLINE_ICON_CCW},
682 {"Rotate180", N_("Rotate 180"), PIXBUF_INLINE_ICON_180},
683 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
684 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
685 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
686 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
687 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
688 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
689 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
690 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
691 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
692 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
693 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
694 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
695 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
696 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
697 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
698 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
699 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
700 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
701 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
702 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
703 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
704 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
705 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
706 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
707 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
708 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
709 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
710 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
711 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
712 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
713 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
714 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
715 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
719 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
721 gchar **option = data;
724 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
726 const UseableMouseItems *list = useable_mouse_items;
730 if (g_strcmp0(list->label, label) == 0)
738 *option = g_strdup(list->name);
742 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
743 gchar *option, gchar **option_c)
751 pref_table_label(table, column, row, text, 0.0);
753 combo = gtk_combo_box_text_new();
755 const UseableMouseItems *list = useable_mouse_items;
759 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
760 if (g_strcmp0(list->name, option) == 0)
768 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
770 g_signal_connect(G_OBJECT(combo), "changed",
771 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
773 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
774 GTK_EXPAND | GTK_FILL, 0, 0, 0);
775 gtk_widget_show(combo);
778 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
782 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
785 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
787 c_options->thumbnails.max_width = thumb_size_list[n].w;
788 c_options->thumbnails.max_height = thumb_size_list[n].h;
792 c_options->thumbnails.max_width = options->thumbnails.max_width;
793 c_options->thumbnails.max_height = options->thumbnails.max_height;
797 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
803 c_options->thumbnails.max_width = options->thumbnails.max_width;
804 c_options->thumbnails.max_height = options->thumbnails.max_height;
806 pref_table_label(table, column, row, text, 0.0);
808 combo = gtk_combo_box_text_new();
811 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
816 w = thumb_size_list[i].w;
817 h = thumb_size_list[i].h;
819 buf = g_strdup_printf("%d x %d", w, h);
820 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
823 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
830 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
831 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
837 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
838 g_signal_connect(G_OBJECT(combo), "changed",
839 G_CALLBACK(thumb_size_menu_cb), NULL);
841 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
842 GTK_EXPAND | GTK_FILL, 0, 0, 0);
843 gtk_widget_show(combo);
846 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
850 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
854 *option = PR_STEREO_NONE;
857 *option = PR_STEREO_ANAGLYPH_RC;
860 *option = PR_STEREO_ANAGLYPH_GM;
863 *option = PR_STEREO_ANAGLYPH_YB;
866 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
869 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
872 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
875 *option = PR_STEREO_ANAGLYPH_DB_RC;
878 *option = PR_STEREO_ANAGLYPH_DB_GM;
881 *option = PR_STEREO_ANAGLYPH_DB_YB;
884 *option = PR_STEREO_HORIZ;
887 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
890 *option = PR_STEREO_VERT;
893 *option = PR_STEREO_VERT | PR_STEREO_HALF;
896 *option = PR_STEREO_FIXED;
901 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
902 gint option, gint *option_c, gboolean add_fixed)
909 pref_table_label(table, column, row, text, 0.0);
911 combo = gtk_combo_box_text_new();
913 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
915 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
916 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
917 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
918 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
919 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
920 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
921 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
922 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
923 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
924 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
925 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
926 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
927 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
928 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
929 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
930 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
931 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
932 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
934 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
935 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
936 if (option & PR_STEREO_HORIZ)
939 if (option & PR_STEREO_HALF) current = 11;
942 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
943 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
944 if (option & PR_STEREO_VERT)
947 if (option & PR_STEREO_HALF) current = 13;
952 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
953 if (option & PR_STEREO_FIXED) current = 14;
956 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
958 g_signal_connect(G_OBJECT(combo), "changed",
959 G_CALLBACK(stereo_mode_menu_cb), option_c);
961 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
962 GTK_EXPAND | GTK_FILL, 0, 0, 0);
963 gtk_widget_show(combo);
966 static void video_menu_cb(GtkWidget *combo, gpointer data)
968 gchar **option = data;
970 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
974 static void video_menu_populate(gpointer data, gpointer user_data)
976 GtkWidget *combo = user_data;
977 EditorDescription *ed = data;
979 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
982 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
983 gchar *option, gchar **option_c)
987 /* use lists since they are sorted */
988 GList *eds = editor_list_get();
992 pref_table_label(table, column, row, text, 0.0);
994 combo = gtk_combo_box_text_new();
995 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
996 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
998 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1000 g_signal_connect(G_OBJECT(combo), "changed",
1001 G_CALLBACK(video_menu_cb), option_c);
1003 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
1004 GTK_EXPAND | GTK_FILL, 0, 0, 0);
1005 gtk_widget_show(combo);
1008 static void filter_store_populate(void)
1012 if (!filter_store) return;
1014 gtk_list_store_clear(filter_store);
1016 work = filter_get_list();
1025 gtk_list_store_append(filter_store, &iter);
1026 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1030 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1031 gchar *new_text, gpointer data)
1033 GtkWidget *model = data;
1034 FilterEntry *fe = data;
1038 if (!new_text || strlen(new_text) < 1) return;
1040 tpath = gtk_tree_path_new_from_string(path_str);
1041 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1042 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1044 g_free(fe->extensions);
1045 fe->extensions = g_strdup(new_text);
1047 gtk_tree_path_free(tpath);
1051 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1052 gchar *new_text, gpointer data)
1054 GtkWidget *model = data;
1055 FilterEntry *fe = data;
1060 if (!new_text || !new_text[0]) return;
1062 tpath = gtk_tree_path_new_from_string(path_str);
1063 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1064 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1066 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1068 if (strcmp(new_text, _(format_class_list[i])) == 0)
1075 gtk_tree_path_free(tpath);
1079 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1080 gchar *new_text, gpointer data)
1082 GtkWidget *model = data;
1087 if (!new_text || !new_text[0]) return;
1089 tpath = gtk_tree_path_new_from_string(path_str);
1090 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1091 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1093 g_free(fe->description);
1094 fe->description = g_strdup(new_text);
1096 gtk_tree_path_free(tpath);
1099 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1100 gchar *path_str, gpointer data)
1102 GtkWidget *model = data;
1107 tpath = gtk_tree_path_new_from_string(path_str);
1108 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1109 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1111 fe->enabled = !fe->enabled;
1113 gtk_tree_path_free(tpath);
1117 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1118 gchar *path_str, gpointer data)
1120 GtkWidget *model = data;
1125 tpath = gtk_tree_path_new_from_string(path_str);
1126 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1127 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1129 fe->writable = !fe->writable;
1130 if (fe->writable) fe->allow_sidecar = FALSE;
1132 gtk_tree_path_free(tpath);
1136 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1137 gchar *path_str, gpointer data)
1139 GtkWidget *model = data;
1144 tpath = gtk_tree_path_new_from_string(path_str);
1145 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1146 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1148 fe->allow_sidecar = !fe->allow_sidecar;
1149 if (fe->allow_sidecar) fe->writable = FALSE;
1151 gtk_tree_path_free(tpath);
1155 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1156 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1160 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1162 switch (GPOINTER_TO_INT(data))
1165 g_object_set(GTK_CELL_RENDERER(cell),
1166 "active", fe->enabled, NULL);
1169 g_object_set(GTK_CELL_RENDERER(cell),
1170 "text", fe->extensions, NULL);
1172 case FE_DESCRIPTION:
1173 g_object_set(GTK_CELL_RENDERER(cell),
1174 "text", fe->description, NULL);
1177 g_object_set(GTK_CELL_RENDERER(cell),
1178 "text", _(format_class_list[fe->file_class]), NULL);
1181 g_object_set(GTK_CELL_RENDERER(cell),
1182 "active", fe->writable, NULL);
1184 case FE_ALLOW_SIDECAR:
1185 g_object_set(GTK_CELL_RENDERER(cell),
1186 "active", fe->allow_sidecar, NULL);
1191 static gboolean filter_add_scroll(gpointer data)
1195 GtkCellRenderer *cell;
1196 GtkTreeViewColumn *column;
1201 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1202 path = gtk_tree_path_new_from_indices(rows-1, -1);
1204 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1206 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1207 cell = g_list_last(list_cells)->data;
1209 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1210 path, column, FALSE, 0.0, 0.0 );
1211 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1212 path, column, cell, TRUE);
1214 gtk_tree_path_free(path);
1215 g_list_free(list_cells);
1220 static void filter_add_cb(GtkWidget *widget, gpointer data)
1222 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1223 filter_store_populate();
1225 g_idle_add((GSourceFunc)filter_add_scroll, data);
1228 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1230 GtkWidget *filter_view = data;
1231 GtkTreeSelection *selection;
1235 if (!filter_store) return;
1236 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1237 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1238 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1241 filter_remove_entry(fe);
1243 filter_store_populate();
1246 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1250 GtkTreeViewColumn *column;
1252 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1253 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1254 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1256 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1260 gtk_tree_path_free(path);
1265 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1268 filter_add_defaults();
1270 filter_store_populate();
1272 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1275 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1277 /* no op, only so cancel button appears */
1280 static void filter_default_cb(GtkWidget *widget, gpointer data)
1284 gd = generic_dialog_new(_("Reset filters"),
1285 "reset_filter", widget, TRUE,
1286 dummy_cancel_cb, data);
1287 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1288 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1289 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1290 gtk_widget_show(gd->dialog);
1293 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1295 GtkWidget *frame = data;
1297 gtk_widget_set_sensitive(frame,
1298 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1301 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1303 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1306 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1308 file_util_trash_clear();
1311 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1315 gd = generic_dialog_new(_("Clear trash"),
1316 "clear_trash", widget, TRUE,
1317 dummy_cancel_cb, NULL);
1318 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1319 _("This will remove the trash contents."), FALSE);
1320 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1321 entry = gtk_entry_new();
1322 gtk_widget_set_can_focus(entry, FALSE);
1323 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1324 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1325 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1326 gtk_widget_show(entry);
1327 gtk_widget_show(gd->dialog);
1330 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1332 GtkWidget *pTextView;
1333 GtkTextBuffer *pTextBuffer;
1337 pTextView = GTK_WIDGET(data);
1339 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1340 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1341 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1343 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1344 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1347 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1349 GtkTextView *text_view = data;
1350 GtkTextBuffer *buffer;
1352 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1353 if (!configwindow) return;
1355 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1356 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1359 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1363 gd = generic_dialog_new(_("Reset image overlay template string"),
1364 "reset_image_overlay_template_string", widget, TRUE,
1365 dummy_cancel_cb, data);
1366 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1367 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1368 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1369 gtk_widget_show(gd->dialog);
1372 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1374 help_window_show("GuideOptionsOSD.html");
1377 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1379 #if GTK_CHECK_VERSION(3,4,0)
1382 PangoFontDescription *font_desc;
1384 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1385 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1387 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1389 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1390 font = pango_font_description_to_string(font_desc);
1391 g_free(c_options->image_overlay.font);
1392 c_options->image_overlay.font = g_strdup(font);
1396 gtk_widget_destroy(dialog);
1400 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1401 c_options->image_overlay.font = g_strdup(font);
1405 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1408 #if GTK_CHECK_VERSION(3,4,0)
1411 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1412 colour.red = options->image_overlay.text_red;
1413 colour.green = options->image_overlay.text_green;
1414 colour.blue = options->image_overlay.text_blue;
1415 colour.alpha = options->image_overlay.text_alpha;
1416 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1417 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1419 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1421 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1422 c_options->image_overlay.text_red = colour.red*255;
1423 c_options->image_overlay.text_green = colour.green*255;
1424 c_options->image_overlay.text_blue = colour.blue*255;
1425 c_options->image_overlay.text_alpha = colour.alpha*255;
1427 gtk_widget_destroy(dialog);
1430 GtkColorSelection *colorsel;
1432 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1433 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1434 colour.red = options->image_overlay.text_red*257;
1435 colour.green = options->image_overlay.text_green*257;
1436 colour.blue = options->image_overlay.text_blue*257;
1437 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1438 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1439 gtk_color_selection_set_current_color(colorsel, &colour);
1440 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1442 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1444 gtk_color_selection_get_current_color(colorsel, &colour);
1445 c_options->image_overlay.text_red = colour.red/257;
1446 c_options->image_overlay.text_green = colour.green/257;
1447 c_options->image_overlay.text_blue = colour.blue/257;
1448 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1450 gtk_widget_destroy (dialog);
1455 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1458 #if GTK_CHECK_VERSION(3,4,0)
1461 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1462 colour.red = options->image_overlay.background_red;
1463 colour.green = options->image_overlay.background_green;
1464 colour.blue = options->image_overlay.background_blue;
1465 colour.alpha = options->image_overlay.background_alpha;
1466 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1467 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1469 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1471 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1472 c_options->image_overlay.background_red = colour.red*255;
1473 c_options->image_overlay.background_green = colour.green*255;
1474 c_options->image_overlay.background_blue = colour.blue*255;
1475 c_options->image_overlay.background_alpha = colour.alpha*255;
1477 gtk_widget_destroy(dialog);
1480 GtkColorSelection *colorsel;
1482 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1483 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1484 colour.red = options->image_overlay.background_red*257;
1485 colour.green = options->image_overlay.background_green*257;
1486 colour.blue = options->image_overlay.background_blue*257;
1487 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1488 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1489 gtk_color_selection_set_current_color(colorsel, &colour);
1490 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1492 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1494 gtk_color_selection_get_current_color(colorsel, &colour);
1495 c_options->image_overlay.background_red = colour.red/257;
1496 c_options->image_overlay.background_green = colour.green/257;
1497 c_options->image_overlay.background_blue = colour.blue/257;
1498 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1500 gtk_widget_destroy(dialog);
1504 static void accel_store_populate(void)
1507 GList *groups, *actions;
1509 const gchar *accel_path;
1513 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1515 gtk_tree_store_clear(accel_store);
1516 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1518 g_assert(lw && lw->ui_manager);
1519 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1522 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1525 action = GTK_ACTION(actions->data);
1526 accel_path = gtk_action_get_accel_path(action);
1527 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1529 gchar *label, *label2, *tooltip, *accel;
1530 g_object_get(action,
1531 "tooltip", &tooltip,
1535 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1541 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1545 gtk_tree_store_append(accel_store, &iter, NULL);
1546 gtk_tree_store_set(accel_store, &iter,
1549 AE_TOOLTIP, tooltip ? tooltip : "",
1550 AE_ACCEL, accel_path,
1558 actions = actions->next;
1561 groups = groups->next;
1565 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1570 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1572 gchar *accel1 = data;
1577 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1579 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1580 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1582 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1584 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1585 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1594 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1596 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1600 GtkAccelKey old_key, key;
1601 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1603 gtk_tree_model_get_iter(model, &iter, path);
1604 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1606 /* test if the accelerator can be stored without conflicts*/
1607 gtk_accel_map_lookup_entry(accel_path, &old_key);
1609 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1610 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1611 gtk_accel_map_lookup_entry(accel_path, &key);
1613 /* restore the original for now, the key will be really changed when the changes are confirmed */
1614 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1616 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1617 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1619 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1620 gtk_tree_path_free(path);
1624 static gboolean accel_default_scroll(GtkTreeView *data)
1628 GtkTreeViewColumn *column;
1630 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1631 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1632 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1634 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1638 gtk_tree_path_free(path);
1643 static void accel_default_cb(GtkWidget *widget, gpointer data)
1645 accel_store_populate();
1647 g_idle_add((GSourceFunc)accel_default_scroll, data);
1650 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1652 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1655 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1658 gchar *accel_path, *accel;
1660 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1661 gtk_accel_map_lookup_entry(accel_path, &key);
1662 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1664 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1666 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1671 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1673 GtkTreeSelection *selection;
1675 if (!accel_store) return;
1676 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1677 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1682 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1686 GtkWidget *scrolled;
1687 GtkWidget *viewport;
1689 scrolled = gtk_scrolled_window_new(NULL, NULL);
1690 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1691 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1692 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1693 label = gtk_label_new(title);
1694 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1695 gtk_widget_show(scrolled);
1697 viewport = gtk_viewport_new(NULL, NULL);
1698 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1699 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1700 gtk_widget_show(viewport);
1702 vbox = gtk_vbox_new(FALSE, 0);
1703 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1704 gtk_widget_show(vbox);
1709 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1711 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1713 c_options->thumbnails.spec_standard =TRUE;
1714 c_options->thumbnails.cache_into_dirs = FALSE;
1718 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1720 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1722 c_options->thumbnails.spec_standard =FALSE;
1723 c_options->thumbnails.cache_into_dirs = FALSE;
1727 static void cache_local_cb(GtkWidget *widget, gpointer data)
1729 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1731 c_options->thumbnails.cache_into_dirs = TRUE;
1732 c_options->thumbnails.spec_standard =FALSE;
1736 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1737 GdkEvent *event, gpointer userdata)
1739 if (pos == GTK_ENTRY_ICON_PRIMARY)
1741 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1745 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1749 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1750 GdkEvent *event, gpointer userdata)
1752 gchar *rating_symbol;
1754 if (pos == GTK_ENTRY_ICON_PRIMARY)
1756 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1757 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1758 g_free(rating_symbol);
1762 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1763 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1764 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1768 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1769 GdkEvent *event, gpointer userdata)
1771 gchar *rating_symbol;
1773 if (pos == GTK_ENTRY_ICON_PRIMARY)
1775 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1776 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1777 g_free(rating_symbol);
1781 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1782 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1783 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1787 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1789 GtkContainer *hbox = data;
1790 GString *str = g_string_new(NULL);
1791 GtkEntry *hex_code_entry;
1792 gchar *hex_code_full;
1795 guint64 hex_value = 0;
1797 list = gtk_container_get_children(hbox);
1799 hex_code_entry = g_list_nth_data(list, 2);
1800 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1802 hex_code = g_strsplit(hex_code_full, "+", 2);
1803 if (hex_code[0] && hex_code[1])
1805 hex_value = strtoull(hex_code[1], NULL, 16);
1807 if (!hex_value || hex_value > 0x10FFFF)
1809 hex_value = 0x003F; // Unicode 'Question Mark'
1811 str = g_string_append_unichar(str, (gunichar)hex_value);
1812 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1814 g_strfreev(hex_code);
1815 g_string_free(str, TRUE);
1816 g_free(hex_code_full);
1821 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1823 guint64 star_symbol;
1825 star_symbol = star_rating_symbol_test(widget, data);
1826 c_options->star_rating.star = star_symbol;
1829 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1831 guint64 rejected_symbol;
1833 rejected_symbol = star_rating_symbol_test(widget, data);
1834 c_options->star_rating.rejected = rejected_symbol;
1837 /* general options tab */
1838 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1839 typedef struct _TZData TZData;
1843 GCancellable *cancellable;
1845 GtkWidget *progress;
1847 GFile *timezone_database_gq;
1848 gchar *timezone_database_user;
1851 static void config_tab_general(GtkWidget *notebook)
1856 GtkWidget *group_frame;
1857 GtkWidget *subgroup;
1859 GtkWidget *ct_button;
1862 gint hours, minutes, remainder;
1864 GtkWidget *star_rating_entry;
1866 gchar *rating_symbol;
1869 GNetworkMonitor *net_mon;
1870 GSocketConnectable *geeqie_org;
1871 gboolean internet_available;
1874 vbox = scrolled_notebook_page(notebook, _("General"));
1876 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1878 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1879 add_thumb_size_menu(table, 0, 0, _("Size:"));
1880 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1882 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1883 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1885 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1886 pref_checkbox_link_sensitivity(ct_button, subgroup);
1888 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1889 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1890 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1891 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1892 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1893 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1894 G_CALLBACK(cache_geeqie_cb), NULL);
1896 group_frame = pref_frame_new(subgroup, TRUE,
1897 _("Store thumbnails local to image folder (non-standard)"),
1898 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1899 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1900 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1901 G_CALLBACK(cache_local_cb), NULL);
1903 group_frame = pref_frame_new(subgroup, TRUE,
1904 _("Use standard thumbnail style and cache, shared with other applications"),
1905 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1906 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1907 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1908 G_CALLBACK(cache_standard_cb), NULL);
1910 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1911 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1913 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1915 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1916 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1918 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1919 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1920 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1922 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1923 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1926 pref_spacer(group, PREF_PAD_GROUP);
1928 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1930 c_options->star_rating.star = options->star_rating.star;
1931 c_options->star_rating.rejected = options->star_rating.rejected;
1933 str = g_string_new(NULL);
1934 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1935 pref_label_new(hbox, "Star character: ");
1936 str = g_string_append_unichar(str, options->star_rating.star);
1937 pref_label_new(hbox, g_strdup(str->str));
1938 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1939 star_rating_entry = gtk_entry_new();
1940 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1941 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1942 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1943 gtk_widget_show(star_rating_entry);
1944 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1945 G_CALLBACK(star_rating_star_test_cb), hbox);
1946 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1947 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1948 gtk_widget_show(button);
1949 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."));
1950 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1951 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1952 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1953 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1954 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1955 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1956 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1957 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1958 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1959 G_CALLBACK(star_rating_star_icon_cb),
1962 g_string_free(str, TRUE);
1963 g_free(rating_symbol);
1965 str = g_string_new(NULL);
1966 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1967 pref_label_new(hbox, "Rejected character: ");
1968 str = g_string_append_unichar(str, options->star_rating.rejected);
1969 pref_label_new(hbox, g_strdup(str->str));
1970 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1971 star_rating_entry = gtk_entry_new();
1972 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1973 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1974 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1975 gtk_widget_show(star_rating_entry);
1976 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1977 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1978 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1979 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1980 gtk_widget_show(button);
1981 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."));
1982 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1983 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1984 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1985 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1986 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1987 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1988 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1989 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1990 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1991 G_CALLBACK(star_rating_rejected_icon_cb),
1994 g_string_free(str, TRUE);
1995 g_free(rating_symbol);
1997 pref_spacer(group, PREF_PAD_GROUP);
1999 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2001 c_options->slideshow.delay = options->slideshow.delay;
2002 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2003 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2004 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2005 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2006 SLIDESHOW_SUBSECOND_PRECISION;
2008 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2010 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2012 options->slideshow.delay ? hours : 0.0,
2013 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2014 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2015 spin = pref_spin_new(hbox, ":" , NULL,
2017 options->slideshow.delay ? minutes: 0.0,
2018 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2019 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2020 spin = pref_spin_new(hbox, ":", NULL,
2021 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2022 options->slideshow.delay ? seconds : 10.0,
2023 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2024 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2026 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2027 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2029 pref_spacer(group, PREF_PAD_GROUP);
2031 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2033 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2034 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2035 pref_checkbox_new_int(group, _("Preload next image"),
2036 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2038 pref_checkbox_new_int(group, _("Refresh on file change"),
2039 options->update_on_time_change, &c_options->update_on_time_change);
2041 pref_spacer(group, PREF_PAD_GROUP);
2043 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2044 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2045 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2046 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2048 options->info_keywords.height, &c_options->info_keywords.height);
2049 pref_spin_new_int(hbox, _("Title:"), NULL,
2051 options->info_title.height, &c_options->info_title.height);
2052 pref_spin_new_int(hbox, _("Comment:"), NULL,
2054 options->info_comment.height, &c_options->info_comment.height);
2055 pref_spin_new_int(hbox, _("Rating:"), NULL,
2057 options->info_rating.height, &c_options->info_rating.height);
2059 pref_spacer(group, PREF_PAD_GROUP);
2061 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2063 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2064 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2066 pref_spacer(group, PREF_PAD_GROUP);
2068 net_mon = g_network_monitor_get_default();
2069 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2070 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2071 g_object_unref(geeqie_org);
2073 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2074 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2076 if (!internet_available)
2078 gtk_widget_set_sensitive(group, FALSE);
2081 tz = g_new0(TZData, 1);
2083 path = path_from_utf8(TIMEZONE_DATABASE);
2084 basename = g_path_get_basename(path);
2085 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2089 if (isfile(tz->timezone_database_user))
2091 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2095 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2098 if (!internet_available)
2100 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"));
2104 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"));
2106 gtk_widget_show(button);
2108 pref_spacer(group, PREF_PAD_GROUP);
2110 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2112 help_search_engine_entry = gtk_entry_new();
2113 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2114 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2115 gtk_widget_show(help_search_engine_entry);
2117 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"));
2119 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2120 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2121 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2122 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2123 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2124 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2125 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2126 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2127 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2128 G_CALLBACK(help_search_engine_entry_icon_cb),
2129 help_search_engine_entry);
2133 static void config_tab_image(GtkWidget *notebook)
2138 GtkWidget *ct_button;
2139 GtkWidget *enlargement_button;
2143 vbox = scrolled_notebook_page(notebook, _("Image"));
2145 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2147 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2148 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2151 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2152 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2155 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2156 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2158 c_options->image.zoom_increment = options->image.zoom_increment;
2159 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2160 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2161 G_CALLBACK(zoom_increment_cb), NULL);
2162 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2164 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2166 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2167 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2168 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2169 spin = pref_spin_new_int(hbox, NULL, NULL,
2171 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2172 pref_checkbox_link_sensitivity(enlargement_button, spin);
2173 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."));
2175 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2176 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2177 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2178 spin = pref_spin_new_int(hbox, NULL, NULL,
2180 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2181 pref_checkbox_link_sensitivity(ct_button, spin);
2182 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."));
2184 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2186 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2187 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2189 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2190 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2192 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2193 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2195 c_options->image.border_color = options->image.border_color;
2197 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2198 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2200 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2201 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2203 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2204 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2206 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2208 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2209 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2213 static void config_tab_windows(GtkWidget *notebook)
2219 GtkWidget *ct_button;
2222 vbox = scrolled_notebook_page(notebook, _("Windows"));
2224 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2226 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2227 options->save_window_positions, &c_options->save_window_positions);
2229 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2230 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2231 pref_checkbox_link_sensitivity(ct_button, button);
2233 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2234 options->tools_restore_state, &c_options->tools_restore_state);
2236 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2237 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2239 pref_checkbox_new_int(group, _("Show window IDs"),
2240 options->show_window_ids, &c_options->show_window_ids);
2242 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2244 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2245 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2247 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2248 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2249 options->image.limit_window_size, &c_options->image.limit_window_size);
2250 spin = pref_spin_new_int(hbox, NULL, NULL,
2252 options->image.max_window_size, &c_options->image.max_window_size);
2253 pref_checkbox_link_sensitivity(ct_button, spin);
2255 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2257 c_options->fullscreen.screen = options->fullscreen.screen;
2258 c_options->fullscreen.above = options->fullscreen.above;
2259 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2260 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2261 gtk_widget_show(hbox);
2263 pref_checkbox_new_int(group, _("Smooth image flip"),
2264 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2265 pref_checkbox_new_int(group, _("Disable screen saver"),
2266 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2269 #define PRE_FORMATTED_COLUMNS 5
2270 static void config_tab_osd(GtkWidget *notebook)
2274 GtkWidget *vbox_buttons;
2277 GtkWidget *image_overlay_template_view;
2278 GtkWidget *scrolled;
2279 GtkWidget *scrolled_pre_formatted;
2280 GtkTextBuffer *buffer;
2282 GtkWidget * subgroup;
2287 vbox = scrolled_notebook_page(notebook, _("OSD"));
2289 image_overlay_template_view = gtk_text_view_new();
2291 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2293 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2295 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2296 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2297 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2298 gtk_widget_show(scrolled_pre_formatted);
2299 gtk_widget_show(subgroup);
2301 pref_line(group, PREF_PAD_GAP);
2303 pref_label_new(group, _("Image overlay template"));
2305 scrolled = gtk_scrolled_window_new(NULL, NULL);
2306 gtk_widget_set_size_request(scrolled, 200, 150);
2307 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2308 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2309 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2310 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2311 gtk_widget_show(scrolled);
2313 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2314 _("Extensive formatting options are shown in the Help file"));
2316 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2317 gtk_widget_show(image_overlay_template_view);
2319 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2321 #if GTK_CHECK_VERSION(3,4,0)
2322 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2323 G_CALLBACK(image_overlay_set_font_cb), notebook);
2325 button = gtk_font_button_new();
2326 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2327 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2328 g_signal_connect(G_OBJECT(button), "font-set",
2329 G_CALLBACK(image_overlay_set_font_cb),NULL);
2331 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2332 gtk_widget_show(button);
2334 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2335 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2336 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2337 gtk_widget_show(button);
2339 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2340 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2341 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2342 gtk_widget_show(button);
2343 image_overlay_set_text_colours();
2345 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2346 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2347 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2348 gtk_widget_show(button);
2350 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2351 G_CALLBACK(image_overlay_help_cb), NULL);
2352 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2353 gtk_widget_show(button);
2355 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2356 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2357 g_signal_connect(G_OBJECT(buffer), "changed",
2358 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2360 pref_line(group, PREF_PAD_GAP);
2362 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2363 hbox = gtk_hbox_new(FALSE, 0);
2364 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2365 gtk_widget_show(hbox);
2366 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2367 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2368 gtk_widget_show(label);
2369 pref_spacer(group,TRUE);
2371 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2372 hbox = gtk_hbox_new(FALSE, 0);
2373 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2374 gtk_widget_show(hbox);
2375 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2376 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2377 gtk_widget_show(label);
2378 pref_spacer(group,TRUE);
2380 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2381 hbox = gtk_hbox_new(FALSE, 0);
2382 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2383 gtk_widget_show(hbox);
2384 label = gtk_label_new(_("%path:39%"));
2385 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2386 gtk_widget_show(label);
2387 pref_spacer(group,TRUE);
2389 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2390 hbox = gtk_hbox_new(FALSE, 0);
2391 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2392 gtk_widget_show(hbox);
2393 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%"));
2394 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2395 gtk_widget_show(label);
2396 pref_spacer(group,TRUE);
2398 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2399 hbox = gtk_hbox_new(FALSE, 0);
2400 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2401 gtk_widget_show(hbox);
2402 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2403 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2404 gtk_widget_show(label);
2407 static GtkTreeModel *create_class_model(void)
2409 GtkListStore *model;
2413 /* create list store */
2414 model = gtk_list_store_new(1, G_TYPE_STRING);
2415 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2417 gtk_list_store_append(model, &iter);
2418 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2420 return GTK_TREE_MODEL (model);
2425 static void config_tab_files(GtkWidget *notebook)
2432 GtkWidget *ct_button;
2433 GtkWidget *scrolled;
2434 GtkWidget *filter_view;
2435 GtkCellRenderer *renderer;
2436 GtkTreeSelection *selection;
2437 GtkTreeViewColumn *column;
2439 vbox = scrolled_notebook_page(notebook, _("Files"));
2441 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2443 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2444 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2445 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2446 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2447 pref_checkbox_new_int(group, _("Case sensitive sort"),
2448 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2449 pref_checkbox_new_int(group, _("Natural sort order"),
2450 options->file_sort.natural, &c_options->file_sort.natural);
2451 pref_checkbox_new_int(group, _("Disable file extension checks"),
2452 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2454 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2455 options->file_filter.disable, &c_options->file_filter.disable);
2458 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2460 sidecar_ext_entry = gtk_entry_new();
2461 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2462 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2463 gtk_widget_show(sidecar_ext_entry);
2465 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2467 frame = pref_group_parent(group);
2468 g_signal_connect(G_OBJECT(ct_button), "toggled",
2469 G_CALLBACK(filter_disable_cb), frame);
2470 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2472 scrolled = gtk_scrolled_window_new(NULL, NULL);
2473 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2474 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2475 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2476 gtk_widget_show(scrolled);
2478 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2479 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2480 g_object_unref(filter_store);
2481 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2482 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2484 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2486 column = gtk_tree_view_column_new();
2487 gtk_tree_view_column_set_title(column, _("Filter"));
2488 gtk_tree_view_column_set_resizable(column, TRUE);
2490 renderer = gtk_cell_renderer_toggle_new();
2491 g_signal_connect(G_OBJECT(renderer), "toggled",
2492 G_CALLBACK(filter_store_enable_cb), filter_store);
2493 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2494 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2495 GINT_TO_POINTER(FE_ENABLE), NULL);
2497 renderer = gtk_cell_renderer_text_new();
2498 g_signal_connect(G_OBJECT(renderer), "edited",
2499 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2500 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2501 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2502 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2503 GINT_TO_POINTER(FE_EXTENSION), NULL);
2504 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2506 column = gtk_tree_view_column_new();
2507 gtk_tree_view_column_set_title(column, _("Description"));
2508 gtk_tree_view_column_set_resizable(column, TRUE);
2509 gtk_tree_view_column_set_fixed_width(column, 200);
2510 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2512 renderer = gtk_cell_renderer_text_new();
2513 g_signal_connect(G_OBJECT(renderer), "edited",
2514 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2515 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2516 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2517 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2518 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2519 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2521 column = gtk_tree_view_column_new();
2522 gtk_tree_view_column_set_title(column, _("Class"));
2523 gtk_tree_view_column_set_resizable(column, TRUE);
2524 renderer = gtk_cell_renderer_combo_new();
2525 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2526 "model", create_class_model(),
2531 g_signal_connect(G_OBJECT(renderer), "edited",
2532 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2533 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2534 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2535 GINT_TO_POINTER(FE_CLASS), NULL);
2536 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2538 column = gtk_tree_view_column_new();
2539 gtk_tree_view_column_set_title(column, _("Writable"));
2540 gtk_tree_view_column_set_resizable(column, FALSE);
2541 renderer = gtk_cell_renderer_toggle_new();
2542 g_signal_connect(G_OBJECT(renderer), "toggled",
2543 G_CALLBACK(filter_store_writable_cb), filter_store);
2544 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2545 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2546 GINT_TO_POINTER(FE_WRITABLE), NULL);
2547 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2549 column = gtk_tree_view_column_new();
2550 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2551 gtk_tree_view_column_set_resizable(column, FALSE);
2552 renderer = gtk_cell_renderer_toggle_new();
2553 g_signal_connect(G_OBJECT(renderer), "toggled",
2554 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2555 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2556 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2557 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2558 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2561 filter_store_populate();
2562 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2563 gtk_widget_show(filter_view);
2565 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2567 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2568 G_CALLBACK(filter_default_cb), filter_view);
2569 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2570 gtk_widget_show(button);
2572 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2573 G_CALLBACK(filter_remove_cb), filter_view);
2574 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2575 gtk_widget_show(button);
2577 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2578 G_CALLBACK(filter_add_cb), filter_view);
2579 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2580 gtk_widget_show(button);
2584 static void config_tab_metadata(GtkWidget *notebook)
2589 GtkWidget *ct_button;
2593 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2596 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2598 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2600 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2601 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2603 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2604 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2606 gtk_widget_set_sensitive(ct_button, FALSE);
2609 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2610 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2612 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2613 label = pref_label_new(group, text);
2614 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2615 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2618 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2620 gtk_widget_set_sensitive(group, FALSE);
2623 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2624 pref_checkbox_link_sensitivity(ct_button, hbox);
2626 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2627 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2629 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2630 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2632 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2633 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2635 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2636 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2638 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2640 gtk_widget_set_sensitive(group, FALSE);
2643 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2644 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2647 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2648 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2649 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2651 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2652 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2654 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2655 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2657 gtk_widget_set_sensitive(ct_button, FALSE);
2660 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2662 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2663 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2665 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2666 pref_checkbox_link_sensitivity(ct_button, hbox);
2668 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2669 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2671 pref_checkbox_new_int(group, _("Write metadata on image change"),
2672 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2674 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2675 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2677 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2679 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2680 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2681 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");
2686 typedef struct _KeywordFindData KeywordFindData;
2687 struct _KeywordFindData
2694 GtkWidget *button_close;
2695 GtkWidget *button_stop;
2696 GtkWidget *button_start;
2697 GtkWidget *progress;
2705 guint idle_id; /* event source id */
2708 #define KEYWORD_DIALOG_WIDTH 400
2710 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2712 GList *list_d = NULL;
2713 GList *list_f = NULL;
2717 filelist_read(dir_fd, &list_f, &list_d);
2721 filelist_read(dir_fd, &list_f, NULL);
2724 list_f = filelist_filter(list_f, FALSE);
2725 list_d = filelist_filter(list_d, TRUE);
2727 kfd->list = g_list_concat(list_f, kfd->list);
2728 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2731 static void keywords_find_reset(KeywordFindData *kfd)
2733 filelist_free(kfd->list);
2736 filelist_free(kfd->list_dir);
2737 kfd->list_dir = NULL;
2740 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2742 KeywordFindData *kfd = data;
2744 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2746 keywords_find_reset(kfd);
2747 generic_dialog_close(kfd->gd);
2751 static void keywords_find_finish(KeywordFindData *kfd)
2753 keywords_find_reset(kfd);
2755 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2756 spinner_set_interval(kfd->spinner, -1);
2758 gtk_widget_set_sensitive(kfd->group, TRUE);
2759 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2760 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2761 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2764 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2766 KeywordFindData *kfd = data;
2768 g_idle_remove_by_data(kfd);
2770 keywords_find_finish(kfd);
2773 static gboolean keywords_find_file(gpointer data)
2775 KeywordFindData *kfd = data;
2777 GtkTextBuffer *buffer;
2785 fd = kfd->list->data;
2786 kfd->list = g_list_remove(kfd->list, fd);
2788 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2789 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2793 gtk_text_buffer_get_end_iter(buffer, &iter);
2794 tmp = g_strconcat(keywords->data, "\n", NULL);
2795 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2797 keywords = keywords->next;
2800 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2801 file_data_unref(fd);
2802 string_list_free(keywords);
2806 else if (kfd->list_dir)
2810 fd = kfd->list_dir->data;
2811 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2813 keywords_find_folder(kfd, fd);
2815 file_data_unref(fd);
2820 keywords_find_finish(kfd);
2825 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2827 KeywordFindData *kfd = data;
2830 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2832 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2833 parse_out_relatives(path);
2837 warning_dialog(_("Invalid folder"),
2838 _("The specified folder can not be found."),
2839 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2845 gtk_widget_set_sensitive(kfd->group, FALSE);
2846 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2847 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2848 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2849 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2851 dir_fd = file_data_new_dir(path);
2852 keywords_find_folder(kfd, dir_fd);
2853 file_data_unref(dir_fd);
2854 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2860 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2862 KeywordFindData *kfd;
2866 kfd = g_new0(KeywordFindData, 1);
2868 kfd->gd = generic_dialog_new(_("Search for keywords"),
2869 "search_for_keywords",
2872 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2873 kfd->gd->cancel_cb = keywords_find_close_cb;
2874 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2875 keywords_find_close_cb, FALSE);
2876 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2877 keywords_find_start_cb, FALSE);
2878 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2879 keywords_find_stop_cb, FALSE);
2880 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2882 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2884 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2885 pref_spacer(hbox, PREF_PAD_INDENT);
2886 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2888 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2889 pref_label_new(hbox, _("Folder:"));
2891 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2892 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2893 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2894 gtk_widget_show(label);
2896 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2898 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2899 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2901 kfd->progress = gtk_entry_new();
2902 gtk_widget_set_can_focus(kfd->progress, FALSE);
2903 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2904 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2905 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2906 gtk_widget_show(kfd->progress);
2908 kfd->spinner = spinner_new(NULL, -1);
2909 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2910 gtk_widget_show(kfd->spinner);
2914 gtk_widget_show(kfd->gd->dialog);
2917 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2919 const gchar *path = layout_get_path(NULL);
2921 if (!path || !*path) path = homedir();
2922 keywords_find_dialog(widget, path);
2925 static void config_tab_keywords_save()
2927 GtkTextIter start, end;
2928 GtkTextBuffer *buffer;
2929 GList *kw_list = NULL;
2935 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2936 gtk_text_buffer_get_bounds(buffer, &start, &end);
2938 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2940 kw_split = strtok(buffer_text, "\n");
2941 while (kw_split != NULL)
2947 if (g_strcmp0(work->data, kw_split) == 0)
2956 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2958 kw_split = strtok(NULL, "\n");
2961 keyword_list_set(kw_list);
2963 string_list_free(kw_list);
2964 g_free(buffer_text);
2967 static void config_tab_keywords(GtkWidget *notebook)
2973 GtkWidget *scrolled;
2975 GtkTextBuffer *buffer;
2978 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2980 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2982 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2984 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2985 G_CALLBACK(keywords_find_cb), keyword_text);
2986 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2989 keyword_text = gtk_text_view_new();
2990 gtk_widget_set_size_request(keyword_text, 20, 20);
2991 scrolled = gtk_scrolled_window_new(NULL, NULL);
2992 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2993 gtk_widget_show(scrolled);
2995 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2996 gtk_widget_show(keyword_text);
2998 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3000 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3001 gtk_text_buffer_create_tag(buffer, "monospace",
3002 "family", "monospace", NULL);
3004 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3005 gtk_text_buffer_get_start_iter(buffer, &iter);
3006 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3009 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3011 GList *kwl = keyword_list_get();
3012 kwl = g_list_first(kwl);
3015 gtk_text_buffer_get_end_iter (buffer, &iter);
3016 tmp = g_strconcat(kwl->data, "\n", NULL);
3017 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3022 gtk_text_buffer_set_modified(buffer, FALSE);
3029 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3031 gint *option = data;
3033 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3037 *option = INTENT_PERCEPTUAL;
3040 *option = INTENT_RELATIVE_COLORIMETRIC;
3043 *option = INTENT_SATURATION;
3046 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3051 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3052 gint option, gint *option_c)
3059 pref_table_label(table, column, row, text, 0.0);
3061 combo = gtk_combo_box_text_new();
3063 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3064 if (option == INTENT_PERCEPTUAL) current = 0;
3065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3066 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3067 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3068 if (option == INTENT_SATURATION) current = 2;
3069 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3070 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3072 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3074 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3076 g_signal_connect(G_OBJECT(combo), "changed",
3077 G_CALLBACK(intent_menu_cb), option_c);
3079 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
3080 GTK_EXPAND | GTK_FILL, 0, 0, 0);
3081 gtk_widget_show(combo);
3085 static void config_tab_color(GtkWidget *notebook)
3094 vbox = scrolled_notebook_page(notebook, _("Color management"));
3096 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3098 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3101 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3102 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3104 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3105 pref_label_bold(label, TRUE, FALSE);
3107 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3108 pref_label_bold(label, TRUE, FALSE);
3110 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3111 pref_label_bold(label, TRUE, FALSE);
3113 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3118 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3119 pref_table_label(table, 0, i + 1, buf, 1.0);
3122 entry = gtk_entry_new();
3123 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3124 if (options->color_profile.input_name[i])
3126 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3128 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3129 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3130 gtk_widget_show(entry);
3131 color_profile_input_name_entry[i] = entry;
3133 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3134 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3135 gtk_widget_set_size_request(entry, 160, -1);
3136 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3137 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3138 gtk_widget_show(tabcomp);
3139 color_profile_input_file_entry[i] = entry;
3142 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3144 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3146 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3147 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3149 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3151 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3152 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3153 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3154 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3155 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3157 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3159 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3161 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3163 gtk_widget_show(tabcomp);
3166 /* advanced entry tab */
3167 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3169 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3171 c_options->file_ops.use_system_trash = FALSE;
3172 c_options->file_ops.no_trash = FALSE;
3176 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3178 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3180 c_options->file_ops.use_system_trash = TRUE;
3181 c_options->file_ops.no_trash = FALSE;
3185 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3187 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3189 c_options->file_ops.no_trash = TRUE;
3193 static void config_tab_behavior(GtkWidget *notebook)
3200 GtkWidget *ct_button;
3204 GtkWidget *with_rename;
3205 GtkWidget *collections_on_top;
3207 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3209 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3211 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3212 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3213 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3214 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3215 pref_checkbox_new_int(group, _("Enable Delete key"),
3216 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3218 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3219 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3221 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3222 pref_checkbox_link_sensitivity(ct_button, hbox);
3224 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3225 pref_label_new(hbox, _("Folder:"));
3227 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3228 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3229 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3230 gtk_widget_show(tabcomp);
3232 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3233 pref_checkbox_link_sensitivity(ct_button, hbox);
3235 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3236 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3237 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3238 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3239 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3240 G_CALLBACK(safe_delete_view_cb), NULL);
3241 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3242 gtk_widget_show(button);
3244 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3245 G_CALLBACK(safe_delete_clear_cb), NULL);
3246 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3247 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3248 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3250 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3251 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3253 gtk_widget_show(button);
3255 pref_spacer(group, PREF_PAD_GROUP);
3258 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3260 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3261 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3263 pref_checkbox_new_int(group, _("In place renaming"),
3264 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3266 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3267 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3269 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3270 options->marks_save, &c_options->marks_save);
3271 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3273 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3274 options->with_rename, &c_options->with_rename);
3275 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3277 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3278 options->collections_on_top, &c_options->collections_on_top);
3279 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3281 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3282 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3284 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3285 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3287 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3288 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3290 pref_spacer(group, PREF_PAD_GROUP);
3292 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3294 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3295 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3296 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3297 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3298 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3299 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3300 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3301 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3302 pref_checkbox_new_int(group, _("Play video by left click on image"),
3303 options->image_l_click_video, &c_options->image_l_click_video);
3304 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3305 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3307 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3308 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3309 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3310 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3311 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3314 pref_spacer(group, PREF_PAD_GROUP);
3316 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3318 pref_spin_new_int(group, _("Debug level:"), NULL,
3319 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3321 pref_checkbox_new_int(group, _("Timer data"),
3322 options->log_window.timer_data, &c_options->log_window.timer_data);
3324 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3325 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3329 /* accelerators tab */
3330 static void config_tab_accelerators(GtkWidget *notebook)
3336 GtkWidget *scrolled;
3337 GtkWidget *accel_view;
3338 GtkCellRenderer *renderer;
3339 GtkTreeSelection *selection;
3340 GtkTreeViewColumn *column;
3342 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3344 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3346 scrolled = gtk_scrolled_window_new(NULL, NULL);
3347 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3348 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3349 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3350 gtk_widget_show(scrolled);
3352 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3354 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3355 g_object_unref(accel_store);
3356 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3357 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3359 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3361 renderer = gtk_cell_renderer_text_new();
3363 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3368 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3369 gtk_tree_view_column_set_resizable(column, TRUE);
3370 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3373 renderer = gtk_cell_renderer_accel_new();
3374 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3375 G_CALLBACK(accel_store_cleared_cb), accel_store);
3376 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3377 G_CALLBACK(accel_store_edited_cb), accel_store);
3380 g_object_set (renderer,
3382 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3385 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3390 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3391 gtk_tree_view_column_set_resizable(column, TRUE);
3392 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3394 renderer = gtk_cell_renderer_text_new();
3396 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3401 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3402 gtk_tree_view_column_set_resizable(column, TRUE);
3403 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3405 renderer = gtk_cell_renderer_text_new();
3407 column = gtk_tree_view_column_new_with_attributes("Accel",
3412 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3413 gtk_tree_view_column_set_resizable(column, TRUE);
3414 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3416 accel_store_populate();
3417 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3418 gtk_widget_show(accel_view);
3420 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3422 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3423 G_CALLBACK(accel_default_cb), accel_view);
3424 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3425 gtk_widget_show(button);
3427 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3428 G_CALLBACK(accel_reset_cb), accel_view);
3429 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3430 gtk_widget_show(button);
3433 /* toolbar main tab */
3434 static void config_tab_toolbar_main(GtkWidget *notebook)
3437 GtkWidget *toolbardata;
3440 lw = layout_window_list->data;
3442 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3444 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3445 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3446 gtk_widget_show(vbox);
3449 /* toolbar status tab */
3450 static void config_tab_toolbar_status(GtkWidget *notebook)
3453 GtkWidget *toolbardata;
3456 lw = layout_window_list->data;
3458 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3460 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3461 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3462 gtk_widget_show(vbox);
3466 static void config_tab_stereo(GtkWidget *notebook)
3474 GtkWidget *fs_button;
3475 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3477 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3479 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3480 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3482 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3483 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3484 pref_checkbox_new_int(box, _("Mirror left image"),
3485 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3486 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3487 pref_checkbox_new_int(box, _("Flip left image"),
3488 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3489 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3490 pref_checkbox_new_int(box, _("Mirror right image"),
3491 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3492 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3493 pref_checkbox_new_int(box, _("Flip right image"),
3494 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3495 pref_checkbox_new_int(group, _("Swap left and right images"),
3496 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3497 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3498 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3500 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3501 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3502 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3503 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3504 pref_checkbox_link_sensitivity(fs_button, box2);
3505 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3506 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3507 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3508 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3509 pref_checkbox_new_int(box, _("Mirror left image"),
3510 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3511 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3512 pref_checkbox_new_int(box, _("Flip left image"),
3513 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3514 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3515 pref_checkbox_new_int(box, _("Mirror right image"),
3516 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3517 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3518 pref_checkbox_new_int(box, _("Flip right image"),
3519 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3520 pref_checkbox_new_int(box2, _("Swap left and right images"),
3521 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3522 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3523 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3525 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3526 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3527 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3528 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3529 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3530 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3531 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3532 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3533 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3534 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3535 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3536 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3537 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3538 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3542 /* Main preferences window */
3543 static void config_window_create(void)
3545 GtkWidget *win_vbox;
3547 GtkWidget *notebook;
3549 GtkWidget *ct_button;
3551 if (!c_options) c_options = init_options(NULL);
3553 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3554 DEBUG_NAME(configwindow);
3555 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3556 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3557 G_CALLBACK(config_window_delete), NULL);
3558 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3559 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3560 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3562 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3563 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3564 gtk_widget_show(win_vbox);
3566 notebook = gtk_notebook_new();
3567 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3568 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3569 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3571 config_tab_general(notebook);
3572 config_tab_image(notebook);
3573 config_tab_osd(notebook);
3574 config_tab_windows(notebook);
3575 config_tab_accelerators(notebook);
3576 config_tab_files(notebook);
3577 config_tab_metadata(notebook);
3578 config_tab_keywords(notebook);
3579 config_tab_color(notebook);
3580 config_tab_stereo(notebook);
3581 config_tab_behavior(notebook);
3582 config_tab_toolbar_main(notebook);
3583 config_tab_toolbar_status(notebook);
3585 hbox = gtk_hbutton_box_new();
3586 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3587 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3588 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3589 gtk_widget_show(hbox);
3591 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3592 G_CALLBACK(config_window_help_cb), notebook);
3593 gtk_container_add(GTK_CONTAINER(hbox), button);
3594 gtk_widget_set_can_default(button, TRUE);
3595 gtk_widget_show(button);
3597 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3598 G_CALLBACK(config_window_ok_cb), NULL);
3599 gtk_container_add(GTK_CONTAINER(hbox), button);
3600 gtk_widget_set_can_default(button, TRUE);
3601 gtk_widget_grab_default(button);
3602 gtk_widget_show(button);
3606 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3607 G_CALLBACK(config_window_save_cb), NULL);
3608 gtk_container_add(GTK_CONTAINER(hbox), button);
3609 gtk_widget_set_can_default(button, TRUE);
3610 gtk_widget_show(button);
3612 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3613 G_CALLBACK(config_window_apply_cb), NULL);
3614 gtk_container_add(GTK_CONTAINER(hbox), button);
3615 gtk_widget_set_can_default(button, TRUE);
3616 gtk_widget_show(button);
3618 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3619 G_CALLBACK(config_window_close_cb), NULL);
3620 gtk_container_add(GTK_CONTAINER(hbox), button);
3621 gtk_widget_set_can_default(button, TRUE);
3622 gtk_widget_show(button);
3624 if (!generic_dialog_get_alternative_button_order(configwindow))
3626 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3629 gtk_widget_show(notebook);
3631 gtk_widget_show(configwindow);
3635 *-----------------------------------------------------------------------------
3636 * config window show (public)
3637 *-----------------------------------------------------------------------------
3640 void show_config_window(void)
3644 gtk_window_present(GTK_WINDOW(configwindow));
3648 config_window_create();
3657 void show_about_window(LayoutWindow *lw)
3659 GdkPixbuf *pixbuf_logo;
3660 GdkPixbuf *pixbuf_icon;
3661 gchar *authors[1000];
3669 #define LINE_LENGTH 1000
3670 gchar line[LINE_LENGTH];
3672 copyright = g_string_new(NULL);
3673 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");
3675 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3676 cd = ZDOpenDatabase(zd_path);
3679 copyright = g_string_append(copyright, ZDGetNotice(cd));
3681 ZDCloseDatabase(cd);
3685 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3686 fp = fopen(path, "r");
3689 while(fgets(line, LINE_LENGTH, fp))
3691 /* get rid of ending \n from fgets */
3692 line[strlen(line) - 1] = '\0';
3693 authors[i_authors] = g_strdup(line);
3696 authors[i_authors] = NULL;
3701 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3702 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3704 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3705 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3706 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3707 "title", _("About Geeqie"),
3709 "program-name", GQ_APPNAME,
3711 "logo", pixbuf_logo,
3712 "icon", pixbuf_icon,
3713 "website", GQ_WEBSITE,
3714 "website-label", "Website",
3715 "comments", comment,
3717 "translator-credits", _("translator-credits"),
3718 "wrap-license", TRUE,
3719 "license", copyright->str,
3722 g_string_free(copyright, TRUE);
3725 while(n < i_authors)
3735 static void image_overlay_set_text_colours()
3737 c_options->image_overlay.text_red = options->image_overlay.text_red;
3738 c_options->image_overlay.text_green = options->image_overlay.text_green;
3739 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3740 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3741 c_options->image_overlay.background_red = options->image_overlay.background_red;
3742 c_options->image_overlay.background_green = options->image_overlay.background_green;
3743 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3744 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3748 *-----------------------------------------------------------------------------
3749 * timezone database routines
3750 *-----------------------------------------------------------------------------
3753 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3755 GError *error = NULL;
3757 gchar *tmp_filename;
3759 if (!g_cancellable_is_cancelled(tz->cancellable))
3761 generic_dialog_close(tz->gd);
3765 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3767 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3768 move_file(tmp_filename, tz->timezone_database_user);
3769 g_free(tmp_filename);
3773 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3776 g_file_delete(tz->tmp_g_file, NULL, &error);
3777 g_object_unref(tz->tmp_g_file);
3778 tz->tmp_g_file = NULL;
3779 g_object_unref(tz->cancellable);
3780 g_object_unref(tz->timezone_database_gq);
3783 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3787 if (!g_cancellable_is_cancelled(tz->cancellable))
3789 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3793 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3796 GError *error = NULL;
3798 g_cancellable_cancel(tz->cancellable);
3801 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3804 GError *error = NULL;
3805 GFileIOStream *io_stream;
3812 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3816 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3817 log_printf("Error: Download timezone database failed:\n%s", error->message);
3818 g_error_free(error);
3819 g_object_unref(tz->tmp_g_file);
3823 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3825 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3827 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3829 tz->progress = gtk_progress_bar_new();
3830 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3831 gtk_widget_show(tz->progress);
3833 gtk_widget_show(tz->gd->dialog);
3834 tz->cancellable = g_cancellable_new();
3835 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);
3837 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3840 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */