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[] = {
124 /* config memory values */
125 static ConfOptions *c_options = NULL;
132 static GtkWidget *configwindow = NULL;
133 static GtkListStore *filter_store = NULL;
134 static GtkTreeStore *accel_store = NULL;
136 static GtkWidget *safe_delete_path_entry;
138 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
139 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
140 static GtkWidget *color_profile_screen_file_entry;
142 static GtkWidget *sidecar_ext_entry;
143 static GtkWidget *help_search_engine_entry;
146 #define CONFIG_WINDOW_DEF_WIDTH 700
147 #define CONFIG_WINDOW_DEF_HEIGHT 600
150 *-----------------------------------------------------------------------------
151 * option widget callbacks (private)
152 *-----------------------------------------------------------------------------
155 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
157 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
160 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
162 gint mins_secs_tenths, delay;
164 mins_secs_tenths = c_options->slideshow.delay %
165 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
167 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
168 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
171 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
172 SLIDESHOW_SUBSECOND_PRECISION;
175 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
177 gint hours, secs_tenths, delay;
179 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
180 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
182 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
183 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
184 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
186 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
187 SLIDESHOW_SUBSECOND_PRECISION;
190 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
192 gint hours_mins, delay;
194 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
196 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
197 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
198 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
200 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
201 SLIDESHOW_SUBSECOND_PRECISION;
205 *-----------------------------------------------------------------------------
206 * sync progam to config window routine (private)
207 *-----------------------------------------------------------------------------
210 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
216 buf = gtk_entry_get_text(GTK_ENTRY(entry));
217 if (buf && strlen(buf) > 0)
222 *option = g_strdup(buf);
227 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
229 gchar *accel_path, *accel;
231 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
233 if (accel_path && accel_path[0])
236 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
237 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
247 static void config_window_apply(void)
250 gboolean refresh = FALSE;
252 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
254 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
255 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
256 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
257 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
258 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
259 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
260 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
262 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
263 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
264 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
265 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
266 options->file_ops.no_trash = c_options->file_ops.no_trash;
267 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
268 options->tools_restore_state = c_options->tools_restore_state;
269 options->save_window_positions = c_options->save_window_positions;
270 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
271 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
272 options->show_window_ids = c_options->show_window_ids;
273 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
274 options->image.zoom_2pass = c_options->image.zoom_2pass;
275 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
276 options->image.limit_window_size = c_options->image.limit_window_size;
277 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
278 options->image.max_window_size = c_options->image.max_window_size;
279 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
280 options->image.max_autofit_size = c_options->image.max_autofit_size;
281 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
282 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
283 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
284 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
286 if (options->thumbnails.max_width != c_options->thumbnails.max_width
287 || options->thumbnails.max_height != c_options->thumbnails.max_height
288 || options->thumbnails.quality != c_options->thumbnails.quality)
290 thumb_format_changed = TRUE;
292 options->thumbnails.max_width = c_options->thumbnails.max_width;
293 options->thumbnails.max_height = c_options->thumbnails.max_height;
294 options->thumbnails.quality = c_options->thumbnails.quality;
296 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
297 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
298 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
299 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
300 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
301 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
302 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
303 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
304 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
305 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
306 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
307 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
309 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
310 options->file_sort.natural = c_options->file_sort.natural;
311 options->file_filter.disable = c_options->file_filter.disable;
313 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
314 sidecar_ext_parse(options->sidecar.ext);
316 options->slideshow.random = c_options->slideshow.random;
317 options->slideshow.repeat = c_options->slideshow.repeat;
318 options->slideshow.delay = c_options->slideshow.delay;
320 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
321 options->image_lm_click_nav = c_options->image_lm_click_nav;
322 options->image_l_click_video = c_options->image_l_click_video;
323 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
325 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
327 options->image.tile_cache_max = c_options->image.tile_cache_max;
328 options->image.image_cache_max = c_options->image.image_cache_max;
330 options->image.zoom_quality = c_options->image.zoom_quality;
332 options->image.zoom_increment = c_options->image.zoom_increment;
334 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
337 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
338 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
339 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
341 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
342 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
343 options->image.border_color = c_options->image.border_color;
344 layout_colors_update();
345 view_window_colors_update();
348 options->image.alpha_color_1 = c_options->image.alpha_color_1;
349 options->image.alpha_color_2 = c_options->image.alpha_color_2;
351 options->fullscreen.screen = c_options->fullscreen.screen;
352 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
353 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
354 options->fullscreen.above = c_options->fullscreen.above;
355 if (c_options->image_overlay.template_string)
356 set_image_overlay_template_string(&options->image_overlay.template_string,
357 c_options->image_overlay.template_string);
358 if (c_options->image_overlay.font)
359 set_image_overlay_font_string(&options->image_overlay.font,
360 c_options->image_overlay.font);
361 options->image_overlay.text_red = c_options->image_overlay.text_red;
362 options->image_overlay.text_green = c_options->image_overlay.text_green;
363 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
364 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
365 options->image_overlay.background_red = c_options->image_overlay.background_red;
366 options->image_overlay.background_green = c_options->image_overlay.background_green;
367 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
368 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
369 options->update_on_time_change = c_options->update_on_time_change;
370 options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
372 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
373 options->rot_invariant_sim = c_options->rot_invariant_sim;
375 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
377 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
379 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
380 options->dnd_icon_size = c_options->dnd_icon_size;
381 options->clipboard_selection = c_options->clipboard_selection;
383 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
384 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
385 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
386 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
387 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
388 options->metadata.confirm_write = c_options->metadata.confirm_write;
389 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
390 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
391 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
392 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
393 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
394 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
395 options->metadata.write_orientation = c_options->metadata.write_orientation;
396 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
397 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
398 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
399 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
400 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
401 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
402 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
403 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
404 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
405 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
406 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
407 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
408 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
409 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
410 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
411 options->stereo.fixed_w = c_options->stereo.fixed_w;
412 options->stereo.fixed_h = c_options->stereo.fixed_h;
413 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
414 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
415 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
416 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
418 options->info_keywords.height = c_options->info_keywords.height;
419 options->info_title.height = c_options->info_title.height;
420 options->info_comment.height = c_options->info_comment.height;
421 options->info_rating.height = c_options->info_rating.height;
423 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
425 options->marks_save = c_options->marks_save;
426 options->with_rename = c_options->with_rename;
427 options->collections_on_top = c_options->collections_on_top;
428 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
430 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
432 options->star_rating.star = c_options->star_rating.star;
433 options->star_rating.rejected = c_options->star_rating.rejected;
435 set_debug_level(debug_c);
439 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
441 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
442 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
444 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
445 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
446 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
448 options->color_profile.render_intent = c_options->color_profile.render_intent;
453 config_tab_keywords_save();
455 image_options_sync();
460 layout_refresh(NULL);
463 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
469 *-----------------------------------------------------------------------------
470 * config window main button callbacks (private)
471 *-----------------------------------------------------------------------------
474 static void config_window_close_cb(GtkWidget *widget, gpointer data)
476 gtk_widget_destroy(configwindow);
481 static void config_window_help_cb(GtkWidget *widget, gpointer data)
483 GtkWidget *notebook = data;
486 static gchar *html_section[] =
488 "GuideOptionsGeneral.html",
489 "GuideOptionsImage.html",
490 "GuideOptionsOSD.html",
491 "GuideOptionsWindow.html",
492 "GuideOptionsKeyboard.html",
493 "GuideOptionsFiltering.html",
494 "GuideOptionsMetadata.html",
495 "GuideOptionsKeywords.html",
496 "GuideOptionsColor.html",
497 "GuideOptionsStereo.html",
498 "GuideOptionsBehavior.html",
499 "GuideOptionsToolbar.html"
502 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
503 help_window_show(html_section[i]);
506 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
508 config_window_close_cb(NULL, NULL);
512 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
514 config_window_apply();
515 config_window_close_cb(NULL, NULL);
518 static void config_window_apply_cb(GtkWidget *widget, gpointer data)
521 lw = layout_window_list->data;
523 config_window_apply();
524 layout_util_sync(lw);
527 static void config_window_save_cb(GtkWidget *widget, gpointer data)
529 config_window_apply();
530 save_options(options);
534 *-----------------------------------------------------------------------------
535 * config window setup (private)
536 *-----------------------------------------------------------------------------
539 static void quality_menu_cb(GtkWidget *combo, gpointer data)
543 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
547 *option = GDK_INTERP_NEAREST;
550 *option = GDK_INTERP_TILES;
553 *option = GDK_INTERP_BILINEAR;
556 *option = GDK_INTERP_HYPER;
561 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
565 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
577 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
578 guint option, guint *option_c)
585 pref_table_label(table, column, row, text, 0.0);
587 combo = gtk_combo_box_text_new();
589 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
590 if (option == GDK_INTERP_NEAREST) current = 0;
591 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
592 if (option == GDK_INTERP_TILES) current = 1;
593 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear"));
594 if (option == GDK_INTERP_BILINEAR) current = 2;
595 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Hyper (best, but slowest)"));
596 if (option == GDK_INTERP_HYPER) current = 3;
598 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
600 g_signal_connect(G_OBJECT(combo), "changed",
601 G_CALLBACK(quality_menu_cb), option_c);
603 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
604 GTK_EXPAND | GTK_FILL, 0, 0, 0);
605 gtk_widget_show(combo);
608 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
609 gint option, gint *option_c)
616 pref_table_label(table, column, row, text, 0.0);
618 combo = gtk_combo_box_text_new();
620 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("PRIMARY"));
621 if (option == PRIMARY) current = 0;
622 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("CLIPBOARD"));
623 if (option == CLIPBOARD) current = 1;
625 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
627 g_signal_connect(G_OBJECT(combo), "changed",
628 G_CALLBACK(clipboard_selection_menu_cb), option_c);
630 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
631 GTK_EXPAND | GTK_FILL, 0, 0, 0);
632 gtk_widget_show(combo);
635 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
639 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
642 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
644 c_options->thumbnails.max_width = thumb_size_list[n].w;
645 c_options->thumbnails.max_height = thumb_size_list[n].h;
649 c_options->thumbnails.max_width = options->thumbnails.max_width;
650 c_options->thumbnails.max_height = options->thumbnails.max_height;
654 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
660 c_options->thumbnails.max_width = options->thumbnails.max_width;
661 c_options->thumbnails.max_height = options->thumbnails.max_height;
663 pref_table_label(table, column, row, text, 0.0);
665 combo = gtk_combo_box_text_new();
668 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
673 w = thumb_size_list[i].w;
674 h = thumb_size_list[i].h;
676 buf = g_strdup_printf("%d x %d", w, h);
677 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
680 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
687 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
688 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
694 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
695 g_signal_connect(G_OBJECT(combo), "changed",
696 G_CALLBACK(thumb_size_menu_cb), NULL);
698 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
699 GTK_EXPAND | GTK_FILL, 0, 0, 0);
700 gtk_widget_show(combo);
703 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
707 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
711 *option = PR_STEREO_NONE;
714 *option = PR_STEREO_ANAGLYPH_RC;
717 *option = PR_STEREO_ANAGLYPH_GM;
720 *option = PR_STEREO_ANAGLYPH_YB;
723 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
726 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
729 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
732 *option = PR_STEREO_ANAGLYPH_DB_RC;
735 *option = PR_STEREO_ANAGLYPH_DB_GM;
738 *option = PR_STEREO_ANAGLYPH_DB_YB;
741 *option = PR_STEREO_HORIZ;
744 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
747 *option = PR_STEREO_VERT;
750 *option = PR_STEREO_VERT | PR_STEREO_HALF;
753 *option = PR_STEREO_FIXED;
758 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
759 gint option, gint *option_c, gboolean add_fixed)
766 pref_table_label(table, column, row, text, 0.0);
768 combo = gtk_combo_box_text_new();
770 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
772 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
773 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
774 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
775 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
776 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
777 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
778 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
779 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
780 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
781 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
782 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
783 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
784 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
785 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
786 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
787 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
788 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
789 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
791 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
792 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
793 if (option & PR_STEREO_HORIZ)
796 if (option & PR_STEREO_HALF) current = 11;
799 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
800 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
801 if (option & PR_STEREO_VERT)
804 if (option & PR_STEREO_HALF) current = 13;
809 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
810 if (option & PR_STEREO_FIXED) current = 14;
813 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
815 g_signal_connect(G_OBJECT(combo), "changed",
816 G_CALLBACK(stereo_mode_menu_cb), option_c);
818 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
819 GTK_EXPAND | GTK_FILL, 0, 0, 0);
820 gtk_widget_show(combo);
823 static void video_menu_cb(GtkWidget *combo, gpointer data)
825 gchar **option = data;
827 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
831 static void video_menu_populate(gpointer data, gpointer user_data)
833 GtkWidget *combo = user_data;
834 EditorDescription *ed = data;
836 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
839 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
840 gchar *option, gchar **option_c)
844 /* use lists since they are sorted */
845 GList *eds = editor_list_get();
849 pref_table_label(table, column, row, text, 0.0);
851 combo = gtk_combo_box_text_new();
852 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
853 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
855 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
857 g_signal_connect(G_OBJECT(combo), "changed",
858 G_CALLBACK(video_menu_cb), option_c);
860 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
861 GTK_EXPAND | GTK_FILL, 0, 0, 0);
862 gtk_widget_show(combo);
865 static void filter_store_populate(void)
869 if (!filter_store) return;
871 gtk_list_store_clear(filter_store);
873 work = filter_get_list();
882 gtk_list_store_append(filter_store, &iter);
883 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
887 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
888 gchar *new_text, gpointer data)
890 GtkWidget *model = data;
891 FilterEntry *fe = data;
895 if (!new_text || strlen(new_text) < 1) return;
897 tpath = gtk_tree_path_new_from_string(path_str);
898 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
899 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
901 g_free(fe->extensions);
902 fe->extensions = g_strdup(new_text);
904 gtk_tree_path_free(tpath);
908 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
909 gchar *new_text, gpointer data)
911 GtkWidget *model = data;
912 FilterEntry *fe = data;
917 if (!new_text || !new_text[0]) return;
919 tpath = gtk_tree_path_new_from_string(path_str);
920 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
921 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
923 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
925 if (strcmp(new_text, _(format_class_list[i])) == 0)
932 gtk_tree_path_free(tpath);
936 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
937 gchar *new_text, gpointer data)
939 GtkWidget *model = data;
944 if (!new_text || !new_text[0]) return;
946 tpath = gtk_tree_path_new_from_string(path_str);
947 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
948 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
950 g_free(fe->description);
951 fe->description = g_strdup(new_text);
953 gtk_tree_path_free(tpath);
956 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
957 gchar *path_str, gpointer data)
959 GtkWidget *model = data;
964 tpath = gtk_tree_path_new_from_string(path_str);
965 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
966 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
968 fe->enabled = !fe->enabled;
970 gtk_tree_path_free(tpath);
974 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
975 gchar *path_str, gpointer data)
977 GtkWidget *model = data;
982 tpath = gtk_tree_path_new_from_string(path_str);
983 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
984 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
986 fe->writable = !fe->writable;
987 if (fe->writable) fe->allow_sidecar = FALSE;
989 gtk_tree_path_free(tpath);
993 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
994 gchar *path_str, gpointer data)
996 GtkWidget *model = data;
1001 tpath = gtk_tree_path_new_from_string(path_str);
1002 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1003 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1005 fe->allow_sidecar = !fe->allow_sidecar;
1006 if (fe->allow_sidecar) fe->writable = FALSE;
1008 gtk_tree_path_free(tpath);
1012 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1013 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1017 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1019 switch (GPOINTER_TO_INT(data))
1022 g_object_set(GTK_CELL_RENDERER(cell),
1023 "active", fe->enabled, NULL);
1026 g_object_set(GTK_CELL_RENDERER(cell),
1027 "text", fe->extensions, NULL);
1029 case FE_DESCRIPTION:
1030 g_object_set(GTK_CELL_RENDERER(cell),
1031 "text", fe->description, NULL);
1034 g_object_set(GTK_CELL_RENDERER(cell),
1035 "text", _(format_class_list[fe->file_class]), NULL);
1038 g_object_set(GTK_CELL_RENDERER(cell),
1039 "active", fe->writable, NULL);
1041 case FE_ALLOW_SIDECAR:
1042 g_object_set(GTK_CELL_RENDERER(cell),
1043 "active", fe->allow_sidecar, NULL);
1048 static gboolean filter_add_scroll(gpointer data)
1052 GtkCellRenderer *cell;
1053 GtkTreeViewColumn *column;
1058 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1059 path = gtk_tree_path_new_from_indices(rows-1, -1);
1061 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1063 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1064 cell = g_list_last(list_cells)->data;
1066 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1067 path, column, FALSE, 0.0, 0.0 );
1068 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1069 path, column, cell, TRUE);
1071 gtk_tree_path_free(path);
1072 g_list_free(list_cells);
1077 static void filter_add_cb(GtkWidget *widget, gpointer data)
1079 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1080 filter_store_populate();
1082 g_idle_add((GSourceFunc)filter_add_scroll, data);
1085 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1087 GtkWidget *filter_view = data;
1088 GtkTreeSelection *selection;
1092 if (!filter_store) return;
1093 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1094 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1095 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1098 filter_remove_entry(fe);
1100 filter_store_populate();
1103 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1107 GtkTreeViewColumn *column;
1109 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1110 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1111 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1113 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1117 gtk_tree_path_free(path);
1122 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1125 filter_add_defaults();
1127 filter_store_populate();
1129 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1132 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1134 /* no op, only so cancel button appears */
1137 static void filter_default_cb(GtkWidget *widget, gpointer data)
1141 gd = generic_dialog_new(_("Reset filters"),
1142 "reset_filter", widget, TRUE,
1143 dummy_cancel_cb, data);
1144 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1145 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1146 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1147 gtk_widget_show(gd->dialog);
1150 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1152 GtkWidget *frame = data;
1154 gtk_widget_set_sensitive(frame,
1155 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1158 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1160 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1163 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1165 file_util_trash_clear();
1168 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1172 gd = generic_dialog_new(_("Clear trash"),
1173 "clear_trash", widget, TRUE,
1174 dummy_cancel_cb, NULL);
1175 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1176 _("This will remove the trash contents."), FALSE);
1177 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1178 entry = gtk_entry_new();
1179 gtk_widget_set_can_focus(entry, FALSE);
1180 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1181 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1182 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1183 gtk_widget_show(entry);
1184 gtk_widget_show(gd->dialog);
1187 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1189 GtkWidget *pTextView;
1190 GtkTextBuffer *pTextBuffer;
1194 pTextView = GTK_WIDGET(data);
1196 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1197 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1198 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1200 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1201 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1204 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1206 GtkTextView *text_view = data;
1207 GtkTextBuffer *buffer;
1209 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1210 if (!configwindow) return;
1212 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1213 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1216 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1220 gd = generic_dialog_new(_("Reset image overlay template string"),
1221 "reset_image_overlay_template_string", widget, TRUE,
1222 dummy_cancel_cb, data);
1223 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1224 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1225 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1226 gtk_widget_show(gd->dialog);
1229 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1231 help_window_show("GuideOptionsOSD.html");
1234 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1236 #if GTK_CHECK_VERSION(3,4,0)
1239 PangoFontDescription *font_desc;
1241 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1242 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1244 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1246 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1247 font = pango_font_description_to_string(font_desc);
1248 g_free(c_options->image_overlay.font);
1249 c_options->image_overlay.font = g_strdup(font);
1253 gtk_widget_destroy(dialog);
1257 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1258 c_options->image_overlay.font = g_strdup(font);
1262 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1265 #if GTK_CHECK_VERSION(3,4,0)
1268 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1269 colour.red = options->image_overlay.text_red;
1270 colour.green = options->image_overlay.text_green;
1271 colour.blue = options->image_overlay.text_blue;
1272 colour.alpha = options->image_overlay.text_alpha;
1273 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1274 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1276 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1278 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1279 c_options->image_overlay.text_red = colour.red*255;
1280 c_options->image_overlay.text_green = colour.green*255;
1281 c_options->image_overlay.text_blue = colour.blue*255;
1282 c_options->image_overlay.text_alpha = colour.alpha*255;
1284 gtk_widget_destroy(dialog);
1287 GtkColorSelection *colorsel;
1289 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1290 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1291 colour.red = options->image_overlay.text_red*257;
1292 colour.green = options->image_overlay.text_green*257;
1293 colour.blue = options->image_overlay.text_blue*257;
1294 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1295 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1296 gtk_color_selection_set_current_color(colorsel, &colour);
1297 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1299 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1301 gtk_color_selection_get_current_color(colorsel, &colour);
1302 c_options->image_overlay.text_red = colour.red/257;
1303 c_options->image_overlay.text_green = colour.green/257;
1304 c_options->image_overlay.text_blue = colour.blue/257;
1305 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1307 gtk_widget_destroy (dialog);
1312 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1315 #if GTK_CHECK_VERSION(3,4,0)
1318 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1319 colour.red = options->image_overlay.background_red;
1320 colour.green = options->image_overlay.background_green;
1321 colour.blue = options->image_overlay.background_blue;
1322 colour.alpha = options->image_overlay.background_alpha;
1323 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1324 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1326 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1328 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1329 c_options->image_overlay.background_red = colour.red*255;
1330 c_options->image_overlay.background_green = colour.green*255;
1331 c_options->image_overlay.background_blue = colour.blue*255;
1332 c_options->image_overlay.background_alpha = colour.alpha*255;
1334 gtk_widget_destroy(dialog);
1337 GtkColorSelection *colorsel;
1339 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1340 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1341 colour.red = options->image_overlay.background_red*257;
1342 colour.green = options->image_overlay.background_green*257;
1343 colour.blue = options->image_overlay.background_blue*257;
1344 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1345 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1346 gtk_color_selection_set_current_color(colorsel, &colour);
1347 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1349 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1351 gtk_color_selection_get_current_color(colorsel, &colour);
1352 c_options->image_overlay.background_red = colour.red/257;
1353 c_options->image_overlay.background_green = colour.green/257;
1354 c_options->image_overlay.background_blue = colour.blue/257;
1355 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1357 gtk_widget_destroy(dialog);
1361 static void accel_store_populate(void)
1364 GList *groups, *actions;
1366 const gchar *accel_path;
1370 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1372 gtk_tree_store_clear(accel_store);
1373 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1375 g_assert(lw && lw->ui_manager);
1376 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1379 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1382 action = GTK_ACTION(actions->data);
1383 accel_path = gtk_action_get_accel_path(action);
1384 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1386 gchar *label, *label2, *tooltip, *accel;
1387 g_object_get(action,
1388 "tooltip", &tooltip,
1392 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1398 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1402 gtk_tree_store_append(accel_store, &iter, NULL);
1403 gtk_tree_store_set(accel_store, &iter,
1406 AE_TOOLTIP, tooltip ? tooltip : "",
1407 AE_ACCEL, accel_path,
1415 actions = actions->next;
1418 groups = groups->next;
1422 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1427 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1429 gchar *accel1 = data;
1434 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1436 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1437 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1439 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1441 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1442 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1451 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1453 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1457 GtkAccelKey old_key, key;
1458 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1460 gtk_tree_model_get_iter(model, &iter, path);
1461 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1463 /* test if the accelerator can be stored without conflicts*/
1464 gtk_accel_map_lookup_entry(accel_path, &old_key);
1466 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1467 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1468 gtk_accel_map_lookup_entry(accel_path, &key);
1470 /* restore the original for now, the key will be really changed when the changes are confirmed */
1471 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1473 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1474 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1476 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1477 gtk_tree_path_free(path);
1481 static gboolean accel_default_scroll(GtkTreeView *data)
1485 GtkTreeViewColumn *column;
1487 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1488 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1489 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1491 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1495 gtk_tree_path_free(path);
1500 static void accel_default_cb(GtkWidget *widget, gpointer data)
1502 accel_store_populate();
1504 g_idle_add((GSourceFunc)accel_default_scroll, data);
1507 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1509 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1512 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1515 gchar *accel_path, *accel;
1517 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1518 gtk_accel_map_lookup_entry(accel_path, &key);
1519 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1521 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1523 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1528 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1530 GtkTreeSelection *selection;
1532 if (!accel_store) return;
1533 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1534 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1539 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1543 GtkWidget *scrolled;
1544 GtkWidget *viewport;
1546 scrolled = gtk_scrolled_window_new(NULL, NULL);
1547 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1548 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1549 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1550 label = gtk_label_new(title);
1551 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1552 gtk_widget_show(scrolled);
1554 viewport = gtk_viewport_new(NULL, NULL);
1555 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1556 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1557 gtk_widget_show(viewport);
1559 vbox = gtk_vbox_new(FALSE, 0);
1560 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1561 gtk_widget_show(vbox);
1566 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1568 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1570 c_options->thumbnails.spec_standard =TRUE;
1571 c_options->thumbnails.cache_into_dirs = FALSE;
1575 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1577 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1579 c_options->thumbnails.spec_standard =FALSE;
1580 c_options->thumbnails.cache_into_dirs = FALSE;
1584 static void cache_local_cb(GtkWidget *widget, gpointer data)
1586 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1588 c_options->thumbnails.cache_into_dirs = TRUE;
1589 c_options->thumbnails.spec_standard =FALSE;
1593 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1594 GdkEvent *event, gpointer userdata)
1596 if (pos == GTK_ENTRY_ICON_PRIMARY)
1598 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1602 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1606 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1607 GdkEvent *event, gpointer userdata)
1609 gchar *rating_symbol;
1611 if (pos == GTK_ENTRY_ICON_PRIMARY)
1613 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1614 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1615 g_free(rating_symbol);
1619 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1620 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1621 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1625 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1626 GdkEvent *event, gpointer userdata)
1628 gchar *rating_symbol;
1630 if (pos == GTK_ENTRY_ICON_PRIMARY)
1632 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1633 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1634 g_free(rating_symbol);
1638 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1639 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1640 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1644 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1646 GtkContainer *hbox = data;
1647 GString *str = g_string_new(NULL);
1648 GtkEntry *hex_code_entry;
1649 gchar *hex_code_full;
1652 guint64 hex_value = 0;
1654 list = gtk_container_get_children(hbox);
1656 hex_code_entry = g_list_nth_data(list, 2);
1657 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1659 hex_code = g_strsplit(hex_code_full, "+", 2);
1660 if (hex_code[0] && hex_code[1])
1662 hex_value = strtoull(hex_code[1], NULL, 16);
1664 if (!hex_value || hex_value > 0x10FFFF)
1666 hex_value = 0x003F; // Unicode 'Question Mark'
1668 str = g_string_append_unichar(str, (gunichar)hex_value);
1669 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1671 g_strfreev(hex_code);
1672 g_string_free(str, TRUE);
1673 g_free(hex_code_full);
1678 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1680 guint64 star_symbol;
1682 star_symbol = star_rating_symbol_test(widget, data);
1683 c_options->star_rating.star = star_symbol;
1686 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1688 guint64 rejected_symbol;
1690 rejected_symbol = star_rating_symbol_test(widget, data);
1691 c_options->star_rating.rejected = rejected_symbol;
1694 /* general options tab */
1695 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1696 typedef struct _TZData TZData;
1700 GCancellable *cancellable;
1702 GtkWidget *progress;
1704 GFile *timezone_database_gq;
1705 gchar *timezone_database_user;
1708 static void config_tab_general(GtkWidget *notebook)
1713 GtkWidget *group_frame;
1714 GtkWidget *subgroup;
1716 GtkWidget *ct_button;
1719 gint hours, minutes, remainder;
1721 GtkWidget *star_rating_entry;
1723 gchar *rating_symbol;
1726 GNetworkMonitor *net_mon;
1727 GSocketConnectable *geeqie_org;
1728 gboolean internet_available;
1731 vbox = scrolled_notebook_page(notebook, _("General"));
1733 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1735 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1736 add_thumb_size_menu(table, 0, 0, _("Size:"));
1737 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1739 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails"),
1740 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
1742 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1743 pref_checkbox_link_sensitivity(ct_button, subgroup);
1745 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
1746 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
1747 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
1748 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1749 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
1750 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1751 G_CALLBACK(cache_geeqie_cb), NULL);
1753 group_frame = pref_frame_new(subgroup, TRUE,
1754 _("Store thumbnails local to image folder (non-standard)"),
1755 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1756 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
1757 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
1758 G_CALLBACK(cache_local_cb), NULL);
1760 group_frame = pref_frame_new(subgroup, TRUE,
1761 _("Use standard thumbnail style and cache, shared with other applications"),
1762 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
1763 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
1764 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
1765 G_CALLBACK(cache_standard_cb), NULL);
1767 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
1768 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
1770 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
1772 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
1773 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
1775 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
1776 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
1777 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
1779 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
1780 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
1783 pref_spacer(group, PREF_PAD_GROUP);
1785 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
1787 c_options->star_rating.star = options->star_rating.star;
1788 c_options->star_rating.rejected = options->star_rating.rejected;
1790 str = g_string_new(NULL);
1791 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1792 pref_label_new(hbox, "Star character: ");
1793 str = g_string_append_unichar(str, options->star_rating.star);
1794 pref_label_new(hbox, g_strdup(str->str));
1795 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
1796 star_rating_entry = gtk_entry_new();
1797 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1798 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1799 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1800 gtk_widget_show(star_rating_entry);
1801 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1802 G_CALLBACK(star_rating_star_test_cb), hbox);
1803 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1804 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1805 gtk_widget_show(button);
1806 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."));
1807 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1808 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1809 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1810 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1811 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1812 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1813 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1814 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1815 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1816 G_CALLBACK(star_rating_star_icon_cb),
1819 g_string_free(str, TRUE);
1820 g_free(rating_symbol);
1822 str = g_string_new(NULL);
1823 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1824 pref_label_new(hbox, "Rejected character: ");
1825 str = g_string_append_unichar(str, options->star_rating.rejected);
1826 pref_label_new(hbox, g_strdup(str->str));
1827 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
1828 star_rating_entry = gtk_entry_new();
1829 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
1830 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
1831 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
1832 gtk_widget_show(star_rating_entry);
1833 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
1834 G_CALLBACK(star_rating_rejected_test_cb), hbox);
1835 gtk_widget_set_tooltip_text(button, _("Display selected character"));
1836 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
1837 gtk_widget_show(button);
1838 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."));
1839 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1840 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1841 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1842 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1843 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
1844 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1845 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
1846 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1847 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
1848 G_CALLBACK(star_rating_rejected_icon_cb),
1851 g_string_free(str, TRUE);
1852 g_free(rating_symbol);
1854 pref_spacer(group, PREF_PAD_GROUP);
1856 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
1858 c_options->slideshow.delay = options->slideshow.delay;
1859 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1860 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
1861 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
1862 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
1863 SLIDESHOW_SUBSECOND_PRECISION;
1865 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1867 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
1869 options->slideshow.delay ? hours : 0.0,
1870 G_CALLBACK(slideshow_delay_hours_cb), NULL);
1871 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1872 spin = pref_spin_new(hbox, ":" , NULL,
1874 options->slideshow.delay ? minutes: 0.0,
1875 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
1876 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1877 spin = pref_spin_new(hbox, ":", NULL,
1878 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
1879 options->slideshow.delay ? seconds : 10.0,
1880 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
1881 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
1883 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
1884 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
1886 pref_spacer(group, PREF_PAD_GROUP);
1888 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
1890 pref_spin_new_int(group, _("Decoded image cache size (Mb):"), NULL,
1891 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
1892 pref_checkbox_new_int(group, _("Preload next image"),
1893 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
1895 pref_checkbox_new_int(group, _("Refresh on file change"),
1896 options->update_on_time_change, &c_options->update_on_time_change);
1898 pref_spacer(group, PREF_PAD_GROUP);
1900 group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
1901 pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
1902 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1903 pref_spin_new_int(hbox, _("Keywords:"), NULL,
1905 options->info_keywords.height, &c_options->info_keywords.height);
1906 pref_spin_new_int(hbox, _("Title:"), NULL,
1908 options->info_title.height, &c_options->info_title.height);
1909 pref_spin_new_int(hbox, _("Comment:"), NULL,
1911 options->info_comment.height, &c_options->info_comment.height);
1912 pref_spin_new_int(hbox, _("Rating:"), NULL,
1914 options->info_rating.height, &c_options->info_rating.height);
1916 pref_spacer(group, PREF_PAD_GROUP);
1918 group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
1920 pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
1921 options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
1923 pref_spacer(group, PREF_PAD_GROUP);
1925 net_mon = g_network_monitor_get_default();
1926 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
1927 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
1928 g_object_unref(geeqie_org);
1930 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
1931 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
1933 if (!internet_available)
1935 gtk_widget_set_sensitive(group, FALSE);
1938 tz = g_new0(TZData, 1);
1940 path = path_from_utf8(TIMEZONE_DATABASE);
1941 basename = g_path_get_basename(path);
1942 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
1946 if (isfile(tz->timezone_database_user))
1948 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
1952 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
1955 if (!internet_available)
1957 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"));
1961 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"));
1963 gtk_widget_show(button);
1965 pref_spacer(group, PREF_PAD_GROUP);
1967 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
1969 help_search_engine_entry = gtk_entry_new();
1970 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
1971 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
1972 gtk_widget_show(help_search_engine_entry);
1974 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"));
1976 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1977 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
1978 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1979 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
1980 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
1981 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
1982 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
1983 GTK_ENTRY_ICON_PRIMARY, _("Default"));
1984 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
1985 G_CALLBACK(help_search_engine_entry_icon_cb),
1986 help_search_engine_entry);
1990 static void config_tab_image(GtkWidget *notebook)
1995 GtkWidget *ct_button;
1996 GtkWidget *enlargement_button;
2000 vbox = scrolled_notebook_page(notebook, _("Image"));
2002 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2004 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2005 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2008 pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library"),
2009 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2012 pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2013 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2015 c_options->image.zoom_increment = options->image.zoom_increment;
2016 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2017 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2018 G_CALLBACK(zoom_increment_cb), NULL);
2019 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2021 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2023 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2024 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2025 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2026 spin = pref_spin_new_int(hbox, NULL, NULL,
2028 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2029 pref_checkbox_link_sensitivity(enlargement_button, spin);
2030 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."));
2032 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2033 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2034 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2035 spin = pref_spin_new_int(hbox, NULL, NULL,
2037 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2038 pref_checkbox_link_sensitivity(ct_button, spin);
2039 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."));
2041 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2043 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2044 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2046 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2047 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2049 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2050 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2052 c_options->image.border_color = options->image.border_color;
2054 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2055 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2057 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2058 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2060 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2061 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2063 group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
2065 pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
2066 options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
2070 static void config_tab_windows(GtkWidget *notebook)
2076 GtkWidget *ct_button;
2079 vbox = scrolled_notebook_page(notebook, _("Windows"));
2081 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2083 ct_button = pref_checkbox_new_int(group, _("Remember window positions"),
2084 options->save_window_positions, &c_options->save_window_positions);
2086 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2087 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2088 pref_checkbox_link_sensitivity(ct_button, button);
2090 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2091 options->tools_restore_state, &c_options->tools_restore_state);
2093 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2094 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2096 pref_checkbox_new_int(group, _("Show window IDs"),
2097 options->show_window_ids, &c_options->show_window_ids);
2099 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2101 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2102 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2104 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2105 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2106 options->image.limit_window_size, &c_options->image.limit_window_size);
2107 spin = pref_spin_new_int(hbox, NULL, NULL,
2109 options->image.max_window_size, &c_options->image.max_window_size);
2110 pref_checkbox_link_sensitivity(ct_button, spin);
2112 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2114 c_options->fullscreen.screen = options->fullscreen.screen;
2115 c_options->fullscreen.above = options->fullscreen.above;
2116 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2117 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2118 gtk_widget_show(hbox);
2120 pref_checkbox_new_int(group, _("Smooth image flip"),
2121 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2122 pref_checkbox_new_int(group, _("Disable screen saver"),
2123 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2126 #define PRE_FORMATTED_COLUMNS 5
2127 static void config_tab_osd(GtkWidget *notebook)
2131 GtkWidget *vbox_buttons;
2134 GtkWidget *image_overlay_template_view;
2135 GtkWidget *scrolled;
2136 GtkWidget *scrolled_pre_formatted;
2137 GtkTextBuffer *buffer;
2139 GtkWidget * subgroup;
2144 vbox = scrolled_notebook_page(notebook, _("OSD"));
2146 image_overlay_template_view = gtk_text_view_new();
2148 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2150 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2152 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2153 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2154 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2155 gtk_widget_show(scrolled_pre_formatted);
2156 gtk_widget_show(subgroup);
2158 pref_line(group, PREF_PAD_GAP);
2160 pref_label_new(group, _("Image overlay template"));
2162 scrolled = gtk_scrolled_window_new(NULL, NULL);
2163 gtk_widget_set_size_request(scrolled, 200, 150);
2164 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2165 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2166 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2167 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2168 gtk_widget_show(scrolled);
2170 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2171 _("Extensive formatting options are shown in the Help file"));
2173 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2174 gtk_widget_show(image_overlay_template_view);
2176 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2178 #if GTK_CHECK_VERSION(3,4,0)
2179 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2180 G_CALLBACK(image_overlay_set_font_cb), notebook);
2182 button = gtk_font_button_new();
2183 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2184 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2185 g_signal_connect(G_OBJECT(button), "font-set",
2186 G_CALLBACK(image_overlay_set_font_cb),NULL);
2188 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2189 gtk_widget_show(button);
2191 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2192 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2193 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2194 gtk_widget_show(button);
2196 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2197 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2198 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2199 gtk_widget_show(button);
2200 image_overlay_set_text_colours();
2202 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2203 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2204 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2205 gtk_widget_show(button);
2207 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2208 G_CALLBACK(image_overlay_help_cb), NULL);
2209 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2210 gtk_widget_show(button);
2212 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2213 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2214 g_signal_connect(G_OBJECT(buffer), "changed",
2215 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2217 pref_line(group, PREF_PAD_GAP);
2219 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2220 hbox = gtk_hbox_new(FALSE, 0);
2221 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2222 gtk_widget_show(hbox);
2223 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2224 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2225 gtk_widget_show(label);
2226 pref_spacer(group,TRUE);
2228 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2229 hbox = gtk_hbox_new(FALSE, 0);
2230 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2231 gtk_widget_show(hbox);
2232 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2233 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2234 gtk_widget_show(label);
2235 pref_spacer(group,TRUE);
2237 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2238 hbox = gtk_hbox_new(FALSE, 0);
2239 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2240 gtk_widget_show(hbox);
2241 label = gtk_label_new(_("%path:39%"));
2242 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2243 gtk_widget_show(label);
2244 pref_spacer(group,TRUE);
2246 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2247 hbox = gtk_hbox_new(FALSE, 0);
2248 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2249 gtk_widget_show(hbox);
2250 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%"));
2251 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2252 gtk_widget_show(label);
2253 pref_spacer(group,TRUE);
2255 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2256 hbox = gtk_hbox_new(FALSE, 0);
2257 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2258 gtk_widget_show(hbox);
2259 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2260 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2261 gtk_widget_show(label);
2264 static GtkTreeModel *create_class_model(void)
2266 GtkListStore *model;
2270 /* create list store */
2271 model = gtk_list_store_new(1, G_TYPE_STRING);
2272 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2274 gtk_list_store_append(model, &iter);
2275 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2277 return GTK_TREE_MODEL (model);
2282 static void config_tab_files(GtkWidget *notebook)
2289 GtkWidget *ct_button;
2290 GtkWidget *scrolled;
2291 GtkWidget *filter_view;
2292 GtkCellRenderer *renderer;
2293 GtkTreeSelection *selection;
2294 GtkTreeViewColumn *column;
2296 vbox = scrolled_notebook_page(notebook, _("Files"));
2298 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2300 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2301 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2302 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2303 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2304 pref_checkbox_new_int(group, _("Case sensitive sort"),
2305 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2306 pref_checkbox_new_int(group, _("Natural sort order"),
2307 options->file_sort.natural, &c_options->file_sort.natural);
2308 pref_checkbox_new_int(group, _("Disable file extension checks"),
2309 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2311 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2312 options->file_filter.disable, &c_options->file_filter.disable);
2315 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2317 sidecar_ext_entry = gtk_entry_new();
2318 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2319 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2320 gtk_widget_show(sidecar_ext_entry);
2322 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2324 frame = pref_group_parent(group);
2325 g_signal_connect(G_OBJECT(ct_button), "toggled",
2326 G_CALLBACK(filter_disable_cb), frame);
2327 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2329 scrolled = gtk_scrolled_window_new(NULL, NULL);
2330 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2331 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2332 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2333 gtk_widget_show(scrolled);
2335 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2336 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2337 g_object_unref(filter_store);
2338 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2339 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2341 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2343 column = gtk_tree_view_column_new();
2344 gtk_tree_view_column_set_title(column, _("Filter"));
2345 gtk_tree_view_column_set_resizable(column, TRUE);
2347 renderer = gtk_cell_renderer_toggle_new();
2348 g_signal_connect(G_OBJECT(renderer), "toggled",
2349 G_CALLBACK(filter_store_enable_cb), filter_store);
2350 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2351 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2352 GINT_TO_POINTER(FE_ENABLE), NULL);
2354 renderer = gtk_cell_renderer_text_new();
2355 g_signal_connect(G_OBJECT(renderer), "edited",
2356 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2357 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2358 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2359 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2360 GINT_TO_POINTER(FE_EXTENSION), NULL);
2361 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2363 column = gtk_tree_view_column_new();
2364 gtk_tree_view_column_set_title(column, _("Description"));
2365 gtk_tree_view_column_set_resizable(column, TRUE);
2366 gtk_tree_view_column_set_fixed_width(column, 200);
2367 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2369 renderer = gtk_cell_renderer_text_new();
2370 g_signal_connect(G_OBJECT(renderer), "edited",
2371 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2372 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2373 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2374 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2375 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2376 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2378 column = gtk_tree_view_column_new();
2379 gtk_tree_view_column_set_title(column, _("Class"));
2380 gtk_tree_view_column_set_resizable(column, TRUE);
2381 renderer = gtk_cell_renderer_combo_new();
2382 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2383 "model", create_class_model(),
2388 g_signal_connect(G_OBJECT(renderer), "edited",
2389 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2390 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2391 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2392 GINT_TO_POINTER(FE_CLASS), NULL);
2393 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2395 column = gtk_tree_view_column_new();
2396 gtk_tree_view_column_set_title(column, _("Writable"));
2397 gtk_tree_view_column_set_resizable(column, FALSE);
2398 renderer = gtk_cell_renderer_toggle_new();
2399 g_signal_connect(G_OBJECT(renderer), "toggled",
2400 G_CALLBACK(filter_store_writable_cb), filter_store);
2401 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2402 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2403 GINT_TO_POINTER(FE_WRITABLE), NULL);
2404 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2406 column = gtk_tree_view_column_new();
2407 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2408 gtk_tree_view_column_set_resizable(column, FALSE);
2409 renderer = gtk_cell_renderer_toggle_new();
2410 g_signal_connect(G_OBJECT(renderer), "toggled",
2411 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2412 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2413 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2414 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2415 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2418 filter_store_populate();
2419 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2420 gtk_widget_show(filter_view);
2422 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2424 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2425 G_CALLBACK(filter_default_cb), filter_view);
2426 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2427 gtk_widget_show(button);
2429 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2430 G_CALLBACK(filter_remove_cb), filter_view);
2431 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2432 gtk_widget_show(button);
2434 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2435 G_CALLBACK(filter_add_cb), filter_view);
2436 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2437 gtk_widget_show(button);
2441 static void config_tab_metadata(GtkWidget *notebook)
2446 GtkWidget *ct_button;
2450 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2453 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2455 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2457 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2458 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2460 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2461 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2463 gtk_widget_set_sensitive(ct_button, FALSE);
2466 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2467 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2469 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2470 label = pref_label_new(group, text);
2471 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2472 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2475 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2477 gtk_widget_set_sensitive(group, FALSE);
2480 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2481 pref_checkbox_link_sensitivity(ct_button, hbox);
2483 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2484 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2486 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2487 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2489 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2490 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2492 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2493 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2495 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2497 gtk_widget_set_sensitive(group, FALSE);
2500 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2501 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2504 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2505 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2506 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2508 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2509 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2511 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2512 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2514 gtk_widget_set_sensitive(ct_button, FALSE);
2517 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2519 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2520 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2522 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2523 pref_checkbox_link_sensitivity(ct_button, hbox);
2525 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2526 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2528 pref_checkbox_new_int(group, _("Write metadata on image change"),
2529 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2531 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2532 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2534 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2536 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2537 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2538 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");
2543 typedef struct _KeywordFindData KeywordFindData;
2544 struct _KeywordFindData
2551 GtkWidget *button_close;
2552 GtkWidget *button_stop;
2553 GtkWidget *button_start;
2554 GtkWidget *progress;
2562 guint idle_id; /* event source id */
2565 #define KEYWORD_DIALOG_WIDTH 400
2567 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2569 GList *list_d = NULL;
2570 GList *list_f = NULL;
2574 filelist_read(dir_fd, &list_f, &list_d);
2578 filelist_read(dir_fd, &list_f, NULL);
2581 list_f = filelist_filter(list_f, FALSE);
2582 list_d = filelist_filter(list_d, TRUE);
2584 kfd->list = g_list_concat(list_f, kfd->list);
2585 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2588 static void keywords_find_reset(KeywordFindData *kfd)
2590 filelist_free(kfd->list);
2593 filelist_free(kfd->list_dir);
2594 kfd->list_dir = NULL;
2597 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2599 KeywordFindData *kfd = data;
2601 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2603 keywords_find_reset(kfd);
2604 generic_dialog_close(kfd->gd);
2608 static void keywords_find_finish(KeywordFindData *kfd)
2610 keywords_find_reset(kfd);
2612 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2613 spinner_set_interval(kfd->spinner, -1);
2615 gtk_widget_set_sensitive(kfd->group, TRUE);
2616 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2617 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2618 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2621 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2623 KeywordFindData *kfd = data;
2625 g_idle_remove_by_data(kfd);
2627 keywords_find_finish(kfd);
2630 static gboolean keywords_find_file(gpointer data)
2632 KeywordFindData *kfd = data;
2634 GtkTextBuffer *buffer;
2642 fd = kfd->list->data;
2643 kfd->list = g_list_remove(kfd->list, fd);
2645 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2646 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2650 gtk_text_buffer_get_end_iter(buffer, &iter);
2651 tmp = g_strconcat(keywords->data, "\n", NULL);
2652 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2654 keywords = keywords->next;
2657 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
2658 file_data_unref(fd);
2659 string_list_free(keywords);
2663 else if (kfd->list_dir)
2667 fd = kfd->list_dir->data;
2668 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
2670 keywords_find_folder(kfd, fd);
2672 file_data_unref(fd);
2677 keywords_find_finish(kfd);
2682 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
2684 KeywordFindData *kfd = data;
2687 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
2689 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
2690 parse_out_relatives(path);
2694 warning_dialog(_("Invalid folder"),
2695 _("The specified folder can not be found."),
2696 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
2702 gtk_widget_set_sensitive(kfd->group, FALSE);
2703 gtk_widget_set_sensitive(kfd->button_start, FALSE);
2704 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
2705 gtk_widget_set_sensitive(kfd->button_close, FALSE);
2706 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
2708 dir_fd = file_data_new_dir(path);
2709 keywords_find_folder(kfd, dir_fd);
2710 file_data_unref(dir_fd);
2711 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
2717 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
2719 KeywordFindData *kfd;
2723 kfd = g_new0(KeywordFindData, 1);
2725 kfd->gd = generic_dialog_new(_("Search for keywords"),
2726 "search_for_keywords",
2729 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
2730 kfd->gd->cancel_cb = keywords_find_close_cb;
2731 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
2732 keywords_find_close_cb, FALSE);
2733 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
2734 keywords_find_start_cb, FALSE);
2735 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
2736 keywords_find_stop_cb, FALSE);
2737 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2739 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
2741 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
2742 pref_spacer(hbox, PREF_PAD_INDENT);
2743 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2745 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2746 pref_label_new(hbox, _("Folder:"));
2748 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
2749 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
2750 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
2751 gtk_widget_show(label);
2753 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
2755 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
2756 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2758 kfd->progress = gtk_entry_new();
2759 gtk_widget_set_can_focus(kfd->progress, FALSE);
2760 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
2761 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
2762 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
2763 gtk_widget_show(kfd->progress);
2765 kfd->spinner = spinner_new(NULL, -1);
2766 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
2767 gtk_widget_show(kfd->spinner);
2771 gtk_widget_show(kfd->gd->dialog);
2774 static void keywords_find_cb(GtkWidget *widget, gpointer data)
2776 const gchar *path = layout_get_path(NULL);
2778 if (!path || !*path) path = homedir();
2779 keywords_find_dialog(widget, path);
2782 static void config_tab_keywords_save()
2784 GtkTextIter start, end;
2785 GtkTextBuffer *buffer;
2786 GList *kw_list = NULL;
2792 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2793 gtk_text_buffer_get_bounds(buffer, &start, &end);
2795 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
2797 kw_split = strtok(buffer_text, "\n");
2798 while (kw_split != NULL)
2804 if (g_strcmp0(work->data, kw_split) == 0)
2813 kw_list = g_list_append(kw_list, g_strdup(kw_split));
2815 kw_split = strtok(NULL, "\n");
2818 keyword_list_set(kw_list);
2820 string_list_free(kw_list);
2821 g_free(buffer_text);
2824 static void config_tab_keywords(GtkWidget *notebook)
2830 GtkWidget *scrolled;
2832 GtkTextBuffer *buffer;
2835 vbox = scrolled_notebook_page(notebook, _("Keywords"));
2837 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
2839 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2841 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
2842 G_CALLBACK(keywords_find_cb), keyword_text);
2843 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
2846 keyword_text = gtk_text_view_new();
2847 gtk_widget_set_size_request(keyword_text, 20, 20);
2848 scrolled = gtk_scrolled_window_new(NULL, NULL);
2849 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2850 gtk_widget_show(scrolled);
2852 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
2853 gtk_widget_show(keyword_text);
2855 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
2857 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
2858 gtk_text_buffer_create_tag(buffer, "monospace",
2859 "family", "monospace", NULL);
2861 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
2862 gtk_text_buffer_get_start_iter(buffer, &iter);
2863 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
2866 path = g_build_filename(get_rc_dir(), "keywords", NULL);
2868 GList *kwl = keyword_list_get();
2869 kwl = g_list_first(kwl);
2872 gtk_text_buffer_get_end_iter (buffer, &iter);
2873 tmp = g_strconcat(kwl->data, "\n", NULL);
2874 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
2879 gtk_text_buffer_set_modified(buffer, FALSE);
2886 static void intent_menu_cb(GtkWidget *combo, gpointer data)
2888 gint *option = data;
2890 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
2894 *option = INTENT_PERCEPTUAL;
2897 *option = INTENT_RELATIVE_COLORIMETRIC;
2900 *option = INTENT_SATURATION;
2903 *option = INTENT_ABSOLUTE_COLORIMETRIC;
2908 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
2909 gint option, gint *option_c)
2916 pref_table_label(table, column, row, text, 0.0);
2918 combo = gtk_combo_box_text_new();
2920 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
2921 if (option == INTENT_PERCEPTUAL) current = 0;
2922 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
2923 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
2924 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
2925 if (option == INTENT_SATURATION) current = 2;
2926 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
2927 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
2929 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
2931 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
2933 g_signal_connect(G_OBJECT(combo), "changed",
2934 G_CALLBACK(intent_menu_cb), option_c);
2936 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1,
2937 GTK_EXPAND | GTK_FILL, 0, 0, 0);
2938 gtk_widget_show(combo);
2942 static void config_tab_color(GtkWidget *notebook)
2951 vbox = scrolled_notebook_page(notebook, _("Color management"));
2953 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
2955 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
2958 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
2959 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
2961 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
2962 pref_label_bold(label, TRUE, FALSE);
2964 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
2965 pref_label_bold(label, TRUE, FALSE);
2967 label = pref_table_label(table, 2, 0, _("File"), 0.0);
2968 pref_label_bold(label, TRUE, FALSE);
2970 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
2975 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
2976 pref_table_label(table, 0, i + 1, buf, 1.0);
2979 entry = gtk_entry_new();
2980 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
2981 if (options->color_profile.input_name[i])
2983 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
2985 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
2986 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2987 gtk_widget_show(entry);
2988 color_profile_input_name_entry[i] = entry;
2990 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
2991 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
2992 gtk_widget_set_size_request(entry, 160, -1);
2993 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
2994 GTK_FILL | GTK_EXPAND, 0, 0, 0);
2995 gtk_widget_show(tabcomp);
2996 color_profile_input_file_entry[i] = entry;
2999 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3001 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3003 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3004 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3006 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3008 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3009 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3010 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3011 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3012 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3014 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3016 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3018 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3020 gtk_widget_show(tabcomp);
3023 /* advanced entry tab */
3024 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3026 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3028 c_options->file_ops.use_system_trash = FALSE;
3029 c_options->file_ops.no_trash = FALSE;
3033 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3035 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3037 c_options->file_ops.use_system_trash = TRUE;
3038 c_options->file_ops.no_trash = FALSE;
3042 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3044 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3046 c_options->file_ops.no_trash = TRUE;
3050 static void config_tab_behavior(GtkWidget *notebook)
3057 GtkWidget *ct_button;
3061 GtkWidget *with_rename;
3062 GtkWidget *collections_on_top;
3064 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3066 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3068 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3069 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3070 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3071 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3072 pref_checkbox_new_int(group, _("Enable Delete key"),
3073 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3075 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3076 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3078 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3079 pref_checkbox_link_sensitivity(ct_button, hbox);
3081 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3082 pref_label_new(hbox, _("Folder:"));
3084 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3085 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3086 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3087 gtk_widget_show(tabcomp);
3089 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3090 pref_checkbox_link_sensitivity(ct_button, hbox);
3092 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3093 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MB"),
3094 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3095 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3096 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3097 G_CALLBACK(safe_delete_view_cb), NULL);
3098 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3099 gtk_widget_show(button);
3101 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3102 G_CALLBACK(safe_delete_clear_cb), NULL);
3103 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3104 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3105 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3107 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3108 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3110 gtk_widget_show(button);
3112 pref_spacer(group, PREF_PAD_GROUP);
3115 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3117 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3118 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3120 pref_checkbox_new_int(group, _("In place renaming"),
3121 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3123 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3124 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3126 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3127 options->marks_save, &c_options->marks_save);
3128 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3130 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3131 options->with_rename, &c_options->with_rename);
3132 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3134 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3135 options->collections_on_top, &c_options->collections_on_top);
3136 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3138 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3139 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3141 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3142 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3144 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3145 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3147 pref_spacer(group, PREF_PAD_GROUP);
3149 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3151 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3152 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3153 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3154 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3155 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3156 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3157 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3158 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3159 pref_checkbox_new_int(group, _("Play video by left click on image"),
3160 options->image_l_click_video, &c_options->image_l_click_video);
3161 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3162 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3166 pref_spacer(group, PREF_PAD_GROUP);
3168 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3170 pref_spin_new_int(group, _("Debug level:"), NULL,
3171 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3173 pref_checkbox_new_int(group, _("Timer data"),
3174 options->log_window.timer_data, &c_options->log_window.timer_data);
3176 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3177 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3181 /* accelerators tab */
3182 static void config_tab_accelerators(GtkWidget *notebook)
3188 GtkWidget *scrolled;
3189 GtkWidget *accel_view;
3190 GtkCellRenderer *renderer;
3191 GtkTreeSelection *selection;
3192 GtkTreeViewColumn *column;
3194 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3196 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3198 scrolled = gtk_scrolled_window_new(NULL, NULL);
3199 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3200 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3201 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3202 gtk_widget_show(scrolled);
3204 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3206 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3207 g_object_unref(accel_store);
3208 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3209 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3211 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3213 renderer = gtk_cell_renderer_text_new();
3215 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3220 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3221 gtk_tree_view_column_set_resizable(column, TRUE);
3222 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3225 renderer = gtk_cell_renderer_accel_new();
3226 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3227 G_CALLBACK(accel_store_cleared_cb), accel_store);
3228 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3229 G_CALLBACK(accel_store_edited_cb), accel_store);
3232 g_object_set (renderer,
3234 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3237 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3242 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3243 gtk_tree_view_column_set_resizable(column, TRUE);
3244 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3246 renderer = gtk_cell_renderer_text_new();
3248 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3253 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3254 gtk_tree_view_column_set_resizable(column, TRUE);
3255 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3257 renderer = gtk_cell_renderer_text_new();
3259 column = gtk_tree_view_column_new_with_attributes("Accel",
3264 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3265 gtk_tree_view_column_set_resizable(column, TRUE);
3266 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3268 accel_store_populate();
3269 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3270 gtk_widget_show(accel_view);
3272 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3274 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3275 G_CALLBACK(accel_default_cb), accel_view);
3276 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3277 gtk_widget_show(button);
3279 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3280 G_CALLBACK(accel_reset_cb), accel_view);
3281 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3282 gtk_widget_show(button);
3286 static void config_tab_toolbar(GtkWidget *notebook)
3289 GtkWidget *toolbardata;
3292 lw = layout_window_list->data;
3294 vbox = scrolled_notebook_page(notebook, _("Toolbar"));
3296 toolbardata = toolbar_select_new(lw);
3297 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3298 gtk_widget_show(vbox);
3302 static void config_tab_stereo(GtkWidget *notebook)
3310 GtkWidget *fs_button;
3311 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3313 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3315 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3316 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3318 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3319 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3320 pref_checkbox_new_int(box, _("Mirror left image"),
3321 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3322 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3323 pref_checkbox_new_int(box, _("Flip left image"),
3324 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3325 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3326 pref_checkbox_new_int(box, _("Mirror right image"),
3327 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3328 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3329 pref_checkbox_new_int(box, _("Flip right image"),
3330 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3331 pref_checkbox_new_int(group, _("Swap left and right images"),
3332 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3333 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3334 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3336 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3337 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3338 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3339 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3340 pref_checkbox_link_sensitivity(fs_button, box2);
3341 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3342 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3343 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3344 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3345 pref_checkbox_new_int(box, _("Mirror left image"),
3346 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3347 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3348 pref_checkbox_new_int(box, _("Flip left image"),
3349 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3350 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3351 pref_checkbox_new_int(box, _("Mirror right image"),
3352 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3353 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3354 pref_checkbox_new_int(box, _("Flip right image"),
3355 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3356 pref_checkbox_new_int(box2, _("Swap left and right images"),
3357 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3358 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3359 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3361 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3362 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3363 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3364 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3365 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3366 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3367 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3368 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3369 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3370 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3371 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3372 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3373 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3374 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3378 /* Main preferences window */
3379 static void config_window_create(void)
3381 GtkWidget *win_vbox;
3383 GtkWidget *notebook;
3385 GtkWidget *ct_button;
3387 if (!c_options) c_options = init_options(NULL);
3389 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3390 DEBUG_NAME(configwindow);
3391 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3392 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3393 G_CALLBACK(config_window_delete), NULL);
3394 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3395 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3396 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3398 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3399 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3400 gtk_widget_show(win_vbox);
3402 notebook = gtk_notebook_new();
3403 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3404 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3405 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3407 config_tab_general(notebook);
3408 config_tab_image(notebook);
3409 config_tab_osd(notebook);
3410 config_tab_windows(notebook);
3411 config_tab_accelerators(notebook);
3412 config_tab_files(notebook);
3413 config_tab_metadata(notebook);
3414 config_tab_keywords(notebook);
3415 config_tab_color(notebook);
3416 config_tab_stereo(notebook);
3417 config_tab_behavior(notebook);
3418 config_tab_toolbar(notebook);
3420 hbox = gtk_hbutton_box_new();
3421 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3422 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3423 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3424 gtk_widget_show(hbox);
3426 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3427 G_CALLBACK(config_window_help_cb), notebook);
3428 gtk_container_add(GTK_CONTAINER(hbox), button);
3429 gtk_widget_set_can_default(button, TRUE);
3430 gtk_widget_show(button);
3432 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3433 G_CALLBACK(config_window_ok_cb), NULL);
3434 gtk_container_add(GTK_CONTAINER(hbox), button);
3435 gtk_widget_set_can_default(button, TRUE);
3436 gtk_widget_grab_default(button);
3437 gtk_widget_show(button);
3441 button = pref_button_new(NULL, GTK_STOCK_SAVE, NULL, FALSE,
3442 G_CALLBACK(config_window_save_cb), NULL);
3443 gtk_container_add(GTK_CONTAINER(hbox), button);
3444 gtk_widget_set_can_default(button, TRUE);
3445 gtk_widget_show(button);
3447 button = pref_button_new(NULL, GTK_STOCK_APPLY, NULL, FALSE,
3448 G_CALLBACK(config_window_apply_cb), NULL);
3449 gtk_container_add(GTK_CONTAINER(hbox), button);
3450 gtk_widget_set_can_default(button, TRUE);
3451 gtk_widget_show(button);
3453 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3454 G_CALLBACK(config_window_close_cb), NULL);
3455 gtk_container_add(GTK_CONTAINER(hbox), button);
3456 gtk_widget_set_can_default(button, TRUE);
3457 gtk_widget_show(button);
3459 if (!generic_dialog_get_alternative_button_order(configwindow))
3461 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3464 gtk_widget_show(notebook);
3466 gtk_widget_show(configwindow);
3470 *-----------------------------------------------------------------------------
3471 * config window show (public)
3472 *-----------------------------------------------------------------------------
3475 void show_config_window(void)
3479 gtk_window_present(GTK_WINDOW(configwindow));
3483 config_window_create();
3492 void show_about_window(LayoutWindow *lw)
3494 GdkPixbuf *pixbuf_logo;
3495 GdkPixbuf *pixbuf_icon;
3496 gchar *authors[1000];
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 zd_path = g_build_filename(GQ_BIN_DIR, TIMEZONE_DATABASE, NULL);
3511 cd = ZDOpenDatabase(zd_path);
3514 copyright = g_string_append(copyright, ZDGetNotice(cd));
3516 ZDCloseDatabase(cd);
3520 path = g_build_filename(GQ_HELPDIR, "AUTHORS", NULL);
3521 fp = fopen(path, "r");
3524 while(fgets(line, LINE_LENGTH, fp))
3526 /* get rid of ending \n from fgets */
3527 line[strlen(line) - 1] = '\0';
3528 authors[i_authors] = g_strdup(line);
3531 authors[i_authors] = NULL;
3536 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
3537 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
3539 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
3540 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
3541 gtk_show_about_dialog(GTK_WINDOW(lw->window),
3542 "title", _("About Geeqie"),
3544 "program-name", GQ_APPNAME,
3546 "logo", pixbuf_logo,
3547 "icon", pixbuf_icon,
3548 "website", GQ_WEBSITE,
3549 "website-label", "Website",
3550 "comments", comment,
3552 "translator-credits", _("translator-credits"),
3553 "wrap-license", TRUE,
3554 "license", copyright->str,
3557 g_string_free(copyright, TRUE);
3560 while(n < i_authors)
3570 static void image_overlay_set_text_colours()
3572 c_options->image_overlay.text_red = options->image_overlay.text_red;
3573 c_options->image_overlay.text_green = options->image_overlay.text_green;
3574 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
3575 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
3576 c_options->image_overlay.background_red = options->image_overlay.background_red;
3577 c_options->image_overlay.background_green = options->image_overlay.background_green;
3578 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
3579 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
3583 *-----------------------------------------------------------------------------
3584 * timezone database routines
3585 *-----------------------------------------------------------------------------
3588 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
3590 GError *error = NULL;
3592 gchar *tmp_filename;
3594 if (!g_cancellable_is_cancelled(tz->cancellable))
3596 generic_dialog_close(tz->gd);
3600 if (g_file_copy_finish(G_FILE(source_object), res, &error))
3602 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
3603 move_file(tmp_filename, tz->timezone_database_user);
3604 g_free(tmp_filename);
3608 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3611 g_file_delete(tz->tmp_g_file, NULL, &error);
3612 g_object_unref(tz->tmp_g_file);
3613 tz->tmp_g_file = NULL;
3614 g_object_unref(tz->cancellable);
3615 g_object_unref(tz->timezone_database_gq);
3618 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
3622 if (!g_cancellable_is_cancelled(tz->cancellable))
3624 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
3628 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
3631 GError *error = NULL;
3633 g_cancellable_cancel(tz->cancellable);
3636 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
3639 GError *error = NULL;
3640 GFileIOStream *io_stream;
3647 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
3651 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
3652 log_printf("Error: Download timezone database failed:\n%s", error->message);
3653 g_error_free(error);
3654 g_object_unref(tz->tmp_g_file);
3658 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
3660 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
3662 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
3664 tz->progress = gtk_progress_bar_new();
3665 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
3666 gtk_widget_show(tz->progress);
3668 gtk_widget_show(tz->gd->dialog);
3669 tz->cancellable = g_cancellable_new();
3670 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);
3672 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
3675 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */