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);
472 *-----------------------------------------------------------------------------
473 * config window main button callbacks (private)
474 *-----------------------------------------------------------------------------
477 static void config_window_close_cb(GtkWidget *widget, gpointer data)
479 gtk_widget_destroy(configwindow);
484 static void config_window_help_cb(GtkWidget *widget, gpointer data)
486 GtkWidget *notebook = data;
489 static gchar *html_section[] =
491 "GuideOptionsGeneral.html",
492 "GuideOptionsImage.html",
493 "GuideOptionsOSD.html",
494 "GuideOptionsWindow.html",
495 "GuideOptionsKeyboard.html",
496 "GuideOptionsFiltering.html",
497 "GuideOptionsMetadata.html",
498 "GuideOptionsKeywords.html",
499 "GuideOptionsColor.html",
500 "GuideOptionsStereo.html",
501 "GuideOptionsBehavior.html",
502 "GuideOptionsToolbar.html"
505 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
506 help_window_show(html_section[i]);
509 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
511 config_window_close_cb(NULL, NULL);
515 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
517 config_window_apply();
518 config_window_close_cb(NULL, NULL);
521 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
524 lw = layout_window_list->data;
526 config_window_apply();
527 layout_util_sync(lw);
530 static void config_window_save_cb(GtkWidget *widget, gpointer data)
532 config_window_apply();
533 save_options(options);
537 *-----------------------------------------------------------------------------
538 * config window setup (private)
539 *-----------------------------------------------------------------------------
542 static void quality_menu_cb(GtkWidget *combo, gpointer data)
546 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
550 *option = GDK_INTERP_NEAREST;
553 *option = GDK_INTERP_TILES;
556 *option = GDK_INTERP_BILINEAR;
559 *option = GDK_INTERP_HYPER;
564 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
568 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
580 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
581 guint option, guint *option_c)
588 pref_table_label(table, column, row, text, 0.0);
590 combo = gtk_combo_box_text_new();
592 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
593 if (option == GDK_INTERP_NEAREST) current = 0;
594 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
595 if (option == GDK_INTERP_TILES) current = 1;
596 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
597 if (option == GDK_INTERP_BILINEAR) current = 2;
598 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
599 if (option == GDK_INTERP_HYPER) current = 3;
601 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
603 g_signal_connect(G_OBJECT(combo), "changed",
604 G_CALLBACK(quality_menu_cb), option_c);
606 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
607 GTK_EXPAND | GTK_FILL, 0, 0, 0);
608 gtk_widget_show(combo);
611 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
612 gint option, gint *option_c)
619 pref_table_label(table, column, row, text, 0.0);
621 combo = gtk_combo_box_text_new();
623 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
624 if (option == PRIMARY) current = 0;
625 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
626 if (option == CLIPBOARD) current = 1;
628 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
630 g_signal_connect(G_OBJECT(combo), "changed",
631 G_CALLBACK(clipboard_selection_menu_cb), option_c);
633 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
634 GTK_EXPAND | GTK_FILL, 0, 0, 0);
635 gtk_widget_show(combo);
638 typedef struct _UseableMouseItems UseableMouseItems;
639 struct _UseableMouseItems
641 gchar *name; /* GtkActionEntry terminology */
646 static const UseableMouseItems useable_mouse_items[] = {
648 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
649 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
650 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
651 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
652 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
653 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
654 {"Home", N_("Home"), GTK_STOCK_HOME},
655 {"Up", N_("Up"), GTK_STOCK_GO_UP},
656 {"NextPage", N_("Next Page"), PIXBUF_INLINE_ICON_NEXT_PAGE},
657 {"PrevPage", N_("Previous Page"), PIXBUF_INLINE_ICON_PREVIOUS_PAGE},
658 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
659 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
660 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
661 {"Search", N_("Search"), GTK_STOCK_FIND},
662 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
663 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
664 {"Copy", N_("Copy"), GTK_STOCK_COPY},
665 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
666 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
667 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
668 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
669 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
670 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
671 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
672 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
673 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
674 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
675 {"Print", N_("Print"), GTK_STOCK_PRINT},
676 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
677 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
678 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
679 {"RotateCW", N_("Rotate clockwise"), PIXBUF_INLINE_ICON_CW},
680 {"RotateCCW", N_("Rotate counterclockwise"), PIXBUF_INLINE_ICON_CCW},
681 {"Rotate180", N_("Rotate 180"), PIXBUF_INLINE_ICON_180},
682 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
683 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
684 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
685 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
686 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
687 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
688 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
689 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
690 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
691 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
692 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
693 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
694 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
695 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
696 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
697 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
698 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
699 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
700 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
701 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
702 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
703 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
704 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
705 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
706 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
707 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
708 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
709 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
710 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
711 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
712 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
713 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
714 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
718 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
720 gchar **option = data;
723 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
725 const UseableMouseItems *list = useable_mouse_items;
729 if (g_strcmp0(list->label, label) == 0)
737 *option = g_strdup(list->name);
741 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
742 gchar *option, gchar **option_c)
750 pref_table_label(table, column, row, text, 0.0);
752 combo = gtk_combo_box_text_new();
754 const UseableMouseItems *list = useable_mouse_items;
758 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
759 if (g_strcmp0(list->name, option) == 0)
767 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
769 g_signal_connect(G_OBJECT(combo), "changed",
770 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
772 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
773 GTK_EXPAND | GTK_FILL, 0, 0, 0);
774 gtk_widget_show(combo);
777 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
781 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
784 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
786 c_options->thumbnails.max_width = thumb_size_list[n].w;
787 c_options->thumbnails.max_height = thumb_size_list[n].h;
791 c_options->thumbnails.max_width = options->thumbnails.max_width;
792 c_options->thumbnails.max_height = options->thumbnails.max_height;
796 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
802 c_options->thumbnails.max_width = options->thumbnails.max_width;
803 c_options->thumbnails.max_height = options->thumbnails.max_height;
805 pref_table_label(table, column, row, text, 0.0);
807 combo = gtk_combo_box_text_new();
810 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
815 w = thumb_size_list[i].w;
816 h = thumb_size_list[i].h;
818 buf = g_strdup_printf("%d x %d", w, h);
819 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
822 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
829 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
830 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
836 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
837 g_signal_connect(G_OBJECT(combo), "changed",
838 G_CALLBACK(thumb_size_menu_cb), NULL);
840 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
841 GTK_EXPAND | GTK_FILL, 0, 0, 0);
842 gtk_widget_show(combo);
845 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
849 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
853 *option = PR_STEREO_NONE;
856 *option = PR_STEREO_ANAGLYPH_RC;
859 *option = PR_STEREO_ANAGLYPH_GM;
862 *option = PR_STEREO_ANAGLYPH_YB;
865 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
868 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
871 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
874 *option = PR_STEREO_ANAGLYPH_DB_RC;
877 *option = PR_STEREO_ANAGLYPH_DB_GM;
880 *option = PR_STEREO_ANAGLYPH_DB_YB;
883 *option = PR_STEREO_HORIZ;
886 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
889 *option = PR_STEREO_VERT;
892 *option = PR_STEREO_VERT | PR_STEREO_HALF;
895 *option = PR_STEREO_FIXED;
900 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
901 gint option, gint *option_c, gboolean add_fixed)
908 pref_table_label(table, column, row, text, 0.0);
910 combo = gtk_combo_box_text_new();
912 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
914 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
915 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
916 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
917 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
918 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
919 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
920 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
921 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
922 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
923 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
924 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
925 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
926 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
927 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
928 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
929 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
930 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
931 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
933 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
934 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
935 if (option & PR_STEREO_HORIZ)
938 if (option & PR_STEREO_HALF) current = 11;
941 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
942 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
943 if (option & PR_STEREO_VERT)
946 if (option & PR_STEREO_HALF) current = 13;
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
952 if (option & PR_STEREO_FIXED) current = 14;
955 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
957 g_signal_connect(G_OBJECT(combo), "changed",
958 G_CALLBACK(stereo_mode_menu_cb), option_c);
960 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
961 GTK_EXPAND | GTK_FILL, 0, 0, 0);
962 gtk_widget_show(combo);
965 static void video_menu_cb(GtkWidget *combo, gpointer data)
967 gchar **option = data;
969 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
973 static void video_menu_populate(gpointer data, gpointer user_data)
975 GtkWidget *combo = user_data;
976 EditorDescription *ed = data;
978 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
981 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
982 gchar *option, gchar **option_c)
986 /* use lists since they are sorted */
987 GList *eds = editor_list_get();
991 pref_table_label(table, column, row, text, 0.0);
993 combo = gtk_combo_box_text_new();
994 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
995 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
997 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
999 g_signal_connect(G_OBJECT(combo), "changed",
1000 G_CALLBACK(video_menu_cb), option_c);
1002 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
1003 GTK_EXPAND | GTK_FILL, 0, 0, 0);
1004 gtk_widget_show(combo);
1007 static void filter_store_populate(void)
1011 if (!filter_store) return;
1013 gtk_list_store_clear(filter_store);
1015 work = filter_get_list();
1024 gtk_list_store_append(filter_store, &iter);
1025 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1029 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1030 gchar *new_text, gpointer data)
1032 GtkWidget *model = data;
1033 FilterEntry *fe = data;
1037 if (!new_text || strlen(new_text) < 1) return;
1039 tpath = gtk_tree_path_new_from_string(path_str);
1040 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1041 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1043 g_free(fe->extensions);
1044 fe->extensions = g_strdup(new_text);
1046 gtk_tree_path_free(tpath);
1050 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1051 gchar *new_text, gpointer data)
1053 GtkWidget *model = data;
1054 FilterEntry *fe = data;
1059 if (!new_text || !new_text[0]) return;
1061 tpath = gtk_tree_path_new_from_string(path_str);
1062 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1063 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1065 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1067 if (strcmp(new_text, _(format_class_list[i])) == 0)
1074 gtk_tree_path_free(tpath);
1078 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1079 gchar *new_text, gpointer data)
1081 GtkWidget *model = data;
1086 if (!new_text || !new_text[0]) return;
1088 tpath = gtk_tree_path_new_from_string(path_str);
1089 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1090 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1092 g_free(fe->description);
1093 fe->description = g_strdup(new_text);
1095 gtk_tree_path_free(tpath);
1098 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1099 gchar *path_str, gpointer data)
1101 GtkWidget *model = data;
1106 tpath = gtk_tree_path_new_from_string(path_str);
1107 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1108 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1110 fe->enabled = !fe->enabled;
1112 gtk_tree_path_free(tpath);
1116 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1117 gchar *path_str, gpointer data)
1119 GtkWidget *model = data;
1124 tpath = gtk_tree_path_new_from_string(path_str);
1125 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1126 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1128 fe->writable = !fe->writable;
1129 if (fe->writable) fe->allow_sidecar = FALSE;
1131 gtk_tree_path_free(tpath);
1135 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1136 gchar *path_str, gpointer data)
1138 GtkWidget *model = data;
1143 tpath = gtk_tree_path_new_from_string(path_str);
1144 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1145 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1147 fe->allow_sidecar = !fe->allow_sidecar;
1148 if (fe->allow_sidecar) fe->writable = FALSE;
1150 gtk_tree_path_free(tpath);
1154 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1155 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1159 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1161 switch (GPOINTER_TO_INT(data))
1164 g_object_set(GTK_CELL_RENDERER(cell),
1165 "active", fe->enabled, NULL);
1168 g_object_set(GTK_CELL_RENDERER(cell),
1169 "text", fe->extensions, NULL);
1171 case FE_DESCRIPTION:
1172 g_object_set(GTK_CELL_RENDERER(cell),
1173 "text", fe->description, NULL);
1176 g_object_set(GTK_CELL_RENDERER(cell),
1177 "text", _(format_class_list[fe->file_class]), NULL);
1180 g_object_set(GTK_CELL_RENDERER(cell),
1181 "active", fe->writable, NULL);
1183 case FE_ALLOW_SIDECAR:
1184 g_object_set(GTK_CELL_RENDERER(cell),
1185 "active", fe->allow_sidecar, NULL);
1190 static gboolean filter_add_scroll(gpointer data)
1194 GtkCellRenderer *cell;
1195 GtkTreeViewColumn *column;
1200 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1201 path = gtk_tree_path_new_from_indices(rows-1, -1);
1203 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1205 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1206 cell = g_list_last(list_cells)->data;
1208 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1209 path, column, FALSE, 0.0, 0.0 );
1210 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1211 path, column, cell, TRUE);
1213 gtk_tree_path_free(path);
1214 g_list_free(list_cells);
1219 static void filter_add_cb(GtkWidget *widget, gpointer data)
1221 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1222 filter_store_populate();
1224 g_idle_add((GSourceFunc)filter_add_scroll, data);
1227 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1229 GtkWidget *filter_view = data;
1230 GtkTreeSelection *selection;
1234 if (!filter_store) return;
1235 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1236 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1237 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1240 filter_remove_entry(fe);
1242 filter_store_populate();
1245 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1249 GtkTreeViewColumn *column;
1251 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1252 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1253 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1255 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1259 gtk_tree_path_free(path);
1264 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1267 filter_add_defaults();
1269 filter_store_populate();
1271 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1274 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1276 /* no op, only so cancel button appears */
1279 static void filter_default_cb(GtkWidget *widget, gpointer data)
1283 gd = generic_dialog_new(_("Reset filters"),
1284 "reset_filter", widget, TRUE,
1285 dummy_cancel_cb, data);
1286 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1287 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1288 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1289 gtk_widget_show(gd->dialog);
1292 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1294 GtkWidget *frame = data;
1296 gtk_widget_set_sensitive(frame,
1297 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1300 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1302 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1305 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1307 file_util_trash_clear();
1310 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1314 gd = generic_dialog_new(_("Clear trash"),
1315 "clear_trash", widget, TRUE,
1316 dummy_cancel_cb, NULL);
1317 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1318 _("This will remove the trash contents."), FALSE);
1319 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1320 entry = gtk_entry_new();
1321 gtk_widget_set_can_focus(entry, FALSE);
1322 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1323 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1324 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1325 gtk_widget_show(entry);
1326 gtk_widget_show(gd->dialog);
1329 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1331 GtkWidget *pTextView;
1332 GtkTextBuffer *pTextBuffer;
1336 pTextView = GTK_WIDGET(data);
1338 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1339 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1340 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1342 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1343 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1346 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1348 GtkTextView *text_view = data;
1349 GtkTextBuffer *buffer;
1351 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1352 if (!configwindow) return;
1354 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1355 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1358 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1362 gd = generic_dialog_new(_("Reset image overlay template string"),
1363 "reset_image_overlay_template_string", widget, TRUE,
1364 dummy_cancel_cb, data);
1365 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1366 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1367 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1368 gtk_widget_show(gd->dialog);
1371 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1373 help_window_show("GuideOptionsOSD.html");
1376 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1378 #if GTK_CHECK_VERSION(3,4,0)
1381 PangoFontDescription *font_desc;
1383 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1384 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1386 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1388 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1389 font = pango_font_description_to_string(font_desc);
1390 g_free(c_options->image_overlay.font);
1391 c_options->image_overlay.font = g_strdup(font);
1395 gtk_widget_destroy(dialog);
1399 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1400 c_options->image_overlay.font = g_strdup(font);
1404 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1407 #if GTK_CHECK_VERSION(3,4,0)
1410 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1411 colour.red = options->image_overlay.text_red;
1412 colour.green = options->image_overlay.text_green;
1413 colour.blue = options->image_overlay.text_blue;
1414 colour.alpha = options->image_overlay.text_alpha;
1415 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1416 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1418 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1420 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1421 c_options->image_overlay.text_red = colour.red*255;
1422 c_options->image_overlay.text_green = colour.green*255;
1423 c_options->image_overlay.text_blue = colour.blue*255;
1424 c_options->image_overlay.text_alpha = colour.alpha*255;
1426 gtk_widget_destroy(dialog);
1429 GtkColorSelection *colorsel;
1431 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1432 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1433 colour.red = options->image_overlay.text_red*257;
1434 colour.green = options->image_overlay.text_green*257;
1435 colour.blue = options->image_overlay.text_blue*257;
1436 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1437 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1438 gtk_color_selection_set_current_color(colorsel, &colour);
1439 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1441 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1443 gtk_color_selection_get_current_color(colorsel, &colour);
1444 c_options->image_overlay.text_red = colour.red/257;
1445 c_options->image_overlay.text_green = colour.green/257;
1446 c_options->image_overlay.text_blue = colour.blue/257;
1447 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1449 gtk_widget_destroy (dialog);
1454 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1457 #if GTK_CHECK_VERSION(3,4,0)
1460 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1461 colour.red = options->image_overlay.background_red;
1462 colour.green = options->image_overlay.background_green;
1463 colour.blue = options->image_overlay.background_blue;
1464 colour.alpha = options->image_overlay.background_alpha;
1465 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1466 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1468 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1470 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1471 c_options->image_overlay.background_red = colour.red*255;
1472 c_options->image_overlay.background_green = colour.green*255;
1473 c_options->image_overlay.background_blue = colour.blue*255;
1474 c_options->image_overlay.background_alpha = colour.alpha*255;
1476 gtk_widget_destroy(dialog);
1479 GtkColorSelection *colorsel;
1481 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1482 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1483 colour.red = options->image_overlay.background_red*257;
1484 colour.green = options->image_overlay.background_green*257;
1485 colour.blue = options->image_overlay.background_blue*257;
1486 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1487 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1488 gtk_color_selection_set_current_color(colorsel, &colour);
1489 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1491 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1493 gtk_color_selection_get_current_color(colorsel, &colour);
1494 c_options->image_overlay.background_red = colour.red/257;
1495 c_options->image_overlay.background_green = colour.green/257;
1496 c_options->image_overlay.background_blue = colour.blue/257;
1497 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1499 gtk_widget_destroy(dialog);
1503 static void accel_store_populate(void)
1506 GList *groups, *actions;
1508 const gchar *accel_path;
1512 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1514 gtk_tree_store_clear(accel_store);
1515 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1517 g_assert(lw && lw->ui_manager);
1518 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1521 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1524 action = GTK_ACTION(actions->data);
1525 accel_path = gtk_action_get_accel_path(action);
1526 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1528 gchar *label, *label2, *tooltip, *accel;
1529 g_object_get(action,
1530 "tooltip", &tooltip,
1534 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1540 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1544 gtk_tree_store_append(accel_store, &iter, NULL);
1545 gtk_tree_store_set(accel_store, &iter,
1548 AE_TOOLTIP, tooltip ? tooltip : "",
1549 AE_ACCEL, accel_path,
1557 actions = actions->next;
1560 groups = groups->next;
1564 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1569 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1571 gchar *accel1 = data;
1576 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1578 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1579 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1581 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1583 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1584 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1593 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1595 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1599 GtkAccelKey old_key, key;
1600 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1602 gtk_tree_model_get_iter(model, &iter, path);
1603 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1605 /* test if the accelerator can be stored without conflicts*/
1606 gtk_accel_map_lookup_entry(accel_path, &old_key);
1608 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1609 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1610 gtk_accel_map_lookup_entry(accel_path, &key);
1612 /* restore the original for now, the key will be really changed when the changes are confirmed */
1613 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1615 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1616 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1618 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1619 gtk_tree_path_free(path);
1623 static gboolean accel_default_scroll(GtkTreeView *data)
1627 GtkTreeViewColumn *column;
1629 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1630 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1631 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1633 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1637 gtk_tree_path_free(path);
1642 static void accel_default_cb(GtkWidget *widget, gpointer data)
1644 accel_store_populate();
1646 g_idle_add((GSourceFunc)accel_default_scroll, data);
1649 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1651 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1654 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1657 gchar *accel_path, *accel;
1659 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1660 gtk_accel_map_lookup_entry(accel_path, &key);
1661 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1663 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1665 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1670 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1672 GtkTreeSelection *selection;
1674 if (!accel_store) return;
1675 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1676 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1681 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1685 GtkWidget *scrolled;
1686 GtkWidget *viewport;
1688 scrolled = gtk_scrolled_window_new(NULL, NULL);
1689 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1690 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1691 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1692 label = gtk_label_new(title);
1693 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1694 gtk_widget_show(scrolled);
1696 viewport = gtk_viewport_new(NULL, NULL);
1697 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1698 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1699 gtk_widget_show(viewport);
1701 vbox = gtk_vbox_new(FALSE, 0);
1702 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1703 gtk_widget_show(vbox);
1708 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1710 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1712 c_options->thumbnails.spec_standard =TRUE;
1713 c_options->thumbnails.cache_into_dirs = FALSE;
1717 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1719 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1721 c_options->thumbnails.spec_standard =FALSE;
1722 c_options->thumbnails.cache_into_dirs = FALSE;
1726 static void cache_local_cb(GtkWidget *widget, gpointer data)
1728 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1730 c_options->thumbnails.cache_into_dirs = TRUE;
1731 c_options->thumbnails.spec_standard =FALSE;
1735 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1736 GdkEvent *event, gpointer userdata)
1738 if (pos == GTK_ENTRY_ICON_PRIMARY)
1740 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1744 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1748 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1749 GdkEvent *event, gpointer userdata)
1751 gchar *rating_symbol;
1753 if (pos == GTK_ENTRY_ICON_PRIMARY)
1755 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1756 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1757 g_free(rating_symbol);
1761 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1762 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1763 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1767 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1768 GdkEvent *event, gpointer userdata)
1770 gchar *rating_symbol;
1772 if (pos == GTK_ENTRY_ICON_PRIMARY)
1774 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1775 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1776 g_free(rating_symbol);
1780 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1781 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1782 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1786 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1788 GtkContainer *hbox = data;
1789 GString *str = g_string_new(NULL);
1790 GtkEntry *hex_code_entry;
1791 gchar *hex_code_full;
1794 guint64 hex_value = 0;
1796 list = gtk_container_get_children(hbox);
1798 hex_code_entry = g_list_nth_data(list, 2);
1799 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1801 hex_code = g_strsplit(hex_code_full, "+", 2);
1802 if (hex_code[0] && hex_code[1])
1804 hex_value = strtoull(hex_code[1], NULL, 16);
1806 if (!hex_value || hex_value > 0x10FFFF)
1808 hex_value = 0x003F; // Unicode 'Question Mark'
1810 str = g_string_append_unichar(str, (gunichar)hex_value);
1811 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1813 g_strfreev(hex_code);
1814 g_string_free(str, TRUE);
1815 g_free(hex_code_full);
1820 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1822 guint64 star_symbol;
1824 star_symbol = star_rating_symbol_test(widget, data);
1825 c_options->star_rating.star = star_symbol;
1828 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1830 guint64 rejected_symbol;
1832 rejected_symbol = star_rating_symbol_test(widget, data);
1833 c_options->star_rating.rejected = rejected_symbol;
1836 /* general options tab */
1837 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1838 typedef struct _TZData TZData;
1842 GCancellable *cancellable;
1844 GtkWidget *progress;
1846 GFile *timezone_database_gq;
1847 gchar *timezone_database_user;
1850 static void config_tab_general(GtkWidget *notebook)
1855 GtkWidget *group_frame;
1856 GtkWidget *subgroup;
1858 GtkWidget *ct_button;
1861 gint hours, minutes, remainder;
1863 GtkWidget *star_rating_entry;
1865 gchar *rating_symbol;
1868 GNetworkMonitor *net_mon;
1869 GSocketConnectable *geeqie_org;
1870 gboolean internet_available;
1873 vbox = scrolled_notebook_page(notebook, _("General"));
1875 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1877 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1878 add_thumb_size_menu(table, 0, 0, _("Size:"));
1879 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1881 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1882 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1884 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1885 pref_checkbox_link_sensitivity(ct_button, subgroup);
1887 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1888 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1889 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1890 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1891 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1892 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1893 G_CALLBACK(cache_geeqie_cb), NULL);
1895 group_frame = pref_frame_new(subgroup, TRUE,
1896 _("Store thumbnails local to image folder (non-standard)"),
1897 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1898 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1899 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1900 G_CALLBACK(cache_local_cb), NULL);
1902 group_frame = pref_frame_new(subgroup, TRUE,
1903 _("Use standard thumbnail style and cache, shared with other applications"),
1904 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1905 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1906 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1907 G_CALLBACK(cache_standard_cb), NULL);
1909 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1910 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1912 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1914 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1915 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1917 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1918 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1919 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1921 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1922 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1925 pref_spacer(group, PREF_PAD_GROUP);
1927 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1929 c_options->star_rating.star = options->star_rating.star;
1930 c_options->star_rating.rejected = options->star_rating.rejected;
1932 str = g_string_new(NULL);
1933 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1934 pref_label_new(hbox, "Star character: ");
1935 str = g_string_append_unichar(str, options->star_rating.star);
1936 pref_label_new(hbox, g_strdup(str->str));
1937 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1938 star_rating_entry = gtk_entry_new();
1939 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1940 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1941 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1942 gtk_widget_show(star_rating_entry);
1943 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1944 G_CALLBACK(star_rating_star_test_cb), hbox);
1945 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1946 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1947 gtk_widget_show(button);
1948 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."));
1949 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1950 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1951 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1952 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1953 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1954 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1955 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1956 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1957 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1958 G_CALLBACK(star_rating_star_icon_cb),
1961 g_string_free(str, TRUE);
1962 g_free(rating_symbol);
1964 str = g_string_new(NULL);
1965 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1966 pref_label_new(hbox, "Rejected character: ");
1967 str = g_string_append_unichar(str, options->star_rating.rejected);
1968 pref_label_new(hbox, g_strdup(str->str));
1969 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1970 star_rating_entry = gtk_entry_new();
1971 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1972 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1973 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1974 gtk_widget_show(star_rating_entry);
1975 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1976 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1977 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1978 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1979 gtk_widget_show(button);
1980 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."));
1981 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1982 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1983 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1984 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1985 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1986 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1987 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1988 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1989 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1990 G_CALLBACK(star_rating_rejected_icon_cb),
1993 g_string_free(str, TRUE);
1994 g_free(rating_symbol);
1996 pref_spacer(group, PREF_PAD_GROUP);
1998 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2000 c_options->slideshow.delay = options->slideshow.delay;
2001 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2002 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2003 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2004 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2005 SLIDESHOW_SUBSECOND_PRECISION;
2007 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2009 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2011 options->slideshow.delay ? hours : 0.0,
2012 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2013 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2014 spin = pref_spin_new(hbox, ":" , NULL,
2016 options->slideshow.delay ? minutes: 0.0,
2017 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2018 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2019 spin = pref_spin_new(hbox, ":", NULL,
2020 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2021 options->slideshow.delay ? seconds : 10.0,
2022 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2023 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2025 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2026 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2028 pref_spacer(group, PREF_PAD_GROUP);
2030 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2032 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2033 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2034 pref_checkbox_new_int(group, _("Preload next image"),
2035 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2037 pref_checkbox_new_int(group, _("Refresh on file change"),
2038 options->update_on_time_change, &c_options->update_on_time_change);
2040 pref_spacer(group, PREF_PAD_GROUP);
2042 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2043 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2044 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2045 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2047 options->info_keywords.height, &c_options->info_keywords.height);
2048 pref_spin_new_int(hbox, _("Title:"), NULL,
2050 options->info_title.height, &c_options->info_title.height);
2051 pref_spin_new_int(hbox, _("Comment:"), NULL,
2053 options->info_comment.height, &c_options->info_comment.height);
2054 pref_spin_new_int(hbox, _("Rating:"), NULL,
2056 options->info_rating.height, &c_options->info_rating.height);
2058 pref_spacer(group, PREF_PAD_GROUP);
2060 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2062 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2063 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2065 pref_spacer(group, PREF_PAD_GROUP);
2067 net_mon = g_network_monitor_get_default();
2068 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2069 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2070 g_object_unref(geeqie_org);
2072 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2073 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2075 if (!internet_available)
2077 gtk_widget_set_sensitive(group, FALSE);
2080 tz = g_new0(TZData, 1);
2082 path = path_from_utf8(TIMEZONE_DATABASE);
2083 basename = g_path_get_basename(path);
2084 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2088 if (isfile(tz->timezone_database_user))
2090 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2094 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2097 if (!internet_available)
2099 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"));
2103 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"));
2105 gtk_widget_show(button);
2107 pref_spacer(group, PREF_PAD_GROUP);
2109 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2111 help_search_engine_entry = gtk_entry_new();
2112 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2113 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2114 gtk_widget_show(help_search_engine_entry);
2116 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"));
2118 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2119 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2120 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2121 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2122 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2123 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2124 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2125 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2126 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2127 G_CALLBACK(help_search_engine_entry_icon_cb),
2128 help_search_engine_entry);
2132 static void config_tab_image(GtkWidget *notebook)
2137 GtkWidget *ct_button;
2138 GtkWidget *enlargement_button;
2142 vbox = scrolled_notebook_page(notebook, _("Image"));
2144 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2146 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2147 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2150 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2151 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2154 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2155 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2157 c_options->image.zoom_increment = options->image.zoom_increment;
2158 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2159 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2160 G_CALLBACK(zoom_increment_cb), NULL);
2161 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2163 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2165 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2166 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2167 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2168 spin = pref_spin_new_int(hbox, NULL, NULL,
2170 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2171 pref_checkbox_link_sensitivity(enlargement_button, spin);
2172 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."));
2174 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2175 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2176 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2177 spin = pref_spin_new_int(hbox, NULL, NULL,
2179 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2180 pref_checkbox_link_sensitivity(ct_button, spin);
2181 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."));
2183 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2185 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2186 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2188 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2189 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2191 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2192 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2194 c_options->image.border_color = options->image.border_color;
2196 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2197 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2199 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2200 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2202 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2203 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2205 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2207 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2208 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2212 static void config_tab_windows(GtkWidget *notebook)
2218 GtkWidget *ct_button;
2221 vbox = scrolled_notebook_page(notebook, _("Windows"));
2223 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2225 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2226 options->save_window_positions, &c_options->save_window_positions);
2228 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2229 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2230 pref_checkbox_link_sensitivity(ct_button, button);
2232 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2233 options->tools_restore_state, &c_options->tools_restore_state);
2235 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2236 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2238 pref_checkbox_new_int(group, _("Show window IDs"),
2239 options->show_window_ids, &c_options->show_window_ids);
2241 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2243 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2244 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2246 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2247 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2248 options->image.limit_window_size, &c_options->image.limit_window_size);
2249 spin = pref_spin_new_int(hbox, NULL, NULL,
2251 options->image.max_window_size, &c_options->image.max_window_size);
2252 pref_checkbox_link_sensitivity(ct_button, spin);
2254 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2256 c_options->fullscreen.screen = options->fullscreen.screen;
2257 c_options->fullscreen.above = options->fullscreen.above;
2258 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2259 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2260 gtk_widget_show(hbox);
2262 pref_checkbox_new_int(group, _("Smooth image flip"),
2263 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2264 pref_checkbox_new_int(group, _("Disable screen saver"),
2265 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2268 #define PRE_FORMATTED_COLUMNS 5
2269 static void config_tab_osd(GtkWidget *notebook)
2273 GtkWidget *vbox_buttons;
2276 GtkWidget *image_overlay_template_view;
2277 GtkWidget *scrolled;
2278 GtkWidget *scrolled_pre_formatted;
2279 GtkTextBuffer *buffer;
2281 GtkWidget * subgroup;
2286 vbox = scrolled_notebook_page(notebook, _("OSD"));
2288 image_overlay_template_view = gtk_text_view_new();
2290 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2292 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2294 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2295 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2296 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2297 gtk_widget_show(scrolled_pre_formatted);
2298 gtk_widget_show(subgroup);
2300 pref_line(group, PREF_PAD_GAP);
2302 pref_label_new(group, _("Image overlay template"));
2304 scrolled = gtk_scrolled_window_new(NULL, NULL);
2305 gtk_widget_set_size_request(scrolled, 200, 150);
2306 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2307 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2308 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2309 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2310 gtk_widget_show(scrolled);
2312 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2313 _("Extensive formatting options are shown in the Help file"));
2315 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2316 gtk_widget_show(image_overlay_template_view);
2318 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2320 #if GTK_CHECK_VERSION(3,4,0)
2321 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2322 G_CALLBACK(image_overlay_set_font_cb), notebook);
2324 button = gtk_font_button_new();
2325 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2326 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2327 g_signal_connect(G_OBJECT(button), "font-set",
2328 G_CALLBACK(image_overlay_set_font_cb),NULL);
2330 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2331 gtk_widget_show(button);
2333 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2334 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2335 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2336 gtk_widget_show(button);
2338 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2339 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2340 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2341 gtk_widget_show(button);
2342 image_overlay_set_text_colours();
2344 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2345 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2346 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2347 gtk_widget_show(button);
2349 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2350 G_CALLBACK(image_overlay_help_cb), NULL);
2351 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2352 gtk_widget_show(button);
2354 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2355 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2356 g_signal_connect(G_OBJECT(buffer), "changed",
2357 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2359 pref_line(group, PREF_PAD_GAP);
2361 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2362 hbox = gtk_hbox_new(FALSE, 0);
2363 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2364 gtk_widget_show(hbox);
2365 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2366 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2367 gtk_widget_show(label);
2368 pref_spacer(group,TRUE);
2370 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2371 hbox = gtk_hbox_new(FALSE, 0);
2372 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2373 gtk_widget_show(hbox);
2374 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2375 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2376 gtk_widget_show(label);
2377 pref_spacer(group,TRUE);
2379 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2380 hbox = gtk_hbox_new(FALSE, 0);
2381 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2382 gtk_widget_show(hbox);
2383 label = gtk_label_new(_("%path:39%"));
2384 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2385 gtk_widget_show(label);
2386 pref_spacer(group,TRUE);
2388 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2389 hbox = gtk_hbox_new(FALSE, 0);
2390 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2391 gtk_widget_show(hbox);
2392 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%"));
2393 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2394 gtk_widget_show(label);
2395 pref_spacer(group,TRUE);
2397 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2398 hbox = gtk_hbox_new(FALSE, 0);
2399 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2400 gtk_widget_show(hbox);
2401 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2402 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2403 gtk_widget_show(label);
2406 static GtkTreeModel *create_class_model(void)
2408 GtkListStore *model;
2412 /* create list store */
2413 model = gtk_list_store_new(1, G_TYPE_STRING);
2414 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2416 gtk_list_store_append(model, &iter);
2417 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2419 return GTK_TREE_MODEL (model);
2424 static void config_tab_files(GtkWidget *notebook)
2431 GtkWidget *ct_button;
2432 GtkWidget *scrolled;
2433 GtkWidget *filter_view;
2434 GtkCellRenderer *renderer;
2435 GtkTreeSelection *selection;
2436 GtkTreeViewColumn *column;
2438 vbox = scrolled_notebook_page(notebook, _("Files"));
2440 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2442 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2443 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2444 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2445 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2446 pref_checkbox_new_int(group, _("Case sensitive sort"),
2447 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2448 pref_checkbox_new_int(group, _("Natural sort order"),
2449 options->file_sort.natural, &c_options->file_sort.natural);
2450 pref_checkbox_new_int(group, _("Disable file extension checks"),
2451 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2453 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2454 options->file_filter.disable, &c_options->file_filter.disable);
2457 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2459 sidecar_ext_entry = gtk_entry_new();
2460 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2461 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2462 gtk_widget_show(sidecar_ext_entry);
2464 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2466 frame = pref_group_parent(group);
2467 g_signal_connect(G_OBJECT(ct_button), "toggled",
2468 G_CALLBACK(filter_disable_cb), frame);
2469 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2471 scrolled = gtk_scrolled_window_new(NULL, NULL);
2472 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2473 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2474 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2475 gtk_widget_show(scrolled);
2477 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2478 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2479 g_object_unref(filter_store);
2480 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2481 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2483 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2485 column = gtk_tree_view_column_new();
2486 gtk_tree_view_column_set_title(column, _("Filter"));
2487 gtk_tree_view_column_set_resizable(column, TRUE);
2489 renderer = gtk_cell_renderer_toggle_new();
2490 g_signal_connect(G_OBJECT(renderer), "toggled",
2491 G_CALLBACK(filter_store_enable_cb), filter_store);
2492 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2493 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2494 GINT_TO_POINTER(FE_ENABLE), NULL);
2496 renderer = gtk_cell_renderer_text_new();
2497 g_signal_connect(G_OBJECT(renderer), "edited",
2498 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2499 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2500 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2501 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2502 GINT_TO_POINTER(FE_EXTENSION), NULL);
2503 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2505 column = gtk_tree_view_column_new();
2506 gtk_tree_view_column_set_title(column, _("Description"));
2507 gtk_tree_view_column_set_resizable(column, TRUE);
2508 gtk_tree_view_column_set_fixed_width(column, 200);
2509 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2511 renderer = gtk_cell_renderer_text_new();
2512 g_signal_connect(G_OBJECT(renderer), "edited",
2513 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2514 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2515 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2516 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2517 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2518 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2520 column = gtk_tree_view_column_new();
2521 gtk_tree_view_column_set_title(column, _("Class"));
2522 gtk_tree_view_column_set_resizable(column, TRUE);
2523 renderer = gtk_cell_renderer_combo_new();
2524 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2525 "model", create_class_model(),
2530 g_signal_connect(G_OBJECT(renderer), "edited",
2531 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2532 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2533 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2534 GINT_TO_POINTER(FE_CLASS), NULL);
2535 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2537 column = gtk_tree_view_column_new();
2538 gtk_tree_view_column_set_title(column, _("Writable"));
2539 gtk_tree_view_column_set_resizable(column, FALSE);
2540 renderer = gtk_cell_renderer_toggle_new();
2541 g_signal_connect(G_OBJECT(renderer), "toggled",
2542 G_CALLBACK(filter_store_writable_cb), filter_store);
2543 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2544 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2545 GINT_TO_POINTER(FE_WRITABLE), NULL);
2546 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2548 column = gtk_tree_view_column_new();
2549 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2550 gtk_tree_view_column_set_resizable(column, FALSE);
2551 renderer = gtk_cell_renderer_toggle_new();
2552 g_signal_connect(G_OBJECT(renderer), "toggled",
2553 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2554 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2555 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2556 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2557 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2560 filter_store_populate();
2561 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2562 gtk_widget_show(filter_view);
2564 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2566 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2567 G_CALLBACK(filter_default_cb), filter_view);
2568 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2569 gtk_widget_show(button);
2571 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2572 G_CALLBACK(filter_remove_cb), filter_view);
2573 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2574 gtk_widget_show(button);
2576 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2577 G_CALLBACK(filter_add_cb), filter_view);
2578 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2579 gtk_widget_show(button);
2583 static void config_tab_metadata(GtkWidget *notebook)
2588 GtkWidget *ct_button;
2592 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2595 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2597 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2599 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2600 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2602 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2603 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2605 gtk_widget_set_sensitive(ct_button, FALSE);
2608 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2609 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2611 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2612 label = pref_label_new(group, text);
2613 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2614 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2617 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2619 gtk_widget_set_sensitive(group, FALSE);
2622 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2623 pref_checkbox_link_sensitivity(ct_button, hbox);
2625 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2626 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2628 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2629 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2631 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2632 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2634 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2635 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2637 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2639 gtk_widget_set_sensitive(group, FALSE);
2642 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2643 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2646 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2647 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2648 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2650 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2651 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2653 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2654 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2656 gtk_widget_set_sensitive(ct_button, FALSE);
2659 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2661 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2662 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2664 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2665 pref_checkbox_link_sensitivity(ct_button, hbox);
2667 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2668 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2670 pref_checkbox_new_int(group, _("Write metadata on image change"),
2671 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2673 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2674 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2676 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2678 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2679 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2680 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");
2685 typedef struct _KeywordFindData KeywordFindData;
2686 struct _KeywordFindData
2693 GtkWidget *button_close;
2694 GtkWidget *button_stop;
2695 GtkWidget *button_start;
2696 GtkWidget *progress;
2704 guint idle_id; /* event source id */
2707 #define KEYWORD_DIALOG_WIDTH 400
2709 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2711 GList *list_d = NULL;
2712 GList *list_f = NULL;
2716 filelist_read(dir_fd, &list_f, &list_d);
2720 filelist_read(dir_fd, &list_f, NULL);
2723 list_f = filelist_filter(list_f, FALSE);
2724 list_d = filelist_filter(list_d, TRUE);
2726 kfd->list = g_list_concat(list_f, kfd->list);
2727 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2730 static void keywords_find_reset(KeywordFindData *kfd)
2732 filelist_free(kfd->list);
2735 filelist_free(kfd->list_dir);
2736 kfd->list_dir = NULL;
2739 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2741 KeywordFindData *kfd = data;
2743 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2745 keywords_find_reset(kfd);
2746 generic_dialog_close(kfd->gd);
2750 static void keywords_find_finish(KeywordFindData *kfd)
2752 keywords_find_reset(kfd);
2754 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2755 spinner_set_interval(kfd->spinner, -1);
2757 gtk_widget_set_sensitive(kfd->group, TRUE);
2758 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2759 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2760 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2763 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2765 KeywordFindData *kfd = data;
2767 g_idle_remove_by_data(kfd);
2769 keywords_find_finish(kfd);
2772 static gboolean keywords_find_file(gpointer data)
2774 KeywordFindData *kfd = data;
2776 GtkTextBuffer *buffer;
2784 fd = kfd->list->data;
2785 kfd->list = g_list_remove(kfd->list, fd);
2787 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2788 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2792 gtk_text_buffer_get_end_iter(buffer, &iter);
2793 tmp = g_strconcat(keywords->data, "\n", NULL);
2794 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2796 keywords = keywords->next;
2799 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2800 file_data_unref(fd);
2801 string_list_free(keywords);
2805 else if (kfd->list_dir)
2809 fd = kfd->list_dir->data;
2810 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2812 keywords_find_folder(kfd, fd);
2814 file_data_unref(fd);
2819 keywords_find_finish(kfd);
2824 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2826 KeywordFindData *kfd = data;
2829 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2831 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2832 parse_out_relatives(path);
2836 warning_dialog(_("Invalid folder"),
2837 _("The specified folder can not be found."),
2838 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2844 gtk_widget_set_sensitive(kfd->group, FALSE);
2845 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2846 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2847 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2848 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2850 dir_fd = file_data_new_dir(path);
2851 keywords_find_folder(kfd, dir_fd);
2852 file_data_unref(dir_fd);
2853 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2859 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2861 KeywordFindData *kfd;
2865 kfd = g_new0(KeywordFindData, 1);
2867 kfd->gd = generic_dialog_new(_("Search for keywords"),
2868 "search_for_keywords",
2871 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2872 kfd->gd->cancel_cb = keywords_find_close_cb;
2873 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2874 keywords_find_close_cb, FALSE);
2875 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2876 keywords_find_start_cb, FALSE);
2877 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2878 keywords_find_stop_cb, FALSE);
2879 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2881 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2883 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2884 pref_spacer(hbox, PREF_PAD_INDENT);
2885 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2887 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2888 pref_label_new(hbox, _("Folder:"));
2890 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2891 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2892 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2893 gtk_widget_show(label);
2895 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2897 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2898 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2900 kfd->progress = gtk_entry_new();
2901 gtk_widget_set_can_focus(kfd->progress, FALSE);
2902 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2903 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2904 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2905 gtk_widget_show(kfd->progress);
2907 kfd->spinner = spinner_new(NULL, -1);
2908 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2909 gtk_widget_show(kfd->spinner);
2913 gtk_widget_show(kfd->gd->dialog);
2916 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2918 const gchar *path = layout_get_path(NULL);
2920 if (!path || !*path) path = homedir();
2921 keywords_find_dialog(widget, path);
2924 static void config_tab_keywords_save()
2926 GtkTextIter start, end;
2927 GtkTextBuffer *buffer;
2928 GList *kw_list = NULL;
2934 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2935 gtk_text_buffer_get_bounds(buffer, &start, &end);
2937 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2939 kw_split = strtok(buffer_text, "\n");
2940 while (kw_split != NULL)
2946 if (g_strcmp0(work->data, kw_split) == 0)
2955 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2957 kw_split = strtok(NULL, "\n");
2960 keyword_list_set(kw_list);
2962 string_list_free(kw_list);
2963 g_free(buffer_text);
2966 static void config_tab_keywords(GtkWidget *notebook)
2972 GtkWidget *scrolled;
2974 GtkTextBuffer *buffer;
2977 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2979 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2981 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2983 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2984 G_CALLBACK(keywords_find_cb), keyword_text);
2985 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2988 keyword_text = gtk_text_view_new();
2989 gtk_widget_set_size_request(keyword_text, 20, 20);
2990 scrolled = gtk_scrolled_window_new(NULL, NULL);
2991 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2992 gtk_widget_show(scrolled);
2994 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2995 gtk_widget_show(keyword_text);
2997 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2999 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3000 gtk_text_buffer_create_tag(buffer, "monospace",
3001 "family", "monospace", NULL);
3003 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3004 gtk_text_buffer_get_start_iter(buffer, &iter);
3005 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3008 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3010 GList *kwl = keyword_list_get();
3011 kwl = g_list_first(kwl);
3014 gtk_text_buffer_get_end_iter (buffer, &iter);
3015 tmp = g_strconcat(kwl->data, "\n", NULL);
3016 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3021 gtk_text_buffer_set_modified(buffer, FALSE);
3028 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3030 gint *option = data;
3032 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3036 *option = INTENT_PERCEPTUAL;
3039 *option = INTENT_RELATIVE_COLORIMETRIC;
3042 *option = INTENT_SATURATION;
3045 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3050 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3051 gint option, gint *option_c)
3058 pref_table_label(table, column, row, text, 0.0);
3060 combo = gtk_combo_box_text_new();
3062 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3063 if (option == INTENT_PERCEPTUAL) current = 0;
3064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3065 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3066 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3067 if (option == INTENT_SATURATION) current = 2;
3068 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3069 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3071 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3073 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3075 g_signal_connect(G_OBJECT(combo), "changed",
3076 G_CALLBACK(intent_menu_cb), option_c);
3078 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
3079 GTK_EXPAND | GTK_FILL, 0, 0, 0);
3080 gtk_widget_show(combo);
3084 static void config_tab_color(GtkWidget *notebook)
3093 vbox = scrolled_notebook_page(notebook, _("Color management"));
3095 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3097 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3100 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3101 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3103 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3104 pref_label_bold(label, TRUE, FALSE);
3106 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3107 pref_label_bold(label, TRUE, FALSE);
3109 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3110 pref_label_bold(label, TRUE, FALSE);
3112 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3117 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3118 pref_table_label(table, 0, i + 1, buf, 1.0);
3121 entry = gtk_entry_new();
3122 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3123 if (options->color_profile.input_name[i])
3125 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3127 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3128 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3129 gtk_widget_show(entry);
3130 color_profile_input_name_entry[i] = entry;
3132 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3133 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3134 gtk_widget_set_size_request(entry, 160, -1);
3135 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3136 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3137 gtk_widget_show(tabcomp);
3138 color_profile_input_file_entry[i] = entry;
3141 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3143 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3145 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3146 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3148 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3150 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3151 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3152 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3153 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3154 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3156 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3158 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3160 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3162 gtk_widget_show(tabcomp);
3165 /* advanced entry tab */
3166 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3168 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3170 c_options->file_ops.use_system_trash = FALSE;
3171 c_options->file_ops.no_trash = FALSE;
3175 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3177 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3179 c_options->file_ops.use_system_trash = TRUE;
3180 c_options->file_ops.no_trash = FALSE;
3184 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3186 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3188 c_options->file_ops.no_trash = TRUE;
3192 static void config_tab_behavior(GtkWidget *notebook)
3199 GtkWidget *ct_button;
3203 GtkWidget *with_rename;
3204 GtkWidget *collections_on_top;
3206 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3208 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3210 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3211 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3212 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3213 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3214 pref_checkbox_new_int(group, _("Enable Delete key"),
3215 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3217 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3218 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3220 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3221 pref_checkbox_link_sensitivity(ct_button, hbox);
3223 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3224 pref_label_new(hbox, _("Folder:"));
3226 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3227 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3228 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3229 gtk_widget_show(tabcomp);
3231 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3232 pref_checkbox_link_sensitivity(ct_button, hbox);
3234 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3235 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3236 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3237 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3238 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3239 G_CALLBACK(safe_delete_view_cb), NULL);
3240 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3241 gtk_widget_show(button);
3243 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3244 G_CALLBACK(safe_delete_clear_cb), NULL);
3245 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3246 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3247 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3249 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3250 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3252 gtk_widget_show(button);
3254 pref_spacer(group, PREF_PAD_GROUP);
3257 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3259 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3260 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3262 pref_checkbox_new_int(group, _("In place renaming"),
3263 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3265 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3266 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3268 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3269 options->marks_save, &c_options->marks_save);
3270 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3272 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3273 options->with_rename, &c_options->with_rename);
3274 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3276 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3277 options->collections_on_top, &c_options->collections_on_top);
3278 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3280 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3281 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3283 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3284 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3286 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3287 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3289 pref_spacer(group, PREF_PAD_GROUP);
3291 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3293 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3294 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3295 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3296 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3297 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3298 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3299 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3300 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3301 pref_checkbox_new_int(group, _("Play video by left click on image"),
3302 options->image_l_click_video, &c_options->image_l_click_video);
3303 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3304 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3306 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3307 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3308 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3309 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3310 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3313 pref_spacer(group, PREF_PAD_GROUP);
3315 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3317 pref_spin_new_int(group, _("Debug level:"), NULL,
3318 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3320 pref_checkbox_new_int(group, _("Timer data"),
3321 options->log_window.timer_data, &c_options->log_window.timer_data);
3323 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3324 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3328 /* accelerators tab */
3329 static void config_tab_accelerators(GtkWidget *notebook)
3335 GtkWidget *scrolled;
3336 GtkWidget *accel_view;
3337 GtkCellRenderer *renderer;
3338 GtkTreeSelection *selection;
3339 GtkTreeViewColumn *column;
3341 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3343 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3345 scrolled = gtk_scrolled_window_new(NULL, NULL);
3346 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3347 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3348 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3349 gtk_widget_show(scrolled);
3351 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3353 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3354 g_object_unref(accel_store);
3355 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3356 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3358 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3360 renderer = gtk_cell_renderer_text_new();
3362 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3367 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3368 gtk_tree_view_column_set_resizable(column, TRUE);
3369 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3372 renderer = gtk_cell_renderer_accel_new();
3373 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3374 G_CALLBACK(accel_store_cleared_cb), accel_store);
3375 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3376 G_CALLBACK(accel_store_edited_cb), accel_store);
3379 g_object_set (renderer,
3381 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3384 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3389 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3390 gtk_tree_view_column_set_resizable(column, TRUE);
3391 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3393 renderer = gtk_cell_renderer_text_new();
3395 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3400 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3401 gtk_tree_view_column_set_resizable(column, TRUE);
3402 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3404 renderer = gtk_cell_renderer_text_new();
3406 column = gtk_tree_view_column_new_with_attributes("Accel",
3411 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3412 gtk_tree_view_column_set_resizable(column, TRUE);
3413 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3415 accel_store_populate();
3416 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3417 gtk_widget_show(accel_view);
3419 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3421 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3422 G_CALLBACK(accel_default_cb), accel_view);
3423 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3424 gtk_widget_show(button);
3426 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3427 G_CALLBACK(accel_reset_cb), accel_view);
3428 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3429 gtk_widget_show(button);
3433 static void config_tab_toolbar(GtkWidget *notebook)
3436 GtkWidget *toolbardata;
3439 lw = layout_window_list->data;
3441 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3443 toolbardata = toolbar_select_new(lw);
3444 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3445 gtk_widget_show(vbox);
3449 static void config_tab_stereo(GtkWidget *notebook)
3457 GtkWidget *fs_button;
3458 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3460 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3462 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3463 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3465 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3466 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3467 pref_checkbox_new_int(box, _("Mirror left image"),
3468 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3469 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3470 pref_checkbox_new_int(box, _("Flip left image"),
3471 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3472 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3473 pref_checkbox_new_int(box, _("Mirror right image"),
3474 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3475 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3476 pref_checkbox_new_int(box, _("Flip right image"),
3477 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3478 pref_checkbox_new_int(group, _("Swap left and right images"),
3479 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3480 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3481 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3483 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3484 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3485 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3486 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3487 pref_checkbox_link_sensitivity(fs_button, box2);
3488 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3489 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3490 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3491 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3492 pref_checkbox_new_int(box, _("Mirror left image"),
3493 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3494 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3495 pref_checkbox_new_int(box, _("Flip left image"),
3496 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3497 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3498 pref_checkbox_new_int(box, _("Mirror right image"),
3499 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3500 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3501 pref_checkbox_new_int(box, _("Flip right image"),
3502 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3503 pref_checkbox_new_int(box2, _("Swap left and right images"),
3504 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3505 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3506 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3508 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3509 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3510 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3511 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3512 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3513 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3514 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3515 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3516 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3517 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3518 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3519 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3520 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3521 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3525 /* Main preferences window */
3526 static void config_window_create(void)
3528 GtkWidget *win_vbox;
3530 GtkWidget *notebook;
3532 GtkWidget *ct_button;
3534 if (!c_options) c_options = init_options(NULL);
3536 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3537 DEBUG_NAME(configwindow);
3538 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3539 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3540 G_CALLBACK(config_window_delete), NULL);
3541 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3542 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3543 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3545 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3546 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3547 gtk_widget_show(win_vbox);
3549 notebook = gtk_notebook_new();
3550 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3551 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3552 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3554 config_tab_general(notebook);
3555 config_tab_image(notebook);
3556 config_tab_osd(notebook);
3557 config_tab_windows(notebook);
3558 config_tab_accelerators(notebook);
3559 config_tab_files(notebook);
3560 config_tab_metadata(notebook);
3561 config_tab_keywords(notebook);
3562 config_tab_color(notebook);
3563 config_tab_stereo(notebook);
3564 config_tab_behavior(notebook);
3565 config_tab_toolbar(notebook);
3567 hbox = gtk_hbutton_box_new();
3568 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3569 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3570 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3571 gtk_widget_show(hbox);
3573 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3574 G_CALLBACK(config_window_help_cb), notebook);
3575 gtk_container_add(GTK_CONTAINER(hbox), button);
3576 gtk_widget_set_can_default(button, TRUE);
3577 gtk_widget_show(button);
3579 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3580 G_CALLBACK(config_window_ok_cb), NULL);
3581 gtk_container_add(GTK_CONTAINER(hbox), button);
3582 gtk_widget_set_can_default(button, TRUE);
3583 gtk_widget_grab_default(button);
3584 gtk_widget_show(button);
3588 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3589 G_CALLBACK(config_window_save_cb), NULL);
3590 gtk_container_add(GTK_CONTAINER(hbox), button);
3591 gtk_widget_set_can_default(button, TRUE);
3592 gtk_widget_show(button);
3594 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3595 G_CALLBACK(config_window_apply_cb), NULL);
3596 gtk_container_add(GTK_CONTAINER(hbox), button);
3597 gtk_widget_set_can_default(button, TRUE);
3598 gtk_widget_show(button);
3600 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3601 G_CALLBACK(config_window_close_cb), NULL);
3602 gtk_container_add(GTK_CONTAINER(hbox), button);
3603 gtk_widget_set_can_default(button, TRUE);
3604 gtk_widget_show(button);
3606 if (!generic_dialog_get_alternative_button_order(configwindow))
3608 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3611 gtk_widget_show(notebook);
3613 gtk_widget_show(configwindow);
3617 *-----------------------------------------------------------------------------
3618 * config window show (public)
3619 *-----------------------------------------------------------------------------
3622 void show_config_window(void)
3626 gtk_window_present(GTK_WINDOW(configwindow));
3630 config_window_create();
3639 void show_about_window(LayoutWindow *lw)
3641 GdkPixbuf *pixbuf_logo;
3642 GdkPixbuf *pixbuf_icon;
3643 gchar *authors[1000];
3651 #define LINE_LENGTH 1000
3652 gchar line[LINE_LENGTH];
3654 copyright = g_string_new(NULL);
3655 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");
3657 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3658 cd = ZDOpenDatabase(zd_path);
3661 copyright = g_string_append(copyright, ZDGetNotice(cd));
3663 ZDCloseDatabase(cd);
3667 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3668 fp = fopen(path, "r");
3671 while(fgets(line, LINE_LENGTH, fp))
3673 /* get rid of ending \n from fgets */
3674 line[strlen(line) - 1] = '\0';
3675 authors[i_authors] = g_strdup(line);
3678 authors[i_authors] = NULL;
3683 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3684 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3686 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3687 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3688 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3689 "title", _("About Geeqie"),
3691 "program-name", GQ_APPNAME,
3693 "logo", pixbuf_logo,
3694 "icon", pixbuf_icon,
3695 "website", GQ_WEBSITE,
3696 "website-label", "Website",
3697 "comments", comment,
3699 "translator-credits", _("translator-credits"),
3700 "wrap-license", TRUE,
3701 "license", copyright->str,
3704 g_string_free(copyright, TRUE);
3707 while(n < i_authors)
3717 static void image_overlay_set_text_colours()
3719 c_options->image_overlay.text_red = options->image_overlay.text_red;
3720 c_options->image_overlay.text_green = options->image_overlay.text_green;
3721 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3722 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3723 c_options->image_overlay.background_red = options->image_overlay.background_red;
3724 c_options->image_overlay.background_green = options->image_overlay.background_green;
3725 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3726 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3730 *-----------------------------------------------------------------------------
3731 * timezone database routines
3732 *-----------------------------------------------------------------------------
3735 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3737 GError *error = NULL;
3739 gchar *tmp_filename;
3741 if (!g_cancellable_is_cancelled(tz->cancellable))
3743 generic_dialog_close(tz->gd);
3747 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3749 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3750 move_file(tmp_filename, tz->timezone_database_user);
3751 g_free(tmp_filename);
3755 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3758 g_file_delete(tz->tmp_g_file, NULL, &error);
3759 g_object_unref(tz->tmp_g_file);
3760 tz->tmp_g_file = NULL;
3761 g_object_unref(tz->cancellable);
3762 g_object_unref(tz->timezone_database_gq);
3765 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3769 if (!g_cancellable_is_cancelled(tz->cancellable))
3771 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3775 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3778 GError *error = NULL;
3780 g_cancellable_cancel(tz->cancellable);
3783 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3786 GError *error = NULL;
3787 GFileIOStream *io_stream;
3794 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3798 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3799 log_printf("Error: Download timezone database failed:\n%s", error->message);
3800 g_error_free(error);
3801 g_object_unref(tz->tmp_g_file);
3805 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3807 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3809 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3811 tz->progress = gtk_progress_bar_new();
3812 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3813 gtk_widget_show(tz->progress);
3815 gtk_widget_show(tz->gd->dialog);
3816 tz->cancellable = g_cancellable_new();
3817 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);
3819 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3822 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */