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,
597 GTK_EXPAND | GTK_FILL, 0, 0, 0);
598 gtk_widget_show(combo);
601 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
602 gint option, gint *option_c)
609 pref_table_label(table, column, row, text, 0.0);
611 combo = gtk_combo_box_text_new();
613 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
614 if (option == PRIMARY) current = 0;
615 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
616 if (option == CLIPBOARD) current = 1;
618 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
620 g_signal_connect(G_OBJECT(combo), "changed",
621 G_CALLBACK(clipboard_selection_menu_cb), option_c);
623 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
624 GTK_EXPAND | GTK_FILL, 0, 0, 0);
625 gtk_widget_show(combo);
628 typedef struct _UseableMouseItems UseableMouseItems;
629 struct _UseableMouseItems
631 gchar *name; /* GtkActionEntry terminology */
636 static const UseableMouseItems useable_mouse_items[] = {
638 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
639 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
640 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
641 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
642 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
643 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
644 {"Home", N_("Home"), GTK_STOCK_HOME},
645 {"Up", N_("Up"), GTK_STOCK_GO_UP},
646 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
647 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
648 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
649 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
650 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
651 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
652 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
653 {"Search", N_("Search"), GTK_STOCK_FIND},
654 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
655 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
656 {"Copy", N_("Copy"), GTK_STOCK_COPY},
657 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
658 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
659 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
660 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
661 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
662 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
663 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
664 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
665 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
666 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
667 {"Print", N_("Print"), GTK_STOCK_PRINT},
668 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
669 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
670 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
671 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
672 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
673 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
674 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
675 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
676 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
677 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
678 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
679 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
680 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
681 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
682 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
683 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
684 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
685 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
686 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
687 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
688 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
689 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
690 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
691 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
692 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
693 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
694 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
695 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
696 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
697 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
698 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
699 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
700 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
701 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
702 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
703 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
704 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
705 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
706 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
710 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
712 gchar **option = data;
715 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
717 const UseableMouseItems *list = useable_mouse_items;
721 if (g_strcmp0(list->label, label) == 0)
729 *option = g_strdup(list->name);
733 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
734 gchar *option, gchar **option_c)
742 pref_table_label(table, column, row, text, 0.0);
744 combo = gtk_combo_box_text_new();
746 const UseableMouseItems *list = useable_mouse_items;
750 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
751 if (g_strcmp0(list->name, option) == 0)
759 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
761 g_signal_connect(G_OBJECT(combo), "changed",
762 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
764 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
765 GTK_EXPAND | GTK_FILL, 0, 0, 0);
766 gtk_widget_show(combo);
769 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
773 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
776 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
778 c_options->thumbnails.max_width = thumb_size_list[n].w;
779 c_options->thumbnails.max_height = thumb_size_list[n].h;
783 c_options->thumbnails.max_width = options->thumbnails.max_width;
784 c_options->thumbnails.max_height = options->thumbnails.max_height;
788 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
794 c_options->thumbnails.max_width = options->thumbnails.max_width;
795 c_options->thumbnails.max_height = options->thumbnails.max_height;
797 pref_table_label(table, column, row, text, 0.0);
799 combo = gtk_combo_box_text_new();
802 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
807 w = thumb_size_list[i].w;
808 h = thumb_size_list[i].h;
810 buf = g_strdup_printf("%d x %d", w, h);
811 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
814 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
821 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
822 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
828 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
829 g_signal_connect(G_OBJECT(combo), "changed",
830 G_CALLBACK(thumb_size_menu_cb), NULL);
832 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
833 GTK_EXPAND | GTK_FILL, 0, 0, 0);
834 gtk_widget_show(combo);
837 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
841 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
845 *option = PR_STEREO_NONE;
848 *option = PR_STEREO_ANAGLYPH_RC;
851 *option = PR_STEREO_ANAGLYPH_GM;
854 *option = PR_STEREO_ANAGLYPH_YB;
857 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
860 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
863 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
866 *option = PR_STEREO_ANAGLYPH_DB_RC;
869 *option = PR_STEREO_ANAGLYPH_DB_GM;
872 *option = PR_STEREO_ANAGLYPH_DB_YB;
875 *option = PR_STEREO_HORIZ;
878 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
881 *option = PR_STEREO_VERT;
884 *option = PR_STEREO_VERT | PR_STEREO_HALF;
887 *option = PR_STEREO_FIXED;
892 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
893 gint option, gint *option_c, gboolean add_fixed)
900 pref_table_label(table, column, row, text, 0.0);
902 combo = gtk_combo_box_text_new();
904 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
906 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
907 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
908 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
909 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
910 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
911 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
912 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
913 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
914 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
915 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
916 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
917 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
918 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
919 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
920 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
921 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
922 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
923 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
925 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
926 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
927 if (option & PR_STEREO_HORIZ)
930 if (option & PR_STEREO_HALF) current = 11;
933 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
934 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
935 if (option & PR_STEREO_VERT)
938 if (option & PR_STEREO_HALF) current = 13;
943 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
944 if (option & PR_STEREO_FIXED) current = 14;
947 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
949 g_signal_connect(G_OBJECT(combo), "changed",
950 G_CALLBACK(stereo_mode_menu_cb), option_c);
952 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
953 GTK_EXPAND | GTK_FILL, 0, 0, 0);
954 gtk_widget_show(combo);
957 static void video_menu_cb(GtkWidget *combo, gpointer data)
959 gchar **option = data;
961 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
965 static void video_menu_populate(gpointer data, gpointer user_data)
967 GtkWidget *combo = user_data;
968 EditorDescription *ed = data;
970 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
973 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
974 gchar *option, gchar **option_c)
978 /* use lists since they are sorted */
979 GList *eds = editor_list_get();
983 pref_table_label(table, column, row, text, 0.0);
985 combo = gtk_combo_box_text_new();
986 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
987 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
989 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
991 g_signal_connect(G_OBJECT(combo), "changed",
992 G_CALLBACK(video_menu_cb), option_c);
994 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
995 GTK_EXPAND | GTK_FILL, 0, 0, 0);
996 gtk_widget_show(combo);
999 static void filter_store_populate(void)
1003 if (!filter_store) return;
1005 gtk_list_store_clear(filter_store);
1007 work = filter_get_list();
1016 gtk_list_store_append(filter_store, &iter);
1017 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1021 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1022 gchar *new_text, gpointer data)
1024 GtkWidget *model = data;
1025 FilterEntry *fe = data;
1029 if (!new_text || strlen(new_text) < 1) return;
1031 tpath = gtk_tree_path_new_from_string(path_str);
1032 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1033 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1035 g_free(fe->extensions);
1036 fe->extensions = g_strdup(new_text);
1038 gtk_tree_path_free(tpath);
1042 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1043 gchar *new_text, gpointer data)
1045 GtkWidget *model = data;
1046 FilterEntry *fe = data;
1051 if (!new_text || !new_text[0]) return;
1053 tpath = gtk_tree_path_new_from_string(path_str);
1054 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1055 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1057 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1059 if (strcmp(new_text, _(format_class_list[i])) == 0)
1066 gtk_tree_path_free(tpath);
1070 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1071 gchar *new_text, gpointer data)
1073 GtkWidget *model = data;
1078 if (!new_text || !new_text[0]) return;
1080 tpath = gtk_tree_path_new_from_string(path_str);
1081 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1082 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1084 g_free(fe->description);
1085 fe->description = g_strdup(new_text);
1087 gtk_tree_path_free(tpath);
1090 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1091 gchar *path_str, gpointer data)
1093 GtkWidget *model = data;
1098 tpath = gtk_tree_path_new_from_string(path_str);
1099 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1100 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1102 fe->enabled = !fe->enabled;
1104 gtk_tree_path_free(tpath);
1108 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1109 gchar *path_str, gpointer data)
1111 GtkWidget *model = data;
1116 tpath = gtk_tree_path_new_from_string(path_str);
1117 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1118 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1120 fe->writable = !fe->writable;
1121 if (fe->writable) fe->allow_sidecar = FALSE;
1123 gtk_tree_path_free(tpath);
1127 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1128 gchar *path_str, gpointer data)
1130 GtkWidget *model = data;
1135 tpath = gtk_tree_path_new_from_string(path_str);
1136 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1137 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1139 fe->allow_sidecar = !fe->allow_sidecar;
1140 if (fe->allow_sidecar) fe->writable = FALSE;
1142 gtk_tree_path_free(tpath);
1146 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1147 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1151 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1153 switch (GPOINTER_TO_INT(data))
1156 g_object_set(GTK_CELL_RENDERER(cell),
1157 "active", fe->enabled, NULL);
1160 g_object_set(GTK_CELL_RENDERER(cell),
1161 "text", fe->extensions, NULL);
1163 case FE_DESCRIPTION:
1164 g_object_set(GTK_CELL_RENDERER(cell),
1165 "text", fe->description, NULL);
1168 g_object_set(GTK_CELL_RENDERER(cell),
1169 "text", _(format_class_list[fe->file_class]), NULL);
1172 g_object_set(GTK_CELL_RENDERER(cell),
1173 "active", fe->writable, NULL);
1175 case FE_ALLOW_SIDECAR:
1176 g_object_set(GTK_CELL_RENDERER(cell),
1177 "active", fe->allow_sidecar, NULL);
1182 static gboolean filter_add_scroll(gpointer data)
1186 GtkCellRenderer *cell;
1187 GtkTreeViewColumn *column;
1192 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1193 path = gtk_tree_path_new_from_indices(rows-1, -1);
1195 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1197 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1198 cell = g_list_last(list_cells)->data;
1200 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1201 path, column, FALSE, 0.0, 0.0 );
1202 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1203 path, column, cell, TRUE);
1205 gtk_tree_path_free(path);
1206 g_list_free(list_cells);
1211 static void filter_add_cb(GtkWidget *widget, gpointer data)
1213 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1214 filter_store_populate();
1216 g_idle_add((GSourceFunc)filter_add_scroll, data);
1219 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1221 GtkWidget *filter_view = data;
1222 GtkTreeSelection *selection;
1226 if (!filter_store) return;
1227 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1228 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1229 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1232 filter_remove_entry(fe);
1234 filter_store_populate();
1237 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1241 GtkTreeViewColumn *column;
1243 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1244 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1245 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1247 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1251 gtk_tree_path_free(path);
1256 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1259 filter_add_defaults();
1261 filter_store_populate();
1263 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1266 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1268 /* no op, only so cancel button appears */
1271 static void filter_default_cb(GtkWidget *widget, gpointer data)
1275 gd = generic_dialog_new(_("Reset filters"),
1276 "reset_filter", widget, TRUE,
1277 dummy_cancel_cb, data);
1278 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1279 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1280 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1281 gtk_widget_show(gd->dialog);
1284 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1286 GtkWidget *frame = data;
1288 gtk_widget_set_sensitive(frame,
1289 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1292 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1294 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1297 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1299 file_util_trash_clear();
1302 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1306 gd = generic_dialog_new(_("Clear trash"),
1307 "clear_trash", widget, TRUE,
1308 dummy_cancel_cb, NULL);
1309 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1310 _("This will remove the trash contents."), FALSE);
1311 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1312 entry = gtk_entry_new();
1313 gtk_widget_set_can_focus(entry, FALSE);
1314 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1315 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1316 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1317 gtk_widget_show(entry);
1318 gtk_widget_show(gd->dialog);
1321 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1323 GtkWidget *pTextView;
1324 GtkTextBuffer *pTextBuffer;
1328 pTextView = GTK_WIDGET(data);
1330 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1331 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1332 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1334 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1335 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1338 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1340 GtkTextView *text_view = data;
1341 GtkTextBuffer *buffer;
1343 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1344 if (!configwindow) return;
1346 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1347 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1350 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1354 gd = generic_dialog_new(_("Reset image overlay template string"),
1355 "reset_image_overlay_template_string", widget, TRUE,
1356 dummy_cancel_cb, data);
1357 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1358 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1359 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1360 gtk_widget_show(gd->dialog);
1363 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1365 help_window_show("GuideOptionsOSD.html");
1368 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1370 #if GTK_CHECK_VERSION(3,4,0)
1373 PangoFontDescription *font_desc;
1375 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1376 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1378 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1380 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1381 font = pango_font_description_to_string(font_desc);
1382 g_free(c_options->image_overlay.font);
1383 c_options->image_overlay.font = g_strdup(font);
1387 gtk_widget_destroy(dialog);
1391 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1392 c_options->image_overlay.font = g_strdup(font);
1396 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1399 #if GTK_CHECK_VERSION(3,4,0)
1402 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1403 colour.red = options->image_overlay.text_red;
1404 colour.green = options->image_overlay.text_green;
1405 colour.blue = options->image_overlay.text_blue;
1406 colour.alpha = options->image_overlay.text_alpha;
1407 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1408 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1410 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1412 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1413 c_options->image_overlay.text_red = colour.red*255;
1414 c_options->image_overlay.text_green = colour.green*255;
1415 c_options->image_overlay.text_blue = colour.blue*255;
1416 c_options->image_overlay.text_alpha = colour.alpha*255;
1418 gtk_widget_destroy(dialog);
1421 GtkColorSelection *colorsel;
1423 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1424 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1425 colour.red = options->image_overlay.text_red*257;
1426 colour.green = options->image_overlay.text_green*257;
1427 colour.blue = options->image_overlay.text_blue*257;
1428 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1429 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1430 gtk_color_selection_set_current_color(colorsel, &colour);
1431 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1433 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1435 gtk_color_selection_get_current_color(colorsel, &colour);
1436 c_options->image_overlay.text_red = colour.red/257;
1437 c_options->image_overlay.text_green = colour.green/257;
1438 c_options->image_overlay.text_blue = colour.blue/257;
1439 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1441 gtk_widget_destroy (dialog);
1446 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1449 #if GTK_CHECK_VERSION(3,4,0)
1452 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1453 colour.red = options->image_overlay.background_red;
1454 colour.green = options->image_overlay.background_green;
1455 colour.blue = options->image_overlay.background_blue;
1456 colour.alpha = options->image_overlay.background_alpha;
1457 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1458 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1460 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1462 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1463 c_options->image_overlay.background_red = colour.red*255;
1464 c_options->image_overlay.background_green = colour.green*255;
1465 c_options->image_overlay.background_blue = colour.blue*255;
1466 c_options->image_overlay.background_alpha = colour.alpha*255;
1468 gtk_widget_destroy(dialog);
1471 GtkColorSelection *colorsel;
1473 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1474 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1475 colour.red = options->image_overlay.background_red*257;
1476 colour.green = options->image_overlay.background_green*257;
1477 colour.blue = options->image_overlay.background_blue*257;
1478 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1479 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1480 gtk_color_selection_set_current_color(colorsel, &colour);
1481 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1483 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1485 gtk_color_selection_get_current_color(colorsel, &colour);
1486 c_options->image_overlay.background_red = colour.red/257;
1487 c_options->image_overlay.background_green = colour.green/257;
1488 c_options->image_overlay.background_blue = colour.blue/257;
1489 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1491 gtk_widget_destroy(dialog);
1495 static void accel_store_populate(void)
1498 GList *groups, *actions;
1500 const gchar *accel_path;
1504 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1506 gtk_tree_store_clear(accel_store);
1507 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1509 g_assert(lw && lw->ui_manager);
1510 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1513 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1516 action = GTK_ACTION(actions->data);
1517 accel_path = gtk_action_get_accel_path(action);
1518 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1520 gchar *label, *label2, *tooltip, *accel;
1521 g_object_get(action,
1522 "tooltip", &tooltip,
1526 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1532 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1536 gtk_tree_store_append(accel_store, &iter, NULL);
1537 gtk_tree_store_set(accel_store, &iter,
1540 AE_TOOLTIP, tooltip ? tooltip : "",
1541 AE_ACCEL, accel_path,
1549 actions = actions->next;
1552 groups = groups->next;
1556 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1561 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1563 gchar *accel1 = data;
1568 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1570 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1571 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1573 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1575 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1576 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1585 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1587 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1591 GtkAccelKey old_key, key;
1592 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1594 gtk_tree_model_get_iter(model, &iter, path);
1595 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1597 /* test if the accelerator can be stored without conflicts*/
1598 gtk_accel_map_lookup_entry(accel_path, &old_key);
1600 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1601 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1602 gtk_accel_map_lookup_entry(accel_path, &key);
1604 /* restore the original for now, the key will be really changed when the changes are confirmed */
1605 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1607 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1608 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1610 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1611 gtk_tree_path_free(path);
1615 static gboolean accel_default_scroll(GtkTreeView *data)
1619 GtkTreeViewColumn *column;
1621 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1622 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1623 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1625 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1629 gtk_tree_path_free(path);
1634 static void accel_default_cb(GtkWidget *widget, gpointer data)
1636 accel_store_populate();
1638 g_idle_add((GSourceFunc)accel_default_scroll, data);
1641 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1643 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1646 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1649 gchar *accel_path, *accel;
1651 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1652 gtk_accel_map_lookup_entry(accel_path, &key);
1653 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1655 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1657 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1662 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1664 GtkTreeSelection *selection;
1666 if (!accel_store) return;
1667 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1668 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1673 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1677 GtkWidget *scrolled;
1678 GtkWidget *viewport;
1680 scrolled = gtk_scrolled_window_new(NULL, NULL);
1681 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1682 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1683 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1684 label = gtk_label_new(title);
1685 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1686 gtk_widget_show(scrolled);
1688 viewport = gtk_viewport_new(NULL, NULL);
1689 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1690 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1691 gtk_widget_show(viewport);
1693 vbox = gtk_vbox_new(FALSE, 0);
1694 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1695 gtk_widget_show(vbox);
1700 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1702 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1704 c_options->thumbnails.spec_standard =TRUE;
1705 c_options->thumbnails.cache_into_dirs = FALSE;
1709 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1711 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1713 c_options->thumbnails.spec_standard =FALSE;
1714 c_options->thumbnails.cache_into_dirs = FALSE;
1718 static void cache_local_cb(GtkWidget *widget, gpointer data)
1720 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1722 c_options->thumbnails.cache_into_dirs = TRUE;
1723 c_options->thumbnails.spec_standard =FALSE;
1727 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1728 GdkEvent *event, gpointer userdata)
1730 if (pos == GTK_ENTRY_ICON_PRIMARY)
1732 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1736 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1740 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1741 GdkEvent *event, gpointer userdata)
1743 gchar *rating_symbol;
1745 if (pos == GTK_ENTRY_ICON_PRIMARY)
1747 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1748 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1749 g_free(rating_symbol);
1753 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1754 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1755 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1759 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1760 GdkEvent *event, gpointer userdata)
1762 gchar *rating_symbol;
1764 if (pos == GTK_ENTRY_ICON_PRIMARY)
1766 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1767 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1768 g_free(rating_symbol);
1772 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1773 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1774 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1778 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1780 GtkContainer *hbox = data;
1781 GString *str = g_string_new(NULL);
1782 GtkEntry *hex_code_entry;
1783 gchar *hex_code_full;
1786 guint64 hex_value = 0;
1788 list = gtk_container_get_children(hbox);
1790 hex_code_entry = g_list_nth_data(list, 2);
1791 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1793 hex_code = g_strsplit(hex_code_full, "+", 2);
1794 if (hex_code[0] && hex_code[1])
1796 hex_value = strtoull(hex_code[1], NULL, 16);
1798 if (!hex_value || hex_value > 0x10FFFF)
1800 hex_value = 0x003F; // Unicode 'Question Mark'
1802 str = g_string_append_unichar(str, (gunichar)hex_value);
1803 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1805 g_strfreev(hex_code);
1806 g_string_free(str, TRUE);
1807 g_free(hex_code_full);
1812 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1814 guint64 star_symbol;
1816 star_symbol = star_rating_symbol_test(widget, data);
1817 c_options->star_rating.star = star_symbol;
1820 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1822 guint64 rejected_symbol;
1824 rejected_symbol = star_rating_symbol_test(widget, data);
1825 c_options->star_rating.rejected = rejected_symbol;
1828 /* general options tab */
1829 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1830 typedef struct _TZData TZData;
1834 GCancellable *cancellable;
1836 GtkWidget *progress;
1838 GFile *timezone_database_gq;
1839 gchar *timezone_database_user;
1842 static void config_tab_general(GtkWidget *notebook)
1847 GtkWidget *group_frame;
1848 GtkWidget *subgroup;
1850 GtkWidget *ct_button;
1853 gint hours, minutes, remainder;
1855 GtkWidget *star_rating_entry;
1857 gchar *rating_symbol;
1860 GNetworkMonitor *net_mon;
1861 GSocketConnectable *geeqie_org;
1862 gboolean internet_available;
1865 vbox = scrolled_notebook_page(notebook, _("General"));
1867 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1869 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1870 add_thumb_size_menu(table, 0, 0, _("Size:"));
1871 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1873 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1874 pref_label_new(hbox, _("Custom size: "));
1875 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1876 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1878 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1879 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1881 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1882 pref_checkbox_link_sensitivity(ct_button, subgroup);
1884 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1885 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1886 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1887 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1888 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1889 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1890 G_CALLBACK(cache_geeqie_cb), NULL);
1892 group_frame = pref_frame_new(subgroup, TRUE,
1893 _("Store thumbnails local to image folder (non-standard)"),
1894 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1895 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1896 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1897 G_CALLBACK(cache_local_cb), NULL);
1899 group_frame = pref_frame_new(subgroup, TRUE,
1900 _("Use standard thumbnail style and cache, shared with other applications"),
1901 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1902 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1903 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1904 G_CALLBACK(cache_standard_cb), NULL);
1906 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1907 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1909 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1911 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1912 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1914 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1915 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1916 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1918 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1919 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1922 pref_spacer(group, PREF_PAD_GROUP);
1924 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1926 c_options->star_rating.star = options->star_rating.star;
1927 c_options->star_rating.rejected = options->star_rating.rejected;
1929 str = g_string_new(NULL);
1930 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1931 pref_label_new(hbox, "Star character: ");
1932 str = g_string_append_unichar(str, options->star_rating.star);
1933 pref_label_new(hbox, g_strdup(str->str));
1934 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1935 star_rating_entry = gtk_entry_new();
1936 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1937 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1938 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1939 gtk_widget_show(star_rating_entry);
1940 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1941 G_CALLBACK(star_rating_star_test_cb), hbox);
1942 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1943 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1944 gtk_widget_show(button);
1945 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."));
1946 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1947 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1948 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1949 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1950 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1951 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1952 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1953 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1954 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1955 G_CALLBACK(star_rating_star_icon_cb),
1958 g_string_free(str, TRUE);
1959 g_free(rating_symbol);
1961 str = g_string_new(NULL);
1962 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1963 pref_label_new(hbox, "Rejected character: ");
1964 str = g_string_append_unichar(str, options->star_rating.rejected);
1965 pref_label_new(hbox, g_strdup(str->str));
1966 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1967 star_rating_entry = gtk_entry_new();
1968 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1969 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1970 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1971 gtk_widget_show(star_rating_entry);
1972 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1973 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1974 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1975 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1976 gtk_widget_show(button);
1977 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."));
1978 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1979 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1980 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1981 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1982 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1983 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1984 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1985 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1986 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1987 G_CALLBACK(star_rating_rejected_icon_cb),
1990 g_string_free(str, TRUE);
1991 g_free(rating_symbol);
1993 pref_spacer(group, PREF_PAD_GROUP);
1995 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1997 c_options->slideshow.delay = options->slideshow.delay;
1998 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1999 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2000 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2001 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2002 SLIDESHOW_SUBSECOND_PRECISION;
2004 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2006 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2008 options->slideshow.delay ? hours : 0.0,
2009 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2010 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2011 spin = pref_spin_new(hbox, ":" , NULL,
2013 options->slideshow.delay ? minutes: 0.0,
2014 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2015 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2016 spin = pref_spin_new(hbox, ":", NULL,
2017 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2018 options->slideshow.delay ? seconds : 10.0,
2019 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2020 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2022 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2023 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2025 pref_spacer(group, PREF_PAD_GROUP);
2027 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2029 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2030 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2031 pref_checkbox_new_int(group, _("Preload next image"),
2032 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2034 pref_checkbox_new_int(group, _("Refresh on file change"),
2035 options->update_on_time_change, &c_options->update_on_time_change);
2037 pref_spacer(group, PREF_PAD_GROUP);
2039 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2040 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2041 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2042 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2044 options->info_keywords.height, &c_options->info_keywords.height);
2045 pref_spin_new_int(hbox, _("Title:"), NULL,
2047 options->info_title.height, &c_options->info_title.height);
2048 pref_spin_new_int(hbox, _("Comment:"), NULL,
2050 options->info_comment.height, &c_options->info_comment.height);
2051 pref_spin_new_int(hbox, _("Rating:"), NULL,
2053 options->info_rating.height, &c_options->info_rating.height);
2055 pref_spacer(group, PREF_PAD_GROUP);
2057 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2059 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2060 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2062 pref_spacer(group, PREF_PAD_GROUP);
2064 net_mon = g_network_monitor_get_default();
2065 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2066 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2067 g_object_unref(geeqie_org);
2069 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2070 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2072 if (!internet_available)
2074 gtk_widget_set_sensitive(group, FALSE);
2077 tz = g_new0(TZData, 1);
2079 path = path_from_utf8(TIMEZONE_DATABASE);
2080 basename = g_path_get_basename(path);
2081 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2085 if (isfile(tz->timezone_database_user))
2087 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2091 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2094 if (!internet_available)
2096 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"));
2100 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"));
2102 gtk_widget_show(button);
2104 pref_spacer(group, PREF_PAD_GROUP);
2106 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2108 help_search_engine_entry = gtk_entry_new();
2109 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2110 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2111 gtk_widget_show(help_search_engine_entry);
2113 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"));
2115 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2116 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2117 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2118 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2119 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2120 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2121 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2122 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2123 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2124 G_CALLBACK(help_search_engine_entry_icon_cb),
2125 help_search_engine_entry);
2129 static void config_tab_image(GtkWidget *notebook)
2134 GtkWidget *ct_button;
2135 GtkWidget *enlargement_button;
2139 vbox = scrolled_notebook_page(notebook, _("Image"));
2141 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2143 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2144 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2147 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2148 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2151 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2152 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2154 c_options->image.zoom_increment = options->image.zoom_increment;
2155 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2156 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2157 G_CALLBACK(zoom_increment_cb), NULL);
2158 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2160 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2162 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2163 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2164 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2165 spin = pref_spin_new_int(hbox, NULL, NULL,
2167 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2168 pref_checkbox_link_sensitivity(enlargement_button, spin);
2169 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."));
2171 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2172 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2173 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2174 spin = pref_spin_new_int(hbox, NULL, NULL,
2176 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2177 pref_checkbox_link_sensitivity(ct_button, spin);
2178 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."));
2180 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2182 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2183 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2185 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2186 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2188 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2189 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2191 c_options->image.border_color = options->image.border_color;
2193 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2194 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2196 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2197 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2199 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2200 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2202 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2204 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2205 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2209 static void config_tab_windows(GtkWidget *notebook)
2215 GtkWidget *ct_button;
2218 vbox = scrolled_notebook_page(notebook, _("Windows"));
2220 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2222 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2223 options->save_window_positions, &c_options->save_window_positions);
2225 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2226 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2227 pref_checkbox_link_sensitivity(ct_button, button);
2229 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2230 options->tools_restore_state, &c_options->tools_restore_state);
2232 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2233 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2235 pref_checkbox_new_int(group, _("Show window IDs"),
2236 options->show_window_ids, &c_options->show_window_ids);
2238 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2240 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2241 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2243 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2244 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2245 options->image.limit_window_size, &c_options->image.limit_window_size);
2246 spin = pref_spin_new_int(hbox, NULL, NULL,
2248 options->image.max_window_size, &c_options->image.max_window_size);
2249 pref_checkbox_link_sensitivity(ct_button, spin);
2251 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2253 c_options->fullscreen.screen = options->fullscreen.screen;
2254 c_options->fullscreen.above = options->fullscreen.above;
2255 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2256 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2257 gtk_widget_show(hbox);
2259 pref_checkbox_new_int(group, _("Smooth image flip"),
2260 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2261 pref_checkbox_new_int(group, _("Disable screen saver"),
2262 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2265 #define PRE_FORMATTED_COLUMNS 5
2266 static void config_tab_osd(GtkWidget *notebook)
2270 GtkWidget *vbox_buttons;
2273 GtkWidget *image_overlay_template_view;
2274 GtkWidget *scrolled;
2275 GtkWidget *scrolled_pre_formatted;
2276 GtkTextBuffer *buffer;
2278 GtkWidget * subgroup;
2283 vbox = scrolled_notebook_page(notebook, _("OSD"));
2285 image_overlay_template_view = gtk_text_view_new();
2287 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2289 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2291 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2292 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2293 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2294 gtk_widget_show(scrolled_pre_formatted);
2295 gtk_widget_show(subgroup);
2297 pref_line(group, PREF_PAD_GAP);
2299 pref_label_new(group, _("Image overlay template"));
2301 scrolled = gtk_scrolled_window_new(NULL, NULL);
2302 gtk_widget_set_size_request(scrolled, 200, 150);
2303 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2304 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2305 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2306 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2307 gtk_widget_show(scrolled);
2309 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2310 _("Extensive formatting options are shown in the Help file"));
2312 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2313 gtk_widget_show(image_overlay_template_view);
2315 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2317 #if GTK_CHECK_VERSION(3,4,0)
2318 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2319 G_CALLBACK(image_overlay_set_font_cb), notebook);
2321 button = gtk_font_button_new();
2322 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2323 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2324 g_signal_connect(G_OBJECT(button), "font-set",
2325 G_CALLBACK(image_overlay_set_font_cb),NULL);
2327 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2328 gtk_widget_show(button);
2330 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2331 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2332 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2333 gtk_widget_show(button);
2335 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2336 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2337 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2338 gtk_widget_show(button);
2339 image_overlay_set_text_colours();
2341 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2342 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2343 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2344 gtk_widget_show(button);
2346 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2347 G_CALLBACK(image_overlay_help_cb), NULL);
2348 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2349 gtk_widget_show(button);
2351 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2352 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2353 g_signal_connect(G_OBJECT(buffer), "changed",
2354 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2356 pref_line(group, PREF_PAD_GAP);
2358 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2359 hbox = gtk_hbox_new(FALSE, 0);
2360 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2361 gtk_widget_show(hbox);
2362 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2363 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2364 gtk_widget_show(label);
2365 pref_spacer(group,TRUE);
2367 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2368 hbox = gtk_hbox_new(FALSE, 0);
2369 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2370 gtk_widget_show(hbox);
2371 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2372 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2373 gtk_widget_show(label);
2374 pref_spacer(group,TRUE);
2376 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2377 hbox = gtk_hbox_new(FALSE, 0);
2378 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2379 gtk_widget_show(hbox);
2380 label = gtk_label_new(_("%path:39%"));
2381 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2382 gtk_widget_show(label);
2383 pref_spacer(group,TRUE);
2385 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2386 hbox = gtk_hbox_new(FALSE, 0);
2387 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2388 gtk_widget_show(hbox);
2389 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%"));
2390 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2391 gtk_widget_show(label);
2392 pref_spacer(group,TRUE);
2394 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2395 hbox = gtk_hbox_new(FALSE, 0);
2396 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2397 gtk_widget_show(hbox);
2398 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2399 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2400 gtk_widget_show(label);
2403 static GtkTreeModel *create_class_model(void)
2405 GtkListStore *model;
2409 /* create list store */
2410 model = gtk_list_store_new(1, G_TYPE_STRING);
2411 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2413 gtk_list_store_append(model, &iter);
2414 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2416 return GTK_TREE_MODEL (model);
2421 static void config_tab_files(GtkWidget *notebook)
2428 GtkWidget *ct_button;
2429 GtkWidget *scrolled;
2430 GtkWidget *filter_view;
2431 GtkCellRenderer *renderer;
2432 GtkTreeSelection *selection;
2433 GtkTreeViewColumn *column;
2435 vbox = scrolled_notebook_page(notebook, _("Files"));
2437 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2439 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2440 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2441 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2442 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2443 pref_checkbox_new_int(group, _("Case sensitive sort"),
2444 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2445 pref_checkbox_new_int(group, _("Natural sort order"),
2446 options->file_sort.natural, &c_options->file_sort.natural);
2447 pref_checkbox_new_int(group, _("Disable file extension checks"),
2448 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2450 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2451 options->file_filter.disable, &c_options->file_filter.disable);
2454 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2456 sidecar_ext_entry = gtk_entry_new();
2457 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2458 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2459 gtk_widget_show(sidecar_ext_entry);
2461 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2463 frame = pref_group_parent(group);
2464 g_signal_connect(G_OBJECT(ct_button), "toggled",
2465 G_CALLBACK(filter_disable_cb), frame);
2466 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2468 scrolled = gtk_scrolled_window_new(NULL, NULL);
2469 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2470 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2471 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2472 gtk_widget_show(scrolled);
2474 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2475 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2476 g_object_unref(filter_store);
2477 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2478 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2480 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2482 column = gtk_tree_view_column_new();
2483 gtk_tree_view_column_set_title(column, _("Filter"));
2484 gtk_tree_view_column_set_resizable(column, TRUE);
2486 renderer = gtk_cell_renderer_toggle_new();
2487 g_signal_connect(G_OBJECT(renderer), "toggled",
2488 G_CALLBACK(filter_store_enable_cb), filter_store);
2489 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2490 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2491 GINT_TO_POINTER(FE_ENABLE), NULL);
2493 renderer = gtk_cell_renderer_text_new();
2494 g_signal_connect(G_OBJECT(renderer), "edited",
2495 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2496 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2497 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2498 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2499 GINT_TO_POINTER(FE_EXTENSION), NULL);
2500 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2502 column = gtk_tree_view_column_new();
2503 gtk_tree_view_column_set_title(column, _("Description"));
2504 gtk_tree_view_column_set_resizable(column, TRUE);
2505 gtk_tree_view_column_set_fixed_width(column, 200);
2506 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2508 renderer = gtk_cell_renderer_text_new();
2509 g_signal_connect(G_OBJECT(renderer), "edited",
2510 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2511 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2512 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2513 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2514 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2515 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2517 column = gtk_tree_view_column_new();
2518 gtk_tree_view_column_set_title(column, _("Class"));
2519 gtk_tree_view_column_set_resizable(column, TRUE);
2520 renderer = gtk_cell_renderer_combo_new();
2521 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2522 "model", create_class_model(),
2527 g_signal_connect(G_OBJECT(renderer), "edited",
2528 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2529 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2530 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2531 GINT_TO_POINTER(FE_CLASS), NULL);
2532 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2534 column = gtk_tree_view_column_new();
2535 gtk_tree_view_column_set_title(column, _("Writable"));
2536 gtk_tree_view_column_set_resizable(column, FALSE);
2537 renderer = gtk_cell_renderer_toggle_new();
2538 g_signal_connect(G_OBJECT(renderer), "toggled",
2539 G_CALLBACK(filter_store_writable_cb), filter_store);
2540 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2541 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2542 GINT_TO_POINTER(FE_WRITABLE), NULL);
2543 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2545 column = gtk_tree_view_column_new();
2546 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2547 gtk_tree_view_column_set_resizable(column, FALSE);
2548 renderer = gtk_cell_renderer_toggle_new();
2549 g_signal_connect(G_OBJECT(renderer), "toggled",
2550 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2551 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2552 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2553 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2554 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2557 filter_store_populate();
2558 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2559 gtk_widget_show(filter_view);
2561 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2563 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2564 G_CALLBACK(filter_default_cb), filter_view);
2565 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2566 gtk_widget_show(button);
2568 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2569 G_CALLBACK(filter_remove_cb), filter_view);
2570 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2571 gtk_widget_show(button);
2573 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2574 G_CALLBACK(filter_add_cb), filter_view);
2575 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2576 gtk_widget_show(button);
2580 static void config_tab_metadata(GtkWidget *notebook)
2585 GtkWidget *ct_button;
2589 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2592 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2594 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2596 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2597 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2599 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2600 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2602 gtk_widget_set_sensitive(ct_button, FALSE);
2605 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2606 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2608 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2609 label = pref_label_new(group, text);
2610 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2611 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2614 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2616 gtk_widget_set_sensitive(group, FALSE);
2619 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2620 pref_checkbox_link_sensitivity(ct_button, hbox);
2622 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2623 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2625 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2626 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2628 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2629 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2631 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2632 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2634 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2636 gtk_widget_set_sensitive(group, FALSE);
2639 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2640 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2643 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2644 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2645 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2647 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2648 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2650 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2651 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2653 gtk_widget_set_sensitive(ct_button, FALSE);
2656 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2658 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2659 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2661 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2662 pref_checkbox_link_sensitivity(ct_button, hbox);
2664 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2665 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2667 pref_checkbox_new_int(group, _("Write metadata on image change"),
2668 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2670 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2671 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2673 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2675 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2676 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2677 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");
2682 typedef struct _KeywordFindData KeywordFindData;
2683 struct _KeywordFindData
2690 GtkWidget *button_close;
2691 GtkWidget *button_stop;
2692 GtkWidget *button_start;
2693 GtkWidget *progress;
2701 guint idle_id; /* event source id */
2704 #define KEYWORD_DIALOG_WIDTH 400
2706 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2708 GList *list_d = NULL;
2709 GList *list_f = NULL;
2713 filelist_read(dir_fd, &list_f, &list_d);
2717 filelist_read(dir_fd, &list_f, NULL);
2720 list_f = filelist_filter(list_f, FALSE);
2721 list_d = filelist_filter(list_d, TRUE);
2723 kfd->list = g_list_concat(list_f, kfd->list);
2724 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2727 static void keywords_find_reset(KeywordFindData *kfd)
2729 filelist_free(kfd->list);
2732 filelist_free(kfd->list_dir);
2733 kfd->list_dir = NULL;
2736 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2738 KeywordFindData *kfd = data;
2740 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2742 keywords_find_reset(kfd);
2743 generic_dialog_close(kfd->gd);
2747 static void keywords_find_finish(KeywordFindData *kfd)
2749 keywords_find_reset(kfd);
2751 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2752 spinner_set_interval(kfd->spinner, -1);
2754 gtk_widget_set_sensitive(kfd->group, TRUE);
2755 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2756 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2757 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2760 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2762 KeywordFindData *kfd = data;
2764 g_idle_remove_by_data(kfd);
2766 keywords_find_finish(kfd);
2769 static gboolean keywords_find_file(gpointer data)
2771 KeywordFindData *kfd = data;
2773 GtkTextBuffer *buffer;
2781 fd = kfd->list->data;
2782 kfd->list = g_list_remove(kfd->list, fd);
2784 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2785 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2789 gtk_text_buffer_get_end_iter(buffer, &iter);
2790 tmp = g_strconcat(keywords->data, "\n", NULL);
2791 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2793 keywords = keywords->next;
2796 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2797 file_data_unref(fd);
2798 string_list_free(keywords);
2802 else if (kfd->list_dir)
2806 fd = kfd->list_dir->data;
2807 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2809 keywords_find_folder(kfd, fd);
2811 file_data_unref(fd);
2816 keywords_find_finish(kfd);
2821 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2823 KeywordFindData *kfd = data;
2826 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2828 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2829 parse_out_relatives(path);
2833 warning_dialog(_("Invalid folder"),
2834 _("The specified folder can not be found."),
2835 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2841 gtk_widget_set_sensitive(kfd->group, FALSE);
2842 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2843 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2844 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2845 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2847 dir_fd = file_data_new_dir(path);
2848 keywords_find_folder(kfd, dir_fd);
2849 file_data_unref(dir_fd);
2850 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2856 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2858 KeywordFindData *kfd;
2862 kfd = g_new0(KeywordFindData, 1);
2864 kfd->gd = generic_dialog_new(_("Search for keywords"),
2865 "search_for_keywords",
2868 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2869 kfd->gd->cancel_cb = keywords_find_close_cb;
2870 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2871 keywords_find_close_cb, FALSE);
2872 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2873 keywords_find_start_cb, FALSE);
2874 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2875 keywords_find_stop_cb, FALSE);
2876 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2878 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2880 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2881 pref_spacer(hbox, PREF_PAD_INDENT);
2882 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2884 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2885 pref_label_new(hbox, _("Folder:"));
2887 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2888 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2889 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2890 gtk_widget_show(label);
2892 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2894 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2895 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2897 kfd->progress = gtk_entry_new();
2898 gtk_widget_set_can_focus(kfd->progress, FALSE);
2899 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2900 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2901 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2902 gtk_widget_show(kfd->progress);
2904 kfd->spinner = spinner_new(NULL, -1);
2905 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2906 gtk_widget_show(kfd->spinner);
2910 gtk_widget_show(kfd->gd->dialog);
2913 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2915 const gchar *path = layout_get_path(NULL);
2917 if (!path || !*path) path = homedir();
2918 keywords_find_dialog(widget, path);
2921 static void config_tab_keywords_save()
2923 GtkTextIter start, end;
2924 GtkTextBuffer *buffer;
2925 GList *kw_list = NULL;
2931 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2932 gtk_text_buffer_get_bounds(buffer, &start, &end);
2934 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2936 kw_split = strtok(buffer_text, "\n");
2937 while (kw_split != NULL)
2943 if (g_strcmp0(work->data, kw_split) == 0)
2952 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2954 kw_split = strtok(NULL, "\n");
2957 keyword_list_set(kw_list);
2959 string_list_free(kw_list);
2960 g_free(buffer_text);
2963 static void config_tab_keywords(GtkWidget *notebook)
2969 GtkWidget *scrolled;
2971 GtkTextBuffer *buffer;
2974 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2976 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2978 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2980 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2981 G_CALLBACK(keywords_find_cb), keyword_text);
2982 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2985 keyword_text = gtk_text_view_new();
2986 gtk_widget_set_size_request(keyword_text, 20, 20);
2987 scrolled = gtk_scrolled_window_new(NULL, NULL);
2988 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2989 gtk_widget_show(scrolled);
2991 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2992 gtk_widget_show(keyword_text);
2994 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2996 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2997 gtk_text_buffer_create_tag(buffer, "monospace",
2998 "family", "monospace", NULL);
3000 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3001 gtk_text_buffer_get_start_iter(buffer, &iter);
3002 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3005 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3007 GList *kwl = keyword_list_get();
3008 kwl = g_list_first(kwl);
3011 gtk_text_buffer_get_end_iter (buffer, &iter);
3012 tmp = g_strconcat(kwl->data, "\n", NULL);
3013 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3018 gtk_text_buffer_set_modified(buffer, FALSE);
3025 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3027 gint *option = data;
3029 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3033 *option = INTENT_PERCEPTUAL;
3036 *option = INTENT_RELATIVE_COLORIMETRIC;
3039 *option = INTENT_SATURATION;
3042 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3047 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3048 gint option, gint *option_c)
3055 pref_table_label(table, column, row, text, 0.0);
3057 combo = gtk_combo_box_text_new();
3059 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3060 if (option == INTENT_PERCEPTUAL) current = 0;
3061 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3062 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3063 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3064 if (option == INTENT_SATURATION) current = 2;
3065 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3066 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3068 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3070 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3072 g_signal_connect(G_OBJECT(combo), "changed",
3073 G_CALLBACK(intent_menu_cb), option_c);
3075 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
3076 GTK_EXPAND | GTK_FILL, 0, 0, 0);
3077 gtk_widget_show(combo);
3081 static void config_tab_color(GtkWidget *notebook)
3090 vbox = scrolled_notebook_page(notebook, _("Color management"));
3092 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3094 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3097 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3098 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3100 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3101 pref_label_bold(label, TRUE, FALSE);
3103 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3104 pref_label_bold(label, TRUE, FALSE);
3106 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3107 pref_label_bold(label, TRUE, FALSE);
3109 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3114 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3115 pref_table_label(table, 0, i + 1, buf, 1.0);
3118 entry = gtk_entry_new();
3119 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3120 if (options->color_profile.input_name[i])
3122 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3124 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3125 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3126 gtk_widget_show(entry);
3127 color_profile_input_name_entry[i] = entry;
3129 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3130 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3131 gtk_widget_set_size_request(entry, 160, -1);
3132 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3133 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3134 gtk_widget_show(tabcomp);
3135 color_profile_input_file_entry[i] = entry;
3138 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3140 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3142 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3143 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3145 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3147 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3148 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3149 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3150 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3151 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3153 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3155 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3157 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3159 gtk_widget_show(tabcomp);
3162 /* advanced entry tab */
3163 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3165 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3167 c_options->file_ops.use_system_trash = FALSE;
3168 c_options->file_ops.no_trash = FALSE;
3172 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3174 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3176 c_options->file_ops.use_system_trash = TRUE;
3177 c_options->file_ops.no_trash = FALSE;
3181 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3183 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3185 c_options->file_ops.no_trash = TRUE;
3189 static void config_tab_behavior(GtkWidget *notebook)
3196 GtkWidget *ct_button;
3200 GtkWidget *with_rename;
3201 GtkWidget *collections_on_top;
3203 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3205 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3207 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3208 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3209 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3210 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3211 pref_checkbox_new_int(group, _("Enable Delete key"),
3212 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3214 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3215 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3217 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3218 pref_checkbox_link_sensitivity(ct_button, hbox);
3220 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3221 pref_label_new(hbox, _("Folder:"));
3223 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3224 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3225 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3226 gtk_widget_show(tabcomp);
3228 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3229 pref_checkbox_link_sensitivity(ct_button, hbox);
3231 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3232 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3233 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3234 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3235 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3236 G_CALLBACK(safe_delete_view_cb), NULL);
3237 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3238 gtk_widget_show(button);
3240 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3241 G_CALLBACK(safe_delete_clear_cb), NULL);
3242 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3243 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3244 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3246 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3247 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3249 gtk_widget_show(button);
3251 pref_spacer(group, PREF_PAD_GROUP);
3254 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3256 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3257 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3259 pref_checkbox_new_int(group, _("In place renaming"),
3260 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3262 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3263 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3265 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3266 options->marks_save, &c_options->marks_save);
3267 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3269 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3270 options->with_rename, &c_options->with_rename);
3271 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3273 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3274 options->collections_on_top, &c_options->collections_on_top);
3275 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3277 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3278 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3280 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3281 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3283 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3284 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3286 pref_spacer(group, PREF_PAD_GROUP);
3288 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3290 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3291 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3292 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3293 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3294 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3295 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3296 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3297 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3298 pref_checkbox_new_int(group, _("Play video by left click on image"),
3299 options->image_l_click_video, &c_options->image_l_click_video);
3300 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3301 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3303 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3304 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3305 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3306 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3307 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3310 pref_spacer(group, PREF_PAD_GROUP);
3312 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3314 pref_spin_new_int(group, _("Debug level:"), NULL,
3315 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3317 pref_checkbox_new_int(group, _("Timer data"),
3318 options->log_window.timer_data, &c_options->log_window.timer_data);
3320 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3321 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3325 /* accelerators tab */
3326 static void config_tab_accelerators(GtkWidget *notebook)
3332 GtkWidget *scrolled;
3333 GtkWidget *accel_view;
3334 GtkCellRenderer *renderer;
3335 GtkTreeSelection *selection;
3336 GtkTreeViewColumn *column;
3338 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3340 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3342 scrolled = gtk_scrolled_window_new(NULL, NULL);
3343 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3344 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3345 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3346 gtk_widget_show(scrolled);
3348 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3350 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3351 g_object_unref(accel_store);
3352 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3353 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3355 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3357 renderer = gtk_cell_renderer_text_new();
3359 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3364 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3365 gtk_tree_view_column_set_resizable(column, TRUE);
3366 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3369 renderer = gtk_cell_renderer_accel_new();
3370 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3371 G_CALLBACK(accel_store_cleared_cb), accel_store);
3372 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3373 G_CALLBACK(accel_store_edited_cb), accel_store);
3376 g_object_set (renderer,
3378 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3381 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3386 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3387 gtk_tree_view_column_set_resizable(column, TRUE);
3388 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3390 renderer = gtk_cell_renderer_text_new();
3392 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3397 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3398 gtk_tree_view_column_set_resizable(column, TRUE);
3399 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3401 renderer = gtk_cell_renderer_text_new();
3403 column = gtk_tree_view_column_new_with_attributes("Accel",
3408 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3409 gtk_tree_view_column_set_resizable(column, TRUE);
3410 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3412 accel_store_populate();
3413 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3414 gtk_widget_show(accel_view);
3416 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3418 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3419 G_CALLBACK(accel_default_cb), accel_view);
3420 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3421 gtk_widget_show(button);
3423 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3424 G_CALLBACK(accel_reset_cb), accel_view);
3425 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3426 gtk_widget_show(button);
3429 /* toolbar main tab */
3430 static void config_tab_toolbar_main(GtkWidget *notebook)
3433 GtkWidget *toolbardata;
3436 lw = layout_window_list->data;
3438 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3440 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3441 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3442 gtk_widget_show(vbox);
3445 /* toolbar status tab */
3446 static void config_tab_toolbar_status(GtkWidget *notebook)
3449 GtkWidget *toolbardata;
3452 lw = layout_window_list->data;
3454 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3456 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3457 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3458 gtk_widget_show(vbox);
3462 static void config_tab_stereo(GtkWidget *notebook)
3470 GtkWidget *fs_button;
3471 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3473 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3475 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3476 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3478 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3479 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3480 pref_checkbox_new_int(box, _("Mirror left image"),
3481 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3482 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3483 pref_checkbox_new_int(box, _("Flip left image"),
3484 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3485 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3486 pref_checkbox_new_int(box, _("Mirror right image"),
3487 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3488 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3489 pref_checkbox_new_int(box, _("Flip right image"),
3490 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3491 pref_checkbox_new_int(group, _("Swap left and right images"),
3492 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3493 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3494 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3496 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3497 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3498 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3499 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3500 pref_checkbox_link_sensitivity(fs_button, box2);
3501 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3502 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3503 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3504 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3505 pref_checkbox_new_int(box, _("Mirror left image"),
3506 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3507 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3508 pref_checkbox_new_int(box, _("Flip left image"),
3509 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3510 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3511 pref_checkbox_new_int(box, _("Mirror right image"),
3512 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3513 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3514 pref_checkbox_new_int(box, _("Flip right image"),
3515 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3516 pref_checkbox_new_int(box2, _("Swap left and right images"),
3517 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3518 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3519 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3521 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3522 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3523 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3524 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3525 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3526 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3527 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3528 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3529 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3530 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3531 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3532 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3533 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3534 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3538 /* Main preferences window */
3539 static void config_window_create(void)
3541 GtkWidget *win_vbox;
3543 GtkWidget *notebook;
3545 GtkWidget *ct_button;
3547 if (!c_options) c_options = init_options(NULL);
3549 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3550 DEBUG_NAME(configwindow);
3551 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3552 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3553 G_CALLBACK(config_window_delete), NULL);
3554 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3555 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3556 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3558 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3559 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3560 gtk_widget_show(win_vbox);
3562 notebook = gtk_notebook_new();
3563 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3564 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3565 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3567 config_tab_general(notebook);
3568 config_tab_image(notebook);
3569 config_tab_osd(notebook);
3570 config_tab_windows(notebook);
3571 config_tab_accelerators(notebook);
3572 config_tab_files(notebook);
3573 config_tab_metadata(notebook);
3574 config_tab_keywords(notebook);
3575 config_tab_color(notebook);
3576 config_tab_stereo(notebook);
3577 config_tab_behavior(notebook);
3578 config_tab_toolbar_main(notebook);
3579 config_tab_toolbar_status(notebook);
3581 hbox = gtk_hbutton_box_new();
3582 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3583 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3584 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3585 gtk_widget_show(hbox);
3587 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3588 G_CALLBACK(config_window_help_cb), notebook);
3589 gtk_container_add(GTK_CONTAINER(hbox), button);
3590 gtk_widget_set_can_default(button, TRUE);
3591 gtk_widget_show(button);
3593 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3594 G_CALLBACK(config_window_ok_cb), NULL);
3595 gtk_container_add(GTK_CONTAINER(hbox), button);
3596 gtk_widget_set_can_default(button, TRUE);
3597 gtk_widget_grab_default(button);
3598 gtk_widget_show(button);
3602 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3603 G_CALLBACK(config_window_close_cb), NULL);
3604 gtk_container_add(GTK_CONTAINER(hbox), button);
3605 gtk_widget_set_can_default(button, TRUE);
3606 gtk_widget_show(button);
3608 if (!generic_dialog_get_alternative_button_order(configwindow))
3610 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3613 gtk_widget_show(notebook);
3615 gtk_widget_show(configwindow);
3619 *-----------------------------------------------------------------------------
3620 * config window show (public)
3621 *-----------------------------------------------------------------------------
3624 void show_config_window(void)
3628 gtk_window_present(GTK_WINDOW(configwindow));
3632 config_window_create();
3641 void show_about_window(LayoutWindow *lw)
3643 GdkPixbuf *pixbuf_logo;
3644 GdkPixbuf *pixbuf_icon;
3645 gchar *authors[1000];
3650 gchar *timezone_path;
3654 #define LINE_LENGTH 1000
3655 gchar line[LINE_LENGTH];
3657 copyright = g_string_new(NULL);
3658 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");
3660 path = path_from_utf8(TIMEZONE_DATABASE);
3661 basename = g_path_get_basename(path);
3662 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3663 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3665 cd = ZDOpenDatabase(timezone_path);
3668 copyright = g_string_append(copyright, ZDGetNotice(cd));
3669 ZDCloseDatabase(cd);
3673 g_free(timezone_path);
3677 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3678 fp = fopen(path, "r");
3681 while(fgets(line, LINE_LENGTH, fp))
3683 /* get rid of ending \n from fgets */
3684 line[strlen(line) - 1] = '\0';
3685 authors[i_authors] = g_strdup(line);
3688 authors[i_authors] = NULL;
3693 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3694 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3696 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3697 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3698 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3699 "title", _("About Geeqie"),
3701 "program-name", GQ_APPNAME,
3703 "logo", pixbuf_logo,
3704 "icon", pixbuf_icon,
3705 "website", GQ_WEBSITE,
3706 "website-label", "Website",
3707 "comments", comment,
3709 "translator-credits", _("translator-credits"),
3710 "wrap-license", TRUE,
3711 "license", copyright->str,
3714 g_string_free(copyright, TRUE);
3717 while(n < i_authors)
3727 static void image_overlay_set_text_colours()
3729 c_options->image_overlay.text_red = options->image_overlay.text_red;
3730 c_options->image_overlay.text_green = options->image_overlay.text_green;
3731 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3732 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3733 c_options->image_overlay.background_red = options->image_overlay.background_red;
3734 c_options->image_overlay.background_green = options->image_overlay.background_green;
3735 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3736 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3740 *-----------------------------------------------------------------------------
3741 * timezone database routines
3742 *-----------------------------------------------------------------------------
3745 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3747 GError *error = NULL;
3749 gchar *tmp_filename;
3751 if (!g_cancellable_is_cancelled(tz->cancellable))
3753 generic_dialog_close(tz->gd);
3757 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3759 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3760 move_file(tmp_filename, tz->timezone_database_user);
3761 g_free(tmp_filename);
3765 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3768 g_file_delete(tz->tmp_g_file, NULL, &error);
3769 g_object_unref(tz->tmp_g_file);
3770 tz->tmp_g_file = NULL;
3771 g_object_unref(tz->cancellable);
3772 g_object_unref(tz->timezone_database_gq);
3775 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3779 if (!g_cancellable_is_cancelled(tz->cancellable))
3781 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3785 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3788 GError *error = NULL;
3790 g_cancellable_cancel(tz->cancellable);
3793 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3796 GError *error = NULL;
3797 GFileIOStream *io_stream;
3804 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3808 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3809 log_printf("Error: Download timezone database failed:\n%s", error->message);
3810 g_error_free(error);
3811 g_object_unref(tz->tmp_g_file);
3815 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3817 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3819 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3821 tz->progress = gtk_progress_bar_new();
3822 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3823 gtk_widget_show(tz->progress);
3825 gtk_widget_show(tz->gd->dialog);
3826 tz->cancellable = g_cancellable_new();
3827 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);
3829 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3832 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */