2 * Copyright (C) 2006 John Ellis
3 * Copyright (C) 2008 - 2016 The Geeqie Team
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "preferences.h"
26 #include "bar_keywords.h"
28 #include "cache_maint.h"
33 #include "filefilter.h"
34 #include "fullscreen.h"
36 #include "image-overlay.h"
37 #include "color-man.h"
39 #include "layout_config.h"
40 #include "layout_util.h"
43 #include "pixbuf_util.h"
44 #include "slideshow.h"
48 #include "ui_fileops.h"
50 #include "ui_spinner.h"
51 #include "ui_tabcomp.h"
52 #include "ui_utildlg.h"
54 #include "zonedetect.h"
64 #define EDITOR_NAME_MAX_LENGTH 32
65 #define EDITOR_COMMAND_MAX_LENGTH 1024
67 static void image_overlay_set_text_colours();
69 GtkWidget *keyword_text;
70 static void config_tab_keywords_save();
72 typedef struct _ThumbSize ThumbSize;
79 static ThumbSize thumb_size_list[] =
113 gchar *format_class_list[] = {
123 /* config memory values */
124 static ConfOptions *c_options = NULL;
131 static GtkWidget *configwindow = NULL;
132 static GtkListStore *filter_store = NULL;
133 static GtkTreeStore *accel_store = NULL;
135 static GtkWidget *safe_delete_path_entry;
137 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
138 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_screen_file_entry;
141 static GtkWidget *sidecar_ext_entry;
142 static GtkWidget *help_search_engine_entry;
145 #define CONFIG_WINDOW_DEF_WIDTH 700
146 #define CONFIG_WINDOW_DEF_HEIGHT 600
149 *-----------------------------------------------------------------------------
150 * option widget callbacks (private)
151 *-----------------------------------------------------------------------------
154 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
156 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
159 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
161 gint mins_secs_tenths, delay;
163 mins_secs_tenths = c_options->slideshow.delay %
164 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
166 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
167 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
170 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
171 SLIDESHOW_SUBSECOND_PRECISION;
174 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
176 gint hours, secs_tenths, delay;
178 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
179 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
181 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
182 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
183 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
185 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
186 SLIDESHOW_SUBSECOND_PRECISION;
189 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
191 gint hours_mins, delay;
193 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
195 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
196 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
197 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
199 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
200 SLIDESHOW_SUBSECOND_PRECISION;
204 *-----------------------------------------------------------------------------
205 * sync progam to config window routine (private)
206 *-----------------------------------------------------------------------------
209 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
215 buf = gtk_entry_get_text(GTK_ENTRY(entry));
216 if (buf && strlen(buf) > 0)
221 *option = g_strdup(buf);
226 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
228 gchar *accel_path, *accel;
230 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
232 if (accel_path && accel_path[0])
235 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
236 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
246 static void config_window_apply(void)
249 gboolean refresh = FALSE;
251 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
253 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
254 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
255 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
256 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
257 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
258 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
259 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
261 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
262 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
263 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
264 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
265 options->file_ops.no_trash = c_options->file_ops.no_trash;
266 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
267 options->tools_restore_state = c_options->tools_restore_state;
268 options->save_window_positions = c_options->save_window_positions;
269 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
270 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
271 options->show_window_ids = c_options->show_window_ids;
272 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
273 options->image.zoom_2pass = c_options->image.zoom_2pass;
274 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
275 options->image.limit_window_size = c_options->image.limit_window_size;
276 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
277 options->image.max_window_size = c_options->image.max_window_size;
278 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
279 options->image.max_autofit_size = c_options->image.max_autofit_size;
280 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
281 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
282 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
283 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
285 if (options->thumbnails.max_width != c_options->thumbnails.max_width
286 || options->thumbnails.max_height != c_options->thumbnails.max_height
287 || options->thumbnails.quality != c_options->thumbnails.quality)
289 thumb_format_changed = TRUE;
291 options->thumbnails.max_width = c_options->thumbnails.max_width;
292 options->thumbnails.max_height = c_options->thumbnails.max_height;
293 options->thumbnails.quality = c_options->thumbnails.quality;
295 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
296 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
297 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
298 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
299 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
300 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
301 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
302 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
303 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
304 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
305 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
306 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
308 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
309 options->file_sort.natural = c_options->file_sort.natural;
310 options->file_filter.disable = c_options->file_filter.disable;
312 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
313 sidecar_ext_parse(options->sidecar.ext);
315 options->slideshow.random = c_options->slideshow.random;
316 options->slideshow.repeat = c_options->slideshow.repeat;
317 options->slideshow.delay = c_options->slideshow.delay;
319 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
320 options->image_lm_click_nav = c_options->image_lm_click_nav;
321 options->image_l_click_video = c_options->image_l_click_video;
322 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
324 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
326 options->image.tile_cache_max = c_options->image.tile_cache_max;
327 options->image.image_cache_max = c_options->image.image_cache_max;
329 options->image.zoom_quality = c_options->image.zoom_quality;
331 options->image.zoom_increment = c_options->image.zoom_increment;
333 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
336 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
337 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
338 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
340 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
341 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
342 options->image.border_color = c_options->image.border_color;
343 layout_colors_update();
344 view_window_colors_update();
347 options->image.alpha_color_1 = c_options->image.alpha_color_1;
348 options->image.alpha_color_2 = c_options->image.alpha_color_2;
350 options->fullscreen.screen = c_options->fullscreen.screen;
351 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
352 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
353 options->fullscreen.above = c_options->fullscreen.above;
354 if (c_options->image_overlay.template_string)
355 set_image_overlay_template_string(&options->image_overlay.template_string,
356 c_options->image_overlay.template_string);
357 if (c_options->image_overlay.font)
358 set_image_overlay_font_string(&options->image_overlay.font,
359 c_options->image_overlay.font);
360 options->image_overlay.text_red = c_options->image_overlay.text_red;
361 options->image_overlay.text_green = c_options->image_overlay.text_green;
362 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
363 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
364 options->image_overlay.background_red = c_options->image_overlay.background_red;
365 options->image_overlay.background_green = c_options->image_overlay.background_green;
366 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
367 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
368 options->update_on_time_change = c_options->update_on_time_change;
369 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
371 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
372 options->rot_invariant_sim = c_options->rot_invariant_sim;
374 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
376 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
378 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
379 options->dnd_icon_size = c_options->dnd_icon_size;
380 options->clipboard_selection = c_options->clipboard_selection;
382 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
383 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
384 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
385 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
386 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
387 options->metadata.confirm_write = c_options->metadata.confirm_write;
388 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
389 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
390 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
391 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
392 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
393 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
394 options->metadata.write_orientation = c_options->metadata.write_orientation;
395 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
396 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
397 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
398 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
399 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
400 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
401 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
402 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
403 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
404 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
406 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
407 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
408 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
409 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
410 options->stereo.fixed_w = c_options->stereo.fixed_w;
411 options->stereo.fixed_h = c_options->stereo.fixed_h;
412 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
413 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
414 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
415 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
417 options->info_keywords.height = c_options->info_keywords.height;
418 options->info_title.height = c_options->info_title.height;
419 options->info_comment.height = c_options->info_comment.height;
420 options->info_rating.height = c_options->info_rating.height;
422 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
424 options->marks_save = c_options->marks_save;
425 options->with_rename = c_options->with_rename;
426 options->collections_on_top = c_options->collections_on_top;
427 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
429 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
431 options->star_rating.star = c_options->star_rating.star;
432 options->star_rating.rejected = c_options->star_rating.rejected;
434 set_debug_level(debug_c);
438 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
440 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
441 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
443 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
444 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
445 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
447 options->color_profile.render_intent = c_options->color_profile.render_intent;
452 config_tab_keywords_save();
454 image_options_sync();
459 layout_refresh(NULL);
462 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
468 *-----------------------------------------------------------------------------
469 * config window main button callbacks (private)
470 *-----------------------------------------------------------------------------
473 static void config_window_close_cb(GtkWidget *widget, gpointer data)
475 gtk_widget_destroy(configwindow);
480 static void config_window_help_cb(GtkWidget *widget, gpointer data)
482 GtkWidget *notebook = data;
485 static gchar *html_section[] =
487 "GuideOptionsGeneral.html",
488 "GuideOptionsImage.html",
489 "GuideOptionsOSD.html",
490 "GuideOptionsWindow.html",
491 "GuideOptionsKeyboard.html",
492 "GuideOptionsFiltering.html",
493 "GuideOptionsMetadata.html",
494 "GuideOptionsKeywords.html",
495 "GuideOptionsColor.html",
496 "GuideOptionsStereo.html",
497 "GuideOptionsBehavior.html",
498 "GuideOptionsToolbar.html"
501 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
502 help_window_show(html_section[i]);
505 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
507 config_window_close_cb(NULL, NULL);
511 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
513 config_window_apply();
514 config_window_close_cb(NULL, NULL);
517 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
520 lw = layout_window_list->data;
522 config_window_apply();
523 layout_util_sync(lw);
526 static void config_window_save_cb(GtkWidget *widget, gpointer data)
528 config_window_apply();
529 save_options(options);
533 *-----------------------------------------------------------------------------
534 * config window setup (private)
535 *-----------------------------------------------------------------------------
538 static void quality_menu_cb(GtkWidget *combo, gpointer data)
542 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
546 *option = GDK_INTERP_NEAREST;
549 *option = GDK_INTERP_TILES;
552 *option = GDK_INTERP_BILINEAR;
555 *option = GDK_INTERP_HYPER;
560 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
564 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
576 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
577 guint option, guint *option_c)
584 pref_table_label(table, column, row, text, 0.0);
586 combo = gtk_combo_box_text_new();
588 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
589 if (option == GDK_INTERP_NEAREST) current = 0;
590 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
591 if (option == GDK_INTERP_TILES) current = 1;
592 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
593 if (option == GDK_INTERP_BILINEAR) current = 2;
594 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
595 if (option == GDK_INTERP_HYPER) current = 3;
597 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
599 g_signal_connect(G_OBJECT(combo), "changed",
600 G_CALLBACK(quality_menu_cb), option_c);
602 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
603 GTK_EXPAND | GTK_FILL, 0, 0, 0);
604 gtk_widget_show(combo);
607 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
608 gint option, gint *option_c)
615 pref_table_label(table, column, row, text, 0.0);
617 combo = gtk_combo_box_text_new();
619 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
620 if (option == PRIMARY) current = 0;
621 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
622 if (option == CLIPBOARD) current = 1;
624 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
626 g_signal_connect(G_OBJECT(combo), "changed",
627 G_CALLBACK(clipboard_selection_menu_cb), option_c);
629 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
630 GTK_EXPAND | GTK_FILL, 0, 0, 0);
631 gtk_widget_show(combo);
634 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
638 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
641 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
643 c_options->thumbnails.max_width = thumb_size_list[n].w;
644 c_options->thumbnails.max_height = thumb_size_list[n].h;
648 c_options->thumbnails.max_width = options->thumbnails.max_width;
649 c_options->thumbnails.max_height = options->thumbnails.max_height;
653 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
659 c_options->thumbnails.max_width = options->thumbnails.max_width;
660 c_options->thumbnails.max_height = options->thumbnails.max_height;
662 pref_table_label(table, column, row, text, 0.0);
664 combo = gtk_combo_box_text_new();
667 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
672 w = thumb_size_list[i].w;
673 h = thumb_size_list[i].h;
675 buf = g_strdup_printf("%d x %d", w, h);
676 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
679 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
686 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
687 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
693 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
694 g_signal_connect(G_OBJECT(combo), "changed",
695 G_CALLBACK(thumb_size_menu_cb), NULL);
697 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
698 GTK_EXPAND | GTK_FILL, 0, 0, 0);
699 gtk_widget_show(combo);
702 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
706 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
710 *option = PR_STEREO_NONE;
713 *option = PR_STEREO_ANAGLYPH_RC;
716 *option = PR_STEREO_ANAGLYPH_GM;
719 *option = PR_STEREO_ANAGLYPH_YB;
722 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
725 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
728 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
731 *option = PR_STEREO_ANAGLYPH_DB_RC;
734 *option = PR_STEREO_ANAGLYPH_DB_GM;
737 *option = PR_STEREO_ANAGLYPH_DB_YB;
740 *option = PR_STEREO_HORIZ;
743 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
746 *option = PR_STEREO_VERT;
749 *option = PR_STEREO_VERT | PR_STEREO_HALF;
752 *option = PR_STEREO_FIXED;
757 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
758 gint option, gint *option_c, gboolean add_fixed)
765 pref_table_label(table, column, row, text, 0.0);
767 combo = gtk_combo_box_text_new();
769 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
771 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
772 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
773 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
774 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
775 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
776 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
777 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
778 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
779 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
780 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
781 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
782 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
783 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
784 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
785 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
786 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
787 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
788 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
790 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
791 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
792 if (option & PR_STEREO_HORIZ)
795 if (option & PR_STEREO_HALF) current = 11;
798 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
799 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
800 if (option & PR_STEREO_VERT)
803 if (option & PR_STEREO_HALF) current = 13;
808 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
809 if (option & PR_STEREO_FIXED) current = 14;
812 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
814 g_signal_connect(G_OBJECT(combo), "changed",
815 G_CALLBACK(stereo_mode_menu_cb), option_c);
817 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
818 GTK_EXPAND | GTK_FILL, 0, 0, 0);
819 gtk_widget_show(combo);
822 static void video_menu_cb(GtkWidget *combo, gpointer data)
824 gchar **option = data;
826 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
830 static void video_menu_populate(gpointer data, gpointer user_data)
832 GtkWidget *combo = user_data;
833 EditorDescription *ed = data;
835 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
838 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
839 gchar *option, gchar **option_c)
843 /* use lists since they are sorted */
844 GList *eds = editor_list_get();
848 pref_table_label(table, column, row, text, 0.0);
850 combo = gtk_combo_box_text_new();
851 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
852 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
854 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
856 g_signal_connect(G_OBJECT(combo), "changed",
857 G_CALLBACK(video_menu_cb), option_c);
859 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
860 GTK_EXPAND | GTK_FILL, 0, 0, 0);
861 gtk_widget_show(combo);
864 static void filter_store_populate(void)
868 if (!filter_store) return;
870 gtk_list_store_clear(filter_store);
872 work = filter_get_list();
881 gtk_list_store_append(filter_store, &iter);
882 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
886 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
887 gchar *new_text, gpointer data)
889 GtkWidget *model = data;
890 FilterEntry *fe = data;
894 if (!new_text || strlen(new_text) < 1) return;
896 tpath = gtk_tree_path_new_from_string(path_str);
897 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
898 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
900 g_free(fe->extensions);
901 fe->extensions = g_strdup(new_text);
903 gtk_tree_path_free(tpath);
907 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
908 gchar *new_text, gpointer data)
910 GtkWidget *model = data;
911 FilterEntry *fe = data;
916 if (!new_text || !new_text[0]) return;
918 tpath = gtk_tree_path_new_from_string(path_str);
919 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
920 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
922 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
924 if (strcmp(new_text, _(format_class_list[i])) == 0)
931 gtk_tree_path_free(tpath);
935 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
936 gchar *new_text, gpointer data)
938 GtkWidget *model = data;
943 if (!new_text || !new_text[0]) return;
945 tpath = gtk_tree_path_new_from_string(path_str);
946 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
947 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
949 g_free(fe->description);
950 fe->description = g_strdup(new_text);
952 gtk_tree_path_free(tpath);
955 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
956 gchar *path_str, gpointer data)
958 GtkWidget *model = data;
963 tpath = gtk_tree_path_new_from_string(path_str);
964 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
965 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
967 fe->enabled = !fe->enabled;
969 gtk_tree_path_free(tpath);
973 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
974 gchar *path_str, gpointer data)
976 GtkWidget *model = data;
981 tpath = gtk_tree_path_new_from_string(path_str);
982 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
983 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
985 fe->writable = !fe->writable;
986 if (fe->writable) fe->allow_sidecar = FALSE;
988 gtk_tree_path_free(tpath);
992 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
993 gchar *path_str, gpointer data)
995 GtkWidget *model = data;
1000 tpath = gtk_tree_path_new_from_string(path_str);
1001 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1002 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1004 fe->allow_sidecar = !fe->allow_sidecar;
1005 if (fe->allow_sidecar) fe->writable = FALSE;
1007 gtk_tree_path_free(tpath);
1011 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1012 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1016 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1018 switch (GPOINTER_TO_INT(data))
1021 g_object_set(GTK_CELL_RENDERER(cell),
1022 "active", fe->enabled, NULL);
1025 g_object_set(GTK_CELL_RENDERER(cell),
1026 "text", fe->extensions, NULL);
1028 case FE_DESCRIPTION:
1029 g_object_set(GTK_CELL_RENDERER(cell),
1030 "text", fe->description, NULL);
1033 g_object_set(GTK_CELL_RENDERER(cell),
1034 "text", _(format_class_list[fe->file_class]), NULL);
1037 g_object_set(GTK_CELL_RENDERER(cell),
1038 "active", fe->writable, NULL);
1040 case FE_ALLOW_SIDECAR:
1041 g_object_set(GTK_CELL_RENDERER(cell),
1042 "active", fe->allow_sidecar, NULL);
1047 static gboolean filter_add_scroll(gpointer data)
1051 GtkCellRenderer *cell;
1052 GtkTreeViewColumn *column;
1057 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1058 path = gtk_tree_path_new_from_indices(rows-1, -1);
1060 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1062 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1063 cell = g_list_last(list_cells)->data;
1065 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1066 path, column, FALSE, 0.0, 0.0 );
1067 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1068 path, column, cell, TRUE);
1070 gtk_tree_path_free(path);
1071 g_list_free(list_cells);
1076 static void filter_add_cb(GtkWidget *widget, gpointer data)
1078 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1079 filter_store_populate();
1081 g_idle_add((GSourceFunc)filter_add_scroll, data);
1084 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1086 GtkWidget *filter_view = data;
1087 GtkTreeSelection *selection;
1091 if (!filter_store) return;
1092 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1093 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1094 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1097 filter_remove_entry(fe);
1099 filter_store_populate();
1102 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1106 GtkTreeViewColumn *column;
1108 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1109 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1110 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1112 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1116 gtk_tree_path_free(path);
1121 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1124 filter_add_defaults();
1126 filter_store_populate();
1128 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1131 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1133 /* no op, only so cancel button appears */
1136 static void filter_default_cb(GtkWidget *widget, gpointer data)
1140 gd = generic_dialog_new(_("Reset filters"),
1141 "reset_filter", widget, TRUE,
1142 dummy_cancel_cb, data);
1143 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1144 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1145 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1146 gtk_widget_show(gd->dialog);
1149 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1151 GtkWidget *frame = data;
1153 gtk_widget_set_sensitive(frame,
1154 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1157 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1159 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1162 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1164 file_util_trash_clear();
1167 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1171 gd = generic_dialog_new(_("Clear trash"),
1172 "clear_trash", widget, TRUE,
1173 dummy_cancel_cb, NULL);
1174 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1175 _("This will remove the trash contents."), FALSE);
1176 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1177 entry = gtk_entry_new();
1178 gtk_widget_set_can_focus(entry, FALSE);
1179 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1180 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1181 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1182 gtk_widget_show(entry);
1183 gtk_widget_show(gd->dialog);
1186 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1188 GtkWidget *pTextView;
1189 GtkTextBuffer *pTextBuffer;
1193 pTextView = GTK_WIDGET(data);
1195 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1196 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1197 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1199 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1200 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1203 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1205 GtkTextView *text_view = data;
1206 GtkTextBuffer *buffer;
1208 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1209 if (!configwindow) return;
1211 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1212 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1215 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1219 gd = generic_dialog_new(_("Reset image overlay template string"),
1220 "reset_image_overlay_template_string", widget, TRUE,
1221 dummy_cancel_cb, data);
1222 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1223 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1224 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1225 gtk_widget_show(gd->dialog);
1228 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1230 help_window_show("GuideOptionsOSD.html");
1233 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1235 #if GTK_CHECK_VERSION(3,4,0)
1238 PangoFontDescription *font_desc;
1240 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1241 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1243 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1245 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1246 font = pango_font_description_to_string(font_desc);
1247 g_free(c_options->image_overlay.font);
1248 c_options->image_overlay.font = g_strdup(font);
1252 gtk_widget_destroy(dialog);
1256 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1257 c_options->image_overlay.font = g_strdup(font);
1261 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1264 #if GTK_CHECK_VERSION(3,4,0)
1267 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1268 colour.red = options->image_overlay.text_red;
1269 colour.green = options->image_overlay.text_green;
1270 colour.blue = options->image_overlay.text_blue;
1271 colour.alpha = options->image_overlay.text_alpha;
1272 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1273 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1275 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1277 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1278 c_options->image_overlay.text_red = colour.red*255;
1279 c_options->image_overlay.text_green = colour.green*255;
1280 c_options->image_overlay.text_blue = colour.blue*255;
1281 c_options->image_overlay.text_alpha = colour.alpha*255;
1283 gtk_widget_destroy(dialog);
1286 GtkColorSelection *colorsel;
1288 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1289 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1290 colour.red = options->image_overlay.text_red*257;
1291 colour.green = options->image_overlay.text_green*257;
1292 colour.blue = options->image_overlay.text_blue*257;
1293 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1294 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1295 gtk_color_selection_set_current_color(colorsel, &colour);
1296 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1298 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1300 gtk_color_selection_get_current_color(colorsel, &colour);
1301 c_options->image_overlay.text_red = colour.red/257;
1302 c_options->image_overlay.text_green = colour.green/257;
1303 c_options->image_overlay.text_blue = colour.blue/257;
1304 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1306 gtk_widget_destroy (dialog);
1311 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1314 #if GTK_CHECK_VERSION(3,4,0)
1317 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1318 colour.red = options->image_overlay.background_red;
1319 colour.green = options->image_overlay.background_green;
1320 colour.blue = options->image_overlay.background_blue;
1321 colour.alpha = options->image_overlay.background_alpha;
1322 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1323 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1325 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1327 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1328 c_options->image_overlay.background_red = colour.red*255;
1329 c_options->image_overlay.background_green = colour.green*255;
1330 c_options->image_overlay.background_blue = colour.blue*255;
1331 c_options->image_overlay.background_alpha = colour.alpha*255;
1333 gtk_widget_destroy(dialog);
1336 GtkColorSelection *colorsel;
1338 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1339 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1340 colour.red = options->image_overlay.background_red*257;
1341 colour.green = options->image_overlay.background_green*257;
1342 colour.blue = options->image_overlay.background_blue*257;
1343 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1344 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1345 gtk_color_selection_set_current_color(colorsel, &colour);
1346 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1348 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1350 gtk_color_selection_get_current_color(colorsel, &colour);
1351 c_options->image_overlay.background_red = colour.red/257;
1352 c_options->image_overlay.background_green = colour.green/257;
1353 c_options->image_overlay.background_blue = colour.blue/257;
1354 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1356 gtk_widget_destroy(dialog);
1360 static void accel_store_populate(void)
1363 GList *groups, *actions;
1365 const gchar *accel_path;
1369 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1371 gtk_tree_store_clear(accel_store);
1372 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1374 g_assert(lw && lw->ui_manager);
1375 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1378 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1381 action = GTK_ACTION(actions->data);
1382 accel_path = gtk_action_get_accel_path(action);
1383 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1385 gchar *label, *label2, *tooltip, *accel;
1386 g_object_get(action,
1387 "tooltip", &tooltip,
1391 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1397 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1401 gtk_tree_store_append(accel_store, &iter, NULL);
1402 gtk_tree_store_set(accel_store, &iter,
1405 AE_TOOLTIP, tooltip ? tooltip : "",
1406 AE_ACCEL, accel_path,
1414 actions = actions->next;
1417 groups = groups->next;
1421 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1426 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1428 gchar *accel1 = data;
1433 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1435 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1436 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1438 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1440 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1441 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1450 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1452 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1456 GtkAccelKey old_key, key;
1457 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1459 gtk_tree_model_get_iter(model, &iter, path);
1460 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1462 /* test if the accelerator can be stored without conflicts*/
1463 gtk_accel_map_lookup_entry(accel_path, &old_key);
1465 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1466 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1467 gtk_accel_map_lookup_entry(accel_path, &key);
1469 /* restore the original for now, the key will be really changed when the changes are confirmed */
1470 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1472 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1473 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1475 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1476 gtk_tree_path_free(path);
1480 static gboolean accel_default_scroll(GtkTreeView *data)
1484 GtkTreeViewColumn *column;
1486 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1487 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1488 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1490 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1494 gtk_tree_path_free(path);
1499 static void accel_default_cb(GtkWidget *widget, gpointer data)
1501 accel_store_populate();
1503 g_idle_add((GSourceFunc)accel_default_scroll, data);
1506 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1508 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1511 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1514 gchar *accel_path, *accel;
1516 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1517 gtk_accel_map_lookup_entry(accel_path, &key);
1518 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1520 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1522 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1527 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1529 GtkTreeSelection *selection;
1531 if (!accel_store) return;
1532 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1533 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1538 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1542 GtkWidget *scrolled;
1543 GtkWidget *viewport;
1545 scrolled = gtk_scrolled_window_new(NULL, NULL);
1546 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1547 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1548 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1549 label = gtk_label_new(title);
1550 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1551 gtk_widget_show(scrolled);
1553 viewport = gtk_viewport_new(NULL, NULL);
1554 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1555 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1556 gtk_widget_show(viewport);
1558 vbox = gtk_vbox_new(FALSE, 0);
1559 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1560 gtk_widget_show(vbox);
1565 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1567 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1569 c_options->thumbnails.spec_standard =TRUE;
1570 c_options->thumbnails.cache_into_dirs = FALSE;
1574 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1576 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1578 c_options->thumbnails.spec_standard =FALSE;
1579 c_options->thumbnails.cache_into_dirs = FALSE;
1583 static void cache_local_cb(GtkWidget *widget, gpointer data)
1585 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1587 c_options->thumbnails.cache_into_dirs = TRUE;
1588 c_options->thumbnails.spec_standard =FALSE;
1592 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1593 GdkEvent *event, gpointer userdata)
1595 if (pos == GTK_ENTRY_ICON_PRIMARY)
1597 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1601 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1605 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1606 GdkEvent *event, gpointer userdata)
1608 gchar *rating_symbol;
1610 if (pos == GTK_ENTRY_ICON_PRIMARY)
1612 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1613 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1614 g_free(rating_symbol);
1618 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1619 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1620 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1624 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1625 GdkEvent *event, gpointer userdata)
1627 gchar *rating_symbol;
1629 if (pos == GTK_ENTRY_ICON_PRIMARY)
1631 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1632 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1633 g_free(rating_symbol);
1637 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1638 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1639 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1643 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1645 GtkContainer *hbox = data;
1646 GString *str = g_string_new(NULL);
1647 GtkEntry *hex_code_entry;
1648 gchar *hex_code_full;
1651 guint64 hex_value = 0;
1653 list = gtk_container_get_children(hbox);
1655 hex_code_entry = g_list_nth_data(list, 2);
1656 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1658 hex_code = g_strsplit(hex_code_full, "+", 2);
1659 if (hex_code[0] && hex_code[1])
1661 hex_value = strtoull(hex_code[1], NULL, 16);
1663 if (!hex_value || hex_value > 0x10FFFF)
1665 hex_value = 0x003F; // Unicode 'Question Mark'
1667 str = g_string_append_unichar(str, (gunichar)hex_value);
1668 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1670 g_strfreev(hex_code);
1671 g_string_free(str, TRUE);
1672 g_free(hex_code_full);
1677 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1679 guint64 star_symbol;
1681 star_symbol = star_rating_symbol_test(widget, data);
1682 c_options->star_rating.star = star_symbol;
1685 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1687 guint64 rejected_symbol;
1689 rejected_symbol = star_rating_symbol_test(widget, data);
1690 c_options->star_rating.rejected = rejected_symbol;
1693 /* general options tab */
1694 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1695 typedef struct _TZData TZData;
1699 GCancellable *cancellable;
1701 GtkWidget *progress;
1703 GFile *timezone_database_gq;
1704 gchar *timezone_database_user;
1707 static void config_tab_general(GtkWidget *notebook)
1712 GtkWidget *group_frame;
1713 GtkWidget *subgroup;
1715 GtkWidget *ct_button;
1718 gint hours, minutes, remainder;
1720 GtkWidget *star_rating_entry;
1722 gchar *rating_symbol;
1725 GNetworkMonitor *net_mon;
1726 GSocketConnectable *geeqie_org;
1727 gboolean internet_available;
1730 vbox = scrolled_notebook_page(notebook, _("General"));
1732 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1734 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1735 add_thumb_size_menu(table, 0, 0, _("Size:"));
1736 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1738 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1739 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1741 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1742 pref_checkbox_link_sensitivity(ct_button, subgroup);
1744 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1745 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1746 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1747 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1748 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1749 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1750 G_CALLBACK(cache_geeqie_cb), NULL);
1752 group_frame = pref_frame_new(subgroup, TRUE,
1753 _("Store thumbnails local to image folder (non-standard)"),
1754 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1755 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1756 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1757 G_CALLBACK(cache_local_cb), NULL);
1759 group_frame = pref_frame_new(subgroup, TRUE,
1760 _("Use standard thumbnail style and cache, shared with other applications"),
1761 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1762 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1763 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1764 G_CALLBACK(cache_standard_cb), NULL);
1766 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1767 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1769 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1771 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1772 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1774 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1775 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1776 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1778 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1779 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1782 pref_spacer(group, PREF_PAD_GROUP);
1784 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1786 c_options->star_rating.star = options->star_rating.star;
1787 c_options->star_rating.rejected = options->star_rating.rejected;
1789 str = g_string_new(NULL);
1790 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1791 pref_label_new(hbox, "Star character: ");
1792 str = g_string_append_unichar(str, options->star_rating.star);
1793 pref_label_new(hbox, g_strdup(str->str));
1794 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1795 star_rating_entry = gtk_entry_new();
1796 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1797 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1798 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1799 gtk_widget_show(star_rating_entry);
1800 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1801 G_CALLBACK(star_rating_star_test_cb), hbox);
1802 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1803 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1804 gtk_widget_show(button);
1805 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."));
1806 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1807 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1808 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1809 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1810 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1811 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1812 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1813 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1814 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1815 G_CALLBACK(star_rating_star_icon_cb),
1818 g_string_free(str, TRUE);
1819 g_free(rating_symbol);
1821 str = g_string_new(NULL);
1822 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1823 pref_label_new(hbox, "Rejected character: ");
1824 str = g_string_append_unichar(str, options->star_rating.rejected);
1825 pref_label_new(hbox, g_strdup(str->str));
1826 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1827 star_rating_entry = gtk_entry_new();
1828 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1829 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1830 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1831 gtk_widget_show(star_rating_entry);
1832 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1833 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1834 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1835 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1836 gtk_widget_show(button);
1837 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."));
1838 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1839 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1840 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1841 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1842 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1843 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1844 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1845 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1846 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1847 G_CALLBACK(star_rating_rejected_icon_cb),
1850 g_string_free(str, TRUE);
1851 g_free(rating_symbol);
1853 pref_spacer(group, PREF_PAD_GROUP);
1855 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1857 c_options->slideshow.delay = options->slideshow.delay;
1858 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1859 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1860 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1861 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1862 SLIDESHOW_SUBSECOND_PRECISION;
1864 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1866 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1868 options->slideshow.delay ? hours : 0.0,
1869 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1870 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1871 spin = pref_spin_new(hbox, ":" , NULL,
1873 options->slideshow.delay ? minutes: 0.0,
1874 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1875 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1876 spin = pref_spin_new(hbox, ":", NULL,
1877 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1878 options->slideshow.delay ? seconds : 10.0,
1879 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1880 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1882 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1883 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1885 pref_spacer(group, PREF_PAD_GROUP);
1887 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1889 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1890 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1891 pref_checkbox_new_int(group, _("Preload next image"),
1892 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1894 pref_checkbox_new_int(group, _("Refresh on file change"),
1895 options->update_on_time_change, &c_options->update_on_time_change);
1897 pref_spacer(group, PREF_PAD_GROUP);
1899 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1900 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1901 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1902 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1904 options->info_keywords.height, &c_options->info_keywords.height);
1905 pref_spin_new_int(hbox, _("Title:"), NULL,
1907 options->info_title.height, &c_options->info_title.height);
1908 pref_spin_new_int(hbox, _("Comment:"), NULL,
1910 options->info_comment.height, &c_options->info_comment.height);
1911 pref_spin_new_int(hbox, _("Rating:"), NULL,
1913 options->info_rating.height, &c_options->info_rating.height);
1915 pref_spacer(group, PREF_PAD_GROUP);
1917 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1919 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1920 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1922 pref_spacer(group, PREF_PAD_GROUP);
1924 net_mon = g_network_monitor_get_default();
1925 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
1926 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
1927 g_object_unref(geeqie_org);
1929 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
1930 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1932 if (!internet_available)
1934 gtk_widget_set_sensitive(group, FALSE);
1937 tz = g_new0(TZData, 1);
1939 path = path_from_utf8(TIMEZONE_DATABASE);
1940 basename = g_path_get_basename(path);
1941 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
1945 if (isfile(tz->timezone_database_user))
1947 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
1951 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
1954 if (!internet_available)
1956 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"));
1960 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"));
1962 gtk_widget_show(button);
1964 pref_spacer(group, PREF_PAD_GROUP);
1966 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1968 help_search_engine_entry = gtk_entry_new();
1969 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1970 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1971 gtk_widget_show(help_search_engine_entry);
1973 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"));
1975 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1976 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1977 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1978 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1979 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1980 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1981 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1982 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1983 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1984 G_CALLBACK(help_search_engine_entry_icon_cb),
1985 help_search_engine_entry);
1989 static void config_tab_image(GtkWidget *notebook)
1994 GtkWidget *ct_button;
1995 GtkWidget *enlargement_button;
1999 vbox = scrolled_notebook_page(notebook, _("Image"));
2001 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2003 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2004 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2007 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2008 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2011 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2012 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2014 c_options->image.zoom_increment = options->image.zoom_increment;
2015 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2016 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2017 G_CALLBACK(zoom_increment_cb), NULL);
2018 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2020 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2022 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2023 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2024 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2025 spin = pref_spin_new_int(hbox, NULL, NULL,
2027 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2028 pref_checkbox_link_sensitivity(enlargement_button, spin);
2029 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."));
2031 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2032 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2033 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2034 spin = pref_spin_new_int(hbox, NULL, NULL,
2036 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2037 pref_checkbox_link_sensitivity(ct_button, spin);
2038 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."));
2040 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2042 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2043 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2045 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2046 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2048 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2049 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2051 c_options->image.border_color = options->image.border_color;
2053 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2054 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2056 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2057 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2059 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2060 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2062 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2064 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2065 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2069 static void config_tab_windows(GtkWidget *notebook)
2075 GtkWidget *ct_button;
2078 vbox = scrolled_notebook_page(notebook, _("Windows"));
2080 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2082 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2083 options->save_window_positions, &c_options->save_window_positions);
2085 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2086 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2087 pref_checkbox_link_sensitivity(ct_button, button);
2089 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2090 options->tools_restore_state, &c_options->tools_restore_state);
2092 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2093 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2095 pref_checkbox_new_int(group, _("Show window IDs"),
2096 options->show_window_ids, &c_options->show_window_ids);
2098 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2100 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2101 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2103 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2104 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2105 options->image.limit_window_size, &c_options->image.limit_window_size);
2106 spin = pref_spin_new_int(hbox, NULL, NULL,
2108 options->image.max_window_size, &c_options->image.max_window_size);
2109 pref_checkbox_link_sensitivity(ct_button, spin);
2111 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2113 c_options->fullscreen.screen = options->fullscreen.screen;
2114 c_options->fullscreen.above = options->fullscreen.above;
2115 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2116 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2117 gtk_widget_show(hbox);
2119 pref_checkbox_new_int(group, _("Smooth image flip"),
2120 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2121 pref_checkbox_new_int(group, _("Disable screen saver"),
2122 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2125 #define PRE_FORMATTED_COLUMNS 5
2126 static void config_tab_osd(GtkWidget *notebook)
2130 GtkWidget *vbox_buttons;
2133 GtkWidget *image_overlay_template_view;
2134 GtkWidget *scrolled;
2135 GtkWidget *scrolled_pre_formatted;
2136 GtkTextBuffer *buffer;
2138 GtkWidget * subgroup;
2143 vbox = scrolled_notebook_page(notebook, _("OSD"));
2145 image_overlay_template_view = gtk_text_view_new();
2147 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2149 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2151 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2152 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2153 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2154 gtk_widget_show(scrolled_pre_formatted);
2155 gtk_widget_show(subgroup);
2157 pref_line(group, PREF_PAD_GAP);
2159 pref_label_new(group, _("Image overlay template"));
2161 scrolled = gtk_scrolled_window_new(NULL, NULL);
2162 gtk_widget_set_size_request(scrolled, 200, 150);
2163 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2164 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2165 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2166 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2167 gtk_widget_show(scrolled);
2169 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2170 _("Extensive formatting options are shown in the Help file"));
2172 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2173 gtk_widget_show(image_overlay_template_view);
2175 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2177 #if GTK_CHECK_VERSION(3,4,0)
2178 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2179 G_CALLBACK(image_overlay_set_font_cb), notebook);
2181 button = gtk_font_button_new();
2182 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2183 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2184 g_signal_connect(G_OBJECT(button), "font-set",
2185 G_CALLBACK(image_overlay_set_font_cb),NULL);
2187 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2188 gtk_widget_show(button);
2190 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2191 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2192 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2193 gtk_widget_show(button);
2195 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2196 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2197 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2198 gtk_widget_show(button);
2199 image_overlay_set_text_colours();
2201 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2202 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2203 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2204 gtk_widget_show(button);
2206 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2207 G_CALLBACK(image_overlay_help_cb), NULL);
2208 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2209 gtk_widget_show(button);
2211 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2212 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2213 g_signal_connect(G_OBJECT(buffer), "changed",
2214 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2216 pref_line(group, PREF_PAD_GAP);
2218 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2219 hbox = gtk_hbox_new(FALSE, 0);
2220 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2221 gtk_widget_show(hbox);
2222 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2223 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2224 gtk_widget_show(label);
2225 pref_spacer(group,TRUE);
2227 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2228 hbox = gtk_hbox_new(FALSE, 0);
2229 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2230 gtk_widget_show(hbox);
2231 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2232 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2233 gtk_widget_show(label);
2234 pref_spacer(group,TRUE);
2236 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2237 hbox = gtk_hbox_new(FALSE, 0);
2238 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2239 gtk_widget_show(hbox);
2240 label = gtk_label_new(_("%path:39%"));
2241 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2242 gtk_widget_show(label);
2243 pref_spacer(group,TRUE);
2245 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2246 hbox = gtk_hbox_new(FALSE, 0);
2247 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2248 gtk_widget_show(hbox);
2249 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%"));
2250 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2251 gtk_widget_show(label);
2252 pref_spacer(group,TRUE);
2254 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2255 hbox = gtk_hbox_new(FALSE, 0);
2256 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2257 gtk_widget_show(hbox);
2258 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2259 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2260 gtk_widget_show(label);
2263 static GtkTreeModel *create_class_model(void)
2265 GtkListStore *model;
2269 /* create list store */
2270 model = gtk_list_store_new(1, G_TYPE_STRING);
2271 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2273 gtk_list_store_append(model, &iter);
2274 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2276 return GTK_TREE_MODEL (model);
2281 static void config_tab_files(GtkWidget *notebook)
2288 GtkWidget *ct_button;
2289 GtkWidget *scrolled;
2290 GtkWidget *filter_view;
2291 GtkCellRenderer *renderer;
2292 GtkTreeSelection *selection;
2293 GtkTreeViewColumn *column;
2295 vbox = scrolled_notebook_page(notebook, _("Files"));
2297 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2299 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2300 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2301 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2302 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2303 pref_checkbox_new_int(group, _("Case sensitive sort"),
2304 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2305 pref_checkbox_new_int(group, _("Natural sort order"),
2306 options->file_sort.natural, &c_options->file_sort.natural);
2307 pref_checkbox_new_int(group, _("Disable file extension checks"),
2308 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2310 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2311 options->file_filter.disable, &c_options->file_filter.disable);
2314 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2316 sidecar_ext_entry = gtk_entry_new();
2317 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2318 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2319 gtk_widget_show(sidecar_ext_entry);
2321 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2323 frame = pref_group_parent(group);
2324 g_signal_connect(G_OBJECT(ct_button), "toggled",
2325 G_CALLBACK(filter_disable_cb), frame);
2326 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2328 scrolled = gtk_scrolled_window_new(NULL, NULL);
2329 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2330 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2331 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2332 gtk_widget_show(scrolled);
2334 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2335 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2336 g_object_unref(filter_store);
2337 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2338 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2340 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2342 column = gtk_tree_view_column_new();
2343 gtk_tree_view_column_set_title(column, _("Filter"));
2344 gtk_tree_view_column_set_resizable(column, TRUE);
2346 renderer = gtk_cell_renderer_toggle_new();
2347 g_signal_connect(G_OBJECT(renderer), "toggled",
2348 G_CALLBACK(filter_store_enable_cb), filter_store);
2349 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2350 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2351 GINT_TO_POINTER(FE_ENABLE), NULL);
2353 renderer = gtk_cell_renderer_text_new();
2354 g_signal_connect(G_OBJECT(renderer), "edited",
2355 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2356 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2357 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2358 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2359 GINT_TO_POINTER(FE_EXTENSION), NULL);
2360 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2362 column = gtk_tree_view_column_new();
2363 gtk_tree_view_column_set_title(column, _("Description"));
2364 gtk_tree_view_column_set_resizable(column, TRUE);
2365 gtk_tree_view_column_set_fixed_width(column, 200);
2366 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2368 renderer = gtk_cell_renderer_text_new();
2369 g_signal_connect(G_OBJECT(renderer), "edited",
2370 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2371 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2372 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2373 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2374 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2375 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2377 column = gtk_tree_view_column_new();
2378 gtk_tree_view_column_set_title(column, _("Class"));
2379 gtk_tree_view_column_set_resizable(column, TRUE);
2380 renderer = gtk_cell_renderer_combo_new();
2381 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2382 "model", create_class_model(),
2387 g_signal_connect(G_OBJECT(renderer), "edited",
2388 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2389 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2390 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2391 GINT_TO_POINTER(FE_CLASS), NULL);
2392 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2394 column = gtk_tree_view_column_new();
2395 gtk_tree_view_column_set_title(column, _("Writable"));
2396 gtk_tree_view_column_set_resizable(column, FALSE);
2397 renderer = gtk_cell_renderer_toggle_new();
2398 g_signal_connect(G_OBJECT(renderer), "toggled",
2399 G_CALLBACK(filter_store_writable_cb), filter_store);
2400 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2401 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2402 GINT_TO_POINTER(FE_WRITABLE), NULL);
2403 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2405 column = gtk_tree_view_column_new();
2406 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2407 gtk_tree_view_column_set_resizable(column, FALSE);
2408 renderer = gtk_cell_renderer_toggle_new();
2409 g_signal_connect(G_OBJECT(renderer), "toggled",
2410 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2411 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2412 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2413 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2414 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2417 filter_store_populate();
2418 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2419 gtk_widget_show(filter_view);
2421 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2423 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2424 G_CALLBACK(filter_default_cb), filter_view);
2425 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2426 gtk_widget_show(button);
2428 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2429 G_CALLBACK(filter_remove_cb), filter_view);
2430 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2431 gtk_widget_show(button);
2433 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2434 G_CALLBACK(filter_add_cb), filter_view);
2435 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2436 gtk_widget_show(button);
2440 static void config_tab_metadata(GtkWidget *notebook)
2445 GtkWidget *ct_button;
2449 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2452 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2454 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2456 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2457 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2459 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2460 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2462 gtk_widget_set_sensitive(ct_button, FALSE);
2465 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2466 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2468 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2469 label = pref_label_new(group, text);
2470 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2471 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2474 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2476 gtk_widget_set_sensitive(group, FALSE);
2479 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2480 pref_checkbox_link_sensitivity(ct_button, hbox);
2482 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2483 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2485 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2486 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2488 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2489 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2491 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2492 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2494 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2496 gtk_widget_set_sensitive(group, FALSE);
2499 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2500 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2503 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2504 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2505 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2507 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2508 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2510 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2511 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2513 gtk_widget_set_sensitive(ct_button, FALSE);
2516 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2518 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2519 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2521 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2522 pref_checkbox_link_sensitivity(ct_button, hbox);
2524 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2525 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2527 pref_checkbox_new_int(group, _("Write metadata on image change"),
2528 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2530 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2531 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2533 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2535 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2536 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2537 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");
2542 typedef struct _KeywordFindData KeywordFindData;
2543 struct _KeywordFindData
2550 GtkWidget *button_close;
2551 GtkWidget *button_stop;
2552 GtkWidget *button_start;
2553 GtkWidget *progress;
2561 guint idle_id; /* event source id */
2564 #define KEYWORD_DIALOG_WIDTH 400
2566 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2568 GList *list_d = NULL;
2569 GList *list_f = NULL;
2573 filelist_read(dir_fd, &list_f, &list_d);
2577 filelist_read(dir_fd, &list_f, NULL);
2580 list_f = filelist_filter(list_f, FALSE);
2581 list_d = filelist_filter(list_d, TRUE);
2583 kfd->list = g_list_concat(list_f, kfd->list);
2584 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2587 static void keywords_find_reset(KeywordFindData *kfd)
2589 filelist_free(kfd->list);
2592 filelist_free(kfd->list_dir);
2593 kfd->list_dir = NULL;
2596 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2598 KeywordFindData *kfd = data;
2600 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2602 keywords_find_reset(kfd);
2603 generic_dialog_close(kfd->gd);
2607 static void keywords_find_finish(KeywordFindData *kfd)
2609 keywords_find_reset(kfd);
2611 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2612 spinner_set_interval(kfd->spinner, -1);
2614 gtk_widget_set_sensitive(kfd->group, TRUE);
2615 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2616 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2617 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2620 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2622 KeywordFindData *kfd = data;
2624 g_idle_remove_by_data(kfd);
2626 keywords_find_finish(kfd);
2629 static gboolean keywords_find_file(gpointer data)
2631 KeywordFindData *kfd = data;
2633 GtkTextBuffer *buffer;
2641 fd = kfd->list->data;
2642 kfd->list = g_list_remove(kfd->list, fd);
2644 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2645 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2649 gtk_text_buffer_get_end_iter(buffer, &iter);
2650 tmp = g_strconcat(keywords->data, "\n", NULL);
2651 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2653 keywords = keywords->next;
2656 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2657 file_data_unref(fd);
2658 string_list_free(keywords);
2662 else if (kfd->list_dir)
2666 fd = kfd->list_dir->data;
2667 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2669 keywords_find_folder(kfd, fd);
2671 file_data_unref(fd);
2676 keywords_find_finish(kfd);
2681 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2683 KeywordFindData *kfd = data;
2686 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2688 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2689 parse_out_relatives(path);
2693 warning_dialog(_("Invalid folder"),
2694 _("The specified folder can not be found."),
2695 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2701 gtk_widget_set_sensitive(kfd->group, FALSE);
2702 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2703 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2704 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2705 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2707 dir_fd = file_data_new_dir(path);
2708 keywords_find_folder(kfd, dir_fd);
2709 file_data_unref(dir_fd);
2710 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2716 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2718 KeywordFindData *kfd;
2722 kfd = g_new0(KeywordFindData, 1);
2724 kfd->gd = generic_dialog_new(_("Search for keywords"),
2725 "search_for_keywords",
2728 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2729 kfd->gd->cancel_cb = keywords_find_close_cb;
2730 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2731 keywords_find_close_cb, FALSE);
2732 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2733 keywords_find_start_cb, FALSE);
2734 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2735 keywords_find_stop_cb, FALSE);
2736 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2738 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2740 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2741 pref_spacer(hbox, PREF_PAD_INDENT);
2742 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2744 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2745 pref_label_new(hbox, _("Folder:"));
2747 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2748 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2749 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2750 gtk_widget_show(label);
2752 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2754 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2755 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2757 kfd->progress = gtk_entry_new();
2758 gtk_widget_set_can_focus(kfd->progress, FALSE);
2759 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2760 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2761 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2762 gtk_widget_show(kfd->progress);
2764 kfd->spinner = spinner_new(NULL, -1);
2765 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2766 gtk_widget_show(kfd->spinner);
2770 gtk_widget_show(kfd->gd->dialog);
2773 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2775 const gchar *path = layout_get_path(NULL);
2777 if (!path || !*path) path = homedir();
2778 keywords_find_dialog(widget, path);
2781 static void config_tab_keywords_save()
2783 GtkTextIter start, end;
2784 GtkTextBuffer *buffer;
2785 GList *kw_list = NULL;
2791 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2792 gtk_text_buffer_get_bounds(buffer, &start, &end);
2794 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2796 kw_split = strtok(buffer_text, "\n");
2797 while (kw_split != NULL)
2803 if (g_strcmp0(work->data, kw_split) == 0)
2812 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2814 kw_split = strtok(NULL, "\n");
2817 keyword_list_set(kw_list);
2819 string_list_free(kw_list);
2820 g_free(buffer_text);
2823 static void config_tab_keywords(GtkWidget *notebook)
2829 GtkWidget *scrolled;
2831 GtkTextBuffer *buffer;
2834 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2836 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2838 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2840 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2841 G_CALLBACK(keywords_find_cb), keyword_text);
2842 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2845 keyword_text = gtk_text_view_new();
2846 gtk_widget_set_size_request(keyword_text, 20, 20);
2847 scrolled = gtk_scrolled_window_new(NULL, NULL);
2848 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2849 gtk_widget_show(scrolled);
2851 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2852 gtk_widget_show(keyword_text);
2854 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2856 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2857 gtk_text_buffer_create_tag(buffer, "monospace",
2858 "family", "monospace", NULL);
2860 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2861 gtk_text_buffer_get_start_iter(buffer, &iter);
2862 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2865 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2867 GList *kwl = keyword_list_get();
2868 kwl = g_list_first(kwl);
2871 gtk_text_buffer_get_end_iter (buffer, &iter);
2872 tmp = g_strconcat(kwl->data, "\n", NULL);
2873 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2878 gtk_text_buffer_set_modified(buffer, FALSE);
2885 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2887 gint *option = data;
2889 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2893 *option = INTENT_PERCEPTUAL;
2896 *option = INTENT_RELATIVE_COLORIMETRIC;
2899 *option = INTENT_SATURATION;
2902 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2907 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2908 gint option, gint *option_c)
2915 pref_table_label(table, column, row, text, 0.0);
2917 combo = gtk_combo_box_text_new();
2919 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2920 if (option == INTENT_PERCEPTUAL) current = 0;
2921 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2922 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2923 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2924 if (option == INTENT_SATURATION) current = 2;
2925 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2926 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2928 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2930 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2932 g_signal_connect(G_OBJECT(combo), "changed",
2933 G_CALLBACK(intent_menu_cb), option_c);
2935 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2936 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2937 gtk_widget_show(combo);
2941 static void config_tab_color(GtkWidget *notebook)
2950 vbox = scrolled_notebook_page(notebook, _("Color management"));
2952 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2954 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2957 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2958 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2960 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2961 pref_label_bold(label, TRUE, FALSE);
2963 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2964 pref_label_bold(label, TRUE, FALSE);
2966 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2967 pref_label_bold(label, TRUE, FALSE);
2969 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2974 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2975 pref_table_label(table, 0, i + 1, buf, 1.0);
2978 entry = gtk_entry_new();
2979 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2980 if (options->color_profile.input_name[i])
2982 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2984 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2985 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2986 gtk_widget_show(entry);
2987 color_profile_input_name_entry[i] = entry;
2989 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2990 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2991 gtk_widget_set_size_request(entry, 160, -1);
2992 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2993 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2994 gtk_widget_show(tabcomp);
2995 color_profile_input_file_entry[i] = entry;
2998 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3000 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3002 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3003 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3005 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3007 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3008 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3009 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3010 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3011 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3013 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3015 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3017 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3019 gtk_widget_show(tabcomp);
3022 /* advanced entry tab */
3023 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3025 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3027 c_options->file_ops.use_system_trash = FALSE;
3028 c_options->file_ops.no_trash = FALSE;
3032 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3034 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3036 c_options->file_ops.use_system_trash = TRUE;
3037 c_options->file_ops.no_trash = FALSE;
3041 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3043 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3045 c_options->file_ops.no_trash = TRUE;
3049 static void config_tab_behavior(GtkWidget *notebook)
3056 GtkWidget *ct_button;
3060 GtkWidget *with_rename;
3061 GtkWidget *collections_on_top;
3063 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3065 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3067 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3068 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3069 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3070 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3071 pref_checkbox_new_int(group, _("Enable Delete key"),
3072 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3074 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3075 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3077 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3078 pref_checkbox_link_sensitivity(ct_button, hbox);
3080 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3081 pref_label_new(hbox, _("Folder:"));
3083 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3084 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3085 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3086 gtk_widget_show(tabcomp);
3088 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3089 pref_checkbox_link_sensitivity(ct_button, hbox);
3091 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3092 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3093 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3094 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3095 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3096 G_CALLBACK(safe_delete_view_cb), NULL);
3097 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3098 gtk_widget_show(button);
3100 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3101 G_CALLBACK(safe_delete_clear_cb), NULL);
3102 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3103 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3104 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3106 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3107 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3109 gtk_widget_show(button);
3111 pref_spacer(group, PREF_PAD_GROUP);
3114 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3116 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3117 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3119 pref_checkbox_new_int(group, _("In place renaming"),
3120 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3122 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3123 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3125 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3126 options->marks_save, &c_options->marks_save);
3127 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3129 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3130 options->with_rename, &c_options->with_rename);
3131 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3133 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3134 options->collections_on_top, &c_options->collections_on_top);
3135 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3137 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3138 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3140 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3141 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3143 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3144 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3146 pref_spacer(group, PREF_PAD_GROUP);
3148 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3150 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3151 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3152 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3153 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3154 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3155 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3156 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3157 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3158 pref_checkbox_new_int(group, _("Play video by left click on image"),
3159 options->image_l_click_video, &c_options->image_l_click_video);
3160 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3161 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3165 pref_spacer(group, PREF_PAD_GROUP);
3167 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3169 pref_spin_new_int(group, _("Debug level:"), NULL,
3170 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3172 pref_checkbox_new_int(group, _("Timer data"),
3173 options->log_window.timer_data, &c_options->log_window.timer_data);
3175 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3176 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3180 /* accelerators tab */
3181 static void config_tab_accelerators(GtkWidget *notebook)
3187 GtkWidget *scrolled;
3188 GtkWidget *accel_view;
3189 GtkCellRenderer *renderer;
3190 GtkTreeSelection *selection;
3191 GtkTreeViewColumn *column;
3193 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3195 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3197 scrolled = gtk_scrolled_window_new(NULL, NULL);
3198 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3199 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3200 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3201 gtk_widget_show(scrolled);
3203 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3205 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3206 g_object_unref(accel_store);
3207 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3208 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3210 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3212 renderer = gtk_cell_renderer_text_new();
3214 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3219 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3220 gtk_tree_view_column_set_resizable(column, TRUE);
3221 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3224 renderer = gtk_cell_renderer_accel_new();
3225 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3226 G_CALLBACK(accel_store_cleared_cb), accel_store);
3227 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3228 G_CALLBACK(accel_store_edited_cb), accel_store);
3231 g_object_set (renderer,
3233 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3236 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3241 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3242 gtk_tree_view_column_set_resizable(column, TRUE);
3243 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3245 renderer = gtk_cell_renderer_text_new();
3247 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3252 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3253 gtk_tree_view_column_set_resizable(column, TRUE);
3254 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3256 renderer = gtk_cell_renderer_text_new();
3258 column = gtk_tree_view_column_new_with_attributes("Accel",
3263 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3264 gtk_tree_view_column_set_resizable(column, TRUE);
3265 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3267 accel_store_populate();
3268 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3269 gtk_widget_show(accel_view);
3271 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3273 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3274 G_CALLBACK(accel_default_cb), accel_view);
3275 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3276 gtk_widget_show(button);
3278 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3279 G_CALLBACK(accel_reset_cb), accel_view);
3280 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3281 gtk_widget_show(button);
3285 static void config_tab_toolbar(GtkWidget *notebook)
3288 GtkWidget *toolbardata;
3291 lw = layout_window_list->data;
3293 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3295 toolbardata = toolbar_select_new(lw);
3296 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3297 gtk_widget_show(vbox);
3301 static void config_tab_stereo(GtkWidget *notebook)
3309 GtkWidget *fs_button;
3310 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3312 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3314 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3315 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3317 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3318 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3319 pref_checkbox_new_int(box, _("Mirror left image"),
3320 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3321 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3322 pref_checkbox_new_int(box, _("Flip left image"),
3323 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3324 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3325 pref_checkbox_new_int(box, _("Mirror right image"),
3326 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3327 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3328 pref_checkbox_new_int(box, _("Flip right image"),
3329 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3330 pref_checkbox_new_int(group, _("Swap left and right images"),
3331 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3332 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3333 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3335 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3336 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3337 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3338 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3339 pref_checkbox_link_sensitivity(fs_button, box2);
3340 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3341 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3342 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3343 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3344 pref_checkbox_new_int(box, _("Mirror left image"),
3345 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3346 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3347 pref_checkbox_new_int(box, _("Flip left image"),
3348 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3349 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3350 pref_checkbox_new_int(box, _("Mirror right image"),
3351 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3352 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3353 pref_checkbox_new_int(box, _("Flip right image"),
3354 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3355 pref_checkbox_new_int(box2, _("Swap left and right images"),
3356 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3357 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3358 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3360 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3361 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3362 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3363 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3364 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3365 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3366 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3367 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3368 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3369 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3370 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3371 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3372 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3373 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3377 /* Main preferences window */
3378 static void config_window_create(void)
3380 GtkWidget *win_vbox;
3382 GtkWidget *notebook;
3384 GtkWidget *ct_button;
3386 if (!c_options) c_options = init_options(NULL);
3388 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3389 DEBUG_NAME(configwindow);
3390 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3391 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3392 G_CALLBACK(config_window_delete), NULL);
3393 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3394 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3395 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3397 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3398 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3399 gtk_widget_show(win_vbox);
3401 notebook = gtk_notebook_new();
3402 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3403 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3404 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3406 config_tab_general(notebook);
3407 config_tab_image(notebook);
3408 config_tab_osd(notebook);
3409 config_tab_windows(notebook);
3410 config_tab_accelerators(notebook);
3411 config_tab_files(notebook);
3412 config_tab_metadata(notebook);
3413 config_tab_keywords(notebook);
3414 config_tab_color(notebook);
3415 config_tab_stereo(notebook);
3416 config_tab_behavior(notebook);
3417 config_tab_toolbar(notebook);
3419 hbox = gtk_hbutton_box_new();
3420 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3421 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3422 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3423 gtk_widget_show(hbox);
3425 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3426 G_CALLBACK(config_window_help_cb), notebook);
3427 gtk_container_add(GTK_CONTAINER(hbox), button);
3428 gtk_widget_set_can_default(button, TRUE);
3429 gtk_widget_show(button);
3431 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3432 G_CALLBACK(config_window_ok_cb), NULL);
3433 gtk_container_add(GTK_CONTAINER(hbox), button);
3434 gtk_widget_set_can_default(button, TRUE);
3435 gtk_widget_grab_default(button);
3436 gtk_widget_show(button);
3440 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3441 G_CALLBACK(config_window_save_cb), NULL);
3442 gtk_container_add(GTK_CONTAINER(hbox), button);
3443 gtk_widget_set_can_default(button, TRUE);
3444 gtk_widget_show(button);
3446 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3447 G_CALLBACK(config_window_apply_cb), NULL);
3448 gtk_container_add(GTK_CONTAINER(hbox), button);
3449 gtk_widget_set_can_default(button, TRUE);
3450 gtk_widget_show(button);
3452 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3453 G_CALLBACK(config_window_close_cb), NULL);
3454 gtk_container_add(GTK_CONTAINER(hbox), button);
3455 gtk_widget_set_can_default(button, TRUE);
3456 gtk_widget_show(button);
3458 if (!generic_dialog_get_alternative_button_order(configwindow))
3460 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3463 gtk_widget_show(notebook);
3465 gtk_widget_show(configwindow);
3469 *-----------------------------------------------------------------------------
3470 * config window show (public)
3471 *-----------------------------------------------------------------------------
3474 void show_config_window(void)
3478 gtk_window_present(GTK_WINDOW(configwindow));
3482 config_window_create();
3491 void show_about_window(LayoutWindow *lw)
3493 GdkPixbuf *pixbuf_logo;
3494 GdkPixbuf *pixbuf_icon;
3495 gchar *authors[1000];
3500 gchar *timezone_path;
3504 #define LINE_LENGTH 1000
3505 gchar line[LINE_LENGTH];
3507 copyright = g_string_new(NULL);
3508 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");
3510 path = path_from_utf8(TIMEZONE_DATABASE);
3511 basename = g_path_get_basename(path);
3512 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
3513 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
3515 cd = ZDOpenDatabase(timezone_path);
3518 copyright = g_string_append(copyright, ZDGetNotice(cd));
3519 ZDCloseDatabase(cd);
3523 g_free(timezone_path);
3527 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3528 fp = fopen(path, "r");
3531 while(fgets(line, LINE_LENGTH, fp))
3533 /* get rid of ending \n from fgets */
3534 line[strlen(line) - 1] = '\0';
3535 authors[i_authors] = g_strdup(line);
3538 authors[i_authors] = NULL;
3543 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3544 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3546 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3547 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3548 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3549 "title", _("About Geeqie"),
3551 "program-name", GQ_APPNAME,
3553 "logo", pixbuf_logo,
3554 "icon", pixbuf_icon,
3555 "website", GQ_WEBSITE,
3556 "website-label", "Website",
3557 "comments", comment,
3559 "translator-credits", _("translator-credits"),
3560 "wrap-license", TRUE,
3561 "license", copyright->str,
3564 g_string_free(copyright, TRUE);
3567 while(n < i_authors)
3577 static void image_overlay_set_text_colours()
3579 c_options->image_overlay.text_red = options->image_overlay.text_red;
3580 c_options->image_overlay.text_green = options->image_overlay.text_green;
3581 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3582 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3583 c_options->image_overlay.background_red = options->image_overlay.background_red;
3584 c_options->image_overlay.background_green = options->image_overlay.background_green;
3585 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3586 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3590 *-----------------------------------------------------------------------------
3591 * timezone database routines
3592 *-----------------------------------------------------------------------------
3595 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3597 GError *error = NULL;
3599 gchar *tmp_filename;
3601 if (!g_cancellable_is_cancelled(tz->cancellable))
3603 generic_dialog_close(tz->gd);
3607 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3609 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3610 move_file(tmp_filename, tz->timezone_database_user);
3611 g_free(tmp_filename);
3615 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3618 g_file_delete(tz->tmp_g_file, NULL, &error);
3619 g_object_unref(tz->tmp_g_file);
3620 tz->tmp_g_file = NULL;
3621 g_object_unref(tz->cancellable);
3622 g_object_unref(tz->timezone_database_gq);
3625 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3629 if (!g_cancellable_is_cancelled(tz->cancellable))
3631 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3635 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3638 GError *error = NULL;
3640 g_cancellable_cancel(tz->cancellable);
3643 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3646 GError *error = NULL;
3647 GFileIOStream *io_stream;
3654 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3658 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3659 log_printf("Error: Download timezone database failed:\n%s", error->message);
3660 g_error_free(error);
3661 g_object_unref(tz->tmp_g_file);
3665 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3667 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3669 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3671 tz->progress = gtk_progress_bar_new();
3672 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3673 gtk_widget_show(tz->progress);
3675 gtk_widget_show(tz->gd->dialog);
3676 tz->cancellable = g_cancellable_new();
3677 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);
3679 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3682 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */