2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
248 gboolean refresh = FALSE;
253 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
255 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
256 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
257 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
258 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
259 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
260 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
261 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
263 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
264 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
265 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
266 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
267 options->file_ops.no_trash = c_options->file_ops.no_trash;
268 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
269 options->tools_restore_state = c_options->tools_restore_state;
270 options->save_window_positions = c_options->save_window_positions;
271 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
272 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
273 options->show_window_ids = c_options->show_window_ids;
274 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
275 options->image.zoom_2pass = c_options->image.zoom_2pass;
276 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
277 options->image.limit_window_size = c_options->image.limit_window_size;
278 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
279 options->image.max_window_size = c_options->image.max_window_size;
280 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
281 options->image.max_autofit_size = c_options->image.max_autofit_size;
282 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
283 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
284 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
285 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
287 if (options->thumbnails.max_width != c_options->thumbnails.max_width
288 || options->thumbnails.max_height != c_options->thumbnails.max_height
289 || options->thumbnails.quality != c_options->thumbnails.quality)
291 thumb_format_changed = TRUE;
293 options->thumbnails.max_width = c_options->thumbnails.max_width;
294 options->thumbnails.max_height = c_options->thumbnails.max_height;
295 options->thumbnails.quality = c_options->thumbnails.quality;
297 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
298 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
299 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
300 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
301 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
302 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
303 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
304 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
305 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
306 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
307 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
308 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
310 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
311 options->file_sort.natural = c_options->file_sort.natural;
312 options->file_filter.disable = c_options->file_filter.disable;
314 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
315 sidecar_ext_parse(options->sidecar.ext);
317 options->slideshow.random = c_options->slideshow.random;
318 options->slideshow.repeat = c_options->slideshow.repeat;
319 options->slideshow.delay = c_options->slideshow.delay;
321 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
322 options->image_lm_click_nav = c_options->image_lm_click_nav;
323 options->image_l_click_video = c_options->image_l_click_video;
324 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
326 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
328 options->image.tile_cache_max = c_options->image.tile_cache_max;
329 options->image.image_cache_max = c_options->image.image_cache_max;
331 options->image.zoom_quality = c_options->image.zoom_quality;
333 options->image.zoom_increment = c_options->image.zoom_increment;
335 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
338 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
339 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
340 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
342 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
343 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
344 options->image.border_color = c_options->image.border_color;
345 layout_colors_update();
346 view_window_colors_update();
349 options->image.alpha_color_1 = c_options->image.alpha_color_1;
350 options->image.alpha_color_2 = c_options->image.alpha_color_2;
352 options->fullscreen.screen = c_options->fullscreen.screen;
353 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
354 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
355 options->fullscreen.above = c_options->fullscreen.above;
356 if (c_options->image_overlay.template_string)
357 set_image_overlay_template_string(&options->image_overlay.template_string,
358 c_options->image_overlay.template_string);
359 if (c_options->image_overlay.font)
360 set_image_overlay_font_string(&options->image_overlay.font,
361 c_options->image_overlay.font);
362 options->image_overlay.text_red = c_options->image_overlay.text_red;
363 options->image_overlay.text_green = c_options->image_overlay.text_green;
364 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
365 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
366 options->image_overlay.background_red = c_options->image_overlay.background_red;
367 options->image_overlay.background_green = c_options->image_overlay.background_green;
368 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
369 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
370 options->update_on_time_change = c_options->update_on_time_change;
371 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
373 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
374 options->rot_invariant_sim = c_options->rot_invariant_sim;
376 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
378 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
380 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
381 options->dnd_icon_size = c_options->dnd_icon_size;
382 options->clipboard_selection = c_options->clipboard_selection;
383 options->dnd_default_action = c_options->dnd_default_action;
385 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
386 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
387 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
388 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
389 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
390 options->metadata.confirm_write = c_options->metadata.confirm_write;
391 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
392 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
393 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
394 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
395 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
396 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
397 options->metadata.write_orientation = c_options->metadata.write_orientation;
398 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
399 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
400 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
401 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
402 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
403 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
404 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
405 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
406 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
407 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
408 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
409 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
410 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
411 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
412 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
413 options->stereo.fixed_w = c_options->stereo.fixed_w;
414 options->stereo.fixed_h = c_options->stereo.fixed_h;
415 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
416 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
417 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
418 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
420 options->info_keywords.height = c_options->info_keywords.height;
421 options->info_title.height = c_options->info_title.height;
422 options->info_comment.height = c_options->info_comment.height;
423 options->info_rating.height = c_options->info_rating.height;
425 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
426 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
428 options->marks_save = c_options->marks_save;
429 options->with_rename = c_options->with_rename;
430 options->collections_on_top = c_options->collections_on_top;
431 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
432 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
434 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
436 options->star_rating.star = c_options->star_rating.star;
437 options->star_rating.rejected = c_options->star_rating.rejected;
439 set_debug_level(debug_c);
443 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
445 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
446 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
448 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
449 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
450 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
452 options->color_profile.render_intent = c_options->color_profile.render_intent;
457 options->mouse_button_8 = c_options->mouse_button_8;
458 options->mouse_button_9 = c_options->mouse_button_9;
460 options->override_disable_gpu = c_options->override_disable_gpu;
462 config_tab_keywords_save();
464 image_options_sync();
469 layout_refresh(NULL);
472 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
474 toolbar_apply(TOOLBAR_MAIN);
475 toolbar_apply(TOOLBAR_STATUS);
479 *-----------------------------------------------------------------------------
480 * config window main button callbacks (private)
481 *-----------------------------------------------------------------------------
484 static void config_window_close_cb(GtkWidget *widget, gpointer data)
486 gtk_widget_destroy(configwindow);
491 static void config_window_help_cb(GtkWidget *widget, gpointer data)
493 GtkWidget *notebook = data;
496 static gchar *html_section[] =
498 "GuideOptionsGeneral.html",
499 "GuideOptionsImage.html",
500 "GuideOptionsOSD.html",
501 "GuideOptionsWindow.html",
502 "GuideOptionsKeyboard.html",
503 "GuideOptionsFiltering.html",
504 "GuideOptionsMetadata.html",
505 "GuideOptionsKeywords.html",
506 "GuideOptionsColor.html",
507 "GuideOptionsStereo.html",
508 "GuideOptionsBehavior.html",
509 "GuideOptionsToolbar.html",
510 "GuideOptionsToolbar.html"
513 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
514 help_window_show(html_section[i]);
517 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
519 config_window_close_cb(NULL, NULL);
523 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
526 lw = layout_window_list->data;
528 config_window_apply();
529 layout_util_sync(lw);
530 save_options(options);
531 config_window_close_cb(NULL, NULL);
535 *-----------------------------------------------------------------------------
536 * config window setup (private)
537 *-----------------------------------------------------------------------------
540 static void quality_menu_cb(GtkWidget *combo, gpointer data)
544 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
548 *option = GDK_INTERP_NEAREST;
551 *option = GDK_INTERP_TILES;
554 *option = GDK_INTERP_BILINEAR;
559 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
563 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
567 *option = DND_ACTION_ASK;
570 *option = DND_ACTION_COPY;
573 *option = DND_ACTION_MOVE;
577 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
581 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
593 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
594 guint option, guint *option_c)
601 pref_table_label(table, column, row, text, 0.0);
603 combo = gtk_combo_box_text_new();
605 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
606 if (option == GDK_INTERP_NEAREST) current = 0;
607 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
608 if (option == GDK_INTERP_TILES) current = 1;
609 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
610 if (option == GDK_INTERP_BILINEAR) current = 2;
612 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
614 g_signal_connect(G_OBJECT(combo), "changed",
615 G_CALLBACK(quality_menu_cb), option_c);
617 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
618 gtk_widget_show(combo);
621 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
628 pref_table_label(table, column, row, text, 0.0);
630 combo = gtk_combo_box_text_new();
632 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
633 if (option == DND_ACTION_ASK) current = 0;
634 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
635 if (option == DND_ACTION_COPY) current = 1;
636 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
637 if (option == DND_ACTION_MOVE) current = 2;
639 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
641 g_signal_connect(G_OBJECT(combo), "changed",
642 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
644 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
645 gtk_widget_show(combo);
648 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
649 gint option, gint *option_c)
656 pref_table_label(table, column, row, text, 0.0);
658 combo = gtk_combo_box_text_new();
660 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
661 if (option == PRIMARY) current = 0;
662 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
663 if (option == CLIPBOARD) current = 1;
665 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
667 g_signal_connect(G_OBJECT(combo), "changed",
668 G_CALLBACK(clipboard_selection_menu_cb), option_c);
670 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
671 gtk_widget_show(combo);
674 typedef struct _UseableMouseItems UseableMouseItems;
675 struct _UseableMouseItems
677 gchar *name; /* GtkActionEntry terminology */
682 static const UseableMouseItems useable_mouse_items[] = {
684 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
685 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
686 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
687 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
688 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
689 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
690 {"Home", N_("Home"), GTK_STOCK_HOME},
691 {"Up", N_("Up"), GTK_STOCK_GO_UP},
692 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
693 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
694 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
695 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
696 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
697 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
698 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
699 {"Search", N_("Search"), GTK_STOCK_FIND},
700 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
701 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
702 {"Copy", N_("Copy"), GTK_STOCK_COPY},
703 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
704 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
705 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
706 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
707 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
708 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
709 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
710 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
711 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
712 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
713 {"Print", N_("Print"), GTK_STOCK_PRINT},
714 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
715 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
716 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
717 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
718 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
719 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
720 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
721 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
722 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
723 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
724 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
725 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
726 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
727 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
728 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
729 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
730 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
731 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
732 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
733 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
734 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
735 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
736 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
737 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
738 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
739 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
740 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
741 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
742 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
743 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
744 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
745 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
746 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
747 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
748 {"ImageGuidelines", N_("Show guidelines"), PIXBUF_INLINE_ICON_GUIDELINES},
749 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
750 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
751 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
752 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
753 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
757 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
759 gchar **option = data;
762 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
764 const UseableMouseItems *list = useable_mouse_items;
768 if (g_strcmp0(list->label, label) == 0)
776 *option = g_strdup(list->name);
780 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
781 gchar *option, gchar **option_c)
789 pref_table_label(table, column, row, text, 0.0);
791 combo = gtk_combo_box_text_new();
793 const UseableMouseItems *list = useable_mouse_items;
797 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
798 if (g_strcmp0(list->name, option) == 0)
806 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
808 g_signal_connect(G_OBJECT(combo), "changed",
809 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
811 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
812 gtk_widget_show(combo);
815 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
819 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
822 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
824 c_options->thumbnails.max_width = thumb_size_list[n].w;
825 c_options->thumbnails.max_height = thumb_size_list[n].h;
829 c_options->thumbnails.max_width = options->thumbnails.max_width;
830 c_options->thumbnails.max_height = options->thumbnails.max_height;
834 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
840 c_options->thumbnails.max_width = options->thumbnails.max_width;
841 c_options->thumbnails.max_height = options->thumbnails.max_height;
843 pref_table_label(table, column, row, text, 0.0);
845 combo = gtk_combo_box_text_new();
848 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
853 w = thumb_size_list[i].w;
854 h = thumb_size_list[i].h;
856 buf = g_strdup_printf("%d x %d", w, h);
857 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
860 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
867 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
868 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
874 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
875 g_signal_connect(G_OBJECT(combo), "changed",
876 G_CALLBACK(thumb_size_menu_cb), NULL);
878 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
879 gtk_widget_show(combo);
882 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
886 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
890 *option = PR_STEREO_NONE;
893 *option = PR_STEREO_ANAGLYPH_RC;
896 *option = PR_STEREO_ANAGLYPH_GM;
899 *option = PR_STEREO_ANAGLYPH_YB;
902 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
905 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
908 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
911 *option = PR_STEREO_ANAGLYPH_DB_RC;
914 *option = PR_STEREO_ANAGLYPH_DB_GM;
917 *option = PR_STEREO_ANAGLYPH_DB_YB;
920 *option = PR_STEREO_HORIZ;
923 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
926 *option = PR_STEREO_VERT;
929 *option = PR_STEREO_VERT | PR_STEREO_HALF;
932 *option = PR_STEREO_FIXED;
937 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
938 gint option, gint *option_c, gboolean add_fixed)
945 pref_table_label(table, column, row, text, 0.0);
947 combo = gtk_combo_box_text_new();
949 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
951 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
952 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
953 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
954 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
955 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
956 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
957 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
958 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
959 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
960 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
961 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
962 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
963 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
964 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
965 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
966 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
967 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
968 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
970 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
971 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
972 if (option & PR_STEREO_HORIZ)
975 if (option & PR_STEREO_HALF) current = 11;
978 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
979 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
980 if (option & PR_STEREO_VERT)
983 if (option & PR_STEREO_HALF) current = 13;
988 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
989 if (option & PR_STEREO_FIXED) current = 14;
992 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
994 g_signal_connect(G_OBJECT(combo), "changed",
995 G_CALLBACK(stereo_mode_menu_cb), option_c);
997 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
998 gtk_widget_show(combo);
1001 static void video_menu_cb(GtkWidget *combo, gpointer data)
1003 gchar **option = data;
1005 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1009 static void video_menu_populate(gpointer data, gpointer user_data)
1011 GtkWidget *combo = user_data;
1012 EditorDescription *ed = data;
1014 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1017 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1018 gchar *option, gchar **option_c)
1022 /* use lists since they are sorted */
1023 GList *eds = editor_list_get();
1027 pref_table_label(table, column, row, text, 0.0);
1029 combo = gtk_combo_box_text_new();
1030 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1031 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1033 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1035 g_signal_connect(G_OBJECT(combo), "changed",
1036 G_CALLBACK(video_menu_cb), option_c);
1038 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1039 gtk_widget_show(combo);
1042 static void filter_store_populate(void)
1046 if (!filter_store) return;
1048 gtk_list_store_clear(filter_store);
1050 work = filter_get_list();
1059 gtk_list_store_append(filter_store, &iter);
1060 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1064 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1065 gchar *new_text, gpointer data)
1067 GtkWidget *model = data;
1068 FilterEntry *fe = data;
1072 if (!new_text || strlen(new_text) < 1) return;
1074 tpath = gtk_tree_path_new_from_string(path_str);
1075 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1076 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1078 g_free(fe->extensions);
1079 fe->extensions = g_strdup(new_text);
1081 gtk_tree_path_free(tpath);
1085 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1086 gchar *new_text, gpointer data)
1088 GtkWidget *model = data;
1089 FilterEntry *fe = data;
1094 if (!new_text || !new_text[0]) return;
1096 tpath = gtk_tree_path_new_from_string(path_str);
1097 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1098 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1100 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1102 if (strcmp(new_text, _(format_class_list[i])) == 0)
1109 gtk_tree_path_free(tpath);
1113 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1114 gchar *new_text, gpointer data)
1116 GtkWidget *model = data;
1121 if (!new_text || !new_text[0]) return;
1123 tpath = gtk_tree_path_new_from_string(path_str);
1124 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1125 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1127 g_free(fe->description);
1128 fe->description = g_strdup(new_text);
1130 gtk_tree_path_free(tpath);
1133 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1134 gchar *path_str, gpointer data)
1136 GtkWidget *model = data;
1141 tpath = gtk_tree_path_new_from_string(path_str);
1142 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1143 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1145 fe->enabled = !fe->enabled;
1147 gtk_tree_path_free(tpath);
1151 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1152 gchar *path_str, gpointer data)
1154 GtkWidget *model = data;
1159 tpath = gtk_tree_path_new_from_string(path_str);
1160 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1161 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1163 fe->writable = !fe->writable;
1164 if (fe->writable) fe->allow_sidecar = FALSE;
1166 gtk_tree_path_free(tpath);
1170 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1171 gchar *path_str, gpointer data)
1173 GtkWidget *model = data;
1178 tpath = gtk_tree_path_new_from_string(path_str);
1179 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1180 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1182 fe->allow_sidecar = !fe->allow_sidecar;
1183 if (fe->allow_sidecar) fe->writable = FALSE;
1185 gtk_tree_path_free(tpath);
1189 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1190 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1194 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1196 switch (GPOINTER_TO_INT(data))
1199 g_object_set(GTK_CELL_RENDERER(cell),
1200 "active", fe->enabled, NULL);
1203 g_object_set(GTK_CELL_RENDERER(cell),
1204 "text", fe->extensions, NULL);
1206 case FE_DESCRIPTION:
1207 g_object_set(GTK_CELL_RENDERER(cell),
1208 "text", fe->description, NULL);
1211 g_object_set(GTK_CELL_RENDERER(cell),
1212 "text", _(format_class_list[fe->file_class]), NULL);
1215 g_object_set(GTK_CELL_RENDERER(cell),
1216 "active", fe->writable, NULL);
1218 case FE_ALLOW_SIDECAR:
1219 g_object_set(GTK_CELL_RENDERER(cell),
1220 "active", fe->allow_sidecar, NULL);
1225 static gboolean filter_add_scroll(gpointer data)
1229 GtkCellRenderer *cell;
1230 GtkTreeViewColumn *column;
1233 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1234 path = gtk_tree_path_new_from_indices(rows-1, -1);
1236 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1238 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1239 cell = g_list_last(list_cells)->data;
1241 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1242 path, column, FALSE, 0.0, 0.0 );
1243 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1244 path, column, cell, TRUE);
1246 gtk_tree_path_free(path);
1247 g_list_free(list_cells);
1252 static void filter_add_cb(GtkWidget *widget, gpointer data)
1254 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1255 filter_store_populate();
1257 g_idle_add((GSourceFunc)filter_add_scroll, data);
1260 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1262 GtkWidget *filter_view = data;
1263 GtkTreeSelection *selection;
1267 if (!filter_store) return;
1268 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1269 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1270 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1273 filter_remove_entry(fe);
1275 filter_store_populate();
1278 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1282 GtkTreeViewColumn *column;
1284 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1285 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1286 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1288 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1292 gtk_tree_path_free(path);
1297 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1300 filter_add_defaults();
1302 filter_store_populate();
1304 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1307 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1309 /* no op, only so cancel button appears */
1312 static void filter_default_cb(GtkWidget *widget, gpointer data)
1316 gd = generic_dialog_new(_("Reset filters"),
1317 "reset_filter", widget, TRUE,
1318 dummy_cancel_cb, data);
1319 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1320 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1321 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1322 gtk_widget_show(gd->dialog);
1325 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1327 GtkWidget *frame = data;
1329 gtk_widget_set_sensitive(frame,
1330 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1333 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1335 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1338 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1340 file_util_trash_clear();
1343 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1347 gd = generic_dialog_new(_("Clear trash"),
1348 "clear_trash", widget, TRUE,
1349 dummy_cancel_cb, NULL);
1350 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1351 _("This will remove the trash contents."), FALSE);
1352 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1353 entry = gtk_entry_new();
1354 gtk_widget_set_can_focus(entry, FALSE);
1355 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1356 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1357 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1358 gtk_widget_show(entry);
1359 gtk_widget_show(gd->dialog);
1362 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1364 GtkWidget *pTextView;
1365 GtkTextBuffer *pTextBuffer;
1369 pTextView = GTK_WIDGET(data);
1371 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1372 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1373 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1375 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1376 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1379 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1381 GtkTextView *text_view = data;
1382 GtkTextBuffer *buffer;
1384 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1385 if (!configwindow) return;
1387 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1388 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1391 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1395 gd = generic_dialog_new(_("Reset image overlay template string"),
1396 "reset_image_overlay_template_string", widget, TRUE,
1397 dummy_cancel_cb, data);
1398 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1399 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1400 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1401 gtk_widget_show(gd->dialog);
1404 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1406 help_window_show("GuideOptionsOSD.html");
1409 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1411 #if GTK_CHECK_VERSION(3,4,0)
1414 PangoFontDescription *font_desc;
1416 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1417 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1419 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1421 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1422 font = pango_font_description_to_string(font_desc);
1423 g_free(c_options->image_overlay.font);
1424 c_options->image_overlay.font = g_strdup(font);
1428 gtk_widget_destroy(dialog);
1432 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1433 c_options->image_overlay.font = g_strdup(font);
1437 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1440 #if GTK_CHECK_VERSION(3,4,0)
1443 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1444 colour.red = options->image_overlay.text_red;
1445 colour.green = options->image_overlay.text_green;
1446 colour.blue = options->image_overlay.text_blue;
1447 colour.alpha = options->image_overlay.text_alpha;
1448 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1449 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1451 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1453 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1454 c_options->image_overlay.text_red = colour.red*255;
1455 c_options->image_overlay.text_green = colour.green*255;
1456 c_options->image_overlay.text_blue = colour.blue*255;
1457 c_options->image_overlay.text_alpha = colour.alpha*255;
1459 gtk_widget_destroy(dialog);
1462 GtkColorSelection *colorsel;
1464 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1465 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1466 colour.red = options->image_overlay.text_red*257;
1467 colour.green = options->image_overlay.text_green*257;
1468 colour.blue = options->image_overlay.text_blue*257;
1469 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1470 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1471 gtk_color_selection_set_current_color(colorsel, &colour);
1472 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1474 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1476 gtk_color_selection_get_current_color(colorsel, &colour);
1477 c_options->image_overlay.text_red = colour.red/257;
1478 c_options->image_overlay.text_green = colour.green/257;
1479 c_options->image_overlay.text_blue = colour.blue/257;
1480 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1482 gtk_widget_destroy (dialog);
1487 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1490 #if GTK_CHECK_VERSION(3,4,0)
1493 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1494 colour.red = options->image_overlay.background_red;
1495 colour.green = options->image_overlay.background_green;
1496 colour.blue = options->image_overlay.background_blue;
1497 colour.alpha = options->image_overlay.background_alpha;
1498 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1499 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1501 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1503 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1504 c_options->image_overlay.background_red = colour.red*255;
1505 c_options->image_overlay.background_green = colour.green*255;
1506 c_options->image_overlay.background_blue = colour.blue*255;
1507 c_options->image_overlay.background_alpha = colour.alpha*255;
1509 gtk_widget_destroy(dialog);
1512 GtkColorSelection *colorsel;
1514 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1515 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1516 colour.red = options->image_overlay.background_red*257;
1517 colour.green = options->image_overlay.background_green*257;
1518 colour.blue = options->image_overlay.background_blue*257;
1519 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1520 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1521 gtk_color_selection_set_current_color(colorsel, &colour);
1522 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1524 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1526 gtk_color_selection_get_current_color(colorsel, &colour);
1527 c_options->image_overlay.background_red = colour.red/257;
1528 c_options->image_overlay.background_green = colour.green/257;
1529 c_options->image_overlay.background_blue = colour.blue/257;
1530 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1532 gtk_widget_destroy(dialog);
1536 static void accel_store_populate(void)
1539 GList *groups, *actions;
1541 const gchar *accel_path;
1545 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1547 gtk_tree_store_clear(accel_store);
1548 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1550 g_assert(lw && lw->ui_manager);
1551 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1554 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1557 action = GTK_ACTION(actions->data);
1558 accel_path = gtk_action_get_accel_path(action);
1559 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1561 gchar *label, *label2, *tooltip, *accel;
1562 g_object_get(action,
1563 "tooltip", &tooltip,
1567 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1573 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1577 gtk_tree_store_append(accel_store, &iter, NULL);
1578 gtk_tree_store_set(accel_store, &iter,
1581 AE_TOOLTIP, tooltip ? tooltip : "",
1582 AE_ACCEL, accel_path,
1590 actions = actions->next;
1593 groups = groups->next;
1597 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1602 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1604 gchar *accel1 = data;
1609 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1611 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1612 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1614 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1616 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1617 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1626 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1628 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1632 GtkAccelKey old_key, key;
1633 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1635 gtk_tree_model_get_iter(model, &iter, path);
1636 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1638 /* test if the accelerator can be stored without conflicts*/
1639 gtk_accel_map_lookup_entry(accel_path, &old_key);
1641 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1642 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1643 gtk_accel_map_lookup_entry(accel_path, &key);
1645 /* restore the original for now, the key will be really changed when the changes are confirmed */
1646 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1648 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1649 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1651 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1652 gtk_tree_path_free(path);
1656 static gboolean accel_default_scroll(GtkTreeView *data)
1660 GtkTreeViewColumn *column;
1662 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1663 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1664 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1666 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1670 gtk_tree_path_free(path);
1675 static void accel_default_cb(GtkWidget *widget, gpointer data)
1677 accel_store_populate();
1679 g_idle_add((GSourceFunc)accel_default_scroll, data);
1682 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1684 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1687 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1690 gchar *accel_path, *accel;
1692 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1693 gtk_accel_map_lookup_entry(accel_path, &key);
1694 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1696 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1698 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1703 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1705 GtkTreeSelection *selection;
1707 if (!accel_store) return;
1708 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1709 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1714 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1718 GtkWidget *scrolled;
1719 GtkWidget *viewport;
1721 scrolled = gtk_scrolled_window_new(NULL, NULL);
1722 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1723 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1724 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1725 label = gtk_label_new(title);
1726 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1727 gtk_widget_show(scrolled);
1729 viewport = gtk_viewport_new(NULL, NULL);
1730 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1731 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1732 gtk_widget_show(viewport);
1734 vbox = gtk_vbox_new(FALSE, 0);
1735 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1736 gtk_widget_show(vbox);
1741 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1743 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1745 c_options->thumbnails.spec_standard =TRUE;
1746 c_options->thumbnails.cache_into_dirs = FALSE;
1750 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1752 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1754 c_options->thumbnails.spec_standard =FALSE;
1755 c_options->thumbnails.cache_into_dirs = FALSE;
1759 static void cache_local_cb(GtkWidget *widget, gpointer data)
1761 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1763 c_options->thumbnails.cache_into_dirs = TRUE;
1764 c_options->thumbnails.spec_standard =FALSE;
1768 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1769 GdkEvent *event, gpointer userdata)
1771 if (pos == GTK_ENTRY_ICON_PRIMARY)
1773 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1777 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1781 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1782 GdkEvent *event, gpointer userdata)
1784 gchar *rating_symbol;
1786 if (pos == GTK_ENTRY_ICON_PRIMARY)
1788 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1789 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1790 g_free(rating_symbol);
1794 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1795 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1796 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1800 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1801 GdkEvent *event, gpointer userdata)
1803 gchar *rating_symbol;
1805 if (pos == GTK_ENTRY_ICON_PRIMARY)
1807 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1808 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1809 g_free(rating_symbol);
1813 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1814 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1815 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1819 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1821 GtkContainer *hbox = data;
1822 GString *str = g_string_new(NULL);
1823 GtkEntry *hex_code_entry;
1824 gchar *hex_code_full;
1827 guint64 hex_value = 0;
1829 list = gtk_container_get_children(hbox);
1831 hex_code_entry = g_list_nth_data(list, 2);
1832 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1834 hex_code = g_strsplit(hex_code_full, "+", 2);
1835 if (hex_code[0] && hex_code[1])
1837 hex_value = strtoull(hex_code[1], NULL, 16);
1839 if (!hex_value || hex_value > 0x10FFFF)
1841 hex_value = 0x003F; // Unicode 'Question Mark'
1843 str = g_string_append_unichar(str, (gunichar)hex_value);
1844 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1846 g_strfreev(hex_code);
1847 g_string_free(str, TRUE);
1848 g_free(hex_code_full);
1853 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1855 guint64 star_symbol;
1857 star_symbol = star_rating_symbol_test(widget, data);
1858 c_options->star_rating.star = star_symbol;
1861 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1863 guint64 rejected_symbol;
1865 rejected_symbol = star_rating_symbol_test(widget, data);
1866 c_options->star_rating.rejected = rejected_symbol;
1869 /* general options tab */
1870 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1871 typedef struct _TZData TZData;
1875 GCancellable *cancellable;
1877 GtkWidget *progress;
1879 GFile *timezone_database_gq;
1880 gchar *timezone_database_user;
1883 static void config_tab_general(GtkWidget *notebook)
1888 GtkWidget *group_frame;
1889 GtkWidget *subgroup;
1891 GtkWidget *ct_button;
1894 gint hours, minutes, remainder;
1896 GtkWidget *star_rating_entry;
1898 gchar *rating_symbol;
1901 GNetworkMonitor *net_mon;
1902 GSocketConnectable *geeqie_org;
1903 gboolean internet_available;
1906 vbox = scrolled_notebook_page(notebook, _("General"));
1908 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1910 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1911 add_thumb_size_menu(table, 0, 0, _("Size:"));
1912 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1914 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1915 pref_label_new(hbox, _("Custom size: "));
1916 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
1917 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
1919 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
1920 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1922 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1923 pref_checkbox_link_sensitivity(ct_button, subgroup);
1925 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1926 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1927 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1928 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1929 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1930 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1931 G_CALLBACK(cache_geeqie_cb), NULL);
1933 group_frame = pref_frame_new(subgroup, TRUE,
1934 _("Store thumbnails local to image folder (non-standard)"),
1935 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1936 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1937 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1938 G_CALLBACK(cache_local_cb), NULL);
1940 group_frame = pref_frame_new(subgroup, TRUE,
1941 _("Use standard thumbnail style and cache, shared with other applications"),
1942 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1943 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1944 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1945 G_CALLBACK(cache_standard_cb), NULL);
1947 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1948 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1950 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1952 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1953 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1955 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1956 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1957 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1959 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1960 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1963 pref_spacer(group, PREF_PAD_GROUP);
1965 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1967 c_options->star_rating.star = options->star_rating.star;
1968 c_options->star_rating.rejected = options->star_rating.rejected;
1970 str = g_string_new(NULL);
1971 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1972 pref_label_new(hbox, "Star character: ");
1973 str = g_string_append_unichar(str, options->star_rating.star);
1974 pref_label_new(hbox, g_strdup(str->str));
1975 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1976 star_rating_entry = gtk_entry_new();
1977 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1978 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1979 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1980 gtk_widget_show(star_rating_entry);
1981 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1982 G_CALLBACK(star_rating_star_test_cb), hbox);
1983 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1984 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1985 gtk_widget_show(button);
1986 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."));
1987 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1988 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1989 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1990 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1991 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1992 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1993 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1994 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1995 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1996 G_CALLBACK(star_rating_star_icon_cb),
1999 g_string_free(str, TRUE);
2000 g_free(rating_symbol);
2002 str = g_string_new(NULL);
2003 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2004 pref_label_new(hbox, "Rejected character: ");
2005 str = g_string_append_unichar(str, options->star_rating.rejected);
2006 pref_label_new(hbox, g_strdup(str->str));
2007 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2008 star_rating_entry = gtk_entry_new();
2009 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2010 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2011 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2012 gtk_widget_show(star_rating_entry);
2013 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2014 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2015 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2016 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2017 gtk_widget_show(button);
2018 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."));
2019 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2020 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2021 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2022 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2023 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2024 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2025 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2026 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2027 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2028 G_CALLBACK(star_rating_rejected_icon_cb),
2031 g_string_free(str, TRUE);
2032 g_free(rating_symbol);
2034 pref_spacer(group, PREF_PAD_GROUP);
2036 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2038 c_options->slideshow.delay = options->slideshow.delay;
2039 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2040 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2041 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2042 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2043 SLIDESHOW_SUBSECOND_PRECISION;
2045 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2047 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2049 options->slideshow.delay ? hours : 0.0,
2050 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2051 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2052 spin = pref_spin_new(hbox, ":" , NULL,
2054 options->slideshow.delay ? minutes: 0.0,
2055 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2056 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2057 spin = pref_spin_new(hbox, ":", NULL,
2058 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2059 options->slideshow.delay ? seconds : 10.0,
2060 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2061 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2063 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2064 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2066 pref_spacer(group, PREF_PAD_GROUP);
2068 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2070 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
2071 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2072 pref_checkbox_new_int(group, _("Preload next image"),
2073 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2075 pref_checkbox_new_int(group, _("Refresh on file change"),
2076 options->update_on_time_change, &c_options->update_on_time_change);
2079 pref_spacer(group, PREF_PAD_GROUP);
2081 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2083 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2084 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2085 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2087 pref_spacer(group, PREF_PAD_GROUP);
2089 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
2090 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
2091 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2092 pref_spin_new_int(hbox, _("Keywords:"), NULL,
2094 options->info_keywords.height, &c_options->info_keywords.height);
2095 pref_spin_new_int(hbox, _("Title:"), NULL,
2097 options->info_title.height, &c_options->info_title.height);
2098 pref_spin_new_int(hbox, _("Comment:"), NULL,
2100 options->info_comment.height, &c_options->info_comment.height);
2101 pref_spin_new_int(hbox, _("Rating:"), NULL,
2103 options->info_rating.height, &c_options->info_rating.height);
2105 pref_spacer(group, PREF_PAD_GROUP);
2107 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
2109 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
2110 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
2112 pref_spacer(group, PREF_PAD_GROUP);
2114 net_mon = g_network_monitor_get_default();
2115 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2116 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2117 g_object_unref(geeqie_org);
2119 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2120 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2122 if (!internet_available)
2124 gtk_widget_set_sensitive(group, FALSE);
2127 tz = g_new0(TZData, 1);
2129 path = path_from_utf8(TIMEZONE_DATABASE);
2130 basename = g_path_get_basename(path);
2131 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2135 if (isfile(tz->timezone_database_user))
2137 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2141 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2144 if (!internet_available)
2146 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"));
2150 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"));
2152 gtk_widget_show(button);
2154 pref_spacer(group, PREF_PAD_GROUP);
2156 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2158 help_search_engine_entry = gtk_entry_new();
2159 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2160 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2161 gtk_widget_show(help_search_engine_entry);
2163 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"));
2165 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2166 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2167 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2168 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2169 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2170 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2171 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2172 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2173 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2174 G_CALLBACK(help_search_engine_entry_icon_cb),
2175 help_search_engine_entry);
2179 static void config_tab_image(GtkWidget *notebook)
2184 GtkWidget *ct_button;
2185 GtkWidget *enlargement_button;
2188 GtkWidget *two_pass;
2190 GtkWidget *gpu_accel;
2193 vbox = scrolled_notebook_page(notebook, _("Image"));
2195 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2197 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2198 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2199 if (options->image.use_clutter_renderer && !options->disable_gpu)
2201 gtk_widget_set_sensitive(table, FALSE);
2205 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2206 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2207 if (options->disable_gpu && !options->override_disable_gpu)
2209 gtk_widget_set_sensitive(gpu_accel, FALSE);
2213 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2214 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2215 if (options->image.use_clutter_renderer && !options->disable_gpu)
2217 gtk_widget_set_sensitive(two_pass, FALSE);
2220 c_options->image.zoom_increment = options->image.zoom_increment;
2221 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2222 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2223 G_CALLBACK(zoom_increment_cb), NULL);
2224 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2226 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2228 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2229 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2230 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2231 spin = pref_spin_new_int(hbox, NULL, NULL,
2233 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2234 pref_checkbox_link_sensitivity(enlargement_button, spin);
2235 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."));
2237 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2238 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2239 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2240 spin = pref_spin_new_int(hbox, NULL, NULL,
2242 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2243 pref_checkbox_link_sensitivity(ct_button, spin);
2244 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."));
2246 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2248 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2249 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2251 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2252 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2254 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2255 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2257 c_options->image.border_color = options->image.border_color;
2259 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2260 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2262 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2263 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2265 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2266 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2268 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2270 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2271 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2275 static void config_tab_windows(GtkWidget *notebook)
2281 GtkWidget *ct_button;
2284 vbox = scrolled_notebook_page(notebook, _("Windows"));
2286 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2288 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2289 options->save_window_positions, &c_options->save_window_positions);
2291 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2292 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2293 pref_checkbox_link_sensitivity(ct_button, button);
2295 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2296 options->tools_restore_state, &c_options->tools_restore_state);
2298 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2299 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2301 pref_checkbox_new_int(group, _("Show window IDs"),
2302 options->show_window_ids, &c_options->show_window_ids);
2304 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2306 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2307 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2309 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2310 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2311 options->image.limit_window_size, &c_options->image.limit_window_size);
2312 spin = pref_spin_new_int(hbox, NULL, NULL,
2314 options->image.max_window_size, &c_options->image.max_window_size);
2315 pref_checkbox_link_sensitivity(ct_button, spin);
2317 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2319 c_options->fullscreen.screen = options->fullscreen.screen;
2320 c_options->fullscreen.above = options->fullscreen.above;
2321 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2322 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2323 gtk_widget_show(hbox);
2325 pref_checkbox_new_int(group, _("Smooth image flip"),
2326 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2327 pref_checkbox_new_int(group, _("Disable screen saver"),
2328 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2331 #define PRE_FORMATTED_COLUMNS 5
2332 static void config_tab_osd(GtkWidget *notebook)
2338 GtkWidget *image_overlay_template_view;
2339 GtkWidget *scrolled;
2340 GtkWidget *scrolled_pre_formatted;
2341 GtkTextBuffer *buffer;
2343 GtkWidget *subgroup;
2345 vbox = scrolled_notebook_page(notebook, _("OSD"));
2347 image_overlay_template_view = gtk_text_view_new();
2349 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2351 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2353 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2354 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2355 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2356 gtk_widget_show(scrolled_pre_formatted);
2357 gtk_widget_show(subgroup);
2359 pref_line(group, PREF_PAD_GAP);
2361 pref_label_new(group, _("Image overlay template"));
2363 scrolled = gtk_scrolled_window_new(NULL, NULL);
2364 gtk_widget_set_size_request(scrolled, 200, 150);
2365 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2366 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2367 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2368 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2369 gtk_widget_show(scrolled);
2371 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2372 _("Extensive formatting options are shown in the Help file"));
2374 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2375 gtk_widget_show(image_overlay_template_view);
2377 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2379 #if GTK_CHECK_VERSION(3,4,0)
2380 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2381 G_CALLBACK(image_overlay_set_font_cb), notebook);
2383 button = gtk_font_button_new();
2384 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2385 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2386 g_signal_connect(G_OBJECT(button), "font-set",
2387 G_CALLBACK(image_overlay_set_font_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, _("Text"), FALSE,
2393 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2394 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2395 gtk_widget_show(button);
2397 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2398 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2399 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2400 gtk_widget_show(button);
2401 image_overlay_set_text_colours();
2403 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2404 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2405 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2406 gtk_widget_show(button);
2408 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2409 G_CALLBACK(image_overlay_help_cb), NULL);
2410 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2411 gtk_widget_show(button);
2413 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2414 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2415 g_signal_connect(G_OBJECT(buffer), "changed",
2416 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2418 pref_line(group, PREF_PAD_GAP);
2420 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2421 hbox = gtk_hbox_new(FALSE, 0);
2422 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2423 gtk_widget_show(hbox);
2424 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2425 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2426 gtk_widget_show(label);
2427 pref_spacer(group,TRUE);
2429 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2430 hbox = gtk_hbox_new(FALSE, 0);
2431 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2432 gtk_widget_show(hbox);
2433 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2434 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2435 gtk_widget_show(label);
2436 pref_spacer(group,TRUE);
2438 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2439 hbox = gtk_hbox_new(FALSE, 0);
2440 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2441 gtk_widget_show(hbox);
2442 label = gtk_label_new(_("%path:39%"));
2443 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2444 gtk_widget_show(label);
2445 pref_spacer(group,TRUE);
2447 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2448 hbox = gtk_hbox_new(FALSE, 0);
2449 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2450 gtk_widget_show(hbox);
2451 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%"));
2452 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2453 gtk_widget_show(label);
2454 pref_spacer(group,TRUE);
2456 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2457 hbox = gtk_hbox_new(FALSE, 0);
2458 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2459 gtk_widget_show(hbox);
2460 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2461 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2462 gtk_widget_show(label);
2465 static GtkTreeModel *create_class_model(void)
2467 GtkListStore *model;
2471 /* create list store */
2472 model = gtk_list_store_new(1, G_TYPE_STRING);
2473 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2475 gtk_list_store_append(model, &iter);
2476 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2478 return GTK_TREE_MODEL (model);
2483 static void config_tab_files(GtkWidget *notebook)
2490 GtkWidget *ct_button;
2491 GtkWidget *scrolled;
2492 GtkWidget *filter_view;
2493 GtkCellRenderer *renderer;
2494 GtkTreeSelection *selection;
2495 GtkTreeViewColumn *column;
2497 vbox = scrolled_notebook_page(notebook, _("Files"));
2499 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2501 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2502 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2503 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2504 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2505 pref_checkbox_new_int(group, _("Case sensitive sort"),
2506 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2507 pref_checkbox_new_int(group, _("Natural sort order"),
2508 options->file_sort.natural, &c_options->file_sort.natural);
2509 pref_checkbox_new_int(group, _("Disable file extension checks"),
2510 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2512 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2513 options->file_filter.disable, &c_options->file_filter.disable);
2516 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2518 sidecar_ext_entry = gtk_entry_new();
2519 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2520 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2521 gtk_widget_show(sidecar_ext_entry);
2523 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2525 frame = pref_group_parent(group);
2526 g_signal_connect(G_OBJECT(ct_button), "toggled",
2527 G_CALLBACK(filter_disable_cb), frame);
2528 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2530 scrolled = gtk_scrolled_window_new(NULL, NULL);
2531 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2532 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2533 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2534 gtk_widget_show(scrolled);
2536 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2537 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2538 g_object_unref(filter_store);
2539 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2540 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2542 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2544 column = gtk_tree_view_column_new();
2545 gtk_tree_view_column_set_title(column, _("Filter"));
2546 gtk_tree_view_column_set_resizable(column, TRUE);
2548 renderer = gtk_cell_renderer_toggle_new();
2549 g_signal_connect(G_OBJECT(renderer), "toggled",
2550 G_CALLBACK(filter_store_enable_cb), filter_store);
2551 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2552 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2553 GINT_TO_POINTER(FE_ENABLE), NULL);
2555 renderer = gtk_cell_renderer_text_new();
2556 g_signal_connect(G_OBJECT(renderer), "edited",
2557 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2558 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2559 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2560 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2561 GINT_TO_POINTER(FE_EXTENSION), NULL);
2562 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2564 column = gtk_tree_view_column_new();
2565 gtk_tree_view_column_set_title(column, _("Description"));
2566 gtk_tree_view_column_set_resizable(column, TRUE);
2567 gtk_tree_view_column_set_fixed_width(column, 200);
2568 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2570 renderer = gtk_cell_renderer_text_new();
2571 g_signal_connect(G_OBJECT(renderer), "edited",
2572 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2573 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2574 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2575 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2576 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2577 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2579 column = gtk_tree_view_column_new();
2580 gtk_tree_view_column_set_title(column, _("Class"));
2581 gtk_tree_view_column_set_resizable(column, TRUE);
2582 renderer = gtk_cell_renderer_combo_new();
2583 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2584 "model", create_class_model(),
2589 g_signal_connect(G_OBJECT(renderer), "edited",
2590 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2591 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2592 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2593 GINT_TO_POINTER(FE_CLASS), NULL);
2594 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2596 column = gtk_tree_view_column_new();
2597 gtk_tree_view_column_set_title(column, _("Writable"));
2598 gtk_tree_view_column_set_resizable(column, FALSE);
2599 renderer = gtk_cell_renderer_toggle_new();
2600 g_signal_connect(G_OBJECT(renderer), "toggled",
2601 G_CALLBACK(filter_store_writable_cb), filter_store);
2602 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2603 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2604 GINT_TO_POINTER(FE_WRITABLE), NULL);
2605 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2607 column = gtk_tree_view_column_new();
2608 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2609 gtk_tree_view_column_set_resizable(column, FALSE);
2610 renderer = gtk_cell_renderer_toggle_new();
2611 g_signal_connect(G_OBJECT(renderer), "toggled",
2612 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2613 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2614 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2615 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2616 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2619 filter_store_populate();
2620 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2621 gtk_widget_show(filter_view);
2623 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2625 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2626 G_CALLBACK(filter_default_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_REMOVE, NULL, FALSE,
2631 G_CALLBACK(filter_remove_cb), filter_view);
2632 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2633 gtk_widget_show(button);
2635 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2636 G_CALLBACK(filter_add_cb), filter_view);
2637 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2638 gtk_widget_show(button);
2642 static void config_tab_metadata(GtkWidget *notebook)
2647 GtkWidget *ct_button;
2651 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2654 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2656 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2658 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2659 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2661 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2662 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2664 gtk_widget_set_sensitive(ct_button, FALSE);
2667 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2668 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2670 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2671 label = pref_label_new(group, text);
2672 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2673 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2676 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2678 gtk_widget_set_sensitive(group, FALSE);
2681 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2682 pref_checkbox_link_sensitivity(ct_button, hbox);
2684 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2685 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2687 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2688 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2690 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2691 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2693 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2694 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2696 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2698 gtk_widget_set_sensitive(group, FALSE);
2701 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2702 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2705 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2706 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2707 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2709 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2710 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2712 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2713 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2715 gtk_widget_set_sensitive(ct_button, FALSE);
2718 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2720 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2721 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2723 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2724 pref_checkbox_link_sensitivity(ct_button, hbox);
2726 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2727 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2729 pref_checkbox_new_int(group, _("Write metadata on image change"),
2730 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2732 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2733 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2735 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2737 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2738 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2739 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");
2744 typedef struct _KeywordFindData KeywordFindData;
2745 struct _KeywordFindData
2752 GtkWidget *button_close;
2753 GtkWidget *button_stop;
2754 GtkWidget *button_start;
2755 GtkWidget *progress;
2763 guint idle_id; /* event source id */
2766 #define KEYWORD_DIALOG_WIDTH 400
2768 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2770 GList *list_d = NULL;
2771 GList *list_f = NULL;
2775 filelist_read(dir_fd, &list_f, &list_d);
2779 filelist_read(dir_fd, &list_f, NULL);
2782 list_f = filelist_filter(list_f, FALSE);
2783 list_d = filelist_filter(list_d, TRUE);
2785 kfd->list = g_list_concat(list_f, kfd->list);
2786 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2789 static void keywords_find_reset(KeywordFindData *kfd)
2791 filelist_free(kfd->list);
2794 filelist_free(kfd->list_dir);
2795 kfd->list_dir = NULL;
2798 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2800 KeywordFindData *kfd = data;
2802 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2804 keywords_find_reset(kfd);
2805 generic_dialog_close(kfd->gd);
2809 static void keywords_find_finish(KeywordFindData *kfd)
2811 keywords_find_reset(kfd);
2813 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2814 spinner_set_interval(kfd->spinner, -1);
2816 gtk_widget_set_sensitive(kfd->group, TRUE);
2817 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2818 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2819 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2822 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2824 KeywordFindData *kfd = data;
2826 g_idle_remove_by_data(kfd);
2828 keywords_find_finish(kfd);
2831 static gboolean keywords_find_file(gpointer data)
2833 KeywordFindData *kfd = data;
2835 GtkTextBuffer *buffer;
2843 fd = kfd->list->data;
2844 kfd->list = g_list_remove(kfd->list, fd);
2846 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2847 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2851 gtk_text_buffer_get_end_iter(buffer, &iter);
2852 tmp = g_strconcat(keywords->data, "\n", NULL);
2853 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2855 keywords = keywords->next;
2858 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2859 file_data_unref(fd);
2860 string_list_free(keywords);
2864 else if (kfd->list_dir)
2868 fd = kfd->list_dir->data;
2869 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2871 keywords_find_folder(kfd, fd);
2873 file_data_unref(fd);
2878 keywords_find_finish(kfd);
2883 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2885 KeywordFindData *kfd = data;
2888 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2890 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2891 parse_out_relatives(path);
2895 warning_dialog(_("Invalid folder"),
2896 _("The specified folder can not be found."),
2897 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2903 gtk_widget_set_sensitive(kfd->group, FALSE);
2904 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2905 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2906 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2907 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2909 dir_fd = file_data_new_dir(path);
2910 keywords_find_folder(kfd, dir_fd);
2911 file_data_unref(dir_fd);
2912 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2918 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2920 KeywordFindData *kfd;
2924 kfd = g_new0(KeywordFindData, 1);
2926 kfd->gd = generic_dialog_new(_("Search for keywords"),
2927 "search_for_keywords",
2930 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2931 kfd->gd->cancel_cb = keywords_find_close_cb;
2932 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2933 keywords_find_close_cb, FALSE);
2934 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2935 keywords_find_start_cb, FALSE);
2936 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2937 keywords_find_stop_cb, FALSE);
2938 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2940 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2942 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2943 pref_spacer(hbox, PREF_PAD_INDENT);
2944 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2946 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2947 pref_label_new(hbox, _("Folder:"));
2949 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2950 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2951 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2952 gtk_widget_show(label);
2954 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2956 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2957 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2959 kfd->progress = gtk_entry_new();
2960 gtk_widget_set_can_focus(kfd->progress, FALSE);
2961 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2962 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2963 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2964 gtk_widget_show(kfd->progress);
2966 kfd->spinner = spinner_new(NULL, -1);
2967 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2968 gtk_widget_show(kfd->spinner);
2972 gtk_widget_show(kfd->gd->dialog);
2975 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2977 const gchar *path = layout_get_path(NULL);
2979 if (!path || !*path) path = homedir();
2980 keywords_find_dialog(widget, path);
2983 static void config_tab_keywords_save()
2985 GtkTextIter start, end;
2986 GtkTextBuffer *buffer;
2987 GList *kw_list = NULL;
2993 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2994 gtk_text_buffer_get_bounds(buffer, &start, &end);
2996 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2998 kw_split = strtok(buffer_text, "\n");
2999 while (kw_split != NULL)
3005 if (g_strcmp0(work->data, kw_split) == 0)
3014 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3016 kw_split = strtok(NULL, "\n");
3019 keyword_list_set(kw_list);
3021 string_list_free(kw_list);
3022 g_free(buffer_text);
3025 static void config_tab_keywords(GtkWidget *notebook)
3031 GtkWidget *scrolled;
3033 GtkTextBuffer *buffer;
3036 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3038 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3040 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3042 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3043 G_CALLBACK(keywords_find_cb), keyword_text);
3044 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3047 keyword_text = gtk_text_view_new();
3048 gtk_widget_set_size_request(keyword_text, 20, 20);
3049 scrolled = gtk_scrolled_window_new(NULL, NULL);
3050 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3051 gtk_widget_show(scrolled);
3053 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3054 gtk_widget_show(keyword_text);
3056 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3058 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3059 gtk_text_buffer_create_tag(buffer, "monospace",
3060 "family", "monospace", NULL);
3062 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3063 gtk_text_buffer_get_start_iter(buffer, &iter);
3064 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3067 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3069 GList *kwl = keyword_list_get();
3070 kwl = g_list_first(kwl);
3073 gtk_text_buffer_get_end_iter (buffer, &iter);
3074 tmp = g_strconcat(kwl->data, "\n", NULL);
3075 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3080 gtk_text_buffer_set_modified(buffer, FALSE);
3087 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3089 gint *option = data;
3091 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3095 *option = INTENT_PERCEPTUAL;
3098 *option = INTENT_RELATIVE_COLORIMETRIC;
3101 *option = INTENT_SATURATION;
3104 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3109 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3110 gint option, gint *option_c)
3117 pref_table_label(table, column, row, text, 0.0);
3119 combo = gtk_combo_box_text_new();
3121 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3122 if (option == INTENT_PERCEPTUAL) current = 0;
3123 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3124 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3125 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3126 if (option == INTENT_SATURATION) current = 2;
3127 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3128 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3130 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3132 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3134 g_signal_connect(G_OBJECT(combo), "changed",
3135 G_CALLBACK(intent_menu_cb), option_c);
3137 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3138 gtk_widget_show(combo);
3142 static void config_tab_color(GtkWidget *notebook)
3151 vbox = scrolled_notebook_page(notebook, _("Color management"));
3153 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3155 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3158 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3159 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3161 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3162 pref_label_bold(label, TRUE, FALSE);
3164 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3165 pref_label_bold(label, TRUE, FALSE);
3167 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3168 pref_label_bold(label, TRUE, FALSE);
3170 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3175 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3176 pref_table_label(table, 0, i + 1, buf, 1.0);
3179 entry = gtk_entry_new();
3180 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3181 if (options->color_profile.input_name[i])
3183 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3185 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3186 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3187 gtk_widget_show(entry);
3188 color_profile_input_name_entry[i] = entry;
3190 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3191 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3192 gtk_widget_set_size_request(entry, 160, -1);
3193 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3194 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3195 gtk_widget_show(tabcomp);
3196 color_profile_input_file_entry[i] = entry;
3199 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3201 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3203 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3204 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3206 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3208 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3209 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3210 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3211 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3212 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3214 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3216 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3218 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3220 gtk_widget_show(tabcomp);
3223 /* advanced entry tab */
3224 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3226 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3228 c_options->file_ops.use_system_trash = FALSE;
3229 c_options->file_ops.no_trash = FALSE;
3233 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3235 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3237 c_options->file_ops.use_system_trash = TRUE;
3238 c_options->file_ops.no_trash = FALSE;
3242 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3244 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3246 c_options->file_ops.no_trash = TRUE;
3250 static void config_tab_behavior(GtkWidget *notebook)
3257 GtkWidget *ct_button;
3261 GtkWidget *with_rename;
3262 GtkWidget *collections_on_top;
3263 GtkWidget *hide_window_in_fullscreen;
3264 GtkWidget *checkbox;
3266 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3268 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3270 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3271 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3272 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3273 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3274 pref_checkbox_new_int(group, _("Enable Delete key"),
3275 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3277 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3278 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3280 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3281 pref_checkbox_link_sensitivity(ct_button, hbox);
3283 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3284 pref_label_new(hbox, _("Folder:"));
3286 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3287 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3288 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3289 gtk_widget_show(tabcomp);
3291 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3292 pref_checkbox_link_sensitivity(ct_button, hbox);
3294 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3295 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3296 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3297 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3298 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3299 G_CALLBACK(safe_delete_view_cb), NULL);
3300 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3301 gtk_widget_show(button);
3303 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3304 G_CALLBACK(safe_delete_clear_cb), NULL);
3305 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3306 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3307 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3309 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3310 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3312 gtk_widget_show(button);
3314 pref_spacer(group, PREF_PAD_GROUP);
3317 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3319 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3320 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3322 pref_checkbox_new_int(group, _("In place renaming"),
3323 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3325 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3326 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3328 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3329 options->marks_save, &c_options->marks_save);
3330 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3332 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3333 options->with_rename, &c_options->with_rename);
3334 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3336 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3337 options->collections_on_top, &c_options->collections_on_top);
3338 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3340 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3341 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3342 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3344 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3345 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3347 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3348 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3350 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3351 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3353 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3354 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3356 pref_spacer(group, PREF_PAD_GROUP);
3358 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3360 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3361 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3362 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3363 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3364 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3365 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3366 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3367 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3368 pref_checkbox_new_int(group, _("Play video by left click on image"),
3369 options->image_l_click_video, &c_options->image_l_click_video);
3370 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3371 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3373 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3374 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3375 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3376 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3377 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3379 pref_spacer(group, PREF_PAD_GROUP);
3381 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3383 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3384 options->override_disable_gpu, &c_options->override_disable_gpu);
3385 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3388 pref_spacer(group, PREF_PAD_GROUP);
3390 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3392 pref_spin_new_int(group, _("Debug level:"), NULL,
3393 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3395 pref_checkbox_new_int(group, _("Timer data"),
3396 options->log_window.timer_data, &c_options->log_window.timer_data);
3398 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3399 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3403 /* accelerators tab */
3404 static void config_tab_accelerators(GtkWidget *notebook)
3410 GtkWidget *scrolled;
3411 GtkWidget *accel_view;
3412 GtkCellRenderer *renderer;
3413 GtkTreeSelection *selection;
3414 GtkTreeViewColumn *column;
3416 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3418 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3420 scrolled = gtk_scrolled_window_new(NULL, NULL);
3421 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3422 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3423 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3424 gtk_widget_show(scrolled);
3426 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3428 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3429 g_object_unref(accel_store);
3430 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3431 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3433 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3435 renderer = gtk_cell_renderer_text_new();
3437 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3442 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3443 gtk_tree_view_column_set_resizable(column, TRUE);
3444 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3447 renderer = gtk_cell_renderer_accel_new();
3448 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3449 G_CALLBACK(accel_store_cleared_cb), accel_store);
3450 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3451 G_CALLBACK(accel_store_edited_cb), accel_store);
3454 g_object_set (renderer,
3456 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3459 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3464 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3465 gtk_tree_view_column_set_resizable(column, TRUE);
3466 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3468 renderer = gtk_cell_renderer_text_new();
3470 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3475 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3476 gtk_tree_view_column_set_resizable(column, TRUE);
3477 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3479 renderer = gtk_cell_renderer_text_new();
3481 column = gtk_tree_view_column_new_with_attributes("Accel",
3486 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3487 gtk_tree_view_column_set_resizable(column, TRUE);
3488 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3490 accel_store_populate();
3491 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3492 gtk_widget_show(accel_view);
3494 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3496 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3497 G_CALLBACK(accel_default_cb), accel_view);
3498 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3499 gtk_widget_show(button);
3501 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3502 G_CALLBACK(accel_reset_cb), accel_view);
3503 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3504 gtk_widget_show(button);
3507 /* toolbar main tab */
3508 static void config_tab_toolbar_main(GtkWidget *notebook)
3511 GtkWidget *toolbardata;
3514 lw = layout_window_list->data;
3516 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3518 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3519 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3520 gtk_widget_show(vbox);
3523 /* toolbar status tab */
3524 static void config_tab_toolbar_status(GtkWidget *notebook)
3527 GtkWidget *toolbardata;
3530 lw = layout_window_list->data;
3532 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3534 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3535 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3536 gtk_widget_show(vbox);
3540 static void config_tab_stereo(GtkWidget *notebook)
3548 GtkWidget *fs_button;
3549 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3551 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3553 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3554 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3556 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3557 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3558 pref_checkbox_new_int(box, _("Mirror left image"),
3559 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3560 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3561 pref_checkbox_new_int(box, _("Flip left image"),
3562 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3563 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3564 pref_checkbox_new_int(box, _("Mirror right image"),
3565 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3566 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3567 pref_checkbox_new_int(box, _("Flip right image"),
3568 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3569 pref_checkbox_new_int(group, _("Swap left and right images"),
3570 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3571 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3572 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3574 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3575 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3576 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3577 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3578 pref_checkbox_link_sensitivity(fs_button, box2);
3579 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3580 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3581 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3582 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3583 pref_checkbox_new_int(box, _("Mirror left image"),
3584 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3585 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3586 pref_checkbox_new_int(box, _("Flip left image"),
3587 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3588 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3589 pref_checkbox_new_int(box, _("Mirror right image"),
3590 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3591 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3592 pref_checkbox_new_int(box, _("Flip right image"),
3593 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3594 pref_checkbox_new_int(box2, _("Swap left and right images"),
3595 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3596 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3597 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3599 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3600 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3601 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3602 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3603 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3604 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3605 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3606 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3607 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3608 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3609 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3610 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3611 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3612 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3616 /* Main preferences window */
3617 static void config_window_create(void)
3619 GtkWidget *win_vbox;
3621 GtkWidget *notebook;
3623 GtkWidget *ct_button;
3625 if (!c_options) c_options = init_options(NULL);
3627 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3628 DEBUG_NAME(configwindow);
3629 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3630 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3631 G_CALLBACK(config_window_delete), NULL);
3632 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3633 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3634 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3636 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3637 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3638 gtk_widget_show(win_vbox);
3640 notebook = gtk_notebook_new();
3641 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3642 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3643 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3645 config_tab_general(notebook);
3646 config_tab_image(notebook);
3647 config_tab_osd(notebook);
3648 config_tab_windows(notebook);
3649 config_tab_accelerators(notebook);
3650 config_tab_files(notebook);
3651 config_tab_metadata(notebook);
3652 config_tab_keywords(notebook);
3653 config_tab_color(notebook);
3654 config_tab_stereo(notebook);
3655 config_tab_behavior(notebook);
3656 config_tab_toolbar_main(notebook);
3657 config_tab_toolbar_status(notebook);
3659 hbox = gtk_hbutton_box_new();
3660 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3661 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3662 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3663 gtk_widget_show(hbox);
3665 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3666 G_CALLBACK(config_window_help_cb), notebook);
3667 gtk_container_add(GTK_CONTAINER(hbox), button);
3668 gtk_widget_set_can_default(button, TRUE);
3669 gtk_widget_show(button);
3671 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3672 G_CALLBACK(config_window_ok_cb), NULL);
3673 gtk_container_add(GTK_CONTAINER(hbox), button);
3674 gtk_widget_set_can_default(button, TRUE);
3675 gtk_widget_grab_default(button);
3676 gtk_widget_show(button);
3680 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3681 G_CALLBACK(config_window_close_cb), NULL);
3682 gtk_container_add(GTK_CONTAINER(hbox), button);
3683 gtk_widget_set_can_default(button, TRUE);
3684 gtk_widget_show(button);
3686 if (!generic_dialog_get_alternative_button_order(configwindow))
3688 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3691 gtk_widget_show(notebook);
3693 gtk_widget_show(configwindow);
3697 *-----------------------------------------------------------------------------
3698 * config window show (public)
3699 *-----------------------------------------------------------------------------
3702 void show_config_window(void)
3706 gtk_window_present(GTK_WINDOW(configwindow));
3710 config_window_create();
3719 void show_about_window(LayoutWindow *lw)
3721 GdkPixbuf *pixbuf_logo;
3722 GdkPixbuf *pixbuf_icon;
3723 gchar *authors[1000];
3728 gchar *timezone_path;
3732 #define LINE_LENGTH 1000
3733 gchar line[LINE_LENGTH];
3735 copyright = g_string_new(NULL);
3736 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");
3738 path = path_from_utf8(TIMEZONE_DATABASE);
3739 basename = g_path_get_basename(path);
3740 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3741 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3743 cd = ZDOpenDatabase(timezone_path);
3746 copyright = g_string_append(copyright, ZDGetNotice(cd));
3747 ZDCloseDatabase(cd);
3751 g_free(timezone_path);
3755 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3756 fp = fopen(path, "r");
3759 while(fgets(line, LINE_LENGTH, fp))
3761 /* get rid of ending \n from fgets */
3762 line[strlen(line) - 1] = '\0';
3763 authors[i_authors] = g_strdup(line);
3766 authors[i_authors] = NULL;
3771 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3772 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3774 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3775 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3776 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3777 "title", _("About Geeqie"),
3779 "program-name", GQ_APPNAME,
3781 "logo", pixbuf_logo,
3782 "icon", pixbuf_icon,
3783 "website", GQ_WEBSITE,
3784 "website-label", "Website",
3785 "comments", comment,
3787 "translator-credits", _("translator-credits"),
3788 "wrap-license", TRUE,
3789 "license", copyright->str,
3792 g_string_free(copyright, TRUE);
3795 while(n < i_authors)
3805 static void image_overlay_set_text_colours()
3807 c_options->image_overlay.text_red = options->image_overlay.text_red;
3808 c_options->image_overlay.text_green = options->image_overlay.text_green;
3809 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3810 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3811 c_options->image_overlay.background_red = options->image_overlay.background_red;
3812 c_options->image_overlay.background_green = options->image_overlay.background_green;
3813 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3814 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3818 *-----------------------------------------------------------------------------
3819 * timezone database routines
3820 *-----------------------------------------------------------------------------
3823 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3825 GError *error = NULL;
3827 gchar *tmp_filename;
3829 if (!g_cancellable_is_cancelled(tz->cancellable))
3831 generic_dialog_close(tz->gd);
3835 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3837 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3838 move_file(tmp_filename, tz->timezone_database_user);
3839 g_free(tmp_filename);
3843 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3846 g_file_delete(tz->tmp_g_file, NULL, &error);
3847 g_object_unref(tz->tmp_g_file);
3848 tz->tmp_g_file = NULL;
3849 g_object_unref(tz->cancellable);
3850 g_object_unref(tz->timezone_database_gq);
3853 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3857 if (!g_cancellable_is_cancelled(tz->cancellable))
3859 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3863 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3867 g_cancellable_cancel(tz->cancellable);
3870 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3873 GError *error = NULL;
3874 GFileIOStream *io_stream;
3881 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3885 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3886 log_printf("Error: Download timezone database failed:\n%s", error->message);
3887 g_error_free(error);
3888 g_object_unref(tz->tmp_g_file);
3892 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3894 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3896 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3898 tz->progress = gtk_progress_bar_new();
3899 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3900 gtk_widget_show(tz->progress);
3902 gtk_widget_show(tz->gd->dialog);
3903 tz->cancellable = g_cancellable_new();
3904 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);
3906 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3909 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */