2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
248 gboolean refresh = FALSE;
253 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
255 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
256 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
257 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
258 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
259 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
260 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
261 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
263 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
264 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
265 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
266 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
267 options->file_ops.no_trash = c_options->file_ops.no_trash;
268 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
269 options->tools_restore_state = c_options->tools_restore_state;
270 options->save_window_positions = c_options->save_window_positions;
271 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
272 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
273 options->show_window_ids = c_options->show_window_ids;
274 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
275 options->image.zoom_2pass = c_options->image.zoom_2pass;
276 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
277 options->image.limit_window_size = c_options->image.limit_window_size;
278 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
279 options->image.max_window_size = c_options->image.max_window_size;
280 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
281 options->image.max_autofit_size = c_options->image.max_autofit_size;
282 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
283 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
284 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
285 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
287 if (options->thumbnails.max_width != c_options->thumbnails.max_width
288 || options->thumbnails.max_height != c_options->thumbnails.max_height
289 || options->thumbnails.quality != c_options->thumbnails.quality)
291 thumb_format_changed = TRUE;
293 options->thumbnails.max_width = c_options->thumbnails.max_width;
294 options->thumbnails.max_height = c_options->thumbnails.max_height;
295 options->thumbnails.quality = c_options->thumbnails.quality;
297 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
298 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
299 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
300 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
301 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
302 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
303 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
304 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
305 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
306 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
307 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
308 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
310 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
311 options->file_sort.natural = c_options->file_sort.natural;
312 options->file_filter.disable = c_options->file_filter.disable;
314 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
315 sidecar_ext_parse(options->sidecar.ext);
317 options->slideshow.random = c_options->slideshow.random;
318 options->slideshow.repeat = c_options->slideshow.repeat;
319 options->slideshow.delay = c_options->slideshow.delay;
321 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
322 options->image_lm_click_nav = c_options->image_lm_click_nav;
323 options->image_l_click_video = c_options->image_l_click_video;
324 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
326 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
328 options->image.tile_cache_max = c_options->image.tile_cache_max;
329 options->image.image_cache_max = c_options->image.image_cache_max;
331 options->image.zoom_quality = c_options->image.zoom_quality;
333 options->image.zoom_increment = c_options->image.zoom_increment;
335 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
338 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
339 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
340 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
342 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
343 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
344 options->image.border_color = c_options->image.border_color;
345 layout_colors_update();
346 view_window_colors_update();
349 options->image.alpha_color_1 = c_options->image.alpha_color_1;
350 options->image.alpha_color_2 = c_options->image.alpha_color_2;
352 options->fullscreen.screen = c_options->fullscreen.screen;
353 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
354 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
355 options->fullscreen.above = c_options->fullscreen.above;
356 if (c_options->image_overlay.template_string)
357 set_image_overlay_template_string(&options->image_overlay.template_string,
358 c_options->image_overlay.template_string);
359 if (c_options->image_overlay.font)
360 set_image_overlay_font_string(&options->image_overlay.font,
361 c_options->image_overlay.font);
362 options->image_overlay.text_red = c_options->image_overlay.text_red;
363 options->image_overlay.text_green = c_options->image_overlay.text_green;
364 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
365 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
366 options->image_overlay.background_red = c_options->image_overlay.background_red;
367 options->image_overlay.background_green = c_options->image_overlay.background_green;
368 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
369 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
370 options->update_on_time_change = c_options->update_on_time_change;
371 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
373 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
374 options->rot_invariant_sim = c_options->rot_invariant_sim;
376 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
378 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
380 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
381 options->dnd_icon_size = c_options->dnd_icon_size;
382 options->clipboard_selection = c_options->clipboard_selection;
383 options->dnd_default_action = c_options->dnd_default_action;
385 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
386 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
387 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
388 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
389 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
390 options->metadata.confirm_write = c_options->metadata.confirm_write;
391 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
392 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
393 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
394 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
395 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
396 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
397 options->metadata.write_orientation = c_options->metadata.write_orientation;
398 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
399 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
400 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
401 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
402 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
403 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
404 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
405 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
406 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
407 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
408 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
409 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
410 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
411 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
412 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
413 options->stereo.fixed_w = c_options->stereo.fixed_w;
414 options->stereo.fixed_h = c_options->stereo.fixed_h;
415 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
416 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
417 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
418 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
420 options->info_keywords.height = c_options->info_keywords.height;
421 options->info_title.height = c_options->info_title.height;
422 options->info_comment.height = c_options->info_comment.height;
423 options->info_rating.height = c_options->info_rating.height;
425 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
426 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
428 options->marks_save = c_options->marks_save;
429 options->with_rename = c_options->with_rename;
430 options->collections_on_top = c_options->collections_on_top;
431 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
432 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
434 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
436 options->star_rating.star = c_options->star_rating.star;
437 options->star_rating.rejected = c_options->star_rating.rejected;
439 set_debug_level(debug_c);
443 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
445 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
446 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
448 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
449 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
450 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
452 options->color_profile.render_intent = c_options->color_profile.render_intent;
457 options->mouse_button_8 = c_options->mouse_button_8;
458 options->mouse_button_9 = c_options->mouse_button_9;
460 options->override_disable_gpu = c_options->override_disable_gpu;
462 config_tab_keywords_save();
464 image_options_sync();
469 layout_refresh(NULL);
472 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
474 toolbar_apply(TOOLBAR_MAIN);
475 toolbar_apply(TOOLBAR_STATUS);
479 *-----------------------------------------------------------------------------
480 * config window main button callbacks (private)
481 *-----------------------------------------------------------------------------
484 static void config_window_close_cb(GtkWidget *widget, gpointer data)
486 gtk_widget_destroy(configwindow);
491 static void config_window_help_cb(GtkWidget *widget, gpointer data)
493 GtkWidget *notebook = data;
496 static gchar *html_section[] =
498 "GuideOptionsGeneral.html",
499 "GuideOptionsImage.html",
500 "GuideOptionsOSD.html",
501 "GuideOptionsWindow.html",
502 "GuideOptionsKeyboard.html",
503 "GuideOptionsFiltering.html",
504 "GuideOptionsMetadata.html",
505 "GuideOptionsKeywords.html",
506 "GuideOptionsColor.html",
507 "GuideOptionsStereo.html",
508 "GuideOptionsBehavior.html",
509 "GuideOptionsToolbar.html",
510 "GuideOptionsToolbar.html"
513 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
514 help_window_show(html_section[i]);
517 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
519 config_window_close_cb(NULL, NULL);
523 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
526 lw = layout_window_list->data;
528 config_window_apply();
529 layout_util_sync(lw);
530 save_options(options);
531 config_window_close_cb(NULL, NULL);
535 *-----------------------------------------------------------------------------
536 * config window setup (private)
537 *-----------------------------------------------------------------------------
540 static void quality_menu_cb(GtkWidget *combo, gpointer data)
544 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
548 *option = GDK_INTERP_NEAREST;
551 *option = GDK_INTERP_TILES;
554 *option = GDK_INTERP_BILINEAR;
559 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
563 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
567 *option = DND_ACTION_ASK;
570 *option = DND_ACTION_COPY;
573 *option = DND_ACTION_MOVE;
577 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
581 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
584 *option = CLIPBOARD_PRIMARY;
587 *option = CLIPBOARD_CLIPBOARD;
590 *option = CLIPBOARD_BOTH;
593 *option = CLIPBOARD_BOTH;
597 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
598 guint option, guint *option_c)
605 pref_table_label(table, column, row, text, 0.0);
607 combo = gtk_combo_box_text_new();
609 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
610 if (option == GDK_INTERP_NEAREST) current = 0;
611 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
612 if (option == GDK_INTERP_TILES) current = 1;
613 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
614 if (option == GDK_INTERP_BILINEAR) current = 2;
616 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
618 g_signal_connect(G_OBJECT(combo), "changed",
619 G_CALLBACK(quality_menu_cb), option_c);
621 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
622 gtk_widget_show(combo);
625 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
632 pref_table_label(table, column, row, text, 0.0);
634 combo = gtk_combo_box_text_new();
636 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
637 if (option == DND_ACTION_ASK) current = 0;
638 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
639 if (option == DND_ACTION_COPY) current = 1;
640 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
641 if (option == DND_ACTION_MOVE) current = 2;
643 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
645 g_signal_connect(G_OBJECT(combo), "changed",
646 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
648 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
649 gtk_widget_show(combo);
652 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
653 gint option, gint *option_c)
660 pref_table_label(table, column, row, text, 0.0);
662 combo = gtk_combo_box_text_new();
664 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
665 if (option == CLIPBOARD_PRIMARY) current = 0;
666 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
667 if (option == CLIPBOARD_CLIPBOARD) current = 1;
668 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
669 if (option == CLIPBOARD_BOTH) current = 2;
671 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
673 g_signal_connect(G_OBJECT(combo), "changed",
674 G_CALLBACK(clipboard_selection_menu_cb), option_c);
676 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
677 gtk_widget_show(combo);
680 typedef struct _UseableMouseItems UseableMouseItems;
681 struct _UseableMouseItems
683 gchar *name; /* GtkActionEntry terminology */
688 static const UseableMouseItems useable_mouse_items[] = {
690 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
691 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
692 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
693 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
694 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
695 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
696 {"Home", N_("Home"), GTK_STOCK_HOME},
697 {"Up", N_("Up"), GTK_STOCK_GO_UP},
698 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
699 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
700 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
701 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
702 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
703 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
704 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
705 {"Search", N_("Search"), GTK_STOCK_FIND},
706 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
707 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
708 {"Copy", N_("Copy"), GTK_STOCK_COPY},
709 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
710 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
711 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
712 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
713 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
714 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
715 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
716 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
717 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
718 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
719 {"Print", N_("Print"), GTK_STOCK_PRINT},
720 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
721 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
722 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
723 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
724 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
725 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
726 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
727 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
728 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
729 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
730 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
731 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
732 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
733 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
734 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
735 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
736 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
737 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
738 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
739 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
740 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
741 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
742 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
743 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
744 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
745 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
746 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
747 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
748 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
749 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
750 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
751 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
752 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
753 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
754 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
755 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
756 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
757 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
758 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
759 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
763 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
765 gchar **option = data;
768 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
770 const UseableMouseItems *list = useable_mouse_items;
774 if (g_strcmp0(list->label, label) == 0)
782 *option = g_strdup(list->name);
786 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
787 gchar *option, gchar **option_c)
795 pref_table_label(table, column, row, text, 0.0);
797 combo = gtk_combo_box_text_new();
799 const UseableMouseItems *list = useable_mouse_items;
803 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
804 if (g_strcmp0(list->name, option) == 0)
812 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
814 g_signal_connect(G_OBJECT(combo), "changed",
815 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
817 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
818 gtk_widget_show(combo);
821 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
825 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
828 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
830 c_options->thumbnails.max_width = thumb_size_list[n].w;
831 c_options->thumbnails.max_height = thumb_size_list[n].h;
835 c_options->thumbnails.max_width = options->thumbnails.max_width;
836 c_options->thumbnails.max_height = options->thumbnails.max_height;
840 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
846 c_options->thumbnails.max_width = options->thumbnails.max_width;
847 c_options->thumbnails.max_height = options->thumbnails.max_height;
849 pref_table_label(table, column, row, text, 0.0);
851 combo = gtk_combo_box_text_new();
854 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
859 w = thumb_size_list[i].w;
860 h = thumb_size_list[i].h;
862 buf = g_strdup_printf("%d x %d", w, h);
863 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
866 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
873 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
874 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
880 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
881 g_signal_connect(G_OBJECT(combo), "changed",
882 G_CALLBACK(thumb_size_menu_cb), NULL);
884 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
885 gtk_widget_show(combo);
888 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
892 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
896 *option = PR_STEREO_NONE;
899 *option = PR_STEREO_ANAGLYPH_RC;
902 *option = PR_STEREO_ANAGLYPH_GM;
905 *option = PR_STEREO_ANAGLYPH_YB;
908 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
911 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
914 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
917 *option = PR_STEREO_ANAGLYPH_DB_RC;
920 *option = PR_STEREO_ANAGLYPH_DB_GM;
923 *option = PR_STEREO_ANAGLYPH_DB_YB;
926 *option = PR_STEREO_HORIZ;
929 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
932 *option = PR_STEREO_VERT;
935 *option = PR_STEREO_VERT | PR_STEREO_HALF;
938 *option = PR_STEREO_FIXED;
943 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
944 gint option, gint *option_c, gboolean add_fixed)
951 pref_table_label(table, column, row, text, 0.0);
953 combo = gtk_combo_box_text_new();
955 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
958 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
959 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
960 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
961 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
962 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
964 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
966 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
967 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
968 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
969 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
970 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
971 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
972 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
973 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
974 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
976 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
977 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
978 if (option & PR_STEREO_HORIZ)
981 if (option & PR_STEREO_HALF) current = 11;
984 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
985 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
986 if (option & PR_STEREO_VERT)
989 if (option & PR_STEREO_HALF) current = 13;
994 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
995 if (option & PR_STEREO_FIXED) current = 14;
998 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1000 g_signal_connect(G_OBJECT(combo), "changed",
1001 G_CALLBACK(stereo_mode_menu_cb), option_c);
1003 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1004 gtk_widget_show(combo);
1007 static void video_menu_cb(GtkWidget *combo, gpointer data)
1009 gchar **option = data;
1011 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1015 static void video_menu_populate(gpointer data, gpointer user_data)
1017 GtkWidget *combo = user_data;
1018 EditorDescription *ed = data;
1020 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1023 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1024 gchar *option, gchar **option_c)
1028 /* use lists since they are sorted */
1029 GList *eds = editor_list_get();
1033 pref_table_label(table, column, row, text, 0.0);
1035 combo = gtk_combo_box_text_new();
1036 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1037 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1039 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1041 g_signal_connect(G_OBJECT(combo), "changed",
1042 G_CALLBACK(video_menu_cb), option_c);
1044 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1045 gtk_widget_show(combo);
1048 static void filter_store_populate(void)
1052 if (!filter_store) return;
1054 gtk_list_store_clear(filter_store);
1056 work = filter_get_list();
1065 gtk_list_store_append(filter_store, &iter);
1066 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1070 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1071 gchar *new_text, gpointer data)
1073 GtkWidget *model = data;
1074 FilterEntry *fe = data;
1078 if (!new_text || strlen(new_text) < 1) 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->extensions);
1085 fe->extensions = g_strdup(new_text);
1087 gtk_tree_path_free(tpath);
1091 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1092 gchar *new_text, gpointer data)
1094 GtkWidget *model = data;
1095 FilterEntry *fe = data;
1100 if (!new_text || !new_text[0]) return;
1102 tpath = gtk_tree_path_new_from_string(path_str);
1103 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1104 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1106 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1108 if (strcmp(new_text, _(format_class_list[i])) == 0)
1115 gtk_tree_path_free(tpath);
1119 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1120 gchar *new_text, gpointer data)
1122 GtkWidget *model = data;
1127 if (!new_text || !new_text[0]) return;
1129 tpath = gtk_tree_path_new_from_string(path_str);
1130 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1131 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1133 g_free(fe->description);
1134 fe->description = g_strdup(new_text);
1136 gtk_tree_path_free(tpath);
1139 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1140 gchar *path_str, gpointer data)
1142 GtkWidget *model = data;
1147 tpath = gtk_tree_path_new_from_string(path_str);
1148 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1149 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1151 fe->enabled = !fe->enabled;
1153 gtk_tree_path_free(tpath);
1157 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1158 gchar *path_str, gpointer data)
1160 GtkWidget *model = data;
1165 tpath = gtk_tree_path_new_from_string(path_str);
1166 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1167 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1169 fe->writable = !fe->writable;
1170 if (fe->writable) fe->allow_sidecar = FALSE;
1172 gtk_tree_path_free(tpath);
1176 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1177 gchar *path_str, gpointer data)
1179 GtkWidget *model = data;
1184 tpath = gtk_tree_path_new_from_string(path_str);
1185 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1186 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1188 fe->allow_sidecar = !fe->allow_sidecar;
1189 if (fe->allow_sidecar) fe->writable = FALSE;
1191 gtk_tree_path_free(tpath);
1195 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1196 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1200 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1202 switch (GPOINTER_TO_INT(data))
1205 g_object_set(GTK_CELL_RENDERER(cell),
1206 "active", fe->enabled, NULL);
1209 g_object_set(GTK_CELL_RENDERER(cell),
1210 "text", fe->extensions, NULL);
1212 case FE_DESCRIPTION:
1213 g_object_set(GTK_CELL_RENDERER(cell),
1214 "text", fe->description, NULL);
1217 g_object_set(GTK_CELL_RENDERER(cell),
1218 "text", _(format_class_list[fe->file_class]), NULL);
1221 g_object_set(GTK_CELL_RENDERER(cell),
1222 "active", fe->writable, NULL);
1224 case FE_ALLOW_SIDECAR:
1225 g_object_set(GTK_CELL_RENDERER(cell),
1226 "active", fe->allow_sidecar, NULL);
1231 static gboolean filter_add_scroll(gpointer data)
1235 GtkCellRenderer *cell;
1236 GtkTreeViewColumn *column;
1239 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1240 path = gtk_tree_path_new_from_indices(rows-1, -1);
1242 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1244 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1245 cell = g_list_last(list_cells)->data;
1247 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1248 path, column, FALSE, 0.0, 0.0 );
1249 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1250 path, column, cell, TRUE);
1252 gtk_tree_path_free(path);
1253 g_list_free(list_cells);
1258 static void filter_add_cb(GtkWidget *widget, gpointer data)
1260 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1261 filter_store_populate();
1263 g_idle_add((GSourceFunc)filter_add_scroll, data);
1266 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1268 GtkWidget *filter_view = data;
1269 GtkTreeSelection *selection;
1273 if (!filter_store) return;
1274 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1275 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1276 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1279 filter_remove_entry(fe);
1281 filter_store_populate();
1284 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1288 GtkTreeViewColumn *column;
1290 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1291 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1292 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1294 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1298 gtk_tree_path_free(path);
1303 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1306 filter_add_defaults();
1308 filter_store_populate();
1310 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1313 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1315 /* no op, only so cancel button appears */
1318 static void filter_default_cb(GtkWidget *widget, gpointer data)
1322 gd = generic_dialog_new(_("Reset filters"),
1323 "reset_filter", widget, TRUE,
1324 dummy_cancel_cb, data);
1325 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1326 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1327 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1328 gtk_widget_show(gd->dialog);
1331 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1333 GtkWidget *frame = data;
1335 gtk_widget_set_sensitive(frame,
1336 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1339 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1341 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1344 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1346 file_util_trash_clear();
1349 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1353 gd = generic_dialog_new(_("Clear trash"),
1354 "clear_trash", widget, TRUE,
1355 dummy_cancel_cb, NULL);
1356 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1357 _("This will remove the trash contents."), FALSE);
1358 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1359 entry = gtk_entry_new();
1360 gtk_widget_set_can_focus(entry, FALSE);
1361 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1362 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1363 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1364 gtk_widget_show(entry);
1365 gtk_widget_show(gd->dialog);
1368 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1370 GtkWidget *pTextView;
1371 GtkTextBuffer *pTextBuffer;
1375 pTextView = GTK_WIDGET(data);
1377 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1378 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1379 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1381 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1382 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1385 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1387 GtkTextView *text_view = data;
1388 GtkTextBuffer *buffer;
1390 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1391 if (!configwindow) return;
1393 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1394 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1397 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1401 gd = generic_dialog_new(_("Reset image overlay template string"),
1402 "reset_image_overlay_template_string", widget, TRUE,
1403 dummy_cancel_cb, data);
1404 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1405 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1406 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1407 gtk_widget_show(gd->dialog);
1410 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1412 help_window_show("GuideOptionsOSD.html");
1415 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1417 #if GTK_CHECK_VERSION(3,4,0)
1420 PangoFontDescription *font_desc;
1422 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1423 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1425 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1427 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1428 font = pango_font_description_to_string(font_desc);
1429 g_free(c_options->image_overlay.font);
1430 c_options->image_overlay.font = g_strdup(font);
1434 gtk_widget_destroy(dialog);
1438 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1439 c_options->image_overlay.font = g_strdup(font);
1443 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1446 #if GTK_CHECK_VERSION(3,4,0)
1449 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1450 colour.red = options->image_overlay.text_red;
1451 colour.green = options->image_overlay.text_green;
1452 colour.blue = options->image_overlay.text_blue;
1453 colour.alpha = options->image_overlay.text_alpha;
1454 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1455 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1457 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1459 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1460 c_options->image_overlay.text_red = colour.red*255;
1461 c_options->image_overlay.text_green = colour.green*255;
1462 c_options->image_overlay.text_blue = colour.blue*255;
1463 c_options->image_overlay.text_alpha = colour.alpha*255;
1465 gtk_widget_destroy(dialog);
1468 GtkColorSelection *colorsel;
1470 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1471 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1472 colour.red = options->image_overlay.text_red*257;
1473 colour.green = options->image_overlay.text_green*257;
1474 colour.blue = options->image_overlay.text_blue*257;
1475 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1476 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1477 gtk_color_selection_set_current_color(colorsel, &colour);
1478 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1480 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1482 gtk_color_selection_get_current_color(colorsel, &colour);
1483 c_options->image_overlay.text_red = colour.red/257;
1484 c_options->image_overlay.text_green = colour.green/257;
1485 c_options->image_overlay.text_blue = colour.blue/257;
1486 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1488 gtk_widget_destroy (dialog);
1493 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1496 #if GTK_CHECK_VERSION(3,4,0)
1499 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1500 colour.red = options->image_overlay.background_red;
1501 colour.green = options->image_overlay.background_green;
1502 colour.blue = options->image_overlay.background_blue;
1503 colour.alpha = options->image_overlay.background_alpha;
1504 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1505 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1507 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1509 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1510 c_options->image_overlay.background_red = colour.red*255;
1511 c_options->image_overlay.background_green = colour.green*255;
1512 c_options->image_overlay.background_blue = colour.blue*255;
1513 c_options->image_overlay.background_alpha = colour.alpha*255;
1515 gtk_widget_destroy(dialog);
1518 GtkColorSelection *colorsel;
1520 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1521 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1522 colour.red = options->image_overlay.background_red*257;
1523 colour.green = options->image_overlay.background_green*257;
1524 colour.blue = options->image_overlay.background_blue*257;
1525 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1526 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1527 gtk_color_selection_set_current_color(colorsel, &colour);
1528 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1530 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1532 gtk_color_selection_get_current_color(colorsel, &colour);
1533 c_options->image_overlay.background_red = colour.red/257;
1534 c_options->image_overlay.background_green = colour.green/257;
1535 c_options->image_overlay.background_blue = colour.blue/257;
1536 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1538 gtk_widget_destroy(dialog);
1542 static void accel_store_populate(void)
1545 GList *groups, *actions;
1547 const gchar *accel_path;
1551 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1553 gtk_tree_store_clear(accel_store);
1554 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1556 g_assert(lw && lw->ui_manager);
1557 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1560 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1563 action = GTK_ACTION(actions->data);
1564 accel_path = gtk_action_get_accel_path(action);
1565 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1567 gchar *label, *label2, *tooltip, *accel;
1568 g_object_get(action,
1569 "tooltip", &tooltip,
1573 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1579 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1583 gtk_tree_store_append(accel_store, &iter, NULL);
1584 gtk_tree_store_set(accel_store, &iter,
1587 AE_TOOLTIP, tooltip ? tooltip : "",
1588 AE_ACCEL, accel_path,
1596 actions = actions->next;
1599 groups = groups->next;
1603 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1608 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1610 gchar *accel1 = data;
1615 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1617 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1618 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1620 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1622 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1623 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1632 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1634 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1638 GtkAccelKey old_key, key;
1639 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1641 gtk_tree_model_get_iter(model, &iter, path);
1642 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1644 /* test if the accelerator can be stored without conflicts*/
1645 gtk_accel_map_lookup_entry(accel_path, &old_key);
1647 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1648 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1649 gtk_accel_map_lookup_entry(accel_path, &key);
1651 /* restore the original for now, the key will be really changed when the changes are confirmed */
1652 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1654 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1655 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1657 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1658 gtk_tree_path_free(path);
1662 static gboolean accel_default_scroll(GtkTreeView *data)
1666 GtkTreeViewColumn *column;
1668 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1669 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1670 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1672 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1676 gtk_tree_path_free(path);
1681 static void accel_default_cb(GtkWidget *widget, gpointer data)
1683 accel_store_populate();
1685 g_idle_add((GSourceFunc)accel_default_scroll, data);
1688 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1690 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1693 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1696 gchar *accel_path, *accel;
1698 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1699 gtk_accel_map_lookup_entry(accel_path, &key);
1700 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1702 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1704 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1709 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1711 GtkTreeSelection *selection;
1713 if (!accel_store) return;
1714 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1715 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1720 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1724 GtkWidget *scrolled;
1725 GtkWidget *viewport;
1727 scrolled = gtk_scrolled_window_new(NULL, NULL);
1728 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1729 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1730 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1731 label = gtk_label_new(title);
1732 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1733 gtk_widget_show(scrolled);
1735 viewport = gtk_viewport_new(NULL, NULL);
1736 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1737 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1738 gtk_widget_show(viewport);
1740 vbox = gtk_vbox_new(FALSE, 0);
1741 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1742 gtk_widget_show(vbox);
1747 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1749 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1751 c_options->thumbnails.spec_standard =TRUE;
1752 c_options->thumbnails.cache_into_dirs = FALSE;
1756 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1758 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1760 c_options->thumbnails.spec_standard =FALSE;
1761 c_options->thumbnails.cache_into_dirs = FALSE;
1765 static void cache_local_cb(GtkWidget *widget, gpointer data)
1767 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1769 c_options->thumbnails.cache_into_dirs = TRUE;
1770 c_options->thumbnails.spec_standard =FALSE;
1774 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1775 GdkEvent *event, gpointer userdata)
1777 if (pos == GTK_ENTRY_ICON_PRIMARY)
1779 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1783 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1787 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1788 GdkEvent *event, gpointer userdata)
1790 gchar *rating_symbol;
1792 if (pos == GTK_ENTRY_ICON_PRIMARY)
1794 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1795 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1796 g_free(rating_symbol);
1800 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1801 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1802 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1806 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1807 GdkEvent *event, gpointer userdata)
1809 gchar *rating_symbol;
1811 if (pos == GTK_ENTRY_ICON_PRIMARY)
1813 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1814 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1815 g_free(rating_symbol);
1819 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1820 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1821 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1825 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1827 GtkContainer *hbox = data;
1828 GString *str = g_string_new(NULL);
1829 GtkEntry *hex_code_entry;
1830 gchar *hex_code_full;
1833 guint64 hex_value = 0;
1835 list = gtk_container_get_children(hbox);
1837 hex_code_entry = g_list_nth_data(list, 2);
1838 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1840 hex_code = g_strsplit(hex_code_full, "+", 2);
1841 if (hex_code[0] && hex_code[1])
1843 hex_value = strtoull(hex_code[1], NULL, 16);
1845 if (!hex_value || hex_value > 0x10FFFF)
1847 hex_value = 0x003F; // Unicode 'Question Mark'
1849 str = g_string_append_unichar(str, (gunichar)hex_value);
1850 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1852 g_strfreev(hex_code);
1853 g_string_free(str, TRUE);
1854 g_free(hex_code_full);
1859 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1861 guint64 star_symbol;
1863 star_symbol = star_rating_symbol_test(widget, data);
1864 c_options->star_rating.star = star_symbol;
1867 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1869 guint64 rejected_symbol;
1871 rejected_symbol = star_rating_symbol_test(widget, data);
1872 c_options->star_rating.rejected = rejected_symbol;
1875 /* general options tab */
1876 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1877 typedef struct _TZData TZData;
1881 GCancellable *cancellable;
1883 GtkWidget *progress;
1885 GFile *timezone_database_gq;
1886 gchar *timezone_database_user;
1889 static void config_tab_general(GtkWidget *notebook)
1894 GtkWidget *group_frame;
1895 GtkWidget *subgroup;
1897 GtkWidget *ct_button;
1900 gint hours, minutes, remainder;
1902 GtkWidget *star_rating_entry;
1904 gchar *rating_symbol;
1907 GNetworkMonitor *net_mon;
1908 GSocketConnectable *geeqie_org;
1909 gboolean internet_available;
1912 vbox = scrolled_notebook_page(notebook, _("General"));
1914 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1916 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1917 add_thumb_size_menu(table, 0, 0, _("Size:"));
1918 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1920 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1921 pref_label_new(hbox, _("Custom size: "));
1922 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1923 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1925 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1926 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1928 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1929 pref_checkbox_link_sensitivity(ct_button, subgroup);
1931 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1932 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1933 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1934 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1935 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1936 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1937 G_CALLBACK(cache_geeqie_cb), NULL);
1939 group_frame = pref_frame_new(subgroup, TRUE,
1940 _("Store thumbnails local to image folder (non-standard)"),
1941 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1942 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1943 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1944 G_CALLBACK(cache_local_cb), NULL);
1946 group_frame = pref_frame_new(subgroup, TRUE,
1947 _("Use standard thumbnail style and cache, shared with other applications"),
1948 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1949 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1950 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1951 G_CALLBACK(cache_standard_cb), NULL);
1953 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1954 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1956 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1958 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1959 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1961 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1962 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1963 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1965 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1966 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1969 pref_spacer(group, PREF_PAD_GROUP);
1971 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1973 c_options->star_rating.star = options->star_rating.star;
1974 c_options->star_rating.rejected = options->star_rating.rejected;
1976 str = g_string_new(NULL);
1977 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1978 pref_label_new(hbox, "Star character: ");
1979 str = g_string_append_unichar(str, options->star_rating.star);
1980 pref_label_new(hbox, g_strdup(str->str));
1981 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1982 star_rating_entry = gtk_entry_new();
1983 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1984 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1985 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1986 gtk_widget_show(star_rating_entry);
1987 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1988 G_CALLBACK(star_rating_star_test_cb), hbox);
1989 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1990 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1991 gtk_widget_show(button);
1992 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."));
1993 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1994 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1995 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1996 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1997 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1998 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1999 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2000 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2001 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2002 G_CALLBACK(star_rating_star_icon_cb),
2005 g_string_free(str, TRUE);
2006 g_free(rating_symbol);
2008 str = g_string_new(NULL);
2009 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2010 pref_label_new(hbox, "Rejected character: ");
2011 str = g_string_append_unichar(str, options->star_rating.rejected);
2012 pref_label_new(hbox, g_strdup(str->str));
2013 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2014 star_rating_entry = gtk_entry_new();
2015 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2016 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2017 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2018 gtk_widget_show(star_rating_entry);
2019 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2020 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2021 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2022 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2023 gtk_widget_show(button);
2024 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."));
2025 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2026 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2027 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2028 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2029 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2030 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2031 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2032 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2033 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2034 G_CALLBACK(star_rating_rejected_icon_cb),
2037 g_string_free(str, TRUE);
2038 g_free(rating_symbol);
2040 pref_spacer(group, PREF_PAD_GROUP);
2042 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2044 c_options->slideshow.delay = options->slideshow.delay;
2045 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2046 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2047 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2048 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2049 SLIDESHOW_SUBSECOND_PRECISION;
2051 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2053 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2055 options->slideshow.delay ? hours : 0.0,
2056 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2057 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2058 spin = pref_spin_new(hbox, ":" , NULL,
2060 options->slideshow.delay ? minutes: 0.0,
2061 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2062 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2063 spin = pref_spin_new(hbox, ":", NULL,
2064 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2065 options->slideshow.delay ? seconds : 10.0,
2066 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2067 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2069 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2070 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2072 pref_spacer(group, PREF_PAD_GROUP);
2074 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2076 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2077 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2078 pref_checkbox_new_int(group, _("Preload next image"),
2079 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2081 pref_checkbox_new_int(group, _("Refresh on file change"),
2082 options->update_on_time_change, &c_options->update_on_time_change);
2085 pref_spacer(group, PREF_PAD_GROUP);
2087 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2089 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2090 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2091 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2093 pref_spacer(group, PREF_PAD_GROUP);
2095 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2096 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2097 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2098 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2100 options->info_keywords.height, &c_options->info_keywords.height);
2101 pref_spin_new_int(hbox, _("Title:"), NULL,
2103 options->info_title.height, &c_options->info_title.height);
2104 pref_spin_new_int(hbox, _("Comment:"), NULL,
2106 options->info_comment.height, &c_options->info_comment.height);
2107 pref_spin_new_int(hbox, _("Rating:"), NULL,
2109 options->info_rating.height, &c_options->info_rating.height);
2111 pref_spacer(group, PREF_PAD_GROUP);
2113 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2115 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2116 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2118 pref_spacer(group, PREF_PAD_GROUP);
2120 net_mon = g_network_monitor_get_default();
2121 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2122 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2123 g_object_unref(geeqie_org);
2125 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2126 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2128 if (!internet_available)
2130 gtk_widget_set_sensitive(group, FALSE);
2133 tz = g_new0(TZData, 1);
2135 path = path_from_utf8(TIMEZONE_DATABASE);
2136 basename = g_path_get_basename(path);
2137 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2141 if (isfile(tz->timezone_database_user))
2143 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2147 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2150 if (!internet_available)
2152 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"));
2156 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"));
2158 gtk_widget_show(button);
2160 pref_spacer(group, PREF_PAD_GROUP);
2162 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2164 help_search_engine_entry = gtk_entry_new();
2165 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2166 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2167 gtk_widget_show(help_search_engine_entry);
2169 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"));
2171 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2172 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2173 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2174 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2175 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2176 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2177 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2178 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2179 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2180 G_CALLBACK(help_search_engine_entry_icon_cb),
2181 help_search_engine_entry);
2185 static void config_tab_image(GtkWidget *notebook)
2190 GtkWidget *ct_button;
2191 GtkWidget *enlargement_button;
2194 GtkWidget *two_pass;
2196 GtkWidget *gpu_accel;
2199 vbox = scrolled_notebook_page(notebook, _("Image"));
2201 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2203 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2204 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2205 if (options->image.use_clutter_renderer && !options->disable_gpu)
2207 gtk_widget_set_sensitive(table, FALSE);
2211 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2212 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2213 if (options->disable_gpu && !options->override_disable_gpu)
2215 gtk_widget_set_sensitive(gpu_accel, FALSE);
2219 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2220 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2221 if (options->image.use_clutter_renderer && !options->disable_gpu)
2223 gtk_widget_set_sensitive(two_pass, FALSE);
2226 c_options->image.zoom_increment = options->image.zoom_increment;
2227 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2228 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2229 G_CALLBACK(zoom_increment_cb), NULL);
2230 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2232 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2234 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2235 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2236 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2237 spin = pref_spin_new_int(hbox, NULL, NULL,
2239 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2240 pref_checkbox_link_sensitivity(enlargement_button, spin);
2241 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."));
2243 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2244 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2245 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2246 spin = pref_spin_new_int(hbox, NULL, NULL,
2248 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2249 pref_checkbox_link_sensitivity(ct_button, spin);
2250 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."));
2252 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2254 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2255 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2257 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2258 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2260 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2261 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2263 c_options->image.border_color = options->image.border_color;
2265 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2266 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2268 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2269 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2271 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2272 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2274 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2276 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2277 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2281 static void config_tab_windows(GtkWidget *notebook)
2287 GtkWidget *ct_button;
2290 vbox = scrolled_notebook_page(notebook, _("Windows"));
2292 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2294 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2295 options->save_window_positions, &c_options->save_window_positions);
2297 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2298 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2299 pref_checkbox_link_sensitivity(ct_button, button);
2301 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2302 options->tools_restore_state, &c_options->tools_restore_state);
2304 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2305 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2307 pref_checkbox_new_int(group, _("Show window IDs"),
2308 options->show_window_ids, &c_options->show_window_ids);
2310 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2312 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2313 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2315 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2316 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2317 options->image.limit_window_size, &c_options->image.limit_window_size);
2318 spin = pref_spin_new_int(hbox, NULL, NULL,
2320 options->image.max_window_size, &c_options->image.max_window_size);
2321 pref_checkbox_link_sensitivity(ct_button, spin);
2323 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2325 c_options->fullscreen.screen = options->fullscreen.screen;
2326 c_options->fullscreen.above = options->fullscreen.above;
2327 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2328 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2329 gtk_widget_show(hbox);
2331 pref_checkbox_new_int(group, _("Smooth image flip"),
2332 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2333 pref_checkbox_new_int(group, _("Disable screen saver"),
2334 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2337 #define PRE_FORMATTED_COLUMNS 5
2338 static void config_tab_osd(GtkWidget *notebook)
2344 GtkWidget *image_overlay_template_view;
2345 GtkWidget *scrolled;
2346 GtkWidget *scrolled_pre_formatted;
2347 GtkTextBuffer *buffer;
2349 GtkWidget *subgroup;
2351 vbox = scrolled_notebook_page(notebook, _("OSD"));
2353 image_overlay_template_view = gtk_text_view_new();
2355 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2357 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2359 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2360 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2361 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2362 gtk_widget_show(scrolled_pre_formatted);
2363 gtk_widget_show(subgroup);
2365 pref_line(group, PREF_PAD_GAP);
2367 pref_label_new(group, _("Image overlay template"));
2369 scrolled = gtk_scrolled_window_new(NULL, NULL);
2370 gtk_widget_set_size_request(scrolled, 200, 150);
2371 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2372 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2373 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2374 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2375 gtk_widget_show(scrolled);
2377 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2378 _("Extensive formatting options are shown in the Help file"));
2380 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2381 gtk_widget_show(image_overlay_template_view);
2383 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2385 #if GTK_CHECK_VERSION(3,4,0)
2386 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2387 G_CALLBACK(image_overlay_set_font_cb), notebook);
2389 button = gtk_font_button_new();
2390 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2391 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2392 g_signal_connect(G_OBJECT(button), "font-set",
2393 G_CALLBACK(image_overlay_set_font_cb),NULL);
2395 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2396 gtk_widget_show(button);
2398 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2399 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2400 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2401 gtk_widget_show(button);
2403 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2404 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2405 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2406 gtk_widget_show(button);
2407 image_overlay_set_text_colours();
2409 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2410 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2411 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2412 gtk_widget_show(button);
2414 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2415 G_CALLBACK(image_overlay_help_cb), NULL);
2416 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2417 gtk_widget_show(button);
2419 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2420 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2421 g_signal_connect(G_OBJECT(buffer), "changed",
2422 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2424 pref_line(group, PREF_PAD_GAP);
2426 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2427 hbox = gtk_hbox_new(FALSE, 0);
2428 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2429 gtk_widget_show(hbox);
2430 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2431 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2432 gtk_widget_show(label);
2433 pref_spacer(group,TRUE);
2435 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2436 hbox = gtk_hbox_new(FALSE, 0);
2437 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2438 gtk_widget_show(hbox);
2439 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2440 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2441 gtk_widget_show(label);
2442 pref_spacer(group,TRUE);
2444 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2445 hbox = gtk_hbox_new(FALSE, 0);
2446 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2447 gtk_widget_show(hbox);
2448 label = gtk_label_new(_("%path:39%"));
2449 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2450 gtk_widget_show(label);
2451 pref_spacer(group,TRUE);
2453 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2454 hbox = gtk_hbox_new(FALSE, 0);
2455 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2456 gtk_widget_show(hbox);
2457 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%"));
2458 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2459 gtk_widget_show(label);
2460 pref_spacer(group,TRUE);
2462 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2463 hbox = gtk_hbox_new(FALSE, 0);
2464 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2465 gtk_widget_show(hbox);
2466 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2467 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2468 gtk_widget_show(label);
2471 static GtkTreeModel *create_class_model(void)
2473 GtkListStore *model;
2477 /* create list store */
2478 model = gtk_list_store_new(1, G_TYPE_STRING);
2479 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2481 gtk_list_store_append(model, &iter);
2482 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2484 return GTK_TREE_MODEL (model);
2489 static void config_tab_files(GtkWidget *notebook)
2496 GtkWidget *ct_button;
2497 GtkWidget *scrolled;
2498 GtkWidget *filter_view;
2499 GtkCellRenderer *renderer;
2500 GtkTreeSelection *selection;
2501 GtkTreeViewColumn *column;
2503 vbox = scrolled_notebook_page(notebook, _("Files"));
2505 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2507 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2508 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2509 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2510 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2511 pref_checkbox_new_int(group, _("Case sensitive sort"),
2512 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2513 pref_checkbox_new_int(group, _("Natural sort order"),
2514 options->file_sort.natural, &c_options->file_sort.natural);
2515 pref_checkbox_new_int(group, _("Disable file extension checks"),
2516 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2518 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2519 options->file_filter.disable, &c_options->file_filter.disable);
2522 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2524 sidecar_ext_entry = gtk_entry_new();
2525 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2526 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2527 gtk_widget_show(sidecar_ext_entry);
2529 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2531 frame = pref_group_parent(group);
2532 g_signal_connect(G_OBJECT(ct_button), "toggled",
2533 G_CALLBACK(filter_disable_cb), frame);
2534 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2536 scrolled = gtk_scrolled_window_new(NULL, NULL);
2537 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2538 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2539 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2540 gtk_widget_show(scrolled);
2542 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2543 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2544 g_object_unref(filter_store);
2545 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2546 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2548 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2550 column = gtk_tree_view_column_new();
2551 gtk_tree_view_column_set_title(column, _("Filter"));
2552 gtk_tree_view_column_set_resizable(column, TRUE);
2554 renderer = gtk_cell_renderer_toggle_new();
2555 g_signal_connect(G_OBJECT(renderer), "toggled",
2556 G_CALLBACK(filter_store_enable_cb), filter_store);
2557 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2558 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2559 GINT_TO_POINTER(FE_ENABLE), NULL);
2561 renderer = gtk_cell_renderer_text_new();
2562 g_signal_connect(G_OBJECT(renderer), "edited",
2563 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2564 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2565 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2566 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2567 GINT_TO_POINTER(FE_EXTENSION), NULL);
2568 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2570 column = gtk_tree_view_column_new();
2571 gtk_tree_view_column_set_title(column, _("Description"));
2572 gtk_tree_view_column_set_resizable(column, TRUE);
2573 gtk_tree_view_column_set_fixed_width(column, 200);
2574 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2576 renderer = gtk_cell_renderer_text_new();
2577 g_signal_connect(G_OBJECT(renderer), "edited",
2578 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2579 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2580 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2581 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2582 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2583 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2585 column = gtk_tree_view_column_new();
2586 gtk_tree_view_column_set_title(column, _("Class"));
2587 gtk_tree_view_column_set_resizable(column, TRUE);
2588 renderer = gtk_cell_renderer_combo_new();
2589 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2590 "model", create_class_model(),
2595 g_signal_connect(G_OBJECT(renderer), "edited",
2596 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2597 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2598 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2599 GINT_TO_POINTER(FE_CLASS), NULL);
2600 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2602 column = gtk_tree_view_column_new();
2603 gtk_tree_view_column_set_title(column, _("Writable"));
2604 gtk_tree_view_column_set_resizable(column, FALSE);
2605 renderer = gtk_cell_renderer_toggle_new();
2606 g_signal_connect(G_OBJECT(renderer), "toggled",
2607 G_CALLBACK(filter_store_writable_cb), filter_store);
2608 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2609 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2610 GINT_TO_POINTER(FE_WRITABLE), NULL);
2611 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2613 column = gtk_tree_view_column_new();
2614 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2615 gtk_tree_view_column_set_resizable(column, FALSE);
2616 renderer = gtk_cell_renderer_toggle_new();
2617 g_signal_connect(G_OBJECT(renderer), "toggled",
2618 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2619 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2620 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2621 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2622 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2625 filter_store_populate();
2626 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2627 gtk_widget_show(filter_view);
2629 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2631 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2632 G_CALLBACK(filter_default_cb), filter_view);
2633 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2634 gtk_widget_show(button);
2636 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2637 G_CALLBACK(filter_remove_cb), filter_view);
2638 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2639 gtk_widget_show(button);
2641 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2642 G_CALLBACK(filter_add_cb), filter_view);
2643 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2644 gtk_widget_show(button);
2648 static void config_tab_metadata(GtkWidget *notebook)
2653 GtkWidget *ct_button;
2657 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2660 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2662 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2664 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2665 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2667 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2668 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2670 gtk_widget_set_sensitive(ct_button, FALSE);
2673 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2674 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2676 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2677 label = pref_label_new(group, text);
2678 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2679 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2682 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2684 gtk_widget_set_sensitive(group, FALSE);
2687 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2688 pref_checkbox_link_sensitivity(ct_button, hbox);
2690 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2691 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2693 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2694 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2696 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2697 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2699 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2700 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2702 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2704 gtk_widget_set_sensitive(group, FALSE);
2707 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2708 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2711 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2712 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2713 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2715 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2716 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2718 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2719 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2721 gtk_widget_set_sensitive(ct_button, FALSE);
2724 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2726 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2727 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2729 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2730 pref_checkbox_link_sensitivity(ct_button, hbox);
2732 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2733 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2735 pref_checkbox_new_int(group, _("Write metadata on image change"),
2736 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2738 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2739 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2741 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2743 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2744 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2745 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");
2750 typedef struct _KeywordFindData KeywordFindData;
2751 struct _KeywordFindData
2758 GtkWidget *button_close;
2759 GtkWidget *button_stop;
2760 GtkWidget *button_start;
2761 GtkWidget *progress;
2769 guint idle_id; /* event source id */
2772 #define KEYWORD_DIALOG_WIDTH 400
2774 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2776 GList *list_d = NULL;
2777 GList *list_f = NULL;
2781 filelist_read(dir_fd, &list_f, &list_d);
2785 filelist_read(dir_fd, &list_f, NULL);
2788 list_f = filelist_filter(list_f, FALSE);
2789 list_d = filelist_filter(list_d, TRUE);
2791 kfd->list = g_list_concat(list_f, kfd->list);
2792 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2795 static void keywords_find_reset(KeywordFindData *kfd)
2797 filelist_free(kfd->list);
2800 filelist_free(kfd->list_dir);
2801 kfd->list_dir = NULL;
2804 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2806 KeywordFindData *kfd = data;
2808 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2810 keywords_find_reset(kfd);
2811 generic_dialog_close(kfd->gd);
2815 static void keywords_find_finish(KeywordFindData *kfd)
2817 keywords_find_reset(kfd);
2819 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2820 spinner_set_interval(kfd->spinner, -1);
2822 gtk_widget_set_sensitive(kfd->group, TRUE);
2823 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2824 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2825 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2828 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2830 KeywordFindData *kfd = data;
2832 g_idle_remove_by_data(kfd);
2834 keywords_find_finish(kfd);
2837 static gboolean keywords_find_file(gpointer data)
2839 KeywordFindData *kfd = data;
2841 GtkTextBuffer *buffer;
2849 fd = kfd->list->data;
2850 kfd->list = g_list_remove(kfd->list, fd);
2852 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2853 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2857 gtk_text_buffer_get_end_iter(buffer, &iter);
2858 tmp = g_strconcat(keywords->data, "\n", NULL);
2859 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2861 keywords = keywords->next;
2864 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2865 file_data_unref(fd);
2866 string_list_free(keywords);
2870 else if (kfd->list_dir)
2874 fd = kfd->list_dir->data;
2875 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2877 keywords_find_folder(kfd, fd);
2879 file_data_unref(fd);
2884 keywords_find_finish(kfd);
2889 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2891 KeywordFindData *kfd = data;
2894 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2896 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2897 parse_out_relatives(path);
2901 warning_dialog(_("Invalid folder"),
2902 _("The specified folder can not be found."),
2903 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2909 gtk_widget_set_sensitive(kfd->group, FALSE);
2910 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2911 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2912 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2913 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2915 dir_fd = file_data_new_dir(path);
2916 keywords_find_folder(kfd, dir_fd);
2917 file_data_unref(dir_fd);
2918 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2924 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2926 KeywordFindData *kfd;
2930 kfd = g_new0(KeywordFindData, 1);
2932 kfd->gd = generic_dialog_new(_("Search for keywords"),
2933 "search_for_keywords",
2936 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2937 kfd->gd->cancel_cb = keywords_find_close_cb;
2938 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2939 keywords_find_close_cb, FALSE);
2940 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2941 keywords_find_start_cb, FALSE);
2942 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2943 keywords_find_stop_cb, FALSE);
2944 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2946 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2948 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2949 pref_spacer(hbox, PREF_PAD_INDENT);
2950 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2952 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2953 pref_label_new(hbox, _("Folder:"));
2955 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2956 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2957 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2958 gtk_widget_show(label);
2960 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2962 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2963 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2965 kfd->progress = gtk_entry_new();
2966 gtk_widget_set_can_focus(kfd->progress, FALSE);
2967 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2968 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2969 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2970 gtk_widget_show(kfd->progress);
2972 kfd->spinner = spinner_new(NULL, -1);
2973 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2974 gtk_widget_show(kfd->spinner);
2978 gtk_widget_show(kfd->gd->dialog);
2981 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2983 const gchar *path = layout_get_path(NULL);
2985 if (!path || !*path) path = homedir();
2986 keywords_find_dialog(widget, path);
2989 static void config_tab_keywords_save()
2991 GtkTextIter start, end;
2992 GtkTextBuffer *buffer;
2993 GList *kw_list = NULL;
2999 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3000 gtk_text_buffer_get_bounds(buffer, &start, &end);
3002 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3004 kw_split = strtok(buffer_text, "\n");
3005 while (kw_split != NULL)
3011 if (g_strcmp0(work->data, kw_split) == 0)
3020 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3022 kw_split = strtok(NULL, "\n");
3025 keyword_list_set(kw_list);
3027 string_list_free(kw_list);
3028 g_free(buffer_text);
3031 static void config_tab_keywords(GtkWidget *notebook)
3037 GtkWidget *scrolled;
3039 GtkTextBuffer *buffer;
3042 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3044 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3046 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3048 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3049 G_CALLBACK(keywords_find_cb), keyword_text);
3050 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3053 keyword_text = gtk_text_view_new();
3054 gtk_widget_set_size_request(keyword_text, 20, 20);
3055 scrolled = gtk_scrolled_window_new(NULL, NULL);
3056 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3057 gtk_widget_show(scrolled);
3059 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3060 gtk_widget_show(keyword_text);
3062 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3064 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3065 gtk_text_buffer_create_tag(buffer, "monospace",
3066 "family", "monospace", NULL);
3068 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3069 gtk_text_buffer_get_start_iter(buffer, &iter);
3070 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3073 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3075 GList *kwl = keyword_list_get();
3076 kwl = g_list_first(kwl);
3079 gtk_text_buffer_get_end_iter (buffer, &iter);
3080 tmp = g_strconcat(kwl->data, "\n", NULL);
3081 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3086 gtk_text_buffer_set_modified(buffer, FALSE);
3093 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3095 gint *option = data;
3097 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3101 *option = INTENT_PERCEPTUAL;
3104 *option = INTENT_RELATIVE_COLORIMETRIC;
3107 *option = INTENT_SATURATION;
3110 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3115 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3116 gint option, gint *option_c)
3123 pref_table_label(table, column, row, text, 0.0);
3125 combo = gtk_combo_box_text_new();
3127 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3128 if (option == INTENT_PERCEPTUAL) current = 0;
3129 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3130 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3131 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3132 if (option == INTENT_SATURATION) current = 2;
3133 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3134 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3136 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3138 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3140 g_signal_connect(G_OBJECT(combo), "changed",
3141 G_CALLBACK(intent_menu_cb), option_c);
3143 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3144 gtk_widget_show(combo);
3148 static void config_tab_color(GtkWidget *notebook)
3157 vbox = scrolled_notebook_page(notebook, _("Color management"));
3159 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3161 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3164 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3165 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3167 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3168 pref_label_bold(label, TRUE, FALSE);
3170 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3171 pref_label_bold(label, TRUE, FALSE);
3173 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3174 pref_label_bold(label, TRUE, FALSE);
3176 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3181 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3182 pref_table_label(table, 0, i + 1, buf, 1.0);
3185 entry = gtk_entry_new();
3186 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3187 if (options->color_profile.input_name[i])
3189 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3191 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3192 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3193 gtk_widget_show(entry);
3194 color_profile_input_name_entry[i] = entry;
3196 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3197 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3198 gtk_widget_set_size_request(entry, 160, -1);
3199 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3200 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3201 gtk_widget_show(tabcomp);
3202 color_profile_input_file_entry[i] = entry;
3205 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3207 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3209 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3210 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3212 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3214 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3215 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3216 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3217 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3218 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3220 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3222 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3224 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3226 gtk_widget_show(tabcomp);
3229 /* advanced entry tab */
3230 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3232 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3234 c_options->file_ops.use_system_trash = FALSE;
3235 c_options->file_ops.no_trash = FALSE;
3239 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3241 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3243 c_options->file_ops.use_system_trash = TRUE;
3244 c_options->file_ops.no_trash = FALSE;
3248 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3250 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3252 c_options->file_ops.no_trash = TRUE;
3256 static void config_tab_behavior(GtkWidget *notebook)
3263 GtkWidget *ct_button;
3267 GtkWidget *with_rename;
3268 GtkWidget *collections_on_top;
3269 GtkWidget *hide_window_in_fullscreen;
3270 GtkWidget *checkbox;
3272 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3274 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3276 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3277 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3278 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3279 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3280 pref_checkbox_new_int(group, _("Enable Delete key"),
3281 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3283 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3284 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3286 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3287 pref_checkbox_link_sensitivity(ct_button, hbox);
3289 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3290 pref_label_new(hbox, _("Folder:"));
3292 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3293 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3294 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3295 gtk_widget_show(tabcomp);
3297 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3298 pref_checkbox_link_sensitivity(ct_button, hbox);
3300 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3301 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3302 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3303 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3304 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3305 G_CALLBACK(safe_delete_view_cb), NULL);
3306 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3307 gtk_widget_show(button);
3309 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3310 G_CALLBACK(safe_delete_clear_cb), NULL);
3311 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3312 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3313 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3315 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3316 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3318 gtk_widget_show(button);
3320 pref_spacer(group, PREF_PAD_GROUP);
3323 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3325 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3326 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3328 pref_checkbox_new_int(group, _("In place renaming"),
3329 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3331 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3332 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3334 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3335 options->marks_save, &c_options->marks_save);
3336 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3338 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3339 options->with_rename, &c_options->with_rename);
3340 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3342 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3343 options->collections_on_top, &c_options->collections_on_top);
3344 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3346 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3347 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3348 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3350 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3351 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3353 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3354 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3356 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3357 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3359 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3360 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3362 pref_spacer(group, PREF_PAD_GROUP);
3364 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3366 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3367 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3368 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3369 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3370 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3371 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3372 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3373 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3374 pref_checkbox_new_int(group, _("Play video by left click on image"),
3375 options->image_l_click_video, &c_options->image_l_click_video);
3376 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3377 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3379 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3380 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3381 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3382 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3383 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3385 pref_spacer(group, PREF_PAD_GROUP);
3387 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3389 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3390 options->override_disable_gpu, &c_options->override_disable_gpu);
3391 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3394 pref_spacer(group, PREF_PAD_GROUP);
3396 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3398 pref_spin_new_int(group, _("Debug level:"), NULL,
3399 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3401 pref_checkbox_new_int(group, _("Timer data"),
3402 options->log_window.timer_data, &c_options->log_window.timer_data);
3404 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3405 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3409 /* accelerators tab */
3410 static void config_tab_accelerators(GtkWidget *notebook)
3416 GtkWidget *scrolled;
3417 GtkWidget *accel_view;
3418 GtkCellRenderer *renderer;
3419 GtkTreeSelection *selection;
3420 GtkTreeViewColumn *column;
3422 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3424 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3426 scrolled = gtk_scrolled_window_new(NULL, NULL);
3427 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3428 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3429 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3430 gtk_widget_show(scrolled);
3432 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3434 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3435 g_object_unref(accel_store);
3436 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3437 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3439 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3441 renderer = gtk_cell_renderer_text_new();
3443 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3448 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3449 gtk_tree_view_column_set_resizable(column, TRUE);
3450 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3453 renderer = gtk_cell_renderer_accel_new();
3454 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3455 G_CALLBACK(accel_store_cleared_cb), accel_store);
3456 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3457 G_CALLBACK(accel_store_edited_cb), accel_store);
3460 g_object_set (renderer,
3462 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3465 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3470 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3471 gtk_tree_view_column_set_resizable(column, TRUE);
3472 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3474 renderer = gtk_cell_renderer_text_new();
3476 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3481 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3482 gtk_tree_view_column_set_resizable(column, TRUE);
3483 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3485 renderer = gtk_cell_renderer_text_new();
3487 column = gtk_tree_view_column_new_with_attributes("Accel",
3492 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3493 gtk_tree_view_column_set_resizable(column, TRUE);
3494 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3496 accel_store_populate();
3497 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3498 gtk_widget_show(accel_view);
3500 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3502 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3503 G_CALLBACK(accel_default_cb), accel_view);
3504 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3505 gtk_widget_show(button);
3507 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3508 G_CALLBACK(accel_reset_cb), accel_view);
3509 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3510 gtk_widget_show(button);
3513 /* toolbar main tab */
3514 static void config_tab_toolbar_main(GtkWidget *notebook)
3517 GtkWidget *toolbardata;
3520 lw = layout_window_list->data;
3522 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3524 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3525 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3526 gtk_widget_show(vbox);
3529 /* toolbar status tab */
3530 static void config_tab_toolbar_status(GtkWidget *notebook)
3533 GtkWidget *toolbardata;
3536 lw = layout_window_list->data;
3538 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3540 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3541 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3542 gtk_widget_show(vbox);
3546 static void config_tab_stereo(GtkWidget *notebook)
3554 GtkWidget *fs_button;
3555 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3557 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3559 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3560 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3562 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3563 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3564 pref_checkbox_new_int(box, _("Mirror left image"),
3565 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3566 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3567 pref_checkbox_new_int(box, _("Flip left image"),
3568 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3569 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3570 pref_checkbox_new_int(box, _("Mirror right image"),
3571 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3572 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3573 pref_checkbox_new_int(box, _("Flip right image"),
3574 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3575 pref_checkbox_new_int(group, _("Swap left and right images"),
3576 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3577 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3578 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3580 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3581 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3582 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3583 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3584 pref_checkbox_link_sensitivity(fs_button, box2);
3585 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3586 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3587 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3588 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3589 pref_checkbox_new_int(box, _("Mirror left image"),
3590 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3591 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3592 pref_checkbox_new_int(box, _("Flip left image"),
3593 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3594 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3595 pref_checkbox_new_int(box, _("Mirror right image"),
3596 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3597 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3598 pref_checkbox_new_int(box, _("Flip right image"),
3599 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3600 pref_checkbox_new_int(box2, _("Swap left and right images"),
3601 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3602 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3603 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3605 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3606 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3607 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3608 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3609 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3610 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3611 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3612 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3613 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3614 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3615 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3616 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3617 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3618 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3622 /* Main preferences window */
3623 static void config_window_create(void)
3625 GtkWidget *win_vbox;
3627 GtkWidget *notebook;
3629 GtkWidget *ct_button;
3631 if (!c_options) c_options = init_options(NULL);
3633 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3634 DEBUG_NAME(configwindow);
3635 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3636 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3637 G_CALLBACK(config_window_delete), NULL);
3638 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3639 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3640 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3642 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3643 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3644 gtk_widget_show(win_vbox);
3646 notebook = gtk_notebook_new();
3647 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3648 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3649 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3651 config_tab_general(notebook);
3652 config_tab_image(notebook);
3653 config_tab_osd(notebook);
3654 config_tab_windows(notebook);
3655 config_tab_accelerators(notebook);
3656 config_tab_files(notebook);
3657 config_tab_metadata(notebook);
3658 config_tab_keywords(notebook);
3659 config_tab_color(notebook);
3660 config_tab_stereo(notebook);
3661 config_tab_behavior(notebook);
3662 config_tab_toolbar_main(notebook);
3663 config_tab_toolbar_status(notebook);
3665 hbox = gtk_hbutton_box_new();
3666 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3667 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3668 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3669 gtk_widget_show(hbox);
3671 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3672 G_CALLBACK(config_window_help_cb), notebook);
3673 gtk_container_add(GTK_CONTAINER(hbox), button);
3674 gtk_widget_set_can_default(button, TRUE);
3675 gtk_widget_show(button);
3677 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3678 G_CALLBACK(config_window_ok_cb), NULL);
3679 gtk_container_add(GTK_CONTAINER(hbox), button);
3680 gtk_widget_set_can_default(button, TRUE);
3681 gtk_widget_grab_default(button);
3682 gtk_widget_show(button);
3686 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3687 G_CALLBACK(config_window_close_cb), NULL);
3688 gtk_container_add(GTK_CONTAINER(hbox), button);
3689 gtk_widget_set_can_default(button, TRUE);
3690 gtk_widget_show(button);
3692 if (!generic_dialog_get_alternative_button_order(configwindow))
3694 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3697 gtk_widget_show(notebook);
3699 gtk_widget_show(configwindow);
3703 *-----------------------------------------------------------------------------
3704 * config window show (public)
3705 *-----------------------------------------------------------------------------
3708 void show_config_window(void)
3712 gtk_window_present(GTK_WINDOW(configwindow));
3716 config_window_create();
3725 void show_about_window(LayoutWindow *lw)
3727 GdkPixbuf *pixbuf_logo;
3728 GdkPixbuf *pixbuf_icon;
3729 gchar *authors[1000];
3734 gchar *timezone_path;
3738 #define LINE_LENGTH 1000
3739 gchar line[LINE_LENGTH];
3741 copyright = g_string_new(NULL);
3742 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");
3744 path = path_from_utf8(TIMEZONE_DATABASE);
3745 basename = g_path_get_basename(path);
3746 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3747 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3749 cd = ZDOpenDatabase(timezone_path);
3752 copyright = g_string_append(copyright, ZDGetNotice(cd));
3753 ZDCloseDatabase(cd);
3757 g_free(timezone_path);
3761 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3762 fp = fopen(path, "r");
3765 while(fgets(line, LINE_LENGTH, fp))
3767 /* get rid of ending \n from fgets */
3768 line[strlen(line) - 1] = '\0';
3769 authors[i_authors] = g_strdup(line);
3772 authors[i_authors] = NULL;
3777 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3778 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3780 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3781 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3782 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3783 "title", _("About Geeqie"),
3785 "program-name", GQ_APPNAME,
3787 "logo", pixbuf_logo,
3788 "icon", pixbuf_icon,
3789 "website", GQ_WEBSITE,
3790 "website-label", "Website",
3791 "comments", comment,
3793 "translator-credits", _("translator-credits"),
3794 "wrap-license", TRUE,
3795 "license", copyright->str,
3798 g_string_free(copyright, TRUE);
3801 while(n < i_authors)
3811 static void image_overlay_set_text_colours()
3813 c_options->image_overlay.text_red = options->image_overlay.text_red;
3814 c_options->image_overlay.text_green = options->image_overlay.text_green;
3815 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3816 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3817 c_options->image_overlay.background_red = options->image_overlay.background_red;
3818 c_options->image_overlay.background_green = options->image_overlay.background_green;
3819 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3820 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3824 *-----------------------------------------------------------------------------
3825 * timezone database routines
3826 *-----------------------------------------------------------------------------
3829 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3831 GError *error = NULL;
3833 gchar *tmp_filename;
3835 if (!g_cancellable_is_cancelled(tz->cancellable))
3837 generic_dialog_close(tz->gd);
3841 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3843 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3844 move_file(tmp_filename, tz->timezone_database_user);
3845 g_free(tmp_filename);
3849 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3852 g_file_delete(tz->tmp_g_file, NULL, &error);
3853 g_object_unref(tz->tmp_g_file);
3854 tz->tmp_g_file = NULL;
3855 g_object_unref(tz->cancellable);
3856 g_object_unref(tz->timezone_database_gq);
3859 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3863 if (!g_cancellable_is_cancelled(tz->cancellable))
3865 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3869 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3873 g_cancellable_cancel(tz->cancellable);
3876 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3879 GError *error = NULL;
3880 GFileIOStream *io_stream;
3887 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3891 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3892 log_printf("Error: Download timezone database failed:\n%s", error->message);
3893 g_error_free(error);
3894 g_object_unref(tz->tmp_g_file);
3898 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3900 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3902 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3904 tz->progress = gtk_progress_bar_new();
3905 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3906 gtk_widget_show(tz->progress);
3908 gtk_widget_show(tz->gd->dialog);
3909 tz->cancellable = g_cancellable_new();
3910 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);
3912 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3915 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */