2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
381 options->dnd_default_action = c_options->dnd_default_action;
383 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
384 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
385 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
386 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
387 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
388 options->metadata.confirm_write = c_options->metadata.confirm_write;
389 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
390 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
391 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
392 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
393 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
394 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
395 options->metadata.write_orientation = c_options->metadata.write_orientation;
396 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
397 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
398 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
399 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
400 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
401 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
402 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
403 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
411 options->stereo.fixed_w = c_options->stereo.fixed_w;
412 options->stereo.fixed_h = c_options->stereo.fixed_h;
413 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
414 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
415 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
416 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
418 options->info_keywords.height = c_options->info_keywords.height;
419 options->info_title.height = c_options->info_title.height;
420 options->info_comment.height = c_options->info_comment.height;
421 options->info_rating.height = c_options->info_rating.height;
423 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
424 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
426 options->marks_save = c_options->marks_save;
427 options->with_rename = c_options->with_rename;
428 options->collections_on_top = c_options->collections_on_top;
429 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
431 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
433 options->star_rating.star = c_options->star_rating.star;
434 options->star_rating.rejected = c_options->star_rating.rejected;
436 set_debug_level(debug_c);
440 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
442 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
443 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
445 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
446 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
447 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
449 options->color_profile.render_intent = c_options->color_profile.render_intent;
454 options->mouse_button_8 = c_options->mouse_button_8;
455 options->mouse_button_9 = c_options->mouse_button_9;
457 options->override_disable_gpu = c_options->override_disable_gpu;
459 config_tab_keywords_save();
461 image_options_sync();
466 layout_refresh(NULL);
469 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
471 toolbar_apply(TOOLBAR_MAIN);
472 toolbar_apply(TOOLBAR_STATUS);
476 *-----------------------------------------------------------------------------
477 * config window main button callbacks (private)
478 *-----------------------------------------------------------------------------
481 static void config_window_close_cb(GtkWidget *widget, gpointer data)
483 gtk_widget_destroy(configwindow);
488 static void config_window_help_cb(GtkWidget *widget, gpointer data)
490 GtkWidget *notebook = data;
493 static gchar *html_section[] =
495 "GuideOptionsGeneral.html",
496 "GuideOptionsImage.html",
497 "GuideOptionsOSD.html",
498 "GuideOptionsWindow.html",
499 "GuideOptionsKeyboard.html",
500 "GuideOptionsFiltering.html",
501 "GuideOptionsMetadata.html",
502 "GuideOptionsKeywords.html",
503 "GuideOptionsColor.html",
504 "GuideOptionsStereo.html",
505 "GuideOptionsBehavior.html",
506 "GuideOptionsToolbar.html",
507 "GuideOptionsToolbar.html"
510 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
511 help_window_show(html_section[i]);
514 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
516 config_window_close_cb(NULL, NULL);
520 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
523 lw = layout_window_list->data;
525 config_window_apply();
526 layout_util_sync(lw);
527 save_options(options);
528 config_window_close_cb(NULL, NULL);
532 *-----------------------------------------------------------------------------
533 * config window setup (private)
534 *-----------------------------------------------------------------------------
537 static void quality_menu_cb(GtkWidget *combo, gpointer data)
541 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
545 *option = GDK_INTERP_NEAREST;
548 *option = GDK_INTERP_TILES;
551 *option = GDK_INTERP_BILINEAR;
556 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
560 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
564 *option = DND_ACTION_ASK;
567 *option = DND_ACTION_COPY;
570 *option = DND_ACTION_MOVE;
574 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
578 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
590 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
591 guint option, guint *option_c)
598 pref_table_label(table, column, row, text, 0.0);
600 combo = gtk_combo_box_text_new();
602 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
603 if (option == GDK_INTERP_NEAREST) current = 0;
604 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
605 if (option == GDK_INTERP_TILES) current = 1;
606 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
607 if (option == GDK_INTERP_BILINEAR) current = 2;
609 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
611 g_signal_connect(G_OBJECT(combo), "changed",
612 G_CALLBACK(quality_menu_cb), option_c);
614 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
615 gtk_widget_show(combo);
618 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
625 pref_table_label(table, column, row, text, 0.0);
627 combo = gtk_combo_box_text_new();
629 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
630 if (option == DND_ACTION_ASK) current = 0;
631 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
632 if (option == DND_ACTION_COPY) current = 1;
633 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
634 if (option == DND_ACTION_MOVE) current = 2;
636 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
638 g_signal_connect(G_OBJECT(combo), "changed",
639 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
641 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
642 gtk_widget_show(combo);
645 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
646 gint option, gint *option_c)
653 pref_table_label(table, column, row, text, 0.0);
655 combo = gtk_combo_box_text_new();
657 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
658 if (option == PRIMARY) current = 0;
659 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
660 if (option == CLIPBOARD) current = 1;
662 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
664 g_signal_connect(G_OBJECT(combo), "changed",
665 G_CALLBACK(clipboard_selection_menu_cb), option_c);
667 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
668 gtk_widget_show(combo);
671 typedef struct _UseableMouseItems UseableMouseItems;
672 struct _UseableMouseItems
674 gchar *name; /* GtkActionEntry terminology */
679 static const UseableMouseItems useable_mouse_items[] = {
681 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
682 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
683 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
684 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
685 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
686 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
687 {"Home", N_("Home"), GTK_STOCK_HOME},
688 {"Up", N_("Up"), GTK_STOCK_GO_UP},
689 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
690 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
691 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
692 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
693 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
694 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
695 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
696 {"Search", N_("Search"), GTK_STOCK_FIND},
697 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
698 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
699 {"Copy", N_("Copy"), GTK_STOCK_COPY},
700 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
701 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
702 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
703 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
704 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
705 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
706 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
707 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
708 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
709 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
710 {"Print", N_("Print"), GTK_STOCK_PRINT},
711 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
712 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
713 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
714 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
715 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
716 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
717 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
718 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
719 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
720 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
721 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
722 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
723 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
724 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
725 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
726 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
727 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
728 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
729 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
730 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
731 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
732 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
733 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
734 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
735 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
736 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
737 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
738 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
739 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
740 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
741 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
742 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
743 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
744 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
745 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
746 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
747 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
748 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
749 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
750 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
754 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
756 gchar **option = data;
759 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
761 const UseableMouseItems *list = useable_mouse_items;
765 if (g_strcmp0(list->label, label) == 0)
773 *option = g_strdup(list->name);
777 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
778 gchar *option, gchar **option_c)
786 pref_table_label(table, column, row, text, 0.0);
788 combo = gtk_combo_box_text_new();
790 const UseableMouseItems *list = useable_mouse_items;
794 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
795 if (g_strcmp0(list->name, option) == 0)
803 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
805 g_signal_connect(G_OBJECT(combo), "changed",
806 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
808 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
809 gtk_widget_show(combo);
812 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
816 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
819 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
821 c_options->thumbnails.max_width = thumb_size_list[n].w;
822 c_options->thumbnails.max_height = thumb_size_list[n].h;
826 c_options->thumbnails.max_width = options->thumbnails.max_width;
827 c_options->thumbnails.max_height = options->thumbnails.max_height;
831 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
837 c_options->thumbnails.max_width = options->thumbnails.max_width;
838 c_options->thumbnails.max_height = options->thumbnails.max_height;
840 pref_table_label(table, column, row, text, 0.0);
842 combo = gtk_combo_box_text_new();
845 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
850 w = thumb_size_list[i].w;
851 h = thumb_size_list[i].h;
853 buf = g_strdup_printf("%d x %d", w, h);
854 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
857 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
864 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
865 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
871 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
872 g_signal_connect(G_OBJECT(combo), "changed",
873 G_CALLBACK(thumb_size_menu_cb), NULL);
875 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
876 gtk_widget_show(combo);
879 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
883 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
887 *option = PR_STEREO_NONE;
890 *option = PR_STEREO_ANAGLYPH_RC;
893 *option = PR_STEREO_ANAGLYPH_GM;
896 *option = PR_STEREO_ANAGLYPH_YB;
899 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
902 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
905 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
908 *option = PR_STEREO_ANAGLYPH_DB_RC;
911 *option = PR_STEREO_ANAGLYPH_DB_GM;
914 *option = PR_STEREO_ANAGLYPH_DB_YB;
917 *option = PR_STEREO_HORIZ;
920 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
923 *option = PR_STEREO_VERT;
926 *option = PR_STEREO_VERT | PR_STEREO_HALF;
929 *option = PR_STEREO_FIXED;
934 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
935 gint option, gint *option_c, gboolean add_fixed)
942 pref_table_label(table, column, row, text, 0.0);
944 combo = gtk_combo_box_text_new();
946 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
948 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
949 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
950 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
951 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
952 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
953 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
954 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
955 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
956 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
957 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
958 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
959 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
960 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
961 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
962 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
963 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
964 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
965 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
967 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
968 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
969 if (option & PR_STEREO_HORIZ)
972 if (option & PR_STEREO_HALF) current = 11;
975 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
976 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
977 if (option & PR_STEREO_VERT)
980 if (option & PR_STEREO_HALF) current = 13;
985 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
986 if (option & PR_STEREO_FIXED) current = 14;
989 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
991 g_signal_connect(G_OBJECT(combo), "changed",
992 G_CALLBACK(stereo_mode_menu_cb), option_c);
994 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
995 gtk_widget_show(combo);
998 static void video_menu_cb(GtkWidget *combo, gpointer data)
1000 gchar **option = data;
1002 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1006 static void video_menu_populate(gpointer data, gpointer user_data)
1008 GtkWidget *combo = user_data;
1009 EditorDescription *ed = data;
1011 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1014 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1015 gchar *option, gchar **option_c)
1019 /* use lists since they are sorted */
1020 GList *eds = editor_list_get();
1024 pref_table_label(table, column, row, text, 0.0);
1026 combo = gtk_combo_box_text_new();
1027 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1028 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1030 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1032 g_signal_connect(G_OBJECT(combo), "changed",
1033 G_CALLBACK(video_menu_cb), option_c);
1035 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1036 gtk_widget_show(combo);
1039 static void filter_store_populate(void)
1043 if (!filter_store) return;
1045 gtk_list_store_clear(filter_store);
1047 work = filter_get_list();
1056 gtk_list_store_append(filter_store, &iter);
1057 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1061 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1062 gchar *new_text, gpointer data)
1064 GtkWidget *model = data;
1065 FilterEntry *fe = data;
1069 if (!new_text || strlen(new_text) < 1) return;
1071 tpath = gtk_tree_path_new_from_string(path_str);
1072 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1073 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1075 g_free(fe->extensions);
1076 fe->extensions = g_strdup(new_text);
1078 gtk_tree_path_free(tpath);
1082 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1083 gchar *new_text, gpointer data)
1085 GtkWidget *model = data;
1086 FilterEntry *fe = data;
1091 if (!new_text || !new_text[0]) return;
1093 tpath = gtk_tree_path_new_from_string(path_str);
1094 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1095 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1097 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1099 if (strcmp(new_text, _(format_class_list[i])) == 0)
1106 gtk_tree_path_free(tpath);
1110 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1111 gchar *new_text, gpointer data)
1113 GtkWidget *model = data;
1118 if (!new_text || !new_text[0]) return;
1120 tpath = gtk_tree_path_new_from_string(path_str);
1121 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1122 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1124 g_free(fe->description);
1125 fe->description = g_strdup(new_text);
1127 gtk_tree_path_free(tpath);
1130 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1131 gchar *path_str, gpointer data)
1133 GtkWidget *model = data;
1138 tpath = gtk_tree_path_new_from_string(path_str);
1139 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1140 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1142 fe->enabled = !fe->enabled;
1144 gtk_tree_path_free(tpath);
1148 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1149 gchar *path_str, gpointer data)
1151 GtkWidget *model = data;
1156 tpath = gtk_tree_path_new_from_string(path_str);
1157 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1158 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1160 fe->writable = !fe->writable;
1161 if (fe->writable) fe->allow_sidecar = FALSE;
1163 gtk_tree_path_free(tpath);
1167 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1168 gchar *path_str, gpointer data)
1170 GtkWidget *model = data;
1175 tpath = gtk_tree_path_new_from_string(path_str);
1176 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1177 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1179 fe->allow_sidecar = !fe->allow_sidecar;
1180 if (fe->allow_sidecar) fe->writable = FALSE;
1182 gtk_tree_path_free(tpath);
1186 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1187 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1191 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1193 switch (GPOINTER_TO_INT(data))
1196 g_object_set(GTK_CELL_RENDERER(cell),
1197 "active", fe->enabled, NULL);
1200 g_object_set(GTK_CELL_RENDERER(cell),
1201 "text", fe->extensions, NULL);
1203 case FE_DESCRIPTION:
1204 g_object_set(GTK_CELL_RENDERER(cell),
1205 "text", fe->description, NULL);
1208 g_object_set(GTK_CELL_RENDERER(cell),
1209 "text", _(format_class_list[fe->file_class]), NULL);
1212 g_object_set(GTK_CELL_RENDERER(cell),
1213 "active", fe->writable, NULL);
1215 case FE_ALLOW_SIDECAR:
1216 g_object_set(GTK_CELL_RENDERER(cell),
1217 "active", fe->allow_sidecar, NULL);
1222 static gboolean filter_add_scroll(gpointer data)
1226 GtkCellRenderer *cell;
1227 GtkTreeViewColumn *column;
1230 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1231 path = gtk_tree_path_new_from_indices(rows-1, -1);
1233 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1235 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1236 cell = g_list_last(list_cells)->data;
1238 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1239 path, column, FALSE, 0.0, 0.0 );
1240 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1241 path, column, cell, TRUE);
1243 gtk_tree_path_free(path);
1244 g_list_free(list_cells);
1249 static void filter_add_cb(GtkWidget *widget, gpointer data)
1251 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1252 filter_store_populate();
1254 g_idle_add((GSourceFunc)filter_add_scroll, data);
1257 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1259 GtkWidget *filter_view = data;
1260 GtkTreeSelection *selection;
1264 if (!filter_store) return;
1265 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1266 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1267 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1270 filter_remove_entry(fe);
1272 filter_store_populate();
1275 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1279 GtkTreeViewColumn *column;
1281 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1282 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1283 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1285 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1289 gtk_tree_path_free(path);
1294 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1297 filter_add_defaults();
1299 filter_store_populate();
1301 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1304 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1306 /* no op, only so cancel button appears */
1309 static void filter_default_cb(GtkWidget *widget, gpointer data)
1313 gd = generic_dialog_new(_("Reset filters"),
1314 "reset_filter", widget, TRUE,
1315 dummy_cancel_cb, data);
1316 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1317 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1318 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1319 gtk_widget_show(gd->dialog);
1322 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1324 GtkWidget *frame = data;
1326 gtk_widget_set_sensitive(frame,
1327 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1330 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1332 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1335 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1337 file_util_trash_clear();
1340 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1344 gd = generic_dialog_new(_("Clear trash"),
1345 "clear_trash", widget, TRUE,
1346 dummy_cancel_cb, NULL);
1347 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1348 _("This will remove the trash contents."), FALSE);
1349 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1350 entry = gtk_entry_new();
1351 gtk_widget_set_can_focus(entry, FALSE);
1352 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1353 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1354 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1355 gtk_widget_show(entry);
1356 gtk_widget_show(gd->dialog);
1359 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1361 GtkWidget *pTextView;
1362 GtkTextBuffer *pTextBuffer;
1366 pTextView = GTK_WIDGET(data);
1368 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1369 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1370 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1372 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1373 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1376 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1378 GtkTextView *text_view = data;
1379 GtkTextBuffer *buffer;
1381 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1382 if (!configwindow) return;
1384 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1385 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1388 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1392 gd = generic_dialog_new(_("Reset image overlay template string"),
1393 "reset_image_overlay_template_string", widget, TRUE,
1394 dummy_cancel_cb, data);
1395 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1396 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1397 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1398 gtk_widget_show(gd->dialog);
1401 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1403 help_window_show("GuideOptionsOSD.html");
1406 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1408 #if GTK_CHECK_VERSION(3,4,0)
1411 PangoFontDescription *font_desc;
1413 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1414 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1416 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1418 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1419 font = pango_font_description_to_string(font_desc);
1420 g_free(c_options->image_overlay.font);
1421 c_options->image_overlay.font = g_strdup(font);
1425 gtk_widget_destroy(dialog);
1429 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1430 c_options->image_overlay.font = g_strdup(font);
1434 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1437 #if GTK_CHECK_VERSION(3,4,0)
1440 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1441 colour.red = options->image_overlay.text_red;
1442 colour.green = options->image_overlay.text_green;
1443 colour.blue = options->image_overlay.text_blue;
1444 colour.alpha = options->image_overlay.text_alpha;
1445 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1446 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1448 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1450 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1451 c_options->image_overlay.text_red = colour.red*255;
1452 c_options->image_overlay.text_green = colour.green*255;
1453 c_options->image_overlay.text_blue = colour.blue*255;
1454 c_options->image_overlay.text_alpha = colour.alpha*255;
1456 gtk_widget_destroy(dialog);
1459 GtkColorSelection *colorsel;
1461 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1462 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1463 colour.red = options->image_overlay.text_red*257;
1464 colour.green = options->image_overlay.text_green*257;
1465 colour.blue = options->image_overlay.text_blue*257;
1466 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1467 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1468 gtk_color_selection_set_current_color(colorsel, &colour);
1469 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1471 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1473 gtk_color_selection_get_current_color(colorsel, &colour);
1474 c_options->image_overlay.text_red = colour.red/257;
1475 c_options->image_overlay.text_green = colour.green/257;
1476 c_options->image_overlay.text_blue = colour.blue/257;
1477 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1479 gtk_widget_destroy (dialog);
1484 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1487 #if GTK_CHECK_VERSION(3,4,0)
1490 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1491 colour.red = options->image_overlay.background_red;
1492 colour.green = options->image_overlay.background_green;
1493 colour.blue = options->image_overlay.background_blue;
1494 colour.alpha = options->image_overlay.background_alpha;
1495 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1496 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1498 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1500 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1501 c_options->image_overlay.background_red = colour.red*255;
1502 c_options->image_overlay.background_green = colour.green*255;
1503 c_options->image_overlay.background_blue = colour.blue*255;
1504 c_options->image_overlay.background_alpha = colour.alpha*255;
1506 gtk_widget_destroy(dialog);
1509 GtkColorSelection *colorsel;
1511 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1512 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1513 colour.red = options->image_overlay.background_red*257;
1514 colour.green = options->image_overlay.background_green*257;
1515 colour.blue = options->image_overlay.background_blue*257;
1516 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1517 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1518 gtk_color_selection_set_current_color(colorsel, &colour);
1519 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1521 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1523 gtk_color_selection_get_current_color(colorsel, &colour);
1524 c_options->image_overlay.background_red = colour.red/257;
1525 c_options->image_overlay.background_green = colour.green/257;
1526 c_options->image_overlay.background_blue = colour.blue/257;
1527 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1529 gtk_widget_destroy(dialog);
1533 static void accel_store_populate(void)
1536 GList *groups, *actions;
1538 const gchar *accel_path;
1542 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1544 gtk_tree_store_clear(accel_store);
1545 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1547 g_assert(lw && lw->ui_manager);
1548 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1551 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1554 action = GTK_ACTION(actions->data);
1555 accel_path = gtk_action_get_accel_path(action);
1556 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1558 gchar *label, *label2, *tooltip, *accel;
1559 g_object_get(action,
1560 "tooltip", &tooltip,
1564 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1570 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1574 gtk_tree_store_append(accel_store, &iter, NULL);
1575 gtk_tree_store_set(accel_store, &iter,
1578 AE_TOOLTIP, tooltip ? tooltip : "",
1579 AE_ACCEL, accel_path,
1587 actions = actions->next;
1590 groups = groups->next;
1594 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1599 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1601 gchar *accel1 = data;
1606 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1608 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1609 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1611 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1613 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1614 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1623 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1625 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1629 GtkAccelKey old_key, key;
1630 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1632 gtk_tree_model_get_iter(model, &iter, path);
1633 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1635 /* test if the accelerator can be stored without conflicts*/
1636 gtk_accel_map_lookup_entry(accel_path, &old_key);
1638 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1639 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1640 gtk_accel_map_lookup_entry(accel_path, &key);
1642 /* restore the original for now, the key will be really changed when the changes are confirmed */
1643 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1645 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1646 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1648 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1649 gtk_tree_path_free(path);
1653 static gboolean accel_default_scroll(GtkTreeView *data)
1657 GtkTreeViewColumn *column;
1659 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1660 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1661 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1663 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1667 gtk_tree_path_free(path);
1672 static void accel_default_cb(GtkWidget *widget, gpointer data)
1674 accel_store_populate();
1676 g_idle_add((GSourceFunc)accel_default_scroll, data);
1679 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1681 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1684 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1687 gchar *accel_path, *accel;
1689 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1690 gtk_accel_map_lookup_entry(accel_path, &key);
1691 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1693 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1695 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1700 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1702 GtkTreeSelection *selection;
1704 if (!accel_store) return;
1705 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1706 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1711 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1715 GtkWidget *scrolled;
1716 GtkWidget *viewport;
1718 scrolled = gtk_scrolled_window_new(NULL, NULL);
1719 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1720 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1721 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1722 label = gtk_label_new(title);
1723 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1724 gtk_widget_show(scrolled);
1726 viewport = gtk_viewport_new(NULL, NULL);
1727 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1728 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1729 gtk_widget_show(viewport);
1731 vbox = gtk_vbox_new(FALSE, 0);
1732 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1733 gtk_widget_show(vbox);
1738 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1740 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1742 c_options->thumbnails.spec_standard =TRUE;
1743 c_options->thumbnails.cache_into_dirs = FALSE;
1747 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1749 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1751 c_options->thumbnails.spec_standard =FALSE;
1752 c_options->thumbnails.cache_into_dirs = FALSE;
1756 static void cache_local_cb(GtkWidget *widget, gpointer data)
1758 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1760 c_options->thumbnails.cache_into_dirs = TRUE;
1761 c_options->thumbnails.spec_standard =FALSE;
1765 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1766 GdkEvent *event, gpointer userdata)
1768 if (pos == GTK_ENTRY_ICON_PRIMARY)
1770 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1774 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1778 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1779 GdkEvent *event, gpointer userdata)
1781 gchar *rating_symbol;
1783 if (pos == GTK_ENTRY_ICON_PRIMARY)
1785 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1786 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1787 g_free(rating_symbol);
1791 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1792 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1793 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1797 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1798 GdkEvent *event, gpointer userdata)
1800 gchar *rating_symbol;
1802 if (pos == GTK_ENTRY_ICON_PRIMARY)
1804 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1805 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1806 g_free(rating_symbol);
1810 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1811 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1812 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1816 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1818 GtkContainer *hbox = data;
1819 GString *str = g_string_new(NULL);
1820 GtkEntry *hex_code_entry;
1821 gchar *hex_code_full;
1824 guint64 hex_value = 0;
1826 list = gtk_container_get_children(hbox);
1828 hex_code_entry = g_list_nth_data(list, 2);
1829 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1831 hex_code = g_strsplit(hex_code_full, "+", 2);
1832 if (hex_code[0] && hex_code[1])
1834 hex_value = strtoull(hex_code[1], NULL, 16);
1836 if (!hex_value || hex_value > 0x10FFFF)
1838 hex_value = 0x003F; // Unicode 'Question Mark'
1840 str = g_string_append_unichar(str, (gunichar)hex_value);
1841 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1843 g_strfreev(hex_code);
1844 g_string_free(str, TRUE);
1845 g_free(hex_code_full);
1850 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1852 guint64 star_symbol;
1854 star_symbol = star_rating_symbol_test(widget, data);
1855 c_options->star_rating.star = star_symbol;
1858 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1860 guint64 rejected_symbol;
1862 rejected_symbol = star_rating_symbol_test(widget, data);
1863 c_options->star_rating.rejected = rejected_symbol;
1866 /* general options tab */
1867 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1868 typedef struct _TZData TZData;
1872 GCancellable *cancellable;
1874 GtkWidget *progress;
1876 GFile *timezone_database_gq;
1877 gchar *timezone_database_user;
1880 static void config_tab_general(GtkWidget *notebook)
1885 GtkWidget *group_frame;
1886 GtkWidget *subgroup;
1888 GtkWidget *ct_button;
1891 gint hours, minutes, remainder;
1893 GtkWidget *star_rating_entry;
1895 gchar *rating_symbol;
1898 GNetworkMonitor *net_mon;
1899 GSocketConnectable *geeqie_org;
1900 gboolean internet_available;
1903 vbox = scrolled_notebook_page(notebook, _("General"));
1905 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1907 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1908 add_thumb_size_menu(table, 0, 0, _("Size:"));
1909 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1911 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1912 pref_label_new(hbox, _("Custom size: "));
1913 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1914 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1916 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1917 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1919 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1920 pref_checkbox_link_sensitivity(ct_button, subgroup);
1922 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1923 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1924 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1925 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1926 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1927 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1928 G_CALLBACK(cache_geeqie_cb), NULL);
1930 group_frame = pref_frame_new(subgroup, TRUE,
1931 _("Store thumbnails local to image folder (non-standard)"),
1932 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1933 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1934 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1935 G_CALLBACK(cache_local_cb), NULL);
1937 group_frame = pref_frame_new(subgroup, TRUE,
1938 _("Use standard thumbnail style and cache, shared with other applications"),
1939 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1940 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1941 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1942 G_CALLBACK(cache_standard_cb), NULL);
1944 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1945 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1947 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1949 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1950 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1952 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1953 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1954 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1956 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1957 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1960 pref_spacer(group, PREF_PAD_GROUP);
1962 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1964 c_options->star_rating.star = options->star_rating.star;
1965 c_options->star_rating.rejected = options->star_rating.rejected;
1967 str = g_string_new(NULL);
1968 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1969 pref_label_new(hbox, "Star character: ");
1970 str = g_string_append_unichar(str, options->star_rating.star);
1971 pref_label_new(hbox, g_strdup(str->str));
1972 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1973 star_rating_entry = gtk_entry_new();
1974 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1975 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1976 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1977 gtk_widget_show(star_rating_entry);
1978 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1979 G_CALLBACK(star_rating_star_test_cb), hbox);
1980 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1981 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1982 gtk_widget_show(button);
1983 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."));
1984 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1985 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1986 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1987 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1988 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1989 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1990 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1991 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1992 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1993 G_CALLBACK(star_rating_star_icon_cb),
1996 g_string_free(str, TRUE);
1997 g_free(rating_symbol);
1999 str = g_string_new(NULL);
2000 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2001 pref_label_new(hbox, "Rejected character: ");
2002 str = g_string_append_unichar(str, options->star_rating.rejected);
2003 pref_label_new(hbox, g_strdup(str->str));
2004 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2005 star_rating_entry = gtk_entry_new();
2006 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2007 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2008 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2009 gtk_widget_show(star_rating_entry);
2010 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2011 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2012 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2013 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2014 gtk_widget_show(button);
2015 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."));
2016 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2017 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2018 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2019 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2020 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2021 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2022 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2023 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2024 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2025 G_CALLBACK(star_rating_rejected_icon_cb),
2028 g_string_free(str, TRUE);
2029 g_free(rating_symbol);
2031 pref_spacer(group, PREF_PAD_GROUP);
2033 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2035 c_options->slideshow.delay = options->slideshow.delay;
2036 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2037 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2038 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2039 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2040 SLIDESHOW_SUBSECOND_PRECISION;
2042 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2044 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2046 options->slideshow.delay ? hours : 0.0,
2047 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2048 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2049 spin = pref_spin_new(hbox, ":" , NULL,
2051 options->slideshow.delay ? minutes: 0.0,
2052 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2053 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2054 spin = pref_spin_new(hbox, ":", NULL,
2055 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2056 options->slideshow.delay ? seconds : 10.0,
2057 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2058 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2060 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2061 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2063 pref_spacer(group, PREF_PAD_GROUP);
2065 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2067 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2068 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2069 pref_checkbox_new_int(group, _("Preload next image"),
2070 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2072 pref_checkbox_new_int(group, _("Refresh on file change"),
2073 options->update_on_time_change, &c_options->update_on_time_change);
2076 pref_spacer(group, PREF_PAD_GROUP);
2078 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2080 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2081 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2082 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2084 pref_spacer(group, PREF_PAD_GROUP);
2086 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2087 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2088 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2089 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2091 options->info_keywords.height, &c_options->info_keywords.height);
2092 pref_spin_new_int(hbox, _("Title:"), NULL,
2094 options->info_title.height, &c_options->info_title.height);
2095 pref_spin_new_int(hbox, _("Comment:"), NULL,
2097 options->info_comment.height, &c_options->info_comment.height);
2098 pref_spin_new_int(hbox, _("Rating:"), NULL,
2100 options->info_rating.height, &c_options->info_rating.height);
2102 pref_spacer(group, PREF_PAD_GROUP);
2104 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2106 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2107 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2109 pref_spacer(group, PREF_PAD_GROUP);
2111 net_mon = g_network_monitor_get_default();
2112 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2113 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2114 g_object_unref(geeqie_org);
2116 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2117 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2119 if (!internet_available)
2121 gtk_widget_set_sensitive(group, FALSE);
2124 tz = g_new0(TZData, 1);
2126 path = path_from_utf8(TIMEZONE_DATABASE);
2127 basename = g_path_get_basename(path);
2128 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2132 if (isfile(tz->timezone_database_user))
2134 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2138 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2141 if (!internet_available)
2143 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"));
2147 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"));
2149 gtk_widget_show(button);
2151 pref_spacer(group, PREF_PAD_GROUP);
2153 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2155 help_search_engine_entry = gtk_entry_new();
2156 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2157 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2158 gtk_widget_show(help_search_engine_entry);
2160 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"));
2162 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2163 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2164 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2165 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2166 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2167 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2168 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2169 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2170 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2171 G_CALLBACK(help_search_engine_entry_icon_cb),
2172 help_search_engine_entry);
2176 static void config_tab_image(GtkWidget *notebook)
2181 GtkWidget *ct_button;
2182 GtkWidget *enlargement_button;
2185 GtkWidget *two_pass;
2186 GtkWidget *gpu_accel;
2188 vbox = scrolled_notebook_page(notebook, _("Image"));
2190 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2192 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2193 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2194 if (options->image.use_clutter_renderer && !options->disable_gpu)
2196 gtk_widget_set_sensitive(table, FALSE);
2200 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2201 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2202 if (options->disable_gpu && !options->override_disable_gpu)
2204 gtk_widget_set_sensitive(gpu_accel, FALSE);
2208 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2209 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2210 if (options->image.use_clutter_renderer && !options->disable_gpu)
2212 gtk_widget_set_sensitive(two_pass, FALSE);
2215 c_options->image.zoom_increment = options->image.zoom_increment;
2216 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2217 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2218 G_CALLBACK(zoom_increment_cb), NULL);
2219 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2221 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2223 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2224 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2225 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2226 spin = pref_spin_new_int(hbox, NULL, NULL,
2228 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2229 pref_checkbox_link_sensitivity(enlargement_button, spin);
2230 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."));
2232 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2233 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2234 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2235 spin = pref_spin_new_int(hbox, NULL, NULL,
2237 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2238 pref_checkbox_link_sensitivity(ct_button, spin);
2239 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."));
2241 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2243 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2244 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2246 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2247 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2249 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2250 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2252 c_options->image.border_color = options->image.border_color;
2254 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2255 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2257 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2258 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2260 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2261 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2263 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2265 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2266 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2270 static void config_tab_windows(GtkWidget *notebook)
2276 GtkWidget *ct_button;
2279 vbox = scrolled_notebook_page(notebook, _("Windows"));
2281 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2283 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2284 options->save_window_positions, &c_options->save_window_positions);
2286 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2287 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2288 pref_checkbox_link_sensitivity(ct_button, button);
2290 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2291 options->tools_restore_state, &c_options->tools_restore_state);
2293 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2294 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2296 pref_checkbox_new_int(group, _("Show window IDs"),
2297 options->show_window_ids, &c_options->show_window_ids);
2299 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2301 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2302 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2304 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2305 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2306 options->image.limit_window_size, &c_options->image.limit_window_size);
2307 spin = pref_spin_new_int(hbox, NULL, NULL,
2309 options->image.max_window_size, &c_options->image.max_window_size);
2310 pref_checkbox_link_sensitivity(ct_button, spin);
2312 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2314 c_options->fullscreen.screen = options->fullscreen.screen;
2315 c_options->fullscreen.above = options->fullscreen.above;
2316 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2317 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2318 gtk_widget_show(hbox);
2320 pref_checkbox_new_int(group, _("Smooth image flip"),
2321 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2322 pref_checkbox_new_int(group, _("Disable screen saver"),
2323 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2326 #define PRE_FORMATTED_COLUMNS 5
2327 static void config_tab_osd(GtkWidget *notebook)
2333 GtkWidget *image_overlay_template_view;
2334 GtkWidget *scrolled;
2335 GtkWidget *scrolled_pre_formatted;
2336 GtkTextBuffer *buffer;
2338 GtkWidget *subgroup;
2340 vbox = scrolled_notebook_page(notebook, _("OSD"));
2342 image_overlay_template_view = gtk_text_view_new();
2344 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2346 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2348 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2349 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2350 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2351 gtk_widget_show(scrolled_pre_formatted);
2352 gtk_widget_show(subgroup);
2354 pref_line(group, PREF_PAD_GAP);
2356 pref_label_new(group, _("Image overlay template"));
2358 scrolled = gtk_scrolled_window_new(NULL, NULL);
2359 gtk_widget_set_size_request(scrolled, 200, 150);
2360 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2361 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2362 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2363 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2364 gtk_widget_show(scrolled);
2366 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2367 _("Extensive formatting options are shown in the Help file"));
2369 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2370 gtk_widget_show(image_overlay_template_view);
2372 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2374 #if GTK_CHECK_VERSION(3,4,0)
2375 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2376 G_CALLBACK(image_overlay_set_font_cb), notebook);
2378 button = gtk_font_button_new();
2379 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2380 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2381 g_signal_connect(G_OBJECT(button), "font-set",
2382 G_CALLBACK(image_overlay_set_font_cb),NULL);
2384 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2385 gtk_widget_show(button);
2387 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2388 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2389 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2390 gtk_widget_show(button);
2392 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2393 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2394 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2395 gtk_widget_show(button);
2396 image_overlay_set_text_colours();
2398 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2399 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2400 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2401 gtk_widget_show(button);
2403 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2404 G_CALLBACK(image_overlay_help_cb), NULL);
2405 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2406 gtk_widget_show(button);
2408 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2409 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2410 g_signal_connect(G_OBJECT(buffer), "changed",
2411 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2413 pref_line(group, PREF_PAD_GAP);
2415 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2416 hbox = gtk_hbox_new(FALSE, 0);
2417 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2418 gtk_widget_show(hbox);
2419 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2420 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2421 gtk_widget_show(label);
2422 pref_spacer(group,TRUE);
2424 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2425 hbox = gtk_hbox_new(FALSE, 0);
2426 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2427 gtk_widget_show(hbox);
2428 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2429 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2430 gtk_widget_show(label);
2431 pref_spacer(group,TRUE);
2433 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2434 hbox = gtk_hbox_new(FALSE, 0);
2435 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2436 gtk_widget_show(hbox);
2437 label = gtk_label_new(_("%path:39%"));
2438 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2439 gtk_widget_show(label);
2440 pref_spacer(group,TRUE);
2442 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2443 hbox = gtk_hbox_new(FALSE, 0);
2444 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2445 gtk_widget_show(hbox);
2446 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%"));
2447 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2448 gtk_widget_show(label);
2449 pref_spacer(group,TRUE);
2451 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2452 hbox = gtk_hbox_new(FALSE, 0);
2453 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2454 gtk_widget_show(hbox);
2455 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2456 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2457 gtk_widget_show(label);
2460 static GtkTreeModel *create_class_model(void)
2462 GtkListStore *model;
2466 /* create list store */
2467 model = gtk_list_store_new(1, G_TYPE_STRING);
2468 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2470 gtk_list_store_append(model, &iter);
2471 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2473 return GTK_TREE_MODEL (model);
2478 static void config_tab_files(GtkWidget *notebook)
2485 GtkWidget *ct_button;
2486 GtkWidget *scrolled;
2487 GtkWidget *filter_view;
2488 GtkCellRenderer *renderer;
2489 GtkTreeSelection *selection;
2490 GtkTreeViewColumn *column;
2492 vbox = scrolled_notebook_page(notebook, _("Files"));
2494 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2496 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2497 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2498 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2499 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2500 pref_checkbox_new_int(group, _("Case sensitive sort"),
2501 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2502 pref_checkbox_new_int(group, _("Natural sort order"),
2503 options->file_sort.natural, &c_options->file_sort.natural);
2504 pref_checkbox_new_int(group, _("Disable file extension checks"),
2505 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2507 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2508 options->file_filter.disable, &c_options->file_filter.disable);
2511 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2513 sidecar_ext_entry = gtk_entry_new();
2514 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2515 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2516 gtk_widget_show(sidecar_ext_entry);
2518 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2520 frame = pref_group_parent(group);
2521 g_signal_connect(G_OBJECT(ct_button), "toggled",
2522 G_CALLBACK(filter_disable_cb), frame);
2523 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2525 scrolled = gtk_scrolled_window_new(NULL, NULL);
2526 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2527 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2528 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2529 gtk_widget_show(scrolled);
2531 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2532 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2533 g_object_unref(filter_store);
2534 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2535 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2537 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2539 column = gtk_tree_view_column_new();
2540 gtk_tree_view_column_set_title(column, _("Filter"));
2541 gtk_tree_view_column_set_resizable(column, TRUE);
2543 renderer = gtk_cell_renderer_toggle_new();
2544 g_signal_connect(G_OBJECT(renderer), "toggled",
2545 G_CALLBACK(filter_store_enable_cb), filter_store);
2546 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2547 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2548 GINT_TO_POINTER(FE_ENABLE), NULL);
2550 renderer = gtk_cell_renderer_text_new();
2551 g_signal_connect(G_OBJECT(renderer), "edited",
2552 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2553 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2554 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2555 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2556 GINT_TO_POINTER(FE_EXTENSION), NULL);
2557 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2559 column = gtk_tree_view_column_new();
2560 gtk_tree_view_column_set_title(column, _("Description"));
2561 gtk_tree_view_column_set_resizable(column, TRUE);
2562 gtk_tree_view_column_set_fixed_width(column, 200);
2563 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2565 renderer = gtk_cell_renderer_text_new();
2566 g_signal_connect(G_OBJECT(renderer), "edited",
2567 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2568 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2569 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2570 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2571 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2572 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2574 column = gtk_tree_view_column_new();
2575 gtk_tree_view_column_set_title(column, _("Class"));
2576 gtk_tree_view_column_set_resizable(column, TRUE);
2577 renderer = gtk_cell_renderer_combo_new();
2578 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2579 "model", create_class_model(),
2584 g_signal_connect(G_OBJECT(renderer), "edited",
2585 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2586 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2587 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2588 GINT_TO_POINTER(FE_CLASS), NULL);
2589 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2591 column = gtk_tree_view_column_new();
2592 gtk_tree_view_column_set_title(column, _("Writable"));
2593 gtk_tree_view_column_set_resizable(column, FALSE);
2594 renderer = gtk_cell_renderer_toggle_new();
2595 g_signal_connect(G_OBJECT(renderer), "toggled",
2596 G_CALLBACK(filter_store_writable_cb), filter_store);
2597 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2598 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2599 GINT_TO_POINTER(FE_WRITABLE), 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, _("Sidecar is allowed"));
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_sidecar_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_ALLOW_SIDECAR), NULL);
2611 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2614 filter_store_populate();
2615 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2616 gtk_widget_show(filter_view);
2618 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2620 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2621 G_CALLBACK(filter_default_cb), filter_view);
2622 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2623 gtk_widget_show(button);
2625 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2626 G_CALLBACK(filter_remove_cb), filter_view);
2627 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2628 gtk_widget_show(button);
2630 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2631 G_CALLBACK(filter_add_cb), filter_view);
2632 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2633 gtk_widget_show(button);
2637 static void config_tab_metadata(GtkWidget *notebook)
2642 GtkWidget *ct_button;
2646 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2649 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2651 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2653 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2654 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2656 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2657 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2659 gtk_widget_set_sensitive(ct_button, FALSE);
2662 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2663 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2665 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2666 label = pref_label_new(group, text);
2667 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2668 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2671 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2673 gtk_widget_set_sensitive(group, FALSE);
2676 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2677 pref_checkbox_link_sensitivity(ct_button, hbox);
2679 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2680 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2682 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2683 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2685 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2686 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2688 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2689 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2691 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2693 gtk_widget_set_sensitive(group, FALSE);
2696 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2697 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2700 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2701 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2702 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2704 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2705 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2707 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2708 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2710 gtk_widget_set_sensitive(ct_button, FALSE);
2713 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2715 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2716 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2718 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2719 pref_checkbox_link_sensitivity(ct_button, hbox);
2721 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2722 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2724 pref_checkbox_new_int(group, _("Write metadata on image change"),
2725 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2727 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2728 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2730 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2732 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2733 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2734 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");
2739 typedef struct _KeywordFindData KeywordFindData;
2740 struct _KeywordFindData
2747 GtkWidget *button_close;
2748 GtkWidget *button_stop;
2749 GtkWidget *button_start;
2750 GtkWidget *progress;
2758 guint idle_id; /* event source id */
2761 #define KEYWORD_DIALOG_WIDTH 400
2763 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2765 GList *list_d = NULL;
2766 GList *list_f = NULL;
2770 filelist_read(dir_fd, &list_f, &list_d);
2774 filelist_read(dir_fd, &list_f, NULL);
2777 list_f = filelist_filter(list_f, FALSE);
2778 list_d = filelist_filter(list_d, TRUE);
2780 kfd->list = g_list_concat(list_f, kfd->list);
2781 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2784 static void keywords_find_reset(KeywordFindData *kfd)
2786 filelist_free(kfd->list);
2789 filelist_free(kfd->list_dir);
2790 kfd->list_dir = NULL;
2793 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2795 KeywordFindData *kfd = data;
2797 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2799 keywords_find_reset(kfd);
2800 generic_dialog_close(kfd->gd);
2804 static void keywords_find_finish(KeywordFindData *kfd)
2806 keywords_find_reset(kfd);
2808 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2809 spinner_set_interval(kfd->spinner, -1);
2811 gtk_widget_set_sensitive(kfd->group, TRUE);
2812 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2813 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2814 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2817 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2819 KeywordFindData *kfd = data;
2821 g_idle_remove_by_data(kfd);
2823 keywords_find_finish(kfd);
2826 static gboolean keywords_find_file(gpointer data)
2828 KeywordFindData *kfd = data;
2830 GtkTextBuffer *buffer;
2838 fd = kfd->list->data;
2839 kfd->list = g_list_remove(kfd->list, fd);
2841 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2842 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2846 gtk_text_buffer_get_end_iter(buffer, &iter);
2847 tmp = g_strconcat(keywords->data, "\n", NULL);
2848 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2850 keywords = keywords->next;
2853 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2854 file_data_unref(fd);
2855 string_list_free(keywords);
2859 else if (kfd->list_dir)
2863 fd = kfd->list_dir->data;
2864 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2866 keywords_find_folder(kfd, fd);
2868 file_data_unref(fd);
2873 keywords_find_finish(kfd);
2878 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2880 KeywordFindData *kfd = data;
2883 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2885 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2886 parse_out_relatives(path);
2890 warning_dialog(_("Invalid folder"),
2891 _("The specified folder can not be found."),
2892 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2898 gtk_widget_set_sensitive(kfd->group, FALSE);
2899 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2900 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2901 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2902 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2904 dir_fd = file_data_new_dir(path);
2905 keywords_find_folder(kfd, dir_fd);
2906 file_data_unref(dir_fd);
2907 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2913 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2915 KeywordFindData *kfd;
2919 kfd = g_new0(KeywordFindData, 1);
2921 kfd->gd = generic_dialog_new(_("Search for keywords"),
2922 "search_for_keywords",
2925 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2926 kfd->gd->cancel_cb = keywords_find_close_cb;
2927 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2928 keywords_find_close_cb, FALSE);
2929 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2930 keywords_find_start_cb, FALSE);
2931 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2932 keywords_find_stop_cb, FALSE);
2933 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2935 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2937 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2938 pref_spacer(hbox, PREF_PAD_INDENT);
2939 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2941 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2942 pref_label_new(hbox, _("Folder:"));
2944 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2945 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2946 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2947 gtk_widget_show(label);
2949 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2951 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2952 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2954 kfd->progress = gtk_entry_new();
2955 gtk_widget_set_can_focus(kfd->progress, FALSE);
2956 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2957 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2958 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2959 gtk_widget_show(kfd->progress);
2961 kfd->spinner = spinner_new(NULL, -1);
2962 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2963 gtk_widget_show(kfd->spinner);
2967 gtk_widget_show(kfd->gd->dialog);
2970 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2972 const gchar *path = layout_get_path(NULL);
2974 if (!path || !*path) path = homedir();
2975 keywords_find_dialog(widget, path);
2978 static void config_tab_keywords_save()
2980 GtkTextIter start, end;
2981 GtkTextBuffer *buffer;
2982 GList *kw_list = NULL;
2988 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2989 gtk_text_buffer_get_bounds(buffer, &start, &end);
2991 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2993 kw_split = strtok(buffer_text, "\n");
2994 while (kw_split != NULL)
3000 if (g_strcmp0(work->data, kw_split) == 0)
3009 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3011 kw_split = strtok(NULL, "\n");
3014 keyword_list_set(kw_list);
3016 string_list_free(kw_list);
3017 g_free(buffer_text);
3020 static void config_tab_keywords(GtkWidget *notebook)
3026 GtkWidget *scrolled;
3028 GtkTextBuffer *buffer;
3031 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3033 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3035 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3037 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3038 G_CALLBACK(keywords_find_cb), keyword_text);
3039 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3042 keyword_text = gtk_text_view_new();
3043 gtk_widget_set_size_request(keyword_text, 20, 20);
3044 scrolled = gtk_scrolled_window_new(NULL, NULL);
3045 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3046 gtk_widget_show(scrolled);
3048 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3049 gtk_widget_show(keyword_text);
3051 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3053 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3054 gtk_text_buffer_create_tag(buffer, "monospace",
3055 "family", "monospace", NULL);
3057 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3058 gtk_text_buffer_get_start_iter(buffer, &iter);
3059 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3062 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3064 GList *kwl = keyword_list_get();
3065 kwl = g_list_first(kwl);
3068 gtk_text_buffer_get_end_iter (buffer, &iter);
3069 tmp = g_strconcat(kwl->data, "\n", NULL);
3070 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3075 gtk_text_buffer_set_modified(buffer, FALSE);
3082 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3084 gint *option = data;
3086 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3090 *option = INTENT_PERCEPTUAL;
3093 *option = INTENT_RELATIVE_COLORIMETRIC;
3096 *option = INTENT_SATURATION;
3099 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3104 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3105 gint option, gint *option_c)
3112 pref_table_label(table, column, row, text, 0.0);
3114 combo = gtk_combo_box_text_new();
3116 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3117 if (option == INTENT_PERCEPTUAL) current = 0;
3118 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3119 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3120 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3121 if (option == INTENT_SATURATION) current = 2;
3122 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3123 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3125 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3127 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3129 g_signal_connect(G_OBJECT(combo), "changed",
3130 G_CALLBACK(intent_menu_cb), option_c);
3132 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3133 gtk_widget_show(combo);
3137 static void config_tab_color(GtkWidget *notebook)
3146 vbox = scrolled_notebook_page(notebook, _("Color management"));
3148 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3150 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3153 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3154 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3156 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3157 pref_label_bold(label, TRUE, FALSE);
3159 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3160 pref_label_bold(label, TRUE, FALSE);
3162 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3163 pref_label_bold(label, TRUE, FALSE);
3165 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3170 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3171 pref_table_label(table, 0, i + 1, buf, 1.0);
3174 entry = gtk_entry_new();
3175 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3176 if (options->color_profile.input_name[i])
3178 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3180 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3181 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3182 gtk_widget_show(entry);
3183 color_profile_input_name_entry[i] = entry;
3185 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3186 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3187 gtk_widget_set_size_request(entry, 160, -1);
3188 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3189 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3190 gtk_widget_show(tabcomp);
3191 color_profile_input_file_entry[i] = entry;
3194 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3196 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3198 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3199 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3201 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3203 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3204 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3205 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3206 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3207 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3209 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3211 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3213 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3215 gtk_widget_show(tabcomp);
3218 /* advanced entry tab */
3219 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3221 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3223 c_options->file_ops.use_system_trash = FALSE;
3224 c_options->file_ops.no_trash = FALSE;
3228 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3230 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3232 c_options->file_ops.use_system_trash = TRUE;
3233 c_options->file_ops.no_trash = FALSE;
3237 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3239 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3241 c_options->file_ops.no_trash = TRUE;
3245 static void config_tab_behavior(GtkWidget *notebook)
3252 GtkWidget *ct_button;
3256 GtkWidget *with_rename;
3257 GtkWidget *collections_on_top;
3258 GtkWidget *checkbox;
3260 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3262 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3264 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3265 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3266 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3267 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3268 pref_checkbox_new_int(group, _("Enable Delete key"),
3269 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3271 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3272 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3274 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3275 pref_checkbox_link_sensitivity(ct_button, hbox);
3277 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3278 pref_label_new(hbox, _("Folder:"));
3280 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3281 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3282 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3283 gtk_widget_show(tabcomp);
3285 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3286 pref_checkbox_link_sensitivity(ct_button, hbox);
3288 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3289 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3290 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3291 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3292 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3293 G_CALLBACK(safe_delete_view_cb), NULL);
3294 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3295 gtk_widget_show(button);
3297 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3298 G_CALLBACK(safe_delete_clear_cb), NULL);
3299 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3300 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3301 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3303 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3304 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3306 gtk_widget_show(button);
3308 pref_spacer(group, PREF_PAD_GROUP);
3311 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3313 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3314 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3316 pref_checkbox_new_int(group, _("In place renaming"),
3317 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3319 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3320 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3322 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3323 options->marks_save, &c_options->marks_save);
3324 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3326 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3327 options->with_rename, &c_options->with_rename);
3328 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3330 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3331 options->collections_on_top, &c_options->collections_on_top);
3332 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3334 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3335 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3337 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3338 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3340 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3341 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3343 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3344 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3346 pref_spacer(group, PREF_PAD_GROUP);
3348 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3350 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3351 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3352 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3353 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3354 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3355 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3356 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3357 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3358 pref_checkbox_new_int(group, _("Play video by left click on image"),
3359 options->image_l_click_video, &c_options->image_l_click_video);
3360 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3361 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3363 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3364 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3365 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3366 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3367 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3369 pref_spacer(group, PREF_PAD_GROUP);
3371 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3373 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3374 options->override_disable_gpu, &c_options->override_disable_gpu);
3375 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3378 pref_spacer(group, PREF_PAD_GROUP);
3380 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3382 pref_spin_new_int(group, _("Debug level:"), NULL,
3383 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3385 pref_checkbox_new_int(group, _("Timer data"),
3386 options->log_window.timer_data, &c_options->log_window.timer_data);
3388 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3389 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3393 /* accelerators tab */
3394 static void config_tab_accelerators(GtkWidget *notebook)
3400 GtkWidget *scrolled;
3401 GtkWidget *accel_view;
3402 GtkCellRenderer *renderer;
3403 GtkTreeSelection *selection;
3404 GtkTreeViewColumn *column;
3406 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3408 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3410 scrolled = gtk_scrolled_window_new(NULL, NULL);
3411 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3412 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3413 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3414 gtk_widget_show(scrolled);
3416 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3418 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3419 g_object_unref(accel_store);
3420 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3421 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3423 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3425 renderer = gtk_cell_renderer_text_new();
3427 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3432 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3433 gtk_tree_view_column_set_resizable(column, TRUE);
3434 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3437 renderer = gtk_cell_renderer_accel_new();
3438 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3439 G_CALLBACK(accel_store_cleared_cb), accel_store);
3440 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3441 G_CALLBACK(accel_store_edited_cb), accel_store);
3444 g_object_set (renderer,
3446 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3449 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3454 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3455 gtk_tree_view_column_set_resizable(column, TRUE);
3456 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3458 renderer = gtk_cell_renderer_text_new();
3460 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3465 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3466 gtk_tree_view_column_set_resizable(column, TRUE);
3467 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3469 renderer = gtk_cell_renderer_text_new();
3471 column = gtk_tree_view_column_new_with_attributes("Accel",
3476 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3477 gtk_tree_view_column_set_resizable(column, TRUE);
3478 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3480 accel_store_populate();
3481 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3482 gtk_widget_show(accel_view);
3484 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3486 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3487 G_CALLBACK(accel_default_cb), accel_view);
3488 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3489 gtk_widget_show(button);
3491 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3492 G_CALLBACK(accel_reset_cb), accel_view);
3493 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3494 gtk_widget_show(button);
3497 /* toolbar main tab */
3498 static void config_tab_toolbar_main(GtkWidget *notebook)
3501 GtkWidget *toolbardata;
3504 lw = layout_window_list->data;
3506 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3508 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3509 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3510 gtk_widget_show(vbox);
3513 /* toolbar status tab */
3514 static void config_tab_toolbar_status(GtkWidget *notebook)
3517 GtkWidget *toolbardata;
3520 lw = layout_window_list->data;
3522 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3524 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3525 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3526 gtk_widget_show(vbox);
3530 static void config_tab_stereo(GtkWidget *notebook)
3538 GtkWidget *fs_button;
3539 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3541 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3543 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3544 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3546 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3547 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3548 pref_checkbox_new_int(box, _("Mirror left image"),
3549 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3550 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3551 pref_checkbox_new_int(box, _("Flip left image"),
3552 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3553 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3554 pref_checkbox_new_int(box, _("Mirror right image"),
3555 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3556 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3557 pref_checkbox_new_int(box, _("Flip right image"),
3558 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3559 pref_checkbox_new_int(group, _("Swap left and right images"),
3560 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3561 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3562 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3564 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3565 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3566 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3567 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3568 pref_checkbox_link_sensitivity(fs_button, box2);
3569 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3570 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3571 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3572 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3573 pref_checkbox_new_int(box, _("Mirror left image"),
3574 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3575 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3576 pref_checkbox_new_int(box, _("Flip left image"),
3577 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3578 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3579 pref_checkbox_new_int(box, _("Mirror right image"),
3580 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3581 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3582 pref_checkbox_new_int(box, _("Flip right image"),
3583 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3584 pref_checkbox_new_int(box2, _("Swap left and right images"),
3585 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3586 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3587 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3589 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3590 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3591 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3592 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3593 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3594 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3595 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3596 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3597 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3598 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3599 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3600 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3601 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3602 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3606 /* Main preferences window */
3607 static void config_window_create(void)
3609 GtkWidget *win_vbox;
3611 GtkWidget *notebook;
3613 GtkWidget *ct_button;
3615 if (!c_options) c_options = init_options(NULL);
3617 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3618 DEBUG_NAME(configwindow);
3619 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3620 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3621 G_CALLBACK(config_window_delete), NULL);
3622 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3623 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3624 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3626 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3627 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3628 gtk_widget_show(win_vbox);
3630 notebook = gtk_notebook_new();
3631 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3632 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3633 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3635 config_tab_general(notebook);
3636 config_tab_image(notebook);
3637 config_tab_osd(notebook);
3638 config_tab_windows(notebook);
3639 config_tab_accelerators(notebook);
3640 config_tab_files(notebook);
3641 config_tab_metadata(notebook);
3642 config_tab_keywords(notebook);
3643 config_tab_color(notebook);
3644 config_tab_stereo(notebook);
3645 config_tab_behavior(notebook);
3646 config_tab_toolbar_main(notebook);
3647 config_tab_toolbar_status(notebook);
3649 hbox = gtk_hbutton_box_new();
3650 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3651 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3652 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3653 gtk_widget_show(hbox);
3655 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3656 G_CALLBACK(config_window_help_cb), notebook);
3657 gtk_container_add(GTK_CONTAINER(hbox), button);
3658 gtk_widget_set_can_default(button, TRUE);
3659 gtk_widget_show(button);
3661 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3662 G_CALLBACK(config_window_ok_cb), NULL);
3663 gtk_container_add(GTK_CONTAINER(hbox), button);
3664 gtk_widget_set_can_default(button, TRUE);
3665 gtk_widget_grab_default(button);
3666 gtk_widget_show(button);
3670 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3671 G_CALLBACK(config_window_close_cb), NULL);
3672 gtk_container_add(GTK_CONTAINER(hbox), button);
3673 gtk_widget_set_can_default(button, TRUE);
3674 gtk_widget_show(button);
3676 if (!generic_dialog_get_alternative_button_order(configwindow))
3678 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3681 gtk_widget_show(notebook);
3683 gtk_widget_show(configwindow);
3687 *-----------------------------------------------------------------------------
3688 * config window show (public)
3689 *-----------------------------------------------------------------------------
3692 void show_config_window(void)
3696 gtk_window_present(GTK_WINDOW(configwindow));
3700 config_window_create();
3709 void show_about_window(LayoutWindow *lw)
3711 GdkPixbuf *pixbuf_logo;
3712 GdkPixbuf *pixbuf_icon;
3713 gchar *authors[1000];
3718 gchar *timezone_path;
3722 #define LINE_LENGTH 1000
3723 gchar line[LINE_LENGTH];
3725 copyright = g_string_new(NULL);
3726 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");
3728 path = path_from_utf8(TIMEZONE_DATABASE);
3729 basename = g_path_get_basename(path);
3730 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3731 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3733 cd = ZDOpenDatabase(timezone_path);
3736 copyright = g_string_append(copyright, ZDGetNotice(cd));
3737 ZDCloseDatabase(cd);
3741 g_free(timezone_path);
3745 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3746 fp = fopen(path, "r");
3749 while(fgets(line, LINE_LENGTH, fp))
3751 /* get rid of ending \n from fgets */
3752 line[strlen(line) - 1] = '\0';
3753 authors[i_authors] = g_strdup(line);
3756 authors[i_authors] = NULL;
3761 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3762 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3764 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3765 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3766 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3767 "title", _("About Geeqie"),
3769 "program-name", GQ_APPNAME,
3771 "logo", pixbuf_logo,
3772 "icon", pixbuf_icon,
3773 "website", GQ_WEBSITE,
3774 "website-label", "Website",
3775 "comments", comment,
3777 "translator-credits", _("translator-credits"),
3778 "wrap-license", TRUE,
3779 "license", copyright->str,
3782 g_string_free(copyright, TRUE);
3785 while(n < i_authors)
3795 static void image_overlay_set_text_colours()
3797 c_options->image_overlay.text_red = options->image_overlay.text_red;
3798 c_options->image_overlay.text_green = options->image_overlay.text_green;
3799 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3800 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3801 c_options->image_overlay.background_red = options->image_overlay.background_red;
3802 c_options->image_overlay.background_green = options->image_overlay.background_green;
3803 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3804 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3808 *-----------------------------------------------------------------------------
3809 * timezone database routines
3810 *-----------------------------------------------------------------------------
3813 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3815 GError *error = NULL;
3817 gchar *tmp_filename;
3819 if (!g_cancellable_is_cancelled(tz->cancellable))
3821 generic_dialog_close(tz->gd);
3825 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3827 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3828 move_file(tmp_filename, tz->timezone_database_user);
3829 g_free(tmp_filename);
3833 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3836 g_file_delete(tz->tmp_g_file, NULL, &error);
3837 g_object_unref(tz->tmp_g_file);
3838 tz->tmp_g_file = NULL;
3839 g_object_unref(tz->cancellable);
3840 g_object_unref(tz->timezone_database_gq);
3843 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3847 if (!g_cancellable_is_cancelled(tz->cancellable))
3849 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3853 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3857 g_cancellable_cancel(tz->cancellable);
3860 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3863 GError *error = NULL;
3864 GFileIOStream *io_stream;
3871 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3875 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3876 log_printf("Error: Download timezone database failed:\n%s", error->message);
3877 g_error_free(error);
3878 g_object_unref(tz->tmp_g_file);
3882 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3884 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3886 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3888 tz->progress = gtk_progress_bar_new();
3889 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3890 gtk_widget_show(tz->progress);
3892 gtk_widget_show(tz->gd->dialog);
3893 tz->cancellable = g_cancellable_new();
3894 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);
3896 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3899 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */