2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
382 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
383 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
384 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
385 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
386 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
387 options->metadata.confirm_write = c_options->metadata.confirm_write;
388 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
389 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
390 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
391 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
392 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
393 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
394 options->metadata.write_orientation = c_options->metadata.write_orientation;
395 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
396 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
397 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
398 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
399 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
400 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
401 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
402 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
403 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
404 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
406 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
407 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
408 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
409 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
410 options->stereo.fixed_w = c_options->stereo.fixed_w;
411 options->stereo.fixed_h = c_options->stereo.fixed_h;
412 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
413 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
414 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
415 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
417 options->info_keywords.height = c_options->info_keywords.height;
418 options->info_title.height = c_options->info_title.height;
419 options->info_comment.height = c_options->info_comment.height;
420 options->info_rating.height = c_options->info_rating.height;
422 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
424 options->marks_save = c_options->marks_save;
425 options->with_rename = c_options->with_rename;
426 options->collections_on_top = c_options->collections_on_top;
427 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
429 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
431 options->star_rating.star = c_options->star_rating.star;
432 options->star_rating.rejected = c_options->star_rating.rejected;
434 set_debug_level(debug_c);
438 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
440 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
441 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
443 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
444 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
445 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
447 options->color_profile.render_intent = c_options->color_profile.render_intent;
452 options->mouse_button_8 = c_options->mouse_button_8;
453 options->mouse_button_9 = c_options->mouse_button_9;
455 config_tab_keywords_save();
457 image_options_sync();
462 layout_refresh(NULL);
465 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
467 toolbar_apply(TOOLBAR_MAIN);
468 toolbar_apply(TOOLBAR_STATUS);
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)
518 lw = layout_window_list->data;
520 config_window_apply();
521 layout_util_sync(lw);
522 save_options(options);
523 config_window_close_cb(NULL, NULL);
527 *-----------------------------------------------------------------------------
528 * config window setup (private)
529 *-----------------------------------------------------------------------------
532 static void quality_menu_cb(GtkWidget *combo, gpointer data)
536 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
540 *option = GDK_INTERP_NEAREST;
543 *option = GDK_INTERP_TILES;
546 *option = GDK_INTERP_BILINEAR;
549 *option = GDK_INTERP_HYPER;
554 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
558 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
570 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
571 guint option, guint *option_c)
578 pref_table_label(table, column, row, text, 0.0);
580 combo = gtk_combo_box_text_new();
582 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
583 if (option == GDK_INTERP_NEAREST) current = 0;
584 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
585 if (option == GDK_INTERP_TILES) current = 1;
586 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
587 if (option == GDK_INTERP_BILINEAR) current = 2;
588 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
589 if (option == GDK_INTERP_HYPER) current = 3;
591 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
593 g_signal_connect(G_OBJECT(combo), "changed",
594 G_CALLBACK(quality_menu_cb), option_c);
596 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
597 gtk_widget_show(combo);
600 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
601 gint option, gint *option_c)
608 pref_table_label(table, column, row, text, 0.0);
610 combo = gtk_combo_box_text_new();
612 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
613 if (option == PRIMARY) current = 0;
614 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
615 if (option == CLIPBOARD) current = 1;
617 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
619 g_signal_connect(G_OBJECT(combo), "changed",
620 G_CALLBACK(clipboard_selection_menu_cb), option_c);
622 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
623 gtk_widget_show(combo);
626 typedef struct _UseableMouseItems UseableMouseItems;
627 struct _UseableMouseItems
629 gchar *name; /* GtkActionEntry terminology */
634 static const UseableMouseItems useable_mouse_items[] = {
636 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
637 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
638 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
639 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
640 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
641 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
642 {"Home", N_("Home"), GTK_STOCK_HOME},
643 {"Up", N_("Up"), GTK_STOCK_GO_UP},
644 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
645 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
646 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
647 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
648 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
649 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
650 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
651 {"Search", N_("Search"), GTK_STOCK_FIND},
652 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
653 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
654 {"Copy", N_("Copy"), GTK_STOCK_COPY},
655 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
656 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
657 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
658 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
659 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
660 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
661 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
662 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
663 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
664 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
665 {"Print", N_("Print"), GTK_STOCK_PRINT},
666 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
667 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
668 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
669 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
670 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
671 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
672 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
673 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
674 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
675 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
676 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
677 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
678 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
679 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
680 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
681 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
682 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
683 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
684 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
685 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
686 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
687 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
688 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
689 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
690 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
691 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
692 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
693 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
694 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
695 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
696 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
697 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
698 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
699 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
700 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
701 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
702 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
703 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
704 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
708 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
710 gchar **option = data;
713 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
715 const UseableMouseItems *list = useable_mouse_items;
719 if (g_strcmp0(list->label, label) == 0)
727 *option = g_strdup(list->name);
731 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
732 gchar *option, gchar **option_c)
740 pref_table_label(table, column, row, text, 0.0);
742 combo = gtk_combo_box_text_new();
744 const UseableMouseItems *list = useable_mouse_items;
748 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
749 if (g_strcmp0(list->name, option) == 0)
757 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
759 g_signal_connect(G_OBJECT(combo), "changed",
760 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
762 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
763 gtk_widget_show(combo);
766 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
770 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
773 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
775 c_options->thumbnails.max_width = thumb_size_list[n].w;
776 c_options->thumbnails.max_height = thumb_size_list[n].h;
780 c_options->thumbnails.max_width = options->thumbnails.max_width;
781 c_options->thumbnails.max_height = options->thumbnails.max_height;
785 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
791 c_options->thumbnails.max_width = options->thumbnails.max_width;
792 c_options->thumbnails.max_height = options->thumbnails.max_height;
794 pref_table_label(table, column, row, text, 0.0);
796 combo = gtk_combo_box_text_new();
799 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
804 w = thumb_size_list[i].w;
805 h = thumb_size_list[i].h;
807 buf = g_strdup_printf("%d x %d", w, h);
808 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
811 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
818 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
819 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
825 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
826 g_signal_connect(G_OBJECT(combo), "changed",
827 G_CALLBACK(thumb_size_menu_cb), NULL);
829 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
830 gtk_widget_show(combo);
833 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
837 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
841 *option = PR_STEREO_NONE;
844 *option = PR_STEREO_ANAGLYPH_RC;
847 *option = PR_STEREO_ANAGLYPH_GM;
850 *option = PR_STEREO_ANAGLYPH_YB;
853 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
856 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
859 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
862 *option = PR_STEREO_ANAGLYPH_DB_RC;
865 *option = PR_STEREO_ANAGLYPH_DB_GM;
868 *option = PR_STEREO_ANAGLYPH_DB_YB;
871 *option = PR_STEREO_HORIZ;
874 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
877 *option = PR_STEREO_VERT;
880 *option = PR_STEREO_VERT | PR_STEREO_HALF;
883 *option = PR_STEREO_FIXED;
888 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
889 gint option, gint *option_c, gboolean add_fixed)
896 pref_table_label(table, column, row, text, 0.0);
898 combo = gtk_combo_box_text_new();
900 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
902 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
903 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
904 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
905 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
906 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
907 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
908 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
909 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
910 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
911 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
912 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
913 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
914 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
915 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
916 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
917 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
918 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
919 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
921 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
922 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
923 if (option & PR_STEREO_HORIZ)
926 if (option & PR_STEREO_HALF) current = 11;
929 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
930 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
931 if (option & PR_STEREO_VERT)
934 if (option & PR_STEREO_HALF) current = 13;
939 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
940 if (option & PR_STEREO_FIXED) current = 14;
943 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
945 g_signal_connect(G_OBJECT(combo), "changed",
946 G_CALLBACK(stereo_mode_menu_cb), option_c);
948 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
949 gtk_widget_show(combo);
952 static void video_menu_cb(GtkWidget *combo, gpointer data)
954 gchar **option = data;
956 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
960 static void video_menu_populate(gpointer data, gpointer user_data)
962 GtkWidget *combo = user_data;
963 EditorDescription *ed = data;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
968 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
969 gchar *option, gchar **option_c)
973 /* use lists since they are sorted */
974 GList *eds = editor_list_get();
978 pref_table_label(table, column, row, text, 0.0);
980 combo = gtk_combo_box_text_new();
981 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
982 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
984 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
986 g_signal_connect(G_OBJECT(combo), "changed",
987 G_CALLBACK(video_menu_cb), option_c);
989 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
990 gtk_widget_show(combo);
993 static void filter_store_populate(void)
997 if (!filter_store) return;
999 gtk_list_store_clear(filter_store);
1001 work = filter_get_list();
1010 gtk_list_store_append(filter_store, &iter);
1011 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1015 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1016 gchar *new_text, gpointer data)
1018 GtkWidget *model = data;
1019 FilterEntry *fe = data;
1023 if (!new_text || strlen(new_text) < 1) return;
1025 tpath = gtk_tree_path_new_from_string(path_str);
1026 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1027 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1029 g_free(fe->extensions);
1030 fe->extensions = g_strdup(new_text);
1032 gtk_tree_path_free(tpath);
1036 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1037 gchar *new_text, gpointer data)
1039 GtkWidget *model = data;
1040 FilterEntry *fe = data;
1045 if (!new_text || !new_text[0]) return;
1047 tpath = gtk_tree_path_new_from_string(path_str);
1048 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1049 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1051 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1053 if (strcmp(new_text, _(format_class_list[i])) == 0)
1060 gtk_tree_path_free(tpath);
1064 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1065 gchar *new_text, gpointer data)
1067 GtkWidget *model = data;
1072 if (!new_text || !new_text[0]) return;
1074 tpath = gtk_tree_path_new_from_string(path_str);
1075 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1076 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1078 g_free(fe->description);
1079 fe->description = g_strdup(new_text);
1081 gtk_tree_path_free(tpath);
1084 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1085 gchar *path_str, gpointer data)
1087 GtkWidget *model = data;
1092 tpath = gtk_tree_path_new_from_string(path_str);
1093 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1094 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1096 fe->enabled = !fe->enabled;
1098 gtk_tree_path_free(tpath);
1102 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1103 gchar *path_str, gpointer data)
1105 GtkWidget *model = data;
1110 tpath = gtk_tree_path_new_from_string(path_str);
1111 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1112 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1114 fe->writable = !fe->writable;
1115 if (fe->writable) fe->allow_sidecar = FALSE;
1117 gtk_tree_path_free(tpath);
1121 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1122 gchar *path_str, gpointer data)
1124 GtkWidget *model = data;
1129 tpath = gtk_tree_path_new_from_string(path_str);
1130 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1131 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1133 fe->allow_sidecar = !fe->allow_sidecar;
1134 if (fe->allow_sidecar) fe->writable = FALSE;
1136 gtk_tree_path_free(tpath);
1140 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1141 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1145 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1147 switch (GPOINTER_TO_INT(data))
1150 g_object_set(GTK_CELL_RENDERER(cell),
1151 "active", fe->enabled, NULL);
1154 g_object_set(GTK_CELL_RENDERER(cell),
1155 "text", fe->extensions, NULL);
1157 case FE_DESCRIPTION:
1158 g_object_set(GTK_CELL_RENDERER(cell),
1159 "text", fe->description, NULL);
1162 g_object_set(GTK_CELL_RENDERER(cell),
1163 "text", _(format_class_list[fe->file_class]), NULL);
1166 g_object_set(GTK_CELL_RENDERER(cell),
1167 "active", fe->writable, NULL);
1169 case FE_ALLOW_SIDECAR:
1170 g_object_set(GTK_CELL_RENDERER(cell),
1171 "active", fe->allow_sidecar, NULL);
1176 static gboolean filter_add_scroll(gpointer data)
1180 GtkCellRenderer *cell;
1181 GtkTreeViewColumn *column;
1186 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1187 path = gtk_tree_path_new_from_indices(rows-1, -1);
1189 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1191 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1192 cell = g_list_last(list_cells)->data;
1194 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1195 path, column, FALSE, 0.0, 0.0 );
1196 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1197 path, column, cell, TRUE);
1199 gtk_tree_path_free(path);
1200 g_list_free(list_cells);
1205 static void filter_add_cb(GtkWidget *widget, gpointer data)
1207 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1208 filter_store_populate();
1210 g_idle_add((GSourceFunc)filter_add_scroll, data);
1213 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1215 GtkWidget *filter_view = data;
1216 GtkTreeSelection *selection;
1220 if (!filter_store) return;
1221 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1222 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1223 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1226 filter_remove_entry(fe);
1228 filter_store_populate();
1231 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1235 GtkTreeViewColumn *column;
1237 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1238 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1239 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1241 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1245 gtk_tree_path_free(path);
1250 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1253 filter_add_defaults();
1255 filter_store_populate();
1257 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1260 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1262 /* no op, only so cancel button appears */
1265 static void filter_default_cb(GtkWidget *widget, gpointer data)
1269 gd = generic_dialog_new(_("Reset filters"),
1270 "reset_filter", widget, TRUE,
1271 dummy_cancel_cb, data);
1272 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1273 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1274 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1275 gtk_widget_show(gd->dialog);
1278 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1280 GtkWidget *frame = data;
1282 gtk_widget_set_sensitive(frame,
1283 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1286 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1288 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1291 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1293 file_util_trash_clear();
1296 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1300 gd = generic_dialog_new(_("Clear trash"),
1301 "clear_trash", widget, TRUE,
1302 dummy_cancel_cb, NULL);
1303 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1304 _("This will remove the trash contents."), FALSE);
1305 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1306 entry = gtk_entry_new();
1307 gtk_widget_set_can_focus(entry, FALSE);
1308 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1309 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1310 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1311 gtk_widget_show(entry);
1312 gtk_widget_show(gd->dialog);
1315 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1317 GtkWidget *pTextView;
1318 GtkTextBuffer *pTextBuffer;
1322 pTextView = GTK_WIDGET(data);
1324 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1325 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1326 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1328 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1329 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1332 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1334 GtkTextView *text_view = data;
1335 GtkTextBuffer *buffer;
1337 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1338 if (!configwindow) return;
1340 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1341 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1344 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1348 gd = generic_dialog_new(_("Reset image overlay template string"),
1349 "reset_image_overlay_template_string", widget, TRUE,
1350 dummy_cancel_cb, data);
1351 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1352 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1353 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1354 gtk_widget_show(gd->dialog);
1357 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1359 help_window_show("GuideOptionsOSD.html");
1362 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1364 #if GTK_CHECK_VERSION(3,4,0)
1367 PangoFontDescription *font_desc;
1369 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1370 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1372 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1374 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1375 font = pango_font_description_to_string(font_desc);
1376 g_free(c_options->image_overlay.font);
1377 c_options->image_overlay.font = g_strdup(font);
1381 gtk_widget_destroy(dialog);
1385 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1386 c_options->image_overlay.font = g_strdup(font);
1390 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1393 #if GTK_CHECK_VERSION(3,4,0)
1396 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1397 colour.red = options->image_overlay.text_red;
1398 colour.green = options->image_overlay.text_green;
1399 colour.blue = options->image_overlay.text_blue;
1400 colour.alpha = options->image_overlay.text_alpha;
1401 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1402 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1404 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1406 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1407 c_options->image_overlay.text_red = colour.red*255;
1408 c_options->image_overlay.text_green = colour.green*255;
1409 c_options->image_overlay.text_blue = colour.blue*255;
1410 c_options->image_overlay.text_alpha = colour.alpha*255;
1412 gtk_widget_destroy(dialog);
1415 GtkColorSelection *colorsel;
1417 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1418 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1419 colour.red = options->image_overlay.text_red*257;
1420 colour.green = options->image_overlay.text_green*257;
1421 colour.blue = options->image_overlay.text_blue*257;
1422 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1423 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1424 gtk_color_selection_set_current_color(colorsel, &colour);
1425 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1427 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1429 gtk_color_selection_get_current_color(colorsel, &colour);
1430 c_options->image_overlay.text_red = colour.red/257;
1431 c_options->image_overlay.text_green = colour.green/257;
1432 c_options->image_overlay.text_blue = colour.blue/257;
1433 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1435 gtk_widget_destroy (dialog);
1440 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1443 #if GTK_CHECK_VERSION(3,4,0)
1446 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1447 colour.red = options->image_overlay.background_red;
1448 colour.green = options->image_overlay.background_green;
1449 colour.blue = options->image_overlay.background_blue;
1450 colour.alpha = options->image_overlay.background_alpha;
1451 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1452 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1454 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1456 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1457 c_options->image_overlay.background_red = colour.red*255;
1458 c_options->image_overlay.background_green = colour.green*255;
1459 c_options->image_overlay.background_blue = colour.blue*255;
1460 c_options->image_overlay.background_alpha = colour.alpha*255;
1462 gtk_widget_destroy(dialog);
1465 GtkColorSelection *colorsel;
1467 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1468 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1469 colour.red = options->image_overlay.background_red*257;
1470 colour.green = options->image_overlay.background_green*257;
1471 colour.blue = options->image_overlay.background_blue*257;
1472 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1473 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1474 gtk_color_selection_set_current_color(colorsel, &colour);
1475 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1477 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1479 gtk_color_selection_get_current_color(colorsel, &colour);
1480 c_options->image_overlay.background_red = colour.red/257;
1481 c_options->image_overlay.background_green = colour.green/257;
1482 c_options->image_overlay.background_blue = colour.blue/257;
1483 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1485 gtk_widget_destroy(dialog);
1489 static void accel_store_populate(void)
1492 GList *groups, *actions;
1494 const gchar *accel_path;
1498 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1500 gtk_tree_store_clear(accel_store);
1501 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1503 g_assert(lw && lw->ui_manager);
1504 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1507 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1510 action = GTK_ACTION(actions->data);
1511 accel_path = gtk_action_get_accel_path(action);
1512 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1514 gchar *label, *label2, *tooltip, *accel;
1515 g_object_get(action,
1516 "tooltip", &tooltip,
1520 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1526 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1530 gtk_tree_store_append(accel_store, &iter, NULL);
1531 gtk_tree_store_set(accel_store, &iter,
1534 AE_TOOLTIP, tooltip ? tooltip : "",
1535 AE_ACCEL, accel_path,
1543 actions = actions->next;
1546 groups = groups->next;
1550 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1555 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1557 gchar *accel1 = data;
1562 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1564 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1565 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1567 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1569 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1570 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1579 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1581 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1585 GtkAccelKey old_key, key;
1586 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1588 gtk_tree_model_get_iter(model, &iter, path);
1589 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1591 /* test if the accelerator can be stored without conflicts*/
1592 gtk_accel_map_lookup_entry(accel_path, &old_key);
1594 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1595 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1596 gtk_accel_map_lookup_entry(accel_path, &key);
1598 /* restore the original for now, the key will be really changed when the changes are confirmed */
1599 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1601 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1602 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1604 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1605 gtk_tree_path_free(path);
1609 static gboolean accel_default_scroll(GtkTreeView *data)
1613 GtkTreeViewColumn *column;
1615 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1616 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1617 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1619 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1623 gtk_tree_path_free(path);
1628 static void accel_default_cb(GtkWidget *widget, gpointer data)
1630 accel_store_populate();
1632 g_idle_add((GSourceFunc)accel_default_scroll, data);
1635 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1637 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1640 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1643 gchar *accel_path, *accel;
1645 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1646 gtk_accel_map_lookup_entry(accel_path, &key);
1647 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1649 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1651 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1656 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1658 GtkTreeSelection *selection;
1660 if (!accel_store) return;
1661 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1662 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1667 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1671 GtkWidget *scrolled;
1672 GtkWidget *viewport;
1674 scrolled = gtk_scrolled_window_new(NULL, NULL);
1675 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1676 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1677 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1678 label = gtk_label_new(title);
1679 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1680 gtk_widget_show(scrolled);
1682 viewport = gtk_viewport_new(NULL, NULL);
1683 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1684 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1685 gtk_widget_show(viewport);
1687 vbox = gtk_vbox_new(FALSE, 0);
1688 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1689 gtk_widget_show(vbox);
1694 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1696 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1698 c_options->thumbnails.spec_standard =TRUE;
1699 c_options->thumbnails.cache_into_dirs = FALSE;
1703 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1705 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1707 c_options->thumbnails.spec_standard =FALSE;
1708 c_options->thumbnails.cache_into_dirs = FALSE;
1712 static void cache_local_cb(GtkWidget *widget, gpointer data)
1714 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1716 c_options->thumbnails.cache_into_dirs = TRUE;
1717 c_options->thumbnails.spec_standard =FALSE;
1721 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1722 GdkEvent *event, gpointer userdata)
1724 if (pos == GTK_ENTRY_ICON_PRIMARY)
1726 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1730 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1734 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1735 GdkEvent *event, gpointer userdata)
1737 gchar *rating_symbol;
1739 if (pos == GTK_ENTRY_ICON_PRIMARY)
1741 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1742 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1743 g_free(rating_symbol);
1747 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1748 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1749 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1753 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1754 GdkEvent *event, gpointer userdata)
1756 gchar *rating_symbol;
1758 if (pos == GTK_ENTRY_ICON_PRIMARY)
1760 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1761 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1762 g_free(rating_symbol);
1766 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1767 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1768 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1772 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1774 GtkContainer *hbox = data;
1775 GString *str = g_string_new(NULL);
1776 GtkEntry *hex_code_entry;
1777 gchar *hex_code_full;
1780 guint64 hex_value = 0;
1782 list = gtk_container_get_children(hbox);
1784 hex_code_entry = g_list_nth_data(list, 2);
1785 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1787 hex_code = g_strsplit(hex_code_full, "+", 2);
1788 if (hex_code[0] && hex_code[1])
1790 hex_value = strtoull(hex_code[1], NULL, 16);
1792 if (!hex_value || hex_value > 0x10FFFF)
1794 hex_value = 0x003F; // Unicode 'Question Mark'
1796 str = g_string_append_unichar(str, (gunichar)hex_value);
1797 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1799 g_strfreev(hex_code);
1800 g_string_free(str, TRUE);
1801 g_free(hex_code_full);
1806 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1808 guint64 star_symbol;
1810 star_symbol = star_rating_symbol_test(widget, data);
1811 c_options->star_rating.star = star_symbol;
1814 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1816 guint64 rejected_symbol;
1818 rejected_symbol = star_rating_symbol_test(widget, data);
1819 c_options->star_rating.rejected = rejected_symbol;
1822 /* general options tab */
1823 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1824 typedef struct _TZData TZData;
1828 GCancellable *cancellable;
1830 GtkWidget *progress;
1832 GFile *timezone_database_gq;
1833 gchar *timezone_database_user;
1836 static void config_tab_general(GtkWidget *notebook)
1841 GtkWidget *group_frame;
1842 GtkWidget *subgroup;
1844 GtkWidget *ct_button;
1847 gint hours, minutes, remainder;
1849 GtkWidget *star_rating_entry;
1851 gchar *rating_symbol;
1854 GNetworkMonitor *net_mon;
1855 GSocketConnectable *geeqie_org;
1856 gboolean internet_available;
1859 vbox = scrolled_notebook_page(notebook, _("General"));
1861 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1863 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1864 add_thumb_size_menu(table, 0, 0, _("Size:"));
1865 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1867 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1868 pref_label_new(hbox, _("Custom size: "));
1869 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1870 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1872 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1873 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1875 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1876 pref_checkbox_link_sensitivity(ct_button, subgroup);
1878 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1879 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1880 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1881 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1882 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1883 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1884 G_CALLBACK(cache_geeqie_cb), NULL);
1886 group_frame = pref_frame_new(subgroup, TRUE,
1887 _("Store thumbnails local to image folder (non-standard)"),
1888 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1889 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1890 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1891 G_CALLBACK(cache_local_cb), NULL);
1893 group_frame = pref_frame_new(subgroup, TRUE,
1894 _("Use standard thumbnail style and cache, shared with other applications"),
1895 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1896 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1897 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1898 G_CALLBACK(cache_standard_cb), NULL);
1900 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1901 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1903 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1905 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1906 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1908 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1909 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1910 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1912 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1913 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1916 pref_spacer(group, PREF_PAD_GROUP);
1918 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1920 c_options->star_rating.star = options->star_rating.star;
1921 c_options->star_rating.rejected = options->star_rating.rejected;
1923 str = g_string_new(NULL);
1924 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1925 pref_label_new(hbox, "Star character: ");
1926 str = g_string_append_unichar(str, options->star_rating.star);
1927 pref_label_new(hbox, g_strdup(str->str));
1928 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1929 star_rating_entry = gtk_entry_new();
1930 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1931 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1932 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1933 gtk_widget_show(star_rating_entry);
1934 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1935 G_CALLBACK(star_rating_star_test_cb), hbox);
1936 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1937 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1938 gtk_widget_show(button);
1939 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."));
1940 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1941 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1942 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1943 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1944 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1945 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1946 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1947 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1948 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1949 G_CALLBACK(star_rating_star_icon_cb),
1952 g_string_free(str, TRUE);
1953 g_free(rating_symbol);
1955 str = g_string_new(NULL);
1956 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1957 pref_label_new(hbox, "Rejected character: ");
1958 str = g_string_append_unichar(str, options->star_rating.rejected);
1959 pref_label_new(hbox, g_strdup(str->str));
1960 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1961 star_rating_entry = gtk_entry_new();
1962 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1963 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1964 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1965 gtk_widget_show(star_rating_entry);
1966 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1967 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1968 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1969 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1970 gtk_widget_show(button);
1971 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."));
1972 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1973 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1974 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1975 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1976 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1977 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1978 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1979 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1980 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1981 G_CALLBACK(star_rating_rejected_icon_cb),
1984 g_string_free(str, TRUE);
1985 g_free(rating_symbol);
1987 pref_spacer(group, PREF_PAD_GROUP);
1989 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1991 c_options->slideshow.delay = options->slideshow.delay;
1992 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1993 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1994 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1995 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1996 SLIDESHOW_SUBSECOND_PRECISION;
1998 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2000 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2002 options->slideshow.delay ? hours : 0.0,
2003 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2004 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2005 spin = pref_spin_new(hbox, ":" , NULL,
2007 options->slideshow.delay ? minutes: 0.0,
2008 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2009 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2010 spin = pref_spin_new(hbox, ":", NULL,
2011 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2012 options->slideshow.delay ? seconds : 10.0,
2013 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2014 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2016 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2017 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2019 pref_spacer(group, PREF_PAD_GROUP);
2021 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2023 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2024 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2025 pref_checkbox_new_int(group, _("Preload next image"),
2026 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2028 pref_checkbox_new_int(group, _("Refresh on file change"),
2029 options->update_on_time_change, &c_options->update_on_time_change);
2031 pref_spacer(group, PREF_PAD_GROUP);
2033 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2034 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2035 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2036 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2038 options->info_keywords.height, &c_options->info_keywords.height);
2039 pref_spin_new_int(hbox, _("Title:"), NULL,
2041 options->info_title.height, &c_options->info_title.height);
2042 pref_spin_new_int(hbox, _("Comment:"), NULL,
2044 options->info_comment.height, &c_options->info_comment.height);
2045 pref_spin_new_int(hbox, _("Rating:"), NULL,
2047 options->info_rating.height, &c_options->info_rating.height);
2049 pref_spacer(group, PREF_PAD_GROUP);
2051 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2053 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2054 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2056 pref_spacer(group, PREF_PAD_GROUP);
2058 net_mon = g_network_monitor_get_default();
2059 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2060 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2061 g_object_unref(geeqie_org);
2063 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2064 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2066 if (!internet_available)
2068 gtk_widget_set_sensitive(group, FALSE);
2071 tz = g_new0(TZData, 1);
2073 path = path_from_utf8(TIMEZONE_DATABASE);
2074 basename = g_path_get_basename(path);
2075 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2079 if (isfile(tz->timezone_database_user))
2081 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2085 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2088 if (!internet_available)
2090 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"));
2094 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"));
2096 gtk_widget_show(button);
2098 pref_spacer(group, PREF_PAD_GROUP);
2100 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2102 help_search_engine_entry = gtk_entry_new();
2103 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2104 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2105 gtk_widget_show(help_search_engine_entry);
2107 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"));
2109 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2110 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2111 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2112 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2113 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2114 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2115 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2116 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2117 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2118 G_CALLBACK(help_search_engine_entry_icon_cb),
2119 help_search_engine_entry);
2123 static void config_tab_image(GtkWidget *notebook)
2128 GtkWidget *ct_button;
2129 GtkWidget *enlargement_button;
2133 vbox = scrolled_notebook_page(notebook, _("Image"));
2135 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2137 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2138 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2141 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2142 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2145 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2146 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2148 c_options->image.zoom_increment = options->image.zoom_increment;
2149 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2150 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2151 G_CALLBACK(zoom_increment_cb), NULL);
2152 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2154 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2156 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2157 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2158 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2159 spin = pref_spin_new_int(hbox, NULL, NULL,
2161 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2162 pref_checkbox_link_sensitivity(enlargement_button, spin);
2163 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."));
2165 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2166 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2167 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2168 spin = pref_spin_new_int(hbox, NULL, NULL,
2170 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2171 pref_checkbox_link_sensitivity(ct_button, spin);
2172 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."));
2174 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2176 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2177 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2179 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2180 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2182 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2183 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2185 c_options->image.border_color = options->image.border_color;
2187 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2188 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2190 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2191 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2193 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2194 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2196 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2198 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2199 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2203 static void config_tab_windows(GtkWidget *notebook)
2209 GtkWidget *ct_button;
2212 vbox = scrolled_notebook_page(notebook, _("Windows"));
2214 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2216 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2217 options->save_window_positions, &c_options->save_window_positions);
2219 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2220 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2221 pref_checkbox_link_sensitivity(ct_button, button);
2223 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2224 options->tools_restore_state, &c_options->tools_restore_state);
2226 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2227 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2229 pref_checkbox_new_int(group, _("Show window IDs"),
2230 options->show_window_ids, &c_options->show_window_ids);
2232 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2234 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2235 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2237 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2238 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2239 options->image.limit_window_size, &c_options->image.limit_window_size);
2240 spin = pref_spin_new_int(hbox, NULL, NULL,
2242 options->image.max_window_size, &c_options->image.max_window_size);
2243 pref_checkbox_link_sensitivity(ct_button, spin);
2245 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2247 c_options->fullscreen.screen = options->fullscreen.screen;
2248 c_options->fullscreen.above = options->fullscreen.above;
2249 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2250 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2251 gtk_widget_show(hbox);
2253 pref_checkbox_new_int(group, _("Smooth image flip"),
2254 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2255 pref_checkbox_new_int(group, _("Disable screen saver"),
2256 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2259 #define PRE_FORMATTED_COLUMNS 5
2260 static void config_tab_osd(GtkWidget *notebook)
2264 GtkWidget *vbox_buttons;
2267 GtkWidget *image_overlay_template_view;
2268 GtkWidget *scrolled;
2269 GtkWidget *scrolled_pre_formatted;
2270 GtkTextBuffer *buffer;
2272 GtkWidget * subgroup;
2277 vbox = scrolled_notebook_page(notebook, _("OSD"));
2279 image_overlay_template_view = gtk_text_view_new();
2281 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2283 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2285 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2286 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2287 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2288 gtk_widget_show(scrolled_pre_formatted);
2289 gtk_widget_show(subgroup);
2291 pref_line(group, PREF_PAD_GAP);
2293 pref_label_new(group, _("Image overlay template"));
2295 scrolled = gtk_scrolled_window_new(NULL, NULL);
2296 gtk_widget_set_size_request(scrolled, 200, 150);
2297 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2298 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2299 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2300 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2301 gtk_widget_show(scrolled);
2303 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2304 _("Extensive formatting options are shown in the Help file"));
2306 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2307 gtk_widget_show(image_overlay_template_view);
2309 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2311 #if GTK_CHECK_VERSION(3,4,0)
2312 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2313 G_CALLBACK(image_overlay_set_font_cb), notebook);
2315 button = gtk_font_button_new();
2316 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2317 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2318 g_signal_connect(G_OBJECT(button), "font-set",
2319 G_CALLBACK(image_overlay_set_font_cb),NULL);
2321 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2322 gtk_widget_show(button);
2324 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2325 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2326 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2327 gtk_widget_show(button);
2329 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2330 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2331 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2332 gtk_widget_show(button);
2333 image_overlay_set_text_colours();
2335 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2336 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2337 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2338 gtk_widget_show(button);
2340 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2341 G_CALLBACK(image_overlay_help_cb), NULL);
2342 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2343 gtk_widget_show(button);
2345 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2346 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2347 g_signal_connect(G_OBJECT(buffer), "changed",
2348 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2350 pref_line(group, PREF_PAD_GAP);
2352 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2353 hbox = gtk_hbox_new(FALSE, 0);
2354 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2355 gtk_widget_show(hbox);
2356 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2357 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2358 gtk_widget_show(label);
2359 pref_spacer(group,TRUE);
2361 group = pref_group_new(vbox, FALSE, _("Field separators"), 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(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
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 maximum length"), 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(_("%path:39%"));
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, _("Pre- and post- text"), 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(_("Text shown only if the field is non-null:\n%formatted.Aperture:F no. * setting%\n %formatted.Aperture:10:F no. * setting%"));
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, _("Pango markup"), 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(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2393 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2394 gtk_widget_show(label);
2397 static GtkTreeModel *create_class_model(void)
2399 GtkListStore *model;
2403 /* create list store */
2404 model = gtk_list_store_new(1, G_TYPE_STRING);
2405 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2407 gtk_list_store_append(model, &iter);
2408 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2410 return GTK_TREE_MODEL (model);
2415 static void config_tab_files(GtkWidget *notebook)
2422 GtkWidget *ct_button;
2423 GtkWidget *scrolled;
2424 GtkWidget *filter_view;
2425 GtkCellRenderer *renderer;
2426 GtkTreeSelection *selection;
2427 GtkTreeViewColumn *column;
2429 vbox = scrolled_notebook_page(notebook, _("Files"));
2431 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2433 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2434 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2435 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2436 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2437 pref_checkbox_new_int(group, _("Case sensitive sort"),
2438 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2439 pref_checkbox_new_int(group, _("Natural sort order"),
2440 options->file_sort.natural, &c_options->file_sort.natural);
2441 pref_checkbox_new_int(group, _("Disable file extension checks"),
2442 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2444 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2445 options->file_filter.disable, &c_options->file_filter.disable);
2448 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2450 sidecar_ext_entry = gtk_entry_new();
2451 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2452 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2453 gtk_widget_show(sidecar_ext_entry);
2455 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2457 frame = pref_group_parent(group);
2458 g_signal_connect(G_OBJECT(ct_button), "toggled",
2459 G_CALLBACK(filter_disable_cb), frame);
2460 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2462 scrolled = gtk_scrolled_window_new(NULL, NULL);
2463 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2464 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2465 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2466 gtk_widget_show(scrolled);
2468 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2469 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2470 g_object_unref(filter_store);
2471 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2472 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2474 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2476 column = gtk_tree_view_column_new();
2477 gtk_tree_view_column_set_title(column, _("Filter"));
2478 gtk_tree_view_column_set_resizable(column, TRUE);
2480 renderer = gtk_cell_renderer_toggle_new();
2481 g_signal_connect(G_OBJECT(renderer), "toggled",
2482 G_CALLBACK(filter_store_enable_cb), filter_store);
2483 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2484 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2485 GINT_TO_POINTER(FE_ENABLE), NULL);
2487 renderer = gtk_cell_renderer_text_new();
2488 g_signal_connect(G_OBJECT(renderer), "edited",
2489 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2490 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2491 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2492 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2493 GINT_TO_POINTER(FE_EXTENSION), NULL);
2494 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2496 column = gtk_tree_view_column_new();
2497 gtk_tree_view_column_set_title(column, _("Description"));
2498 gtk_tree_view_column_set_resizable(column, TRUE);
2499 gtk_tree_view_column_set_fixed_width(column, 200);
2500 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2502 renderer = gtk_cell_renderer_text_new();
2503 g_signal_connect(G_OBJECT(renderer), "edited",
2504 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2505 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2506 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2507 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2508 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2509 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2511 column = gtk_tree_view_column_new();
2512 gtk_tree_view_column_set_title(column, _("Class"));
2513 gtk_tree_view_column_set_resizable(column, TRUE);
2514 renderer = gtk_cell_renderer_combo_new();
2515 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2516 "model", create_class_model(),
2521 g_signal_connect(G_OBJECT(renderer), "edited",
2522 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2523 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2524 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2525 GINT_TO_POINTER(FE_CLASS), NULL);
2526 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2528 column = gtk_tree_view_column_new();
2529 gtk_tree_view_column_set_title(column, _("Writable"));
2530 gtk_tree_view_column_set_resizable(column, FALSE);
2531 renderer = gtk_cell_renderer_toggle_new();
2532 g_signal_connect(G_OBJECT(renderer), "toggled",
2533 G_CALLBACK(filter_store_writable_cb), filter_store);
2534 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2535 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2536 GINT_TO_POINTER(FE_WRITABLE), NULL);
2537 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2539 column = gtk_tree_view_column_new();
2540 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2541 gtk_tree_view_column_set_resizable(column, FALSE);
2542 renderer = gtk_cell_renderer_toggle_new();
2543 g_signal_connect(G_OBJECT(renderer), "toggled",
2544 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2545 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2546 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2547 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2548 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2551 filter_store_populate();
2552 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2553 gtk_widget_show(filter_view);
2555 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2557 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2558 G_CALLBACK(filter_default_cb), filter_view);
2559 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2560 gtk_widget_show(button);
2562 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2563 G_CALLBACK(filter_remove_cb), filter_view);
2564 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2565 gtk_widget_show(button);
2567 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2568 G_CALLBACK(filter_add_cb), filter_view);
2569 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2570 gtk_widget_show(button);
2574 static void config_tab_metadata(GtkWidget *notebook)
2579 GtkWidget *ct_button;
2583 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2586 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2588 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2590 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2591 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2593 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2594 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2596 gtk_widget_set_sensitive(ct_button, FALSE);
2599 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2600 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2602 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2603 label = pref_label_new(group, text);
2604 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2605 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2608 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2610 gtk_widget_set_sensitive(group, FALSE);
2613 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2614 pref_checkbox_link_sensitivity(ct_button, hbox);
2616 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2617 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2619 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2620 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2622 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2623 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2625 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2626 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2628 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2630 gtk_widget_set_sensitive(group, FALSE);
2633 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2634 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2637 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2638 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2639 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2641 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2642 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2644 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2645 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2647 gtk_widget_set_sensitive(ct_button, FALSE);
2650 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2652 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2653 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2655 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2656 pref_checkbox_link_sensitivity(ct_button, hbox);
2658 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2659 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2661 pref_checkbox_new_int(group, _("Write metadata on image change"),
2662 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2664 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2665 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2667 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2669 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2670 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2671 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");
2676 typedef struct _KeywordFindData KeywordFindData;
2677 struct _KeywordFindData
2684 GtkWidget *button_close;
2685 GtkWidget *button_stop;
2686 GtkWidget *button_start;
2687 GtkWidget *progress;
2695 guint idle_id; /* event source id */
2698 #define KEYWORD_DIALOG_WIDTH 400
2700 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2702 GList *list_d = NULL;
2703 GList *list_f = NULL;
2707 filelist_read(dir_fd, &list_f, &list_d);
2711 filelist_read(dir_fd, &list_f, NULL);
2714 list_f = filelist_filter(list_f, FALSE);
2715 list_d = filelist_filter(list_d, TRUE);
2717 kfd->list = g_list_concat(list_f, kfd->list);
2718 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2721 static void keywords_find_reset(KeywordFindData *kfd)
2723 filelist_free(kfd->list);
2726 filelist_free(kfd->list_dir);
2727 kfd->list_dir = NULL;
2730 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2732 KeywordFindData *kfd = data;
2734 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2736 keywords_find_reset(kfd);
2737 generic_dialog_close(kfd->gd);
2741 static void keywords_find_finish(KeywordFindData *kfd)
2743 keywords_find_reset(kfd);
2745 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2746 spinner_set_interval(kfd->spinner, -1);
2748 gtk_widget_set_sensitive(kfd->group, TRUE);
2749 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2750 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2751 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2754 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2756 KeywordFindData *kfd = data;
2758 g_idle_remove_by_data(kfd);
2760 keywords_find_finish(kfd);
2763 static gboolean keywords_find_file(gpointer data)
2765 KeywordFindData *kfd = data;
2767 GtkTextBuffer *buffer;
2775 fd = kfd->list->data;
2776 kfd->list = g_list_remove(kfd->list, fd);
2778 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2779 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2783 gtk_text_buffer_get_end_iter(buffer, &iter);
2784 tmp = g_strconcat(keywords->data, "\n", NULL);
2785 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2787 keywords = keywords->next;
2790 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2791 file_data_unref(fd);
2792 string_list_free(keywords);
2796 else if (kfd->list_dir)
2800 fd = kfd->list_dir->data;
2801 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2803 keywords_find_folder(kfd, fd);
2805 file_data_unref(fd);
2810 keywords_find_finish(kfd);
2815 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2817 KeywordFindData *kfd = data;
2820 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2822 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2823 parse_out_relatives(path);
2827 warning_dialog(_("Invalid folder"),
2828 _("The specified folder can not be found."),
2829 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2835 gtk_widget_set_sensitive(kfd->group, FALSE);
2836 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2837 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2838 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2839 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2841 dir_fd = file_data_new_dir(path);
2842 keywords_find_folder(kfd, dir_fd);
2843 file_data_unref(dir_fd);
2844 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2850 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2852 KeywordFindData *kfd;
2856 kfd = g_new0(KeywordFindData, 1);
2858 kfd->gd = generic_dialog_new(_("Search for keywords"),
2859 "search_for_keywords",
2862 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2863 kfd->gd->cancel_cb = keywords_find_close_cb;
2864 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2865 keywords_find_close_cb, FALSE);
2866 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2867 keywords_find_start_cb, FALSE);
2868 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2869 keywords_find_stop_cb, FALSE);
2870 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2872 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2874 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2875 pref_spacer(hbox, PREF_PAD_INDENT);
2876 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2878 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2879 pref_label_new(hbox, _("Folder:"));
2881 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2882 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2883 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2884 gtk_widget_show(label);
2886 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2888 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2889 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2891 kfd->progress = gtk_entry_new();
2892 gtk_widget_set_can_focus(kfd->progress, FALSE);
2893 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2894 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2895 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2896 gtk_widget_show(kfd->progress);
2898 kfd->spinner = spinner_new(NULL, -1);
2899 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2900 gtk_widget_show(kfd->spinner);
2904 gtk_widget_show(kfd->gd->dialog);
2907 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2909 const gchar *path = layout_get_path(NULL);
2911 if (!path || !*path) path = homedir();
2912 keywords_find_dialog(widget, path);
2915 static void config_tab_keywords_save()
2917 GtkTextIter start, end;
2918 GtkTextBuffer *buffer;
2919 GList *kw_list = NULL;
2925 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2926 gtk_text_buffer_get_bounds(buffer, &start, &end);
2928 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2930 kw_split = strtok(buffer_text, "\n");
2931 while (kw_split != NULL)
2937 if (g_strcmp0(work->data, kw_split) == 0)
2946 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2948 kw_split = strtok(NULL, "\n");
2951 keyword_list_set(kw_list);
2953 string_list_free(kw_list);
2954 g_free(buffer_text);
2957 static void config_tab_keywords(GtkWidget *notebook)
2963 GtkWidget *scrolled;
2965 GtkTextBuffer *buffer;
2968 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2970 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2972 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2974 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2975 G_CALLBACK(keywords_find_cb), keyword_text);
2976 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2979 keyword_text = gtk_text_view_new();
2980 gtk_widget_set_size_request(keyword_text, 20, 20);
2981 scrolled = gtk_scrolled_window_new(NULL, NULL);
2982 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2983 gtk_widget_show(scrolled);
2985 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2986 gtk_widget_show(keyword_text);
2988 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2990 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2991 gtk_text_buffer_create_tag(buffer, "monospace",
2992 "family", "monospace", NULL);
2994 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2995 gtk_text_buffer_get_start_iter(buffer, &iter);
2996 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2999 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3001 GList *kwl = keyword_list_get();
3002 kwl = g_list_first(kwl);
3005 gtk_text_buffer_get_end_iter (buffer, &iter);
3006 tmp = g_strconcat(kwl->data, "\n", NULL);
3007 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3012 gtk_text_buffer_set_modified(buffer, FALSE);
3019 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3021 gint *option = data;
3023 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3027 *option = INTENT_PERCEPTUAL;
3030 *option = INTENT_RELATIVE_COLORIMETRIC;
3033 *option = INTENT_SATURATION;
3036 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3041 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3042 gint option, gint *option_c)
3049 pref_table_label(table, column, row, text, 0.0);
3051 combo = gtk_combo_box_text_new();
3053 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3054 if (option == INTENT_PERCEPTUAL) current = 0;
3055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3056 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3057 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3058 if (option == INTENT_SATURATION) current = 2;
3059 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3060 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3062 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3064 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3066 g_signal_connect(G_OBJECT(combo), "changed",
3067 G_CALLBACK(intent_menu_cb), option_c);
3069 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3070 gtk_widget_show(combo);
3074 static void config_tab_color(GtkWidget *notebook)
3083 vbox = scrolled_notebook_page(notebook, _("Color management"));
3085 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3087 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3090 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3091 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3093 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3094 pref_label_bold(label, TRUE, FALSE);
3096 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3097 pref_label_bold(label, TRUE, FALSE);
3099 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3100 pref_label_bold(label, TRUE, FALSE);
3102 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3107 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3108 pref_table_label(table, 0, i + 1, buf, 1.0);
3111 entry = gtk_entry_new();
3112 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3113 if (options->color_profile.input_name[i])
3115 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3117 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3118 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3119 gtk_widget_show(entry);
3120 color_profile_input_name_entry[i] = entry;
3122 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3123 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3124 gtk_widget_set_size_request(entry, 160, -1);
3125 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3126 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3127 gtk_widget_show(tabcomp);
3128 color_profile_input_file_entry[i] = entry;
3131 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3133 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3135 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3136 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3138 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3140 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3141 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3142 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3143 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3144 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3146 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3148 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3150 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3152 gtk_widget_show(tabcomp);
3155 /* advanced entry tab */
3156 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3158 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3160 c_options->file_ops.use_system_trash = FALSE;
3161 c_options->file_ops.no_trash = FALSE;
3165 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3167 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3169 c_options->file_ops.use_system_trash = TRUE;
3170 c_options->file_ops.no_trash = FALSE;
3174 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3176 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3178 c_options->file_ops.no_trash = TRUE;
3182 static void config_tab_behavior(GtkWidget *notebook)
3189 GtkWidget *ct_button;
3193 GtkWidget *with_rename;
3194 GtkWidget *collections_on_top;
3196 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3198 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3200 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3201 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3202 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3203 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3204 pref_checkbox_new_int(group, _("Enable Delete key"),
3205 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3207 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3208 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3210 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3211 pref_checkbox_link_sensitivity(ct_button, hbox);
3213 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3214 pref_label_new(hbox, _("Folder:"));
3216 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3217 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3218 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3219 gtk_widget_show(tabcomp);
3221 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3222 pref_checkbox_link_sensitivity(ct_button, hbox);
3224 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3225 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3226 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3227 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3228 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3229 G_CALLBACK(safe_delete_view_cb), NULL);
3230 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3231 gtk_widget_show(button);
3233 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3234 G_CALLBACK(safe_delete_clear_cb), NULL);
3235 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3236 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3237 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3239 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3240 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3242 gtk_widget_show(button);
3244 pref_spacer(group, PREF_PAD_GROUP);
3247 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3249 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3250 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3252 pref_checkbox_new_int(group, _("In place renaming"),
3253 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3255 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3256 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3258 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3259 options->marks_save, &c_options->marks_save);
3260 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3262 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3263 options->with_rename, &c_options->with_rename);
3264 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3266 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3267 options->collections_on_top, &c_options->collections_on_top);
3268 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3270 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3271 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3273 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3274 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3276 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3277 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3279 pref_spacer(group, PREF_PAD_GROUP);
3281 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3283 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3284 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3285 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3286 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3287 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3288 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3289 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3290 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3291 pref_checkbox_new_int(group, _("Play video by left click on image"),
3292 options->image_l_click_video, &c_options->image_l_click_video);
3293 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3294 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3296 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3297 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3298 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3299 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3300 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3303 pref_spacer(group, PREF_PAD_GROUP);
3305 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3307 pref_spin_new_int(group, _("Debug level:"), NULL,
3308 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3310 pref_checkbox_new_int(group, _("Timer data"),
3311 options->log_window.timer_data, &c_options->log_window.timer_data);
3313 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3314 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3318 /* accelerators tab */
3319 static void config_tab_accelerators(GtkWidget *notebook)
3325 GtkWidget *scrolled;
3326 GtkWidget *accel_view;
3327 GtkCellRenderer *renderer;
3328 GtkTreeSelection *selection;
3329 GtkTreeViewColumn *column;
3331 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3333 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3335 scrolled = gtk_scrolled_window_new(NULL, NULL);
3336 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3337 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3338 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3339 gtk_widget_show(scrolled);
3341 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3343 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3344 g_object_unref(accel_store);
3345 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3346 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3348 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3350 renderer = gtk_cell_renderer_text_new();
3352 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3357 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3358 gtk_tree_view_column_set_resizable(column, TRUE);
3359 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3362 renderer = gtk_cell_renderer_accel_new();
3363 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3364 G_CALLBACK(accel_store_cleared_cb), accel_store);
3365 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3366 G_CALLBACK(accel_store_edited_cb), accel_store);
3369 g_object_set (renderer,
3371 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3374 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3379 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3380 gtk_tree_view_column_set_resizable(column, TRUE);
3381 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3383 renderer = gtk_cell_renderer_text_new();
3385 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3390 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3391 gtk_tree_view_column_set_resizable(column, TRUE);
3392 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3394 renderer = gtk_cell_renderer_text_new();
3396 column = gtk_tree_view_column_new_with_attributes("Accel",
3401 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3402 gtk_tree_view_column_set_resizable(column, TRUE);
3403 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3405 accel_store_populate();
3406 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3407 gtk_widget_show(accel_view);
3409 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3411 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3412 G_CALLBACK(accel_default_cb), accel_view);
3413 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3414 gtk_widget_show(button);
3416 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3417 G_CALLBACK(accel_reset_cb), accel_view);
3418 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3419 gtk_widget_show(button);
3422 /* toolbar main tab */
3423 static void config_tab_toolbar_main(GtkWidget *notebook)
3426 GtkWidget *toolbardata;
3429 lw = layout_window_list->data;
3431 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3433 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3434 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3435 gtk_widget_show(vbox);
3438 /* toolbar status tab */
3439 static void config_tab_toolbar_status(GtkWidget *notebook)
3442 GtkWidget *toolbardata;
3445 lw = layout_window_list->data;
3447 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3449 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3450 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3451 gtk_widget_show(vbox);
3455 static void config_tab_stereo(GtkWidget *notebook)
3463 GtkWidget *fs_button;
3464 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3466 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3468 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3469 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3471 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3472 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3473 pref_checkbox_new_int(box, _("Mirror left image"),
3474 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3475 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3476 pref_checkbox_new_int(box, _("Flip left image"),
3477 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3478 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3479 pref_checkbox_new_int(box, _("Mirror right image"),
3480 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3481 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3482 pref_checkbox_new_int(box, _("Flip right image"),
3483 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3484 pref_checkbox_new_int(group, _("Swap left and right images"),
3485 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3486 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3487 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3489 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3490 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3491 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3492 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3493 pref_checkbox_link_sensitivity(fs_button, box2);
3494 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3495 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3496 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3497 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3498 pref_checkbox_new_int(box, _("Mirror left image"),
3499 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3500 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3501 pref_checkbox_new_int(box, _("Flip left image"),
3502 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3503 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3504 pref_checkbox_new_int(box, _("Mirror right image"),
3505 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3506 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3507 pref_checkbox_new_int(box, _("Flip right image"),
3508 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3509 pref_checkbox_new_int(box2, _("Swap left and right images"),
3510 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3511 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3512 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3514 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3515 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3516 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3517 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3518 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3519 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3520 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3521 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3522 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3523 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3524 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3525 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3526 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3527 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3531 /* Main preferences window */
3532 static void config_window_create(void)
3534 GtkWidget *win_vbox;
3536 GtkWidget *notebook;
3538 GtkWidget *ct_button;
3540 if (!c_options) c_options = init_options(NULL);
3542 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3543 DEBUG_NAME(configwindow);
3544 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3545 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3546 G_CALLBACK(config_window_delete), NULL);
3547 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3548 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3549 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3551 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3552 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3553 gtk_widget_show(win_vbox);
3555 notebook = gtk_notebook_new();
3556 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3557 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3558 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3560 config_tab_general(notebook);
3561 config_tab_image(notebook);
3562 config_tab_osd(notebook);
3563 config_tab_windows(notebook);
3564 config_tab_accelerators(notebook);
3565 config_tab_files(notebook);
3566 config_tab_metadata(notebook);
3567 config_tab_keywords(notebook);
3568 config_tab_color(notebook);
3569 config_tab_stereo(notebook);
3570 config_tab_behavior(notebook);
3571 config_tab_toolbar_main(notebook);
3572 config_tab_toolbar_status(notebook);
3574 hbox = gtk_hbutton_box_new();
3575 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3576 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3577 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3578 gtk_widget_show(hbox);
3580 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3581 G_CALLBACK(config_window_help_cb), notebook);
3582 gtk_container_add(GTK_CONTAINER(hbox), button);
3583 gtk_widget_set_can_default(button, TRUE);
3584 gtk_widget_show(button);
3586 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3587 G_CALLBACK(config_window_ok_cb), NULL);
3588 gtk_container_add(GTK_CONTAINER(hbox), button);
3589 gtk_widget_set_can_default(button, TRUE);
3590 gtk_widget_grab_default(button);
3591 gtk_widget_show(button);
3595 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3596 G_CALLBACK(config_window_close_cb), NULL);
3597 gtk_container_add(GTK_CONTAINER(hbox), button);
3598 gtk_widget_set_can_default(button, TRUE);
3599 gtk_widget_show(button);
3601 if (!generic_dialog_get_alternative_button_order(configwindow))
3603 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3606 gtk_widget_show(notebook);
3608 gtk_widget_show(configwindow);
3612 *-----------------------------------------------------------------------------
3613 * config window show (public)
3614 *-----------------------------------------------------------------------------
3617 void show_config_window(void)
3621 gtk_window_present(GTK_WINDOW(configwindow));
3625 config_window_create();
3634 void show_about_window(LayoutWindow *lw)
3636 GdkPixbuf *pixbuf_logo;
3637 GdkPixbuf *pixbuf_icon;
3638 gchar *authors[1000];
3643 gchar *timezone_path;
3647 #define LINE_LENGTH 1000
3648 gchar line[LINE_LENGTH];
3650 copyright = g_string_new(NULL);
3651 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");
3653 path = path_from_utf8(TIMEZONE_DATABASE);
3654 basename = g_path_get_basename(path);
3655 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3656 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3658 cd = ZDOpenDatabase(timezone_path);
3661 copyright = g_string_append(copyright, ZDGetNotice(cd));
3662 ZDCloseDatabase(cd);
3666 g_free(timezone_path);
3670 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3671 fp = fopen(path, "r");
3674 while(fgets(line, LINE_LENGTH, fp))
3676 /* get rid of ending \n from fgets */
3677 line[strlen(line) - 1] = '\0';
3678 authors[i_authors] = g_strdup(line);
3681 authors[i_authors] = NULL;
3686 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3687 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3689 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3690 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3691 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3692 "title", _("About Geeqie"),
3694 "program-name", GQ_APPNAME,
3696 "logo", pixbuf_logo,
3697 "icon", pixbuf_icon,
3698 "website", GQ_WEBSITE,
3699 "website-label", "Website",
3700 "comments", comment,
3702 "translator-credits", _("translator-credits"),
3703 "wrap-license", TRUE,
3704 "license", copyright->str,
3707 g_string_free(copyright, TRUE);
3710 while(n < i_authors)
3720 static void image_overlay_set_text_colours()
3722 c_options->image_overlay.text_red = options->image_overlay.text_red;
3723 c_options->image_overlay.text_green = options->image_overlay.text_green;
3724 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3725 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3726 c_options->image_overlay.background_red = options->image_overlay.background_red;
3727 c_options->image_overlay.background_green = options->image_overlay.background_green;
3728 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3729 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3733 *-----------------------------------------------------------------------------
3734 * timezone database routines
3735 *-----------------------------------------------------------------------------
3738 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3740 GError *error = NULL;
3742 gchar *tmp_filename;
3744 if (!g_cancellable_is_cancelled(tz->cancellable))
3746 generic_dialog_close(tz->gd);
3750 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3752 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3753 move_file(tmp_filename, tz->timezone_database_user);
3754 g_free(tmp_filename);
3758 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3761 g_file_delete(tz->tmp_g_file, NULL, &error);
3762 g_object_unref(tz->tmp_g_file);
3763 tz->tmp_g_file = NULL;
3764 g_object_unref(tz->cancellable);
3765 g_object_unref(tz->timezone_database_gq);
3768 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3772 if (!g_cancellable_is_cancelled(tz->cancellable))
3774 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3778 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3781 GError *error = NULL;
3783 g_cancellable_cancel(tz->cancellable);
3786 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3789 GError *error = NULL;
3790 GFileIOStream *io_stream;
3797 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3801 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3802 log_printf("Error: Download timezone database failed:\n%s", error->message);
3803 g_error_free(error);
3804 g_object_unref(tz->tmp_g_file);
3808 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3810 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3812 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3814 tz->progress = gtk_progress_bar_new();
3815 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3816 gtk_widget_show(tz->progress);
3818 gtk_widget_show(tz->gd->dialog);
3819 tz->cancellable = g_cancellable_new();
3820 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);
3822 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3825 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */