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"
44 #include "pixbuf_util.h"
46 #include "slideshow.h"
50 #include "ui_fileops.h"
52 #include "ui_spinner.h"
53 #include "ui_tabcomp.h"
54 #include "ui_utildlg.h"
56 #include "zonedetect.h"
66 #define EDITOR_NAME_MAX_LENGTH 32
67 #define EDITOR_COMMAND_MAX_LENGTH 1024
69 static void image_overlay_set_text_colours();
71 GtkWidget *keyword_text;
72 static void config_tab_keywords_save();
74 typedef struct _ThumbSize ThumbSize;
81 static ThumbSize thumb_size_list[] =
115 gchar *format_class_list[] = {
126 /* config memory values */
127 static ConfOptions *c_options = NULL;
134 static GtkWidget *configwindow = NULL;
135 static GtkListStore *filter_store = NULL;
136 static GtkTreeStore *accel_store = NULL;
138 static GtkWidget *safe_delete_path_entry;
140 static GtkWidget *color_profile_input_file_entry[COLOR_PROFILE_INPUTS];
141 static GtkWidget *color_profile_input_name_entry[COLOR_PROFILE_INPUTS];
142 static GtkWidget *color_profile_screen_file_entry;
143 static GtkWidget *external_preview_select_entry;
144 static GtkWidget *external_preview_extract_entry;
146 static GtkWidget *sidecar_ext_entry;
147 static GtkWidget *help_search_engine_entry;
150 #define CONFIG_WINDOW_DEF_WIDTH 700
151 #define CONFIG_WINDOW_DEF_HEIGHT 600
154 *-----------------------------------------------------------------------------
155 * option widget callbacks (private)
156 *-----------------------------------------------------------------------------
159 static void zoom_increment_cb(GtkWidget *spin, gpointer data)
161 c_options->image.zoom_increment = (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) * 100.0 + 0.01);
164 static void slideshow_delay_hours_cb(GtkWidget *spin, gpointer data)
166 gint mins_secs_tenths, delay;
168 mins_secs_tenths = c_options->slideshow.delay %
169 (3600 * SLIDESHOW_SUBSECOND_PRECISION);
171 delay = (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
172 (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
175 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
176 SLIDESHOW_SUBSECOND_PRECISION;
179 static void slideshow_delay_minutes_cb(GtkWidget *spin, gpointer data)
181 gint hours, secs_tenths, delay;
183 hours = c_options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
184 secs_tenths = c_options->slideshow.delay % (60 * SLIDESHOW_SUBSECOND_PRECISION);
186 delay = hours * (3600 * SLIDESHOW_SUBSECOND_PRECISION) +
187 (gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
188 (60 * SLIDESHOW_SUBSECOND_PRECISION) + secs_tenths);
190 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
191 SLIDESHOW_SUBSECOND_PRECISION;
194 static void slideshow_delay_seconds_cb(GtkWidget *spin, gpointer data)
196 gint hours_mins, delay;
198 hours_mins = c_options->slideshow.delay / (60 * SLIDESHOW_SUBSECOND_PRECISION);
200 delay = (hours_mins * (60 * SLIDESHOW_SUBSECOND_PRECISION)) +
201 (gint)(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin)) *
202 (gdouble)(SLIDESHOW_SUBSECOND_PRECISION) + 0.01);
204 c_options->slideshow.delay = delay > 0 ? delay : SLIDESHOW_MIN_SECONDS *
205 SLIDESHOW_SUBSECOND_PRECISION;
209 *-----------------------------------------------------------------------------
210 * sync program to config window routine (private)
211 *-----------------------------------------------------------------------------
214 void config_entry_to_option(GtkWidget *entry, gchar **option, gchar *(*func)(const gchar *))
220 buf = gtk_entry_get_text(GTK_ENTRY(entry));
221 if (buf && strlen(buf) > 0)
226 *option = g_strdup(buf);
231 static gboolean accel_apply_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
233 gchar *accel_path, *accel;
235 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, AE_KEY, &accel, -1);
237 if (accel_path && accel_path[0])
240 gtk_accelerator_parse(accel, &key.accel_key, &key.accel_mods);
241 gtk_accel_map_change_entry(accel_path, key.accel_key, key.accel_mods, TRUE);
251 static void config_window_apply(void)
253 gboolean refresh = FALSE;
258 config_entry_to_option(safe_delete_path_entry, &options->file_ops.safe_delete_path, remove_trailing_slash);
260 if (options->file_filter.show_hidden_files != c_options->file_filter.show_hidden_files) refresh = TRUE;
261 if (options->file_filter.show_parent_directory != c_options->file_filter.show_parent_directory) refresh = TRUE;
262 if (options->file_filter.show_dot_directory != c_options->file_filter.show_dot_directory) refresh = TRUE;
263 if (options->file_sort.case_sensitive != c_options->file_sort.case_sensitive) refresh = TRUE;
264 if (options->file_sort.natural != c_options->file_sort.natural) refresh = TRUE;
265 if (options->file_filter.disable_file_extension_checks != c_options->file_filter.disable_file_extension_checks) refresh = TRUE;
266 if (options->file_filter.disable != c_options->file_filter.disable) refresh = TRUE;
268 options->file_ops.confirm_delete = c_options->file_ops.confirm_delete;
269 options->file_ops.enable_delete_key = c_options->file_ops.enable_delete_key;
270 options->file_ops.confirm_move_to_trash = c_options->file_ops.confirm_move_to_trash;
271 options->file_ops.use_system_trash = c_options->file_ops.use_system_trash;
272 options->file_ops.no_trash = c_options->file_ops.no_trash;
273 options->file_ops.safe_delete_folder_maxsize = c_options->file_ops.safe_delete_folder_maxsize;
274 options->tools_restore_state = c_options->tools_restore_state;
275 options->save_window_positions = c_options->save_window_positions;
276 options->use_saved_window_positions_for_new_windows = c_options->use_saved_window_positions_for_new_windows;
277 options->save_window_workspace = c_options->save_window_workspace;
278 options->save_dialog_window_positions = c_options->save_dialog_window_positions;
279 options->show_window_ids = c_options->show_window_ids;
280 options->image.scroll_reset_method = c_options->image.scroll_reset_method;
281 options->image.zoom_2pass = c_options->image.zoom_2pass;
282 options->image.fit_window_to_image = c_options->image.fit_window_to_image;
283 options->image.limit_window_size = c_options->image.limit_window_size;
284 options->image.zoom_to_fit_allow_expand = c_options->image.zoom_to_fit_allow_expand;
285 options->image.max_window_size = c_options->image.max_window_size;
286 options->image.limit_autofit_size = c_options->image.limit_autofit_size;
287 options->image.max_autofit_size = c_options->image.max_autofit_size;
288 options->image.max_enlargement_size = c_options->image.max_enlargement_size;
289 options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
290 options->image.tile_size = c_options->image.tile_size;
291 options->progressive_key_scrolling = c_options->progressive_key_scrolling;
292 options->keyboard_scroll_step = c_options->keyboard_scroll_step;
294 if (options->thumbnails.max_width != c_options->thumbnails.max_width
295 || options->thumbnails.max_height != c_options->thumbnails.max_height
296 || options->thumbnails.quality != c_options->thumbnails.quality)
298 thumb_format_changed = TRUE;
300 options->thumbnails.max_width = c_options->thumbnails.max_width;
301 options->thumbnails.max_height = c_options->thumbnails.max_height;
302 options->thumbnails.quality = c_options->thumbnails.quality;
304 options->thumbnails.enable_caching = c_options->thumbnails.enable_caching;
305 options->thumbnails.cache_into_dirs = c_options->thumbnails.cache_into_dirs;
306 options->thumbnails.use_exif = c_options->thumbnails.use_exif;
307 options->thumbnails.use_color_management = c_options->thumbnails.use_color_management;
308 options->thumbnails.collection_preview = c_options->thumbnails.collection_preview;
309 options->thumbnails.use_ft_metadata = c_options->thumbnails.use_ft_metadata;
310 // options->thumbnails.use_ft_metadata_small = c_options->thumbnails.use_ft_metadata_small;
311 options->thumbnails.spec_standard = c_options->thumbnails.spec_standard;
312 options->metadata.enable_metadata_dirs = c_options->metadata.enable_metadata_dirs;
313 options->file_filter.show_hidden_files = c_options->file_filter.show_hidden_files;
314 options->file_filter.show_parent_directory = c_options->file_filter.show_parent_directory;
315 options->file_filter.show_dot_directory = c_options->file_filter.show_dot_directory;
316 options->file_filter.disable_file_extension_checks = c_options->file_filter.disable_file_extension_checks;
318 options->file_sort.case_sensitive = c_options->file_sort.case_sensitive;
319 options->file_sort.natural = c_options->file_sort.natural;
320 options->file_filter.disable = c_options->file_filter.disable;
322 config_entry_to_option(sidecar_ext_entry, &options->sidecar.ext, NULL);
323 sidecar_ext_parse(options->sidecar.ext);
325 options->slideshow.random = c_options->slideshow.random;
326 options->slideshow.repeat = c_options->slideshow.repeat;
327 options->slideshow.delay = c_options->slideshow.delay;
329 options->mousewheel_scrolls = c_options->mousewheel_scrolls;
330 options->image_lm_click_nav = c_options->image_lm_click_nav;
331 options->image_l_click_archive = c_options->image_l_click_archive;
332 options->image_l_click_video = c_options->image_l_click_video;
333 options->image_l_click_video_editor = c_options->image_l_click_video_editor;
335 options->file_ops.enable_in_place_rename = c_options->file_ops.enable_in_place_rename;
337 options->image.tile_cache_max = c_options->image.tile_cache_max;
338 options->image.image_cache_max = c_options->image.image_cache_max;
340 options->image.zoom_quality = c_options->image.zoom_quality;
342 options->image.zoom_increment = c_options->image.zoom_increment;
344 options->image.zoom_style = c_options->image.zoom_style;
346 options->image.enable_read_ahead = c_options->image.enable_read_ahead;
349 if (options->image.use_custom_border_color != c_options->image.use_custom_border_color
350 || options->image.use_custom_border_color_in_fullscreen != c_options->image.use_custom_border_color_in_fullscreen
351 || !gdk_color_equal(&options->image.border_color, &c_options->image.border_color))
353 options->image.use_custom_border_color_in_fullscreen = c_options->image.use_custom_border_color_in_fullscreen;
354 options->image.use_custom_border_color = c_options->image.use_custom_border_color;
355 options->image.border_color = c_options->image.border_color;
356 layout_colors_update();
357 view_window_colors_update();
360 options->image.alpha_color_1 = c_options->image.alpha_color_1;
361 options->image.alpha_color_2 = c_options->image.alpha_color_2;
363 options->fullscreen.screen = c_options->fullscreen.screen;
364 options->fullscreen.clean_flip = c_options->fullscreen.clean_flip;
365 options->fullscreen.disable_saver = c_options->fullscreen.disable_saver;
366 options->fullscreen.above = c_options->fullscreen.above;
367 if (c_options->image_overlay.template_string)
368 set_image_overlay_template_string(&options->image_overlay.template_string,
369 c_options->image_overlay.template_string);
370 if (c_options->image_overlay.font)
371 set_image_overlay_font_string(&options->image_overlay.font,
372 c_options->image_overlay.font);
373 options->image_overlay.text_red = c_options->image_overlay.text_red;
374 options->image_overlay.text_green = c_options->image_overlay.text_green;
375 options->image_overlay.text_blue = c_options->image_overlay.text_blue;
376 options->image_overlay.text_alpha = c_options->image_overlay.text_alpha;
377 options->image_overlay.background_red = c_options->image_overlay.background_red;
378 options->image_overlay.background_green = c_options->image_overlay.background_green;
379 options->image_overlay.background_blue = c_options->image_overlay.background_blue;
380 options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
381 options->update_on_time_change = c_options->update_on_time_change;
383 options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
384 options->rot_invariant_sim = c_options->rot_invariant_sim;
386 options->tree_descend_subdirs = c_options->tree_descend_subdirs;
388 options->view_dir_list_single_click_enter = c_options->view_dir_list_single_click_enter;
389 options->circular_selection_lists = c_options->circular_selection_lists;
391 options->open_recent_list_maxsize = c_options->open_recent_list_maxsize;
392 options->dnd_icon_size = c_options->dnd_icon_size;
393 options->clipboard_selection = c_options->clipboard_selection;
394 options->dnd_default_action = c_options->dnd_default_action;
396 options->metadata.save_in_image_file = c_options->metadata.save_in_image_file;
397 options->metadata.save_legacy_IPTC = c_options->metadata.save_legacy_IPTC;
398 options->metadata.warn_on_write_problems = c_options->metadata.warn_on_write_problems;
399 options->metadata.save_legacy_format = c_options->metadata.save_legacy_format;
400 options->metadata.sync_grouped_files = c_options->metadata.sync_grouped_files;
401 options->metadata.confirm_write = c_options->metadata.confirm_write;
402 options->metadata.sidecar_extended_name = c_options->metadata.sidecar_extended_name;
403 options->metadata.confirm_timeout = c_options->metadata.confirm_timeout;
404 options->metadata.confirm_after_timeout = c_options->metadata.confirm_after_timeout;
405 options->metadata.confirm_on_image_change = c_options->metadata.confirm_on_image_change;
406 options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
407 options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
408 options->metadata.write_orientation = c_options->metadata.write_orientation;
409 options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
410 (c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
411 (c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
412 (c_options->stereo.tmp.mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
413 (c_options->stereo.tmp.flip_left ? PR_STEREO_FLIP_LEFT : 0) |
414 (c_options->stereo.tmp.swap ? PR_STEREO_SWAP : 0) |
415 (c_options->stereo.tmp.temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
416 options->stereo.fsmode = (c_options->stereo.fsmode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
417 (c_options->stereo.tmp.fs_mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
418 (c_options->stereo.tmp.fs_flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
419 (c_options->stereo.tmp.fs_mirror_left ? PR_STEREO_MIRROR_LEFT : 0) |
420 (c_options->stereo.tmp.fs_flip_left ? PR_STEREO_FLIP_LEFT : 0) |
421 (c_options->stereo.tmp.fs_swap ? PR_STEREO_SWAP : 0) |
422 (c_options->stereo.tmp.fs_temp_disable ? PR_STEREO_TEMP_DISABLE : 0);
423 options->stereo.enable_fsmode = c_options->stereo.enable_fsmode;
424 options->stereo.fixed_w = c_options->stereo.fixed_w;
425 options->stereo.fixed_h = c_options->stereo.fixed_h;
426 options->stereo.fixed_x1 = c_options->stereo.fixed_x1;
427 options->stereo.fixed_y1 = c_options->stereo.fixed_y1;
428 options->stereo.fixed_x2 = c_options->stereo.fixed_x2;
429 options->stereo.fixed_y2 = c_options->stereo.fixed_y2;
431 options->info_keywords.height = c_options->info_keywords.height;
432 options->info_title.height = c_options->info_title.height;
433 options->info_comment.height = c_options->info_comment.height;
434 options->info_rating.height = c_options->info_rating.height;
436 options->show_predefined_keyword_tree = c_options->show_predefined_keyword_tree;
437 options->expand_menu_toolbar = c_options->expand_menu_toolbar;
439 options->marks_save = c_options->marks_save;
440 options->with_rename = c_options->with_rename;
441 options->collections_on_top = c_options->collections_on_top;
442 options->hide_window_in_fullscreen = c_options->hide_window_in_fullscreen;
443 config_entry_to_option(help_search_engine_entry, &options->help_search_engine, NULL);
445 options->external_preview.enable = c_options->external_preview.enable;
446 config_entry_to_option(external_preview_select_entry, &options->external_preview.select, NULL);
447 config_entry_to_option(external_preview_extract_entry, &options->external_preview.extract, NULL);
449 options->read_metadata_in_idle = c_options->read_metadata_in_idle;
451 options->star_rating.star = c_options->star_rating.star;
452 options->star_rating.rejected = c_options->star_rating.rejected;
454 options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
457 set_debug_level(debug_c);
461 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
463 config_entry_to_option(color_profile_input_name_entry[i], &options->color_profile.input_name[i], NULL);
464 config_entry_to_option(color_profile_input_file_entry[i], &options->color_profile.input_file[i], NULL);
466 config_entry_to_option(color_profile_screen_file_entry, &options->color_profile.screen_file, NULL);
467 options->color_profile.use_x11_screen_profile = c_options->color_profile.use_x11_screen_profile;
468 if (options->color_profile.render_intent != c_options->color_profile.render_intent)
470 options->color_profile.render_intent = c_options->color_profile.render_intent;
475 options->mouse_button_8 = c_options->mouse_button_8;
476 options->mouse_button_9 = c_options->mouse_button_9;
478 options->override_disable_gpu = c_options->override_disable_gpu;
480 config_tab_keywords_save();
482 image_options_sync();
487 layout_refresh(NULL);
490 if (accel_store) gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_apply_cb, NULL);
492 toolbar_apply(TOOLBAR_MAIN);
493 toolbar_apply(TOOLBAR_STATUS);
497 *-----------------------------------------------------------------------------
498 * config window main button callbacks (private)
499 *-----------------------------------------------------------------------------
502 static void config_window_close_cb(GtkWidget *widget, gpointer data)
504 gtk_widget_destroy(configwindow);
509 static void config_window_help_cb(GtkWidget *widget, gpointer data)
511 GtkWidget *notebook = data;
514 static gchar *html_section[] =
516 "GuideOptionsGeneral.html",
517 "GuideOptionsImage.html",
518 "GuideOptionsOSD.html",
519 "GuideOptionsWindow.html",
520 "GuideOptionsKeyboard.html",
521 "GuideOptionsFiltering.html",
522 "GuideOptionsMetadata.html",
523 "GuideOptionsKeywords.html",
524 "GuideOptionsColor.html",
525 "GuideOptionsStereo.html",
526 "GuideOptionsBehavior.html",
527 "GuideOptionsToolbar.html",
528 "GuideOptionsToolbar.html",
529 "GuideOptionsAdvanced.html"
532 i = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
533 help_window_show(html_section[i]);
536 static gboolean config_window_delete(GtkWidget *widget, GdkEventAny *event, gpointer data)
538 config_window_close_cb(NULL, NULL);
542 static void config_window_ok_cb(GtkWidget *widget, gpointer data)
545 GtkNotebook *notebook = data;
553 lw = layout_window_list->data;
555 window = gtk_widget_get_window(widget);
556 gdk_window_get_root_origin(window, &x, &y);
557 w = gdk_window_get_width(window);
558 h = gdk_window_get_height(window);
559 page_number = gtk_notebook_get_current_page(notebook);
561 lw->options.preferences_window.x = x;
562 lw->options.preferences_window.y = y;
563 lw->options.preferences_window.w = w;
564 lw->options.preferences_window.h = h;
565 lw->options.preferences_window.page_number = page_number;
567 config_window_apply();
568 layout_util_sync(lw);
569 save_options(options);
570 config_window_close_cb(NULL, NULL);
574 *-----------------------------------------------------------------------------
575 * config window setup (private)
576 *-----------------------------------------------------------------------------
579 static void quality_menu_cb(GtkWidget *combo, gpointer data)
583 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
587 *option = GDK_INTERP_NEAREST;
590 *option = GDK_INTERP_TILES;
593 *option = GDK_INTERP_BILINEAR;
598 static void dnd_default_action_selection_menu_cb(GtkWidget *combo, gpointer data)
602 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
606 *option = DND_ACTION_ASK;
609 *option = DND_ACTION_COPY;
612 *option = DND_ACTION_MOVE;
616 static void clipboard_selection_menu_cb(GtkWidget *combo, gpointer data)
620 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
623 *option = CLIPBOARD_PRIMARY;
626 *option = CLIPBOARD_CLIPBOARD;
629 *option = CLIPBOARD_BOTH;
632 *option = CLIPBOARD_BOTH;
636 static void add_quality_menu(GtkWidget *table, gint column, gint row, const gchar *text,
637 guint option, guint *option_c)
644 pref_table_label(table, column, row, text, 0.0);
646 combo = gtk_combo_box_text_new();
648 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Nearest (worst, but fastest)"));
649 if (option == GDK_INTERP_NEAREST) current = 0;
650 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Tiles"));
651 if (option == GDK_INTERP_TILES) current = 1;
652 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Bilinear (best, but slowest)"));
653 if (option == GDK_INTERP_BILINEAR) current = 2;
655 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
657 g_signal_connect(G_OBJECT(combo), "changed",
658 G_CALLBACK(quality_menu_cb), option_c);
660 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
661 gtk_widget_show(combo);
664 static void add_dnd_default_action_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, DnDAction option, DnDAction *option_c)
671 pref_table_label(table, column, row, text, 0.0);
673 combo = gtk_combo_box_text_new();
675 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Ask"));
676 if (option == DND_ACTION_ASK) current = 0;
677 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Copy"));
678 if (option == DND_ACTION_COPY) current = 1;
679 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Move"));
680 if (option == DND_ACTION_MOVE) current = 2;
682 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
684 g_signal_connect(G_OBJECT(combo), "changed",
685 G_CALLBACK(dnd_default_action_selection_menu_cb), option_c);
687 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
688 gtk_widget_show(combo);
691 static void add_clipboard_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
692 gint option, gint *option_c)
699 pref_table_label(table, column, row, text, 0.0);
701 combo = gtk_combo_box_text_new();
703 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Primary"));
704 if (option == CLIPBOARD_PRIMARY) current = 0;
705 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Clipboard"));
706 if (option == CLIPBOARD_CLIPBOARD) current = 1;
707 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Both"));
708 if (option == CLIPBOARD_BOTH) current = 2;
710 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
712 g_signal_connect(G_OBJECT(combo), "changed",
713 G_CALLBACK(clipboard_selection_menu_cb), option_c);
715 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
716 gtk_widget_show(combo);
719 static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
723 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
726 *option = ZOOM_GEOMETRIC;
729 *option = ZOOM_ARITHMETIC;
732 *option = ZOOM_GEOMETRIC;
736 static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
743 pref_table_label(table, column, row, text, 0.0);
745 combo = gtk_combo_box_text_new();
747 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
748 if (option == ZOOM_GEOMETRIC) current = 0;
749 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
750 if (option == ZOOM_ARITHMETIC) current = 1;
752 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
754 g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
756 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
757 gtk_widget_show(combo);
760 typedef struct _UseableMouseItems UseableMouseItems;
761 struct _UseableMouseItems
763 gchar *name; /* GtkActionEntry terminology */
768 static const UseableMouseItems useable_mouse_items[] = {
770 {"FirstImage", N_("First Image"), GTK_STOCK_GOTO_TOP},
771 {"PrevImage", N_("Previous Image"), GTK_STOCK_GO_UP},
772 {"NextImage", N_("Next Image"), GTK_STOCK_GO_DOWN},
773 {"LastImage", N_("Last Image"), GTK_STOCK_GOTO_BOTTOM},
774 {"Back", N_("Back"), GTK_STOCK_GO_BACK},
775 {"Forward", N_("Forward"), GTK_STOCK_GO_FORWARD},
776 {"Home", N_("Home"), GTK_STOCK_HOME},
777 {"Up", N_("Up"), GTK_STOCK_GO_UP},
778 {"FirstPage", N_("First page"), GTK_STOCK_MEDIA_PREVIOUS},
779 {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT},
780 {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD},
781 {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND},
782 {"NewWindow", N_("New _window"), GTK_STOCK_NEW},
783 {"NewCollection", N_("New collection"), GTK_STOCK_INDEX},
784 {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN},
785 {"Search", N_("Search"), GTK_STOCK_FIND},
786 {"FindDupes", N_("Find duplicates"), GTK_STOCK_FIND},
787 {"NewFolder", N_("New folder"),GTK_STOCK_DIRECTORY},
788 {"Copy", N_("Copy"), GTK_STOCK_COPY},
789 {"Move", N_("Move"), PIXBUF_INLINE_ICON_MOVE},
790 {"Rename", N_("Rename"), PIXBUF_INLINE_ICON_RENAME},
791 {"Delete", N_("Delete"), GTK_STOCK_DELETE},
792 {"CloseWindow", N_("Close Window"), GTK_STOCK_CLOSE},
793 {"PanView", N_("Pan view"), PIXBUF_INLINE_ICON_PANORAMA},
794 {"SelectAll", N_("Select all"), PIXBUF_INLINE_ICON_SELECT_ALL},
795 {"SelectNone", N_("Select none"), PIXBUF_INLINE_ICON_SELECT_NONE},
796 {"SelectInvert", N_("Select invert"), PIXBUF_INLINE_ICON_SELECT_INVERT},
797 {"ShowFileFilter", N_("Show file filter"), PIXBUF_INLINE_ICON_FILE_FILTER},
798 {"RectangularSelection", N_("Select rectangle"), PIXBUF_INLINE_ICON_SELECT_RECTANGLE},
799 {"Print", N_("Print"), GTK_STOCK_PRINT},
800 {"Preferences", N_("Preferences"), GTK_STOCK_PREFERENCES},
801 {"LayoutConfig", N_("Configure this window"), GTK_STOCK_PREFERENCES},
802 {"Maintenance", N_("Cache maintenance"), PIXBUF_INLINE_ICON_MAINTENANCE},
803 {"RotateCW", N_("Rotate clockwise 90°"), PIXBUF_INLINE_ICON_CW},
804 {"RotateCCW", N_("Rotate counterclockwise 90°"), PIXBUF_INLINE_ICON_CCW},
805 {"Rotate180", N_("Rotate 180°"), PIXBUF_INLINE_ICON_180},
806 {"Mirror", N_("Mirror"), PIXBUF_INLINE_ICON_MIRROR},
807 {"Flip", N_("Flip"), PIXBUF_INLINE_ICON_FLIP},
808 {"AlterNone", N_("Original state"), PIXBUF_INLINE_ICON_ORIGINAL},
809 {"ZoomIn", N_("Zoom in"), GTK_STOCK_ZOOM_IN},
810 {"ZoomOut", N_("Zoom out"), GTK_STOCK_ZOOM_OUT},
811 {"Zoom100", N_("Zoom 1:1"), GTK_STOCK_ZOOM_100},
812 {"ZoomFit", N_("Zoom to fit"), GTK_STOCK_ZOOM_FIT},
813 {"ZoomFillHor", N_("Fit Horizontaly"), PIXBUF_INLINE_ICON_ZOOMFILLHOR},
814 {"ZoomFillVert", N_("Fit vertically"), PIXBUF_INLINE_ICON_ZOOMFILLVERT},
815 {"Zoom200", N_("Zoom 2:1"), GTK_STOCK_FILE},
816 {"Zoom300", N_("Zoom 3:1"), GTK_STOCK_FILE},
817 {"Zoom400", N_("Zoom 4:1"), GTK_STOCK_FILE},
818 {"Zoom50", N_("Zoom 1:2"), GTK_STOCK_FILE},
819 {"Zoom33", N_("Zoom1:3"), GTK_STOCK_FILE},
820 {"Zoom25", N_("Zoom 1:4"), GTK_STOCK_FILE},
821 {"ConnectZoomIn", N_("Connected Zoom in"), GTK_STOCK_ZOOM_IN},
822 {"SplitPaneSync", N_("Split Pane Sync"), PIXBUF_INLINE_SPLIT_PANE_SYNC},
823 {"Grayscale", N_("Grayscale"), PIXBUF_INLINE_ICON_GRAYSCALE},
824 {"OverUnderExposed", N_("Over Under Exposed"), PIXBUF_INLINE_ICON_EXPOSURE},
825 {"HideTools", N_("Hide file list"), PIXBUF_INLINE_ICON_HIDETOOLS},
826 {"SlideShowPause", N_("Pause slideshow"), GTK_STOCK_MEDIA_PAUSE},
827 {"SlideShowFaster", N_("Slideshow Faster"), GTK_STOCK_FILE},
828 {"SlideShowSlower", N_("Slideshow Slower"), GTK_STOCK_FILE},
829 {"Refresh", N_("Refresh"), GTK_STOCK_REFRESH},
830 {"HelpContents", N_("Help"), GTK_STOCK_HELP},
831 {"ExifWin", N_("Exif window"), PIXBUF_INLINE_ICON_EXIF},
832 {"Thumbnails", N_("Show thumbnails"), PIXBUF_INLINE_ICON_THUMB},
833 {"ShowMarks", N_("Show marks"), PIXBUF_INLINE_ICON_MARKS},
834 {"DrawRectangle", N_("Draw Rectangle"), PIXBUF_INLINE_ICON_DRAW_RECTANGLE},
835 {"FloatTools", N_("Float file list"), PIXBUF_INLINE_ICON_FLOAT},
836 {"SBar", N_("Info sidebar"), PIXBUF_INLINE_ICON_INFO},
837 {"SBarSort", N_("Sort manager"), PIXBUF_INLINE_ICON_SORT},
838 {"Quit", N_("Quit"), GTK_STOCK_QUIT},
842 static void mouse_buttons_selection_menu_cb(GtkWidget *combo, gpointer data)
844 gchar **option = data;
847 label = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
849 const UseableMouseItems *list = useable_mouse_items;
853 if (g_strcmp0(list->label, label) == 0)
861 *option = g_strdup(list->name);
865 static void add_mouse_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text,
866 gchar *option, gchar **option_c)
874 pref_table_label(table, column, row, text, 0.0);
876 combo = gtk_combo_box_text_new();
878 const UseableMouseItems *list = useable_mouse_items;
882 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), list->label);
883 if (g_strcmp0(list->name, option) == 0)
891 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
893 g_signal_connect(G_OBJECT(combo), "changed",
894 G_CALLBACK(mouse_buttons_selection_menu_cb), option_c);
896 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
897 gtk_widget_show(combo);
900 static void thumb_size_menu_cb(GtkWidget *combo, gpointer data)
904 n = gtk_combo_box_get_active(GTK_COMBO_BOX(combo));
907 if ((guint) n < sizeof(thumb_size_list) / sizeof(ThumbSize))
909 c_options->thumbnails.max_width = thumb_size_list[n].w;
910 c_options->thumbnails.max_height = thumb_size_list[n].h;
914 c_options->thumbnails.max_width = options->thumbnails.max_width;
915 c_options->thumbnails.max_height = options->thumbnails.max_height;
919 static void add_thumb_size_menu(GtkWidget *table, gint column, gint row, gchar *text)
925 c_options->thumbnails.max_width = options->thumbnails.max_width;
926 c_options->thumbnails.max_height = options->thumbnails.max_height;
928 pref_table_label(table, column, row, text, 0.0);
930 combo = gtk_combo_box_text_new();
933 for (i = 0; (guint) i < sizeof(thumb_size_list) / sizeof(ThumbSize); i++)
938 w = thumb_size_list[i].w;
939 h = thumb_size_list[i].h;
941 buf = g_strdup_printf("%d x %d", w, h);
942 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
945 if (w == options->thumbnails.max_width && h == options->thumbnails.max_height) current = i;
952 buf = g_strdup_printf("%s %d x %d", _("Custom"), options->thumbnails.max_width, options->thumbnails.max_height);
953 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), buf);
959 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
960 g_signal_connect(G_OBJECT(combo), "changed",
961 G_CALLBACK(thumb_size_menu_cb), NULL);
963 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
964 gtk_widget_show(combo);
967 static void stereo_mode_menu_cb(GtkWidget *combo, gpointer data)
971 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
975 *option = PR_STEREO_NONE;
978 *option = PR_STEREO_ANAGLYPH_RC;
981 *option = PR_STEREO_ANAGLYPH_GM;
984 *option = PR_STEREO_ANAGLYPH_YB;
987 *option = PR_STEREO_ANAGLYPH_GRAY_RC;
990 *option = PR_STEREO_ANAGLYPH_GRAY_GM;
993 *option = PR_STEREO_ANAGLYPH_GRAY_YB;
996 *option = PR_STEREO_ANAGLYPH_DB_RC;
999 *option = PR_STEREO_ANAGLYPH_DB_GM;
1002 *option = PR_STEREO_ANAGLYPH_DB_YB;
1005 *option = PR_STEREO_HORIZ;
1008 *option = PR_STEREO_HORIZ | PR_STEREO_HALF;
1011 *option = PR_STEREO_VERT;
1014 *option = PR_STEREO_VERT | PR_STEREO_HALF;
1017 *option = PR_STEREO_FIXED;
1022 static void add_stereo_mode_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1023 gint option, gint *option_c, gboolean add_fixed)
1030 pref_table_label(table, column, row, text, 0.0);
1032 combo = gtk_combo_box_text_new();
1034 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Single image"));
1036 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Red-Cyan"));
1037 if (option & PR_STEREO_ANAGLYPH_RC) current = 1;
1038 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Green-Magenta"));
1039 if (option & PR_STEREO_ANAGLYPH_GM) current = 2;
1040 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Yellow-Blue"));
1041 if (option & PR_STEREO_ANAGLYPH_YB) current = 3;
1042 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Red-Cyan"));
1043 if (option & PR_STEREO_ANAGLYPH_GRAY_RC) current = 4;
1044 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Green-Magenta"));
1045 if (option & PR_STEREO_ANAGLYPH_GRAY_GM) current = 5;
1046 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Gray Yellow-Blue"));
1047 if (option & PR_STEREO_ANAGLYPH_GRAY_YB) current = 6;
1048 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Red-Cyan"));
1049 if (option & PR_STEREO_ANAGLYPH_DB_RC) current = 7;
1050 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Green-Magenta"));
1051 if (option & PR_STEREO_ANAGLYPH_DB_GM) current = 8;
1052 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Anaglyph Dubois Yellow-Blue"));
1053 if (option & PR_STEREO_ANAGLYPH_DB_YB) current = 9;
1055 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side"));
1056 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Side by Side Half size"));
1057 if (option & PR_STEREO_HORIZ)
1060 if (option & PR_STEREO_HALF) current = 11;
1063 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom"));
1064 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Top - Bottom Half size"));
1065 if (option & PR_STEREO_VERT)
1068 if (option & PR_STEREO_HALF) current = 13;
1073 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Fixed position"));
1074 if (option & PR_STEREO_FIXED) current = 14;
1077 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1079 g_signal_connect(G_OBJECT(combo), "changed",
1080 G_CALLBACK(stereo_mode_menu_cb), option_c);
1082 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1083 gtk_widget_show(combo);
1086 static void video_menu_cb(GtkWidget *combo, gpointer data)
1088 gchar **option = data;
1090 EditorDescription *ed = g_list_nth_data(editor_list_get(), gtk_combo_box_get_active(GTK_COMBO_BOX(combo)));
1094 static void video_menu_populate(gpointer data, gpointer user_data)
1096 GtkWidget *combo = user_data;
1097 EditorDescription *ed = data;
1099 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), ed->name);
1102 static void add_video_menu(GtkWidget *table, gint column, gint row, const gchar *text,
1103 gchar *option, gchar **option_c)
1107 /* use lists since they are sorted */
1108 GList *eds = editor_list_get();
1112 pref_table_label(table, column, row, text, 0.0);
1114 combo = gtk_combo_box_text_new();
1115 g_list_foreach(eds,video_menu_populate,(gpointer)combo);
1116 current = option ? g_list_index(eds,g_hash_table_lookup(editors,option)): -1;
1118 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
1120 g_signal_connect(G_OBJECT(combo), "changed",
1121 G_CALLBACK(video_menu_cb), option_c);
1123 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
1124 gtk_widget_show(combo);
1127 static void filter_store_populate(void)
1131 if (!filter_store) return;
1133 gtk_list_store_clear(filter_store);
1135 work = filter_get_list();
1144 gtk_list_store_append(filter_store, &iter);
1145 gtk_list_store_set(filter_store, &iter, 0, fe, -1);
1149 static void filter_store_ext_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1150 gchar *new_text, gpointer data)
1152 GtkWidget *model = data;
1153 FilterEntry *fe = data;
1157 if (!new_text || strlen(new_text) < 1) return;
1159 tpath = gtk_tree_path_new_from_string(path_str);
1160 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1161 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1163 g_free(fe->extensions);
1164 fe->extensions = g_strdup(new_text);
1166 gtk_tree_path_free(tpath);
1170 static void filter_store_class_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1171 gchar *new_text, gpointer data)
1173 GtkWidget *model = data;
1174 FilterEntry *fe = data;
1179 if (!new_text || !new_text[0]) return;
1181 tpath = gtk_tree_path_new_from_string(path_str);
1182 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1183 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1185 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
1187 if (strcmp(new_text, _(format_class_list[i])) == 0)
1194 gtk_tree_path_free(tpath);
1198 static void filter_store_desc_edit_cb(GtkCellRendererText *cell, gchar *path_str,
1199 gchar *new_text, gpointer data)
1201 GtkWidget *model = data;
1206 if (!new_text || !new_text[0]) return;
1208 tpath = gtk_tree_path_new_from_string(path_str);
1209 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1210 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1212 g_free(fe->description);
1213 fe->description = g_strdup(new_text);
1215 gtk_tree_path_free(tpath);
1218 static void filter_store_enable_cb(GtkCellRendererToggle *renderer,
1219 gchar *path_str, gpointer data)
1221 GtkWidget *model = data;
1226 tpath = gtk_tree_path_new_from_string(path_str);
1227 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1228 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1230 fe->enabled = !fe->enabled;
1232 gtk_tree_path_free(tpath);
1236 static void filter_store_writable_cb(GtkCellRendererToggle *renderer,
1237 gchar *path_str, gpointer data)
1239 GtkWidget *model = data;
1244 tpath = gtk_tree_path_new_from_string(path_str);
1245 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1246 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1248 fe->writable = !fe->writable;
1249 if (fe->writable) fe->allow_sidecar = FALSE;
1251 gtk_tree_path_free(tpath);
1255 static void filter_store_sidecar_cb(GtkCellRendererToggle *renderer,
1256 gchar *path_str, gpointer data)
1258 GtkWidget *model = data;
1263 tpath = gtk_tree_path_new_from_string(path_str);
1264 gtk_tree_model_get_iter(GTK_TREE_MODEL(model), &iter, tpath);
1265 gtk_tree_model_get(GTK_TREE_MODEL(model), &iter, 0, &fe, -1);
1267 fe->allow_sidecar = !fe->allow_sidecar;
1268 if (fe->allow_sidecar) fe->writable = FALSE;
1270 gtk_tree_path_free(tpath);
1274 static void filter_set_func(GtkTreeViewColumn *tree_column, GtkCellRenderer *cell,
1275 GtkTreeModel *tree_model, GtkTreeIter *iter, gpointer data)
1279 gtk_tree_model_get(tree_model, iter, 0, &fe, -1);
1281 switch (GPOINTER_TO_INT(data))
1284 g_object_set(GTK_CELL_RENDERER(cell),
1285 "active", fe->enabled, NULL);
1288 g_object_set(GTK_CELL_RENDERER(cell),
1289 "text", fe->extensions, NULL);
1291 case FE_DESCRIPTION:
1292 g_object_set(GTK_CELL_RENDERER(cell),
1293 "text", fe->description, NULL);
1296 g_object_set(GTK_CELL_RENDERER(cell),
1297 "text", _(format_class_list[fe->file_class]), NULL);
1300 g_object_set(GTK_CELL_RENDERER(cell),
1301 "active", fe->writable, NULL);
1303 case FE_ALLOW_SIDECAR:
1304 g_object_set(GTK_CELL_RENDERER(cell),
1305 "active", fe->allow_sidecar, NULL);
1310 static gboolean filter_add_scroll(gpointer data)
1314 GtkCellRenderer *cell;
1315 GtkTreeViewColumn *column;
1318 rows = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(filter_store), NULL);
1319 path = gtk_tree_path_new_from_indices(rows-1, -1);
1321 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data), 0);
1323 list_cells = gtk_cell_layout_get_cells(GTK_CELL_LAYOUT(column));
1324 cell = g_list_last(list_cells)->data;
1326 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1327 path, column, FALSE, 0.0, 0.0 );
1328 gtk_tree_view_set_cursor_on_cell(GTK_TREE_VIEW(data),
1329 path, column, cell, TRUE);
1331 gtk_tree_path_free(path);
1332 g_list_free(list_cells);
1337 static void filter_add_cb(GtkWidget *widget, gpointer data)
1339 filter_add_unique("description", ".new", FORMAT_CLASS_IMAGE, TRUE, FALSE, TRUE);
1340 filter_store_populate();
1342 g_idle_add((GSourceFunc)filter_add_scroll, data);
1345 static void filter_remove_cb(GtkWidget *widget, gpointer data)
1347 GtkWidget *filter_view = data;
1348 GtkTreeSelection *selection;
1352 if (!filter_store) return;
1353 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
1354 if (!gtk_tree_selection_get_selected(selection, NULL, &iter)) return;
1355 gtk_tree_model_get(GTK_TREE_MODEL(filter_store), &iter, 0, &fe, -1);
1358 filter_remove_entry(fe);
1360 filter_store_populate();
1363 static gboolean filter_default_ok_scroll(GtkTreeView *data)
1367 GtkTreeViewColumn *column;
1369 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(filter_store), &iter);
1370 path = gtk_tree_model_get_path(GTK_TREE_MODEL(filter_store), &iter);
1371 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1373 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1377 gtk_tree_path_free(path);
1382 static void filter_default_ok_cb(GenericDialog *gd, gpointer data)
1385 filter_add_defaults();
1387 filter_store_populate();
1389 g_idle_add((GSourceFunc)filter_default_ok_scroll, gd->data);
1392 static void dummy_cancel_cb(GenericDialog *gd, gpointer data)
1394 /* no op, only so cancel button appears */
1397 static void filter_default_cb(GtkWidget *widget, gpointer data)
1401 gd = generic_dialog_new(_("Reset filters"),
1402 "reset_filter", widget, TRUE,
1403 dummy_cancel_cb, data);
1404 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset filters"),
1405 _("This will reset the file filters to the defaults.\nContinue?"), TRUE);
1406 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, filter_default_ok_cb, TRUE);
1407 gtk_widget_show(gd->dialog);
1410 static void filter_disable_cb(GtkWidget *widget, gpointer data)
1412 GtkWidget *frame = data;
1414 gtk_widget_set_sensitive(frame,
1415 !gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)));
1418 static void safe_delete_view_cb(GtkWidget *widget, gpointer data)
1420 layout_set_path(NULL, gtk_entry_get_text(GTK_ENTRY(safe_delete_path_entry)));
1423 static void safe_delete_clear_ok_cb(GenericDialog *gd, gpointer data)
1425 file_util_trash_clear();
1428 static void safe_delete_clear_cb(GtkWidget *widget, gpointer data)
1432 gd = generic_dialog_new(_("Clear trash"),
1433 "clear_trash", widget, TRUE,
1434 dummy_cancel_cb, NULL);
1435 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Clear trash"),
1436 _("This will remove the trash contents."), FALSE);
1437 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, safe_delete_clear_ok_cb, TRUE);
1438 entry = gtk_entry_new();
1439 gtk_widget_set_can_focus(entry, FALSE);
1440 gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE);
1441 if (options->file_ops.safe_delete_path) gtk_entry_set_text(GTK_ENTRY(entry), options->file_ops.safe_delete_path);
1442 gtk_box_pack_start(GTK_BOX(gd->vbox), entry, FALSE, FALSE, 0);
1443 gtk_widget_show(entry);
1444 gtk_widget_show(gd->dialog);
1447 static void image_overlay_template_view_changed_cb(GtkWidget *widget, gpointer data)
1449 GtkWidget *pTextView;
1450 GtkTextBuffer *pTextBuffer;
1454 pTextView = GTK_WIDGET(data);
1456 pTextBuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(pTextView));
1457 gtk_text_buffer_get_start_iter(pTextBuffer, &iStart);
1458 gtk_text_buffer_get_end_iter(pTextBuffer, &iEnd);
1460 set_image_overlay_template_string(&c_options->image_overlay.template_string,
1461 gtk_text_buffer_get_text(pTextBuffer, &iStart, &iEnd, TRUE));
1464 static void image_overlay_default_template_ok_cb(GenericDialog *gd, gpointer data)
1466 GtkTextView *text_view = data;
1467 GtkTextBuffer *buffer;
1469 set_default_image_overlay_template_string(&options->image_overlay.template_string);
1470 if (!configwindow) return;
1472 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view));
1473 gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
1476 static void image_overlay_default_template_cb(GtkWidget *widget, gpointer data)
1480 gd = generic_dialog_new(_("Reset image overlay template string"),
1481 "reset_image_overlay_template_string", widget, TRUE,
1482 dummy_cancel_cb, data);
1483 generic_dialog_add_message(gd, GTK_STOCK_DIALOG_QUESTION, _("Reset image overlay template string"),
1484 _("This will reset the image overlay template string to the default.\nContinue?"), TRUE);
1485 generic_dialog_add_button(gd, GTK_STOCK_OK, NULL, image_overlay_default_template_ok_cb, TRUE);
1486 gtk_widget_show(gd->dialog);
1489 static void image_overlay_help_cb(GtkWidget *widget, gpointer data)
1491 help_window_show("GuideOptionsOSD.html");
1494 static void image_overlay_set_font_cb(GtkWidget *widget, gpointer data)
1496 #if GTK_CHECK_VERSION(3,4,0)
1499 PangoFontDescription *font_desc;
1501 dialog = gtk_font_chooser_dialog_new("Image Overlay Font", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1502 gtk_font_chooser_set_font(GTK_FONT_CHOOSER(dialog), options->image_overlay.font);
1504 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1506 font_desc = gtk_font_chooser_get_font_desc(GTK_FONT_CHOOSER(dialog));
1507 font = pango_font_description_to_string(font_desc);
1508 g_free(c_options->image_overlay.font);
1509 c_options->image_overlay.font = g_strdup(font);
1513 gtk_widget_destroy(dialog);
1517 font = gtk_font_button_get_font_name(GTK_FONT_BUTTON(widget));
1518 c_options->image_overlay.font = g_strdup(font);
1522 static void image_overlay_set_text_colour_cb(GtkWidget *widget, gpointer data)
1525 #if GTK_CHECK_VERSION(3,4,0)
1528 dialog = gtk_color_chooser_dialog_new("Image Overlay Text Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1529 colour.red = options->image_overlay.text_red;
1530 colour.green = options->image_overlay.text_green;
1531 colour.blue = options->image_overlay.text_blue;
1532 colour.alpha = options->image_overlay.text_alpha;
1533 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1534 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1536 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1538 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1539 c_options->image_overlay.text_red = colour.red*255;
1540 c_options->image_overlay.text_green = colour.green*255;
1541 c_options->image_overlay.text_blue = colour.blue*255;
1542 c_options->image_overlay.text_alpha = colour.alpha*255;
1544 gtk_widget_destroy(dialog);
1547 GtkColorSelection *colorsel;
1549 dialog = gtk_color_selection_dialog_new("Image Overlay Text Colour");
1550 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1551 colour.red = options->image_overlay.text_red*257;
1552 colour.green = options->image_overlay.text_green*257;
1553 colour.blue = options->image_overlay.text_blue*257;
1554 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1555 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1556 gtk_color_selection_set_current_color(colorsel, &colour);
1557 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.text_alpha*257);
1559 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1561 gtk_color_selection_get_current_color(colorsel, &colour);
1562 c_options->image_overlay.text_red = colour.red/257;
1563 c_options->image_overlay.text_green = colour.green/257;
1564 c_options->image_overlay.text_blue = colour.blue/257;
1565 c_options->image_overlay.text_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1567 gtk_widget_destroy (dialog);
1572 static void image_overlay_set_background_colour_cb(GtkWidget *widget, gpointer data)
1575 #if GTK_CHECK_VERSION(3,4,0)
1578 dialog = gtk_color_chooser_dialog_new("Image Overlay Background Colour", GTK_WINDOW(gtk_widget_get_toplevel(widget)));
1579 colour.red = options->image_overlay.background_red;
1580 colour.green = options->image_overlay.background_green;
1581 colour.blue = options->image_overlay.background_blue;
1582 colour.alpha = options->image_overlay.background_alpha;
1583 gtk_color_chooser_set_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1584 gtk_color_chooser_set_use_alpha(GTK_COLOR_CHOOSER(dialog), TRUE);
1586 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_CANCEL)
1588 gtk_color_chooser_get_rgba(GTK_COLOR_CHOOSER(dialog), &colour);
1589 c_options->image_overlay.background_red = colour.red*255;
1590 c_options->image_overlay.background_green = colour.green*255;
1591 c_options->image_overlay.background_blue = colour.blue*255;
1592 c_options->image_overlay.background_alpha = colour.alpha*255;
1594 gtk_widget_destroy(dialog);
1597 GtkColorSelection *colorsel;
1599 dialog = gtk_color_selection_dialog_new("Image Overlay Background Colour");
1600 gtk_window_set_keep_above(GTK_WINDOW(dialog),TRUE);
1601 colour.red = options->image_overlay.background_red*257;
1602 colour.green = options->image_overlay.background_green*257;
1603 colour.blue = options->image_overlay.background_blue*257;
1604 colorsel = GTK_COLOR_SELECTION(gtk_color_selection_dialog_get_color_selection(GTK_COLOR_SELECTION_DIALOG(dialog)));
1605 gtk_color_selection_set_has_opacity_control(colorsel, TRUE);
1606 gtk_color_selection_set_current_color(colorsel, &colour);
1607 gtk_color_selection_set_current_alpha(colorsel, options->image_overlay.background_alpha*257);
1609 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK)
1611 gtk_color_selection_get_current_color(colorsel, &colour);
1612 c_options->image_overlay.background_red = colour.red/257;
1613 c_options->image_overlay.background_green = colour.green/257;
1614 c_options->image_overlay.background_blue = colour.blue/257;
1615 c_options->image_overlay.background_alpha = gtk_color_selection_get_current_alpha(colorsel)/257;
1617 gtk_widget_destroy(dialog);
1621 static void accel_store_populate(void)
1624 GList *groups, *actions;
1626 const gchar *accel_path;
1630 if (!accel_store || !layout_window_list || !layout_window_list->data) return;
1632 gtk_tree_store_clear(accel_store);
1633 lw = layout_window_list->data; /* get the actions from the first window, it should not matter, they should be the same in all windows */
1635 g_assert(lw && lw->ui_manager);
1636 groups = gtk_ui_manager_get_action_groups(lw->ui_manager);
1639 actions = gtk_action_group_list_actions(GTK_ACTION_GROUP(groups->data));
1642 action = GTK_ACTION(actions->data);
1643 accel_path = gtk_action_get_accel_path(action);
1644 if (accel_path && gtk_accel_map_lookup_entry(accel_path, &key))
1646 gchar *label, *label2, *tooltip, *accel;
1647 g_object_get(action,
1648 "tooltip", &tooltip,
1652 if (pango_parse_markup(label, -1, '_', NULL, &label2, NULL, NULL) && label2)
1658 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1662 gtk_tree_store_append(accel_store, &iter, NULL);
1663 gtk_tree_store_set(accel_store, &iter,
1666 AE_TOOLTIP, tooltip ? tooltip : "",
1667 AE_ACCEL, accel_path,
1675 actions = actions->next;
1678 groups = groups->next;
1682 static void accel_store_cleared_cb(GtkCellRendererAccel *accel, gchar *path_string, gpointer user_data)
1687 static gboolean accel_remove_key_cb(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1689 gchar *accel1 = data;
1694 gtk_tree_model_get(model, iter, AE_KEY, &accel2, -1);
1696 gtk_accelerator_parse(accel1, &key1.accel_key, &key1.accel_mods);
1697 gtk_accelerator_parse(accel2, &key2.accel_key, &key2.accel_mods);
1699 if (key1.accel_key == key2.accel_key && key1.accel_mods == key2.accel_mods)
1701 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1702 DEBUG_1("accelerator key '%s' is already used, removing.", accel1);
1711 static void accel_store_edited_cb(GtkCellRendererAccel *accel, gchar *path_string, guint accel_key, GdkModifierType accel_mods, guint hardware_keycode, gpointer user_data)
1713 GtkTreeModel *model = (GtkTreeModel *)accel_store;
1717 GtkAccelKey old_key, key;
1718 GtkTreePath *path = gtk_tree_path_new_from_string(path_string);
1720 gtk_tree_model_get_iter(model, &iter, path);
1721 gtk_tree_model_get(model, &iter, AE_ACCEL, &accel_path, -1);
1723 /* test if the accelerator can be stored without conflicts*/
1724 gtk_accel_map_lookup_entry(accel_path, &old_key);
1726 /* change the key and read it back (change may fail on keys hardcoded in gtk)*/
1727 gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE);
1728 gtk_accel_map_lookup_entry(accel_path, &key);
1730 /* restore the original for now, the key will be really changed when the changes are confirmed */
1731 gtk_accel_map_change_entry(accel_path, old_key.accel_key, old_key.accel_mods, TRUE);
1733 acc = gtk_accelerator_name(key.accel_key, key.accel_mods);
1734 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, acc);
1736 gtk_tree_store_set(accel_store, &iter, AE_KEY, acc, -1);
1737 gtk_tree_path_free(path);
1741 static gboolean accel_default_scroll(GtkTreeView *data)
1745 GtkTreeViewColumn *column;
1747 gtk_tree_model_get_iter_first(GTK_TREE_MODEL(accel_store), &iter);
1748 path = gtk_tree_model_get_path(GTK_TREE_MODEL(accel_store), &iter);
1749 column = gtk_tree_view_get_column(GTK_TREE_VIEW(data),0);
1751 gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(data),
1755 gtk_tree_path_free(path);
1760 static void accel_default_cb(GtkWidget *widget, gpointer data)
1762 accel_store_populate();
1764 g_idle_add((GSourceFunc)accel_default_scroll, data);
1767 void accel_remove_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1769 gtk_tree_store_set(accel_store, iter, AE_KEY, "", -1);
1772 void accel_reset_selection(GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data)
1775 gchar *accel_path, *accel;
1777 gtk_tree_model_get(model, iter, AE_ACCEL, &accel_path, -1);
1778 gtk_accel_map_lookup_entry(accel_path, &key);
1779 accel = gtk_accelerator_name(key.accel_key, key.accel_mods);
1781 gtk_tree_model_foreach(GTK_TREE_MODEL(accel_store), accel_remove_key_cb, accel);
1783 gtk_tree_store_set(accel_store, iter, AE_KEY, accel, -1);
1788 static void accel_reset_cb(GtkWidget *widget, gpointer data)
1790 GtkTreeSelection *selection;
1792 if (!accel_store) return;
1793 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(data));
1794 gtk_tree_selection_selected_foreach(selection, &accel_reset_selection, NULL);
1799 static GtkWidget *scrolled_notebook_page(GtkWidget *notebook, const gchar *title)
1803 GtkWidget *scrolled;
1804 GtkWidget *viewport;
1806 scrolled = gtk_scrolled_window_new(NULL, NULL);
1807 gtk_container_set_border_width(GTK_CONTAINER(scrolled), PREF_PAD_BORDER);
1808 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
1809 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1810 label = gtk_label_new(title);
1811 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled, label);
1812 gtk_widget_show(scrolled);
1814 viewport = gtk_viewport_new(NULL, NULL);
1815 gtk_viewport_set_shadow_type(GTK_VIEWPORT(viewport), GTK_SHADOW_NONE);
1816 gtk_container_add(GTK_CONTAINER(scrolled), viewport);
1817 gtk_widget_show(viewport);
1819 vbox = gtk_vbox_new(FALSE, 0);
1820 gtk_container_add(GTK_CONTAINER(viewport), vbox);
1821 gtk_widget_show(vbox);
1826 static void cache_standard_cb(GtkWidget *widget, gpointer data)
1828 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1830 c_options->thumbnails.spec_standard =TRUE;
1831 c_options->thumbnails.cache_into_dirs = FALSE;
1835 static void cache_geeqie_cb(GtkWidget *widget, gpointer data)
1837 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1839 c_options->thumbnails.spec_standard =FALSE;
1840 c_options->thumbnails.cache_into_dirs = FALSE;
1844 static void cache_local_cb(GtkWidget *widget, gpointer data)
1846 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
1848 c_options->thumbnails.cache_into_dirs = TRUE;
1849 c_options->thumbnails.spec_standard =FALSE;
1853 static void help_search_engine_entry_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1854 GdkEvent *event, gpointer userdata)
1856 if (pos == GTK_ENTRY_ICON_PRIMARY)
1858 gtk_entry_set_text(GTK_ENTRY(userdata), HELP_SEARCH_ENGINE);
1862 gtk_entry_set_text(GTK_ENTRY(userdata), "");
1866 static void star_rating_star_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1867 GdkEvent *event, gpointer userdata)
1869 gchar *rating_symbol;
1871 if (pos == GTK_ENTRY_ICON_PRIMARY)
1873 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_STAR);
1874 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1875 g_free(rating_symbol);
1879 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1880 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1881 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1885 static void star_rating_rejected_icon_cb(GtkEntry *entry, GtkEntryIconPosition pos,
1886 GdkEvent *event, gpointer userdata)
1888 gchar *rating_symbol;
1890 if (pos == GTK_ENTRY_ICON_PRIMARY)
1892 rating_symbol = g_strdup_printf("U+%X", STAR_RATING_REJECTED);
1893 gtk_entry_set_text(GTK_ENTRY(userdata), rating_symbol);
1894 g_free(rating_symbol);
1898 gtk_entry_set_text(GTK_ENTRY(userdata), "U+");
1899 gtk_widget_grab_focus(GTK_WIDGET(userdata));
1900 gtk_editable_select_region(GTK_EDITABLE(userdata), 2, 2);
1904 static guint star_rating_symbol_test(GtkWidget *widget, gpointer data)
1906 GtkContainer *hbox = data;
1907 GString *str = g_string_new(NULL);
1908 GtkEntry *hex_code_entry;
1909 gchar *hex_code_full;
1912 guint64 hex_value = 0;
1914 list = gtk_container_get_children(hbox);
1916 hex_code_entry = g_list_nth_data(list, 2);
1917 hex_code_full = g_strdup(gtk_entry_get_text(hex_code_entry));
1919 hex_code = g_strsplit(hex_code_full, "+", 2);
1920 if (hex_code[0] && hex_code[1])
1922 hex_value = strtoull(hex_code[1], NULL, 16);
1924 if (!hex_value || hex_value > 0x10FFFF)
1926 hex_value = 0x003F; // Unicode 'Question Mark'
1928 str = g_string_append_unichar(str, (gunichar)hex_value);
1929 gtk_label_set_text(g_list_nth_data(list, 1), str->str);
1931 g_strfreev(hex_code);
1932 g_string_free(str, TRUE);
1933 g_free(hex_code_full);
1938 static void star_rating_star_test_cb(GtkWidget *widget, gpointer data)
1940 guint64 star_symbol;
1942 star_symbol = star_rating_symbol_test(widget, data);
1943 c_options->star_rating.star = star_symbol;
1946 static void star_rating_rejected_test_cb(GtkWidget *widget, gpointer data)
1948 guint64 rejected_symbol;
1950 rejected_symbol = star_rating_symbol_test(widget, data);
1951 c_options->star_rating.rejected = rejected_symbol;
1954 /* general options tab */
1955 static void timezone_database_install_cb(GtkWidget *widget, gpointer data);
1956 typedef struct _TZData TZData;
1960 GCancellable *cancellable;
1962 GtkWidget *progress;
1964 GFile *timezone_database_gq;
1965 gchar *timezone_database_user;
1968 static void config_tab_general(GtkWidget *notebook)
1973 GtkWidget *group_frame;
1974 GtkWidget *subgroup;
1976 GtkWidget *ct_button;
1979 gint hours, minutes, remainder;
1981 GtkWidget *star_rating_entry;
1983 gchar *rating_symbol;
1986 GNetworkMonitor *net_mon;
1987 GSocketConnectable *geeqie_org;
1988 gboolean internet_available;
1991 vbox = scrolled_notebook_page(notebook, _("General"));
1993 group = pref_group_new(vbox, FALSE, _("Thumbnails"), GTK_ORIENTATION_VERTICAL);
1995 table = pref_table_new(group, 2, 2, FALSE, FALSE);
1996 add_thumb_size_menu(table, 0, 0, _("Size:"));
1997 add_quality_menu(table, 0, 1, _("Quality:"), options->thumbnails.quality, &c_options->thumbnails.quality);
1999 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2000 pref_label_new(hbox, _("Custom size: "));
2001 pref_spin_new_int(hbox, _("Width:"), NULL, 1, 512, 1, options->thumbnails.max_width, &c_options->thumbnails.max_width);
2002 pref_spin_new_int(hbox, _("Height:"), NULL, 1, 512, 1, options->thumbnails.max_height, &c_options->thumbnails.max_height);
2004 ct_button = pref_checkbox_new_int(group, _("Cache thumbnails and sim. files"),
2005 options->thumbnails.enable_caching, &c_options->thumbnails.enable_caching);
2007 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2008 pref_checkbox_link_sensitivity(ct_button, subgroup);
2010 c_options->thumbnails.spec_standard = options->thumbnails.spec_standard;
2011 c_options->thumbnails.cache_into_dirs = options->thumbnails.cache_into_dirs;
2012 group_frame = pref_frame_new(subgroup, TRUE, _("Use Geeqie thumbnail style and cache"),
2013 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2014 button = pref_radiobutton_new(group_frame, NULL, get_thumbnails_cache_dir(),
2015 !options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2016 G_CALLBACK(cache_geeqie_cb), NULL);
2018 group_frame = pref_frame_new(subgroup, TRUE,
2019 _("Store thumbnails local to image folder (non-standard)"),
2020 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2021 pref_radiobutton_new(group_frame, button, "*/.thumbnails",
2022 !options->thumbnails.spec_standard && options->thumbnails.cache_into_dirs,
2023 G_CALLBACK(cache_local_cb), NULL);
2025 group_frame = pref_frame_new(subgroup, TRUE,
2026 _("Use standard thumbnail style and cache, shared with other applications"),
2027 GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2028 pref_radiobutton_new(group_frame, button, get_thumbnails_standard_cache_dir(),
2029 options->thumbnails.spec_standard && !options->thumbnails.cache_into_dirs,
2030 G_CALLBACK(cache_standard_cb), NULL);
2032 pref_checkbox_new_int(group, _("Use EXIF thumbnails when available (EXIF thumbnails may be outdated)"),
2033 options->thumbnails.use_exif, &c_options->thumbnails.use_exif);
2035 pref_checkbox_new_int(group, _("Thumbnail color management"),
2036 options->thumbnails.use_color_management, &c_options->thumbnails.use_color_management);
2038 spin = pref_spin_new_int(group, _("Collection preview:"), NULL,
2040 options->thumbnails.collection_preview, &c_options->thumbnails.collection_preview);
2041 gtk_widget_set_tooltip_text(spin, _("The maximum number of thumbnails shown in a Collection preview montage"));
2043 #ifdef HAVE_FFMPEGTHUMBNAILER_METADATA
2044 pref_checkbox_new_int(group, _("Use embedded metadata in video files as thumbnails when available"),
2045 options->thumbnails.use_ft_metadata, &c_options->thumbnails.use_ft_metadata);
2047 // pref_checkbox_new_int(group, _("Ignore embedded metadata if size is too small"),
2048 // options->thumbnails.use_ft_metadata_small, &c_options->thumbnails.use_ft_metadata_small);
2051 pref_spacer(group, PREF_PAD_GROUP);
2053 group = pref_group_new(vbox, FALSE, _("Star Rating"), GTK_ORIENTATION_VERTICAL);
2055 c_options->star_rating.star = options->star_rating.star;
2056 c_options->star_rating.rejected = options->star_rating.rejected;
2058 str = g_string_new(NULL);
2059 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2060 pref_label_new(hbox, _("Star character: "));
2061 str = g_string_append_unichar(str, options->star_rating.star);
2062 pref_label_new(hbox, g_strdup(str->str));
2063 rating_symbol = g_strdup_printf("U+%X", options->star_rating.star);
2064 star_rating_entry = gtk_entry_new();
2065 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2066 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2067 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2068 gtk_widget_show(star_rating_entry);
2069 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2070 G_CALLBACK(star_rating_star_test_cb), hbox);
2071 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2072 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2073 gtk_widget_show(button);
2074 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."));
2075 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2076 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2077 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2078 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2079 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2080 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2081 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2082 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2083 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2084 G_CALLBACK(star_rating_star_icon_cb),
2087 g_string_free(str, TRUE);
2088 g_free(rating_symbol);
2090 str = g_string_new(NULL);
2091 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2092 pref_label_new(hbox, _("Rejected character: "));
2093 str = g_string_append_unichar(str, options->star_rating.rejected);
2094 pref_label_new(hbox, g_strdup(str->str));
2095 rating_symbol = g_strdup_printf("U+%X", options->star_rating.rejected);
2096 star_rating_entry = gtk_entry_new();
2097 gtk_entry_set_text(GTK_ENTRY(star_rating_entry), rating_symbol);
2098 gtk_box_pack_start(GTK_BOX(hbox), star_rating_entry, FALSE, FALSE, 0);
2099 gtk_entry_set_width_chars(GTK_ENTRY(star_rating_entry), 15);
2100 gtk_widget_show(star_rating_entry);
2101 button = pref_button_new(NULL, NULL, _("Set"), FALSE,
2102 G_CALLBACK(star_rating_rejected_test_cb), hbox);
2103 gtk_widget_set_tooltip_text(button, _("Display selected character"));
2104 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2105 gtk_widget_show(button);
2106 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."));
2107 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2108 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2109 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2110 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2111 gtk_entry_set_icon_from_stock(GTK_ENTRY(star_rating_entry),
2112 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2113 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(star_rating_entry),
2114 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2115 g_signal_connect(GTK_ENTRY(star_rating_entry), "icon-press",
2116 G_CALLBACK(star_rating_rejected_icon_cb),
2119 g_string_free(str, TRUE);
2120 g_free(rating_symbol);
2122 pref_spacer(group, PREF_PAD_GROUP);
2124 group = pref_group_new(vbox, FALSE, _("Slide show"), GTK_ORIENTATION_VERTICAL);
2126 c_options->slideshow.delay = options->slideshow.delay;
2127 hours = options->slideshow.delay / (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2128 remainder = options->slideshow.delay % (3600 * SLIDESHOW_SUBSECOND_PRECISION);
2129 minutes = remainder / (60 * SLIDESHOW_SUBSECOND_PRECISION);
2130 seconds = (gdouble)(remainder % (60 * SLIDESHOW_SUBSECOND_PRECISION)) /
2131 SLIDESHOW_SUBSECOND_PRECISION;
2133 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2135 spin = pref_spin_new(hbox, _("Delay between image change hrs:mins:secs.dec"), NULL,
2137 options->slideshow.delay ? hours : 0.0,
2138 G_CALLBACK(slideshow_delay_hours_cb), NULL);
2139 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2140 spin = pref_spin_new(hbox, ":" , NULL,
2142 options->slideshow.delay ? minutes: 0.0,
2143 G_CALLBACK(slideshow_delay_minutes_cb), NULL);
2144 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2145 spin = pref_spin_new(hbox, ":", NULL,
2146 SLIDESHOW_MIN_SECONDS, 59, 1.0, 1,
2147 options->slideshow.delay ? seconds : 10.0,
2148 G_CALLBACK(slideshow_delay_seconds_cb), NULL);
2149 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2151 pref_checkbox_new_int(group, _("Random"), options->slideshow.random, &c_options->slideshow.random);
2152 pref_checkbox_new_int(group, _("Repeat"), options->slideshow.repeat, &c_options->slideshow.repeat);
2154 pref_spacer(group, PREF_PAD_GROUP);
2156 group = pref_group_new(vbox, FALSE, _("Image loading and caching"), GTK_ORIENTATION_VERTICAL);
2158 pref_spin_new_int(group, _("Decoded image cache size (MiB):"), NULL,
2159 0, 99999, 1, options->image.image_cache_max, &c_options->image.image_cache_max);
2160 pref_checkbox_new_int(group, _("Preload next image"),
2161 options->image.enable_read_ahead, &c_options->image.enable_read_ahead);
2163 pref_checkbox_new_int(group, _("Refresh on file change"),
2164 options->update_on_time_change, &c_options->update_on_time_change);
2167 pref_spacer(group, PREF_PAD_GROUP);
2169 group = pref_group_new(vbox, FALSE, _("Expand menu and toolbar"), GTK_ORIENTATION_VERTICAL);
2171 pref_checkbox_new_int(group, _("Expand menu and toolbar (NOTE! Geeqie must be restarted for change to take effect)"),
2172 options->expand_menu_toolbar, &c_options->expand_menu_toolbar);
2173 gtk_widget_set_tooltip_text(group, _("Expand the menu and toolbar to the full width of the window"));
2175 pref_spacer(group, PREF_PAD_GROUP);
2177 net_mon = g_network_monitor_get_default();
2178 geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
2179 internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
2180 g_object_unref(geeqie_org);
2182 group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
2183 hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2185 if (!internet_available)
2187 gtk_widget_set_sensitive(group, FALSE);
2190 tz = g_new0(TZData, 1);
2192 path = path_from_utf8(TIMEZONE_DATABASE);
2193 basename = g_path_get_basename(path);
2194 tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
2198 if (isfile(tz->timezone_database_user))
2200 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Update"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2204 button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
2207 if (!internet_available)
2209 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"));
2213 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"));
2215 gtk_widget_show(button);
2217 pref_spacer(group, PREF_PAD_GROUP);
2219 group = pref_group_new(vbox, FALSE, _("On-line help search engine"), GTK_ORIENTATION_VERTICAL);
2221 help_search_engine_entry = gtk_entry_new();
2222 gtk_entry_set_text(GTK_ENTRY(help_search_engine_entry), options->help_search_engine);
2223 gtk_box_pack_start(GTK_BOX(group), help_search_engine_entry, FALSE, FALSE, 0);
2224 gtk_widget_show(help_search_engine_entry);
2226 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"));
2228 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2229 GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR);
2230 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2231 GTK_ENTRY_ICON_SECONDARY, _("Clear"));
2232 gtk_entry_set_icon_from_stock(GTK_ENTRY(help_search_engine_entry),
2233 GTK_ENTRY_ICON_PRIMARY, GTK_STOCK_REVERT_TO_SAVED);
2234 gtk_entry_set_icon_tooltip_text (GTK_ENTRY(help_search_engine_entry),
2235 GTK_ENTRY_ICON_PRIMARY, _("Default"));
2236 g_signal_connect(GTK_ENTRY(help_search_engine_entry), "icon-press",
2237 G_CALLBACK(help_search_engine_entry_icon_cb),
2238 help_search_engine_entry);
2242 static void config_tab_image(GtkWidget *notebook)
2247 GtkWidget *ct_button;
2248 GtkWidget *enlargement_button;
2251 GtkWidget *two_pass;
2253 GtkWidget *gpu_accel;
2256 vbox = scrolled_notebook_page(notebook, _("Image"));
2258 group = pref_group_new(vbox, FALSE, _("Zoom"), GTK_ORIENTATION_VERTICAL);
2260 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2261 add_quality_menu(table, 0, 0, _("Quality:"), options->image.zoom_quality, &c_options->image.zoom_quality);
2262 if (options->image.use_clutter_renderer && !options->disable_gpu)
2264 gtk_widget_set_sensitive(table, FALSE);
2268 gpu_accel = pref_checkbox_new_int(group, _("Use GPU acceleration via Clutter library (Requires restart)"),
2269 options->image.use_clutter_renderer, &c_options->image.use_clutter_renderer);
2270 if (options->disable_gpu && !options->override_disable_gpu)
2272 gtk_widget_set_sensitive(gpu_accel, FALSE);
2276 two_pass = pref_checkbox_new_int(group, _("Two pass rendering (apply HQ zoom and color correction in second pass)"),
2277 options->image.zoom_2pass, &c_options->image.zoom_2pass);
2278 if (options->image.use_clutter_renderer && !options->disable_gpu)
2280 gtk_widget_set_sensitive(two_pass, FALSE);
2283 c_options->image.zoom_increment = options->image.zoom_increment;
2284 spin = pref_spin_new(group, _("Zoom increment:"), NULL,
2285 0.01, 4.0, 0.01, 2, (gdouble)options->image.zoom_increment / 100.0,
2286 G_CALLBACK(zoom_increment_cb), NULL);
2287 gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
2289 c_options->image.zoom_style = options->image.zoom_style;
2290 table = pref_table_new(group, 2, 1, FALSE, FALSE);
2291 add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
2293 group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
2295 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2296 enlargement_button = pref_checkbox_new_int(hbox, _("Allow enlargement of image (max. size in %)"),
2297 options->image.zoom_to_fit_allow_expand, &c_options->image.zoom_to_fit_allow_expand);
2298 spin = pref_spin_new_int(hbox, NULL, NULL,
2300 options->image.max_enlargement_size, &c_options->image.max_enlargement_size);
2301 pref_checkbox_link_sensitivity(enlargement_button, spin);
2302 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."));
2304 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2305 ct_button = pref_checkbox_new_int(hbox, _("Virtual window size (% of actual window):"),
2306 options->image.limit_autofit_size, &c_options->image.limit_autofit_size);
2307 spin = pref_spin_new_int(hbox, NULL, NULL,
2309 options->image.max_autofit_size, &c_options->image.max_autofit_size);
2310 pref_checkbox_link_sensitivity(ct_button, spin);
2311 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."));
2313 group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
2314 gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
2316 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2317 spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
2319 options->image.tile_size, &c_options->image.tile_size);
2320 gtk_widget_set_tooltip_text(GTK_WIDGET(hbox), _("This value changes the size of the tiles large images are split into. Increasing the size of the tiles will reduce the tiling effect seen on image changes, but will also slightly increase the delay before the first part of a large image is seen."));
2322 group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
2324 pref_checkbox_new_int(group, _("Use custom border color in window mode"),
2325 options->image.use_custom_border_color, &c_options->image.use_custom_border_color);
2327 pref_checkbox_new_int(group, _("Use custom border color in fullscreen mode"),
2328 options->image.use_custom_border_color_in_fullscreen, &c_options->image.use_custom_border_color_in_fullscreen);
2330 pref_color_button_new(group, _("Border color"), &options->image.border_color,
2331 G_CALLBACK(pref_color_button_set_cb), &c_options->image.border_color);
2333 c_options->image.border_color = options->image.border_color;
2335 pref_color_button_new(group, _("Alpha channel color 1"), &options->image.alpha_color_1,
2336 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_1);
2338 pref_color_button_new(group, _("Alpha channel color 2"), &options->image.alpha_color_2,
2339 G_CALLBACK(pref_color_button_set_cb), &c_options->image.alpha_color_2);
2341 c_options->image.alpha_color_1 = options->image.alpha_color_1;
2342 c_options->image.alpha_color_2 = options->image.alpha_color_2;
2347 static void save_default_window_layout_cb(GtkWidget *widget, gpointer data)
2349 LayoutWindow *lw = NULL;
2350 gchar *default_path;
2353 /* Get current lw */
2356 tmp_id = lw->options.id;
2357 lw->options.id = g_strdup("lw_default");
2359 default_path = g_build_filename(get_rc_dir(), DEFAULT_WINDOW_LAYOUT, NULL);
2360 save_default_layout_options_to_file(default_path, options, lw);
2361 g_free(lw->options.id);
2362 lw->options.id = tmp_id;
2363 g_free(default_path);
2366 #if GTK_CHECK_VERSION(3,22,0)
2367 static gboolean popover_cb(gpointer data)
2369 GtkPopover *popover = data;
2371 gtk_popover_popdown(popover);
2376 static void default_layout_changed_cb(GtkWidget *button, GtkPopover *popover)
2378 gtk_popover_popup(popover);
2380 g_timeout_add(2000, popover_cb, popover);
2383 static GtkWidget *create_popover(GtkWidget *parent, GtkWidget *child, GtkPositionType pos)
2387 popover = gtk_popover_new(parent);
2388 gtk_popover_set_position(GTK_POPOVER (popover), pos);
2389 gtk_container_add (GTK_CONTAINER(popover), child);
2390 gtk_container_set_border_width(GTK_CONTAINER (popover), 6);
2391 gtk_widget_show (child);
2397 static void config_tab_windows(GtkWidget *notebook)
2402 GtkWidget *subgroup;
2404 GtkWidget *ct_button;
2407 vbox = scrolled_notebook_page(notebook, _("Windows"));
2409 group = pref_group_new(vbox, FALSE, _("State"), GTK_ORIENTATION_VERTICAL);
2411 ct_button = pref_checkbox_new_int(group, _("Remember session"),
2412 options->save_window_positions, &c_options->save_window_positions);
2414 button = pref_checkbox_new_int(group, _("Use saved window positions also for new windows"),
2415 options->use_saved_window_positions_for_new_windows, &c_options->use_saved_window_positions_for_new_windows);
2416 pref_checkbox_link_sensitivity(ct_button, button);
2418 button = pref_checkbox_new_int(group, _("Remember window workspace"),
2419 options->save_window_workspace, &c_options->save_window_workspace);
2420 pref_checkbox_link_sensitivity(ct_button, button);
2422 pref_checkbox_new_int(group, _("Remember tool state (float/hidden)"),
2423 options->tools_restore_state, &c_options->tools_restore_state);
2425 pref_checkbox_new_int(group, _("Remember dialog window positions"),
2426 options->save_dialog_window_positions, &c_options->save_dialog_window_positions);
2428 pref_checkbox_new_int(group, _("Show window IDs"),
2429 options->show_window_ids, &c_options->show_window_ids);
2431 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2432 pref_label_new(subgroup, _("Use current layout for default: "));
2433 button = pref_button_new(subgroup, NULL, _("Set"), FALSE, G_CALLBACK(save_default_window_layout_cb), NULL);
2435 #if GTK_CHECK_VERSION(3,22,0)
2438 popover = create_popover(button, gtk_label_new(_("Current window layout\nhas been set as default")), GTK_POS_TOP);
2439 gtk_popover_set_modal(GTK_POPOVER (popover), FALSE);
2440 g_signal_connect(button, "clicked", G_CALLBACK(default_layout_changed_cb), popover);
2443 group = pref_group_new(vbox, FALSE, _("Size"), GTK_ORIENTATION_VERTICAL);
2445 pref_checkbox_new_int(group, _("Fit window to image when tools are hidden/floating"),
2446 options->image.fit_window_to_image, &c_options->image.fit_window_to_image);
2448 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2449 ct_button = pref_checkbox_new_int(hbox, _("Limit size when auto-sizing window (%):"),
2450 options->image.limit_window_size, &c_options->image.limit_window_size);
2451 spin = pref_spin_new_int(hbox, NULL, NULL,
2453 options->image.max_window_size, &c_options->image.max_window_size);
2454 pref_checkbox_link_sensitivity(ct_button, spin);
2456 group = pref_group_new(vbox, FALSE, _("Full screen"), GTK_ORIENTATION_VERTICAL);
2458 c_options->fullscreen.screen = options->fullscreen.screen;
2459 c_options->fullscreen.above = options->fullscreen.above;
2460 hbox = fullscreen_prefs_selection_new(_("Location:"), &c_options->fullscreen.screen, &c_options->fullscreen.above);
2461 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2462 gtk_widget_show(hbox);
2464 pref_checkbox_new_int(group, _("Smooth image flip"),
2465 options->fullscreen.clean_flip, &c_options->fullscreen.clean_flip);
2466 pref_checkbox_new_int(group, _("Disable screen saver"),
2467 options->fullscreen.disable_saver, &c_options->fullscreen.disable_saver);
2470 #define PRE_FORMATTED_COLUMNS 5
2471 static void config_tab_osd(GtkWidget *notebook)
2477 GtkWidget *image_overlay_template_view;
2478 GtkWidget *scrolled;
2479 GtkWidget *scrolled_pre_formatted;
2480 GtkTextBuffer *buffer;
2482 GtkWidget *subgroup;
2484 vbox = scrolled_notebook_page(notebook, _("OSD"));
2486 image_overlay_template_view = gtk_text_view_new();
2488 group = pref_group_new(vbox, FALSE, _("Overlay Screen Display"), GTK_ORIENTATION_VERTICAL);
2490 subgroup = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2492 scrolled_pre_formatted = osd_new(PRE_FORMATTED_COLUMNS, image_overlay_template_view);
2493 gtk_widget_set_size_request(scrolled_pre_formatted, 200, 150);
2494 gtk_box_pack_start(GTK_BOX(subgroup), scrolled_pre_formatted, FALSE, FALSE, 0);
2495 gtk_widget_show(scrolled_pre_formatted);
2496 gtk_widget_show(subgroup);
2498 pref_line(group, PREF_PAD_GAP);
2500 pref_label_new(group, _("Image overlay template"));
2502 scrolled = gtk_scrolled_window_new(NULL, NULL);
2503 gtk_widget_set_size_request(scrolled, 200, 150);
2504 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2505 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled),
2506 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2507 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 5);
2508 gtk_widget_show(scrolled);
2510 gtk_widget_set_tooltip_markup(image_overlay_template_view,
2511 _("Extensive formatting options are shown in the Help file"));
2513 gtk_container_add(GTK_CONTAINER(scrolled), image_overlay_template_view);
2514 gtk_widget_show(image_overlay_template_view);
2516 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2518 #if GTK_CHECK_VERSION(3,4,0)
2519 button = pref_button_new(NULL, GTK_STOCK_SELECT_FONT, _("Font"), FALSE,
2520 G_CALLBACK(image_overlay_set_font_cb), notebook);
2522 button = gtk_font_button_new();
2523 gtk_font_button_set_title(GTK_FONT_BUTTON(button), "Image Overlay Font");
2524 gtk_font_button_set_font_name(GTK_FONT_BUTTON(button), options->image_overlay.font);
2525 g_signal_connect(G_OBJECT(button), "font-set",
2526 G_CALLBACK(image_overlay_set_font_cb),NULL);
2528 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2529 gtk_widget_show(button);
2531 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Text"), FALSE,
2532 G_CALLBACK(image_overlay_set_text_colour_cb), NULL);
2533 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2534 gtk_widget_show(button);
2536 button = pref_button_new(NULL, GTK_STOCK_COLOR_PICKER, _("Background"), FALSE,
2537 G_CALLBACK(image_overlay_set_background_colour_cb), NULL);
2538 gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2539 gtk_widget_show(button);
2540 image_overlay_set_text_colours();
2542 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2543 G_CALLBACK(image_overlay_default_template_cb), image_overlay_template_view);
2544 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2545 gtk_widget_show(button);
2547 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
2548 G_CALLBACK(image_overlay_help_cb), NULL);
2549 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2550 gtk_widget_show(button);
2552 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(image_overlay_template_view));
2553 if (options->image_overlay.template_string) gtk_text_buffer_set_text(buffer, options->image_overlay.template_string, -1);
2554 g_signal_connect(G_OBJECT(buffer), "changed",
2555 G_CALLBACK(image_overlay_template_view_changed_cb), image_overlay_template_view);
2557 pref_line(group, PREF_PAD_GAP);
2559 group = pref_group_new(vbox, FALSE, _("Exif, XMP or IPTC tags"), GTK_ORIENTATION_VERTICAL);
2560 hbox = gtk_hbox_new(FALSE, 0);
2561 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2562 gtk_widget_show(hbox);
2563 label = gtk_label_new(_("%Exif.Image.Orientation%"));
2564 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2565 gtk_widget_show(label);
2566 pref_spacer(group,TRUE);
2568 group = pref_group_new(vbox, FALSE, _("Field separators"), GTK_ORIENTATION_VERTICAL);
2569 hbox = gtk_hbox_new(FALSE, 0);
2570 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2571 gtk_widget_show(hbox);
2572 label = gtk_label_new(_("Separator shown only if both fields are non-null:\n%formatted.ShutterSpeed%|%formatted.ISOSpeedRating%"));
2573 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2574 gtk_widget_show(label);
2575 pref_spacer(group,TRUE);
2577 group = pref_group_new(vbox, FALSE, _("Field maximum length"), GTK_ORIENTATION_VERTICAL);
2578 hbox = gtk_hbox_new(FALSE, 0);
2579 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2580 gtk_widget_show(hbox);
2581 label = gtk_label_new(_("%path:39%"));
2582 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2583 gtk_widget_show(label);
2584 pref_spacer(group,TRUE);
2586 group = pref_group_new(vbox, FALSE, _("Pre- and post- text"), GTK_ORIENTATION_VERTICAL);
2587 hbox = gtk_hbox_new(FALSE, 0);
2588 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2589 gtk_widget_show(hbox);
2590 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%"));
2591 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2592 gtk_widget_show(label);
2593 pref_spacer(group,TRUE);
2595 group = pref_group_new(vbox, FALSE, _("Pango markup"), GTK_ORIENTATION_VERTICAL);
2596 hbox = gtk_hbox_new(FALSE, 0);
2597 gtk_box_pack_start(GTK_BOX(group), hbox, FALSE, FALSE, 0);
2598 gtk_widget_show(hbox);
2599 label = gtk_label_new(_("<b>bold</b>\n<u>underline</u>\n<i>italic</i>\n<s>strikethrough</s>"));
2600 gtk_box_pack_start(GTK_BOX(hbox),label, FALSE,FALSE,0);
2601 gtk_widget_show(label);
2604 static GtkTreeModel *create_class_model(void)
2606 GtkListStore *model;
2610 /* create list store */
2611 model = gtk_list_store_new(1, G_TYPE_STRING);
2612 for (i = 0; i < FILE_FORMAT_CLASSES; i++)
2614 gtk_list_store_append(model, &iter);
2615 gtk_list_store_set(model, &iter, 0, _(format_class_list[i]), -1);
2617 return GTK_TREE_MODEL (model);
2622 static void config_tab_files(GtkWidget *notebook)
2629 GtkWidget *ct_button;
2630 GtkWidget *scrolled;
2631 GtkWidget *filter_view;
2632 GtkCellRenderer *renderer;
2633 GtkTreeSelection *selection;
2634 GtkTreeViewColumn *column;
2636 vbox = scrolled_notebook_page(notebook, _("Files"));
2638 group = pref_box_new(vbox, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
2640 pref_checkbox_new_int(group, _("Show hidden files or folders"),
2641 options->file_filter.show_hidden_files, &c_options->file_filter.show_hidden_files);
2642 pref_checkbox_new_int(group, _("Show parent folder (..)"),
2643 options->file_filter.show_parent_directory, &c_options->file_filter.show_parent_directory);
2644 pref_checkbox_new_int(group, _("Case sensitive sort"),
2645 options->file_sort.case_sensitive, &c_options->file_sort.case_sensitive);
2646 pref_checkbox_new_int(group, _("Natural sort order"),
2647 options->file_sort.natural, &c_options->file_sort.natural);
2648 pref_checkbox_new_int(group, _("Disable file extension checks"),
2649 options->file_filter.disable_file_extension_checks, &c_options->file_filter.disable_file_extension_checks);
2651 ct_button = pref_checkbox_new_int(group, _("Disable File Filtering"),
2652 options->file_filter.disable, &c_options->file_filter.disable);
2655 group = pref_group_new(vbox, FALSE, _("Grouping sidecar extensions"), GTK_ORIENTATION_VERTICAL);
2657 sidecar_ext_entry = gtk_entry_new();
2658 gtk_entry_set_text(GTK_ENTRY(sidecar_ext_entry), options->sidecar.ext);
2659 gtk_box_pack_start(GTK_BOX(group), sidecar_ext_entry, FALSE, FALSE, 0);
2660 gtk_widget_show(sidecar_ext_entry);
2662 group = pref_group_new(vbox, TRUE, _("File types"), GTK_ORIENTATION_VERTICAL);
2664 frame = pref_group_parent(group);
2665 g_signal_connect(G_OBJECT(ct_button), "toggled",
2666 G_CALLBACK(filter_disable_cb), frame);
2667 gtk_widget_set_sensitive(frame, !options->file_filter.disable);
2669 scrolled = gtk_scrolled_window_new(NULL, NULL);
2670 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
2671 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
2672 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
2673 gtk_widget_show(scrolled);
2675 filter_store = gtk_list_store_new(1, G_TYPE_POINTER);
2676 filter_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(filter_store));
2677 g_object_unref(filter_store);
2678 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(filter_view));
2679 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_SINGLE);
2681 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), FALSE);
2683 column = gtk_tree_view_column_new();
2684 gtk_tree_view_column_set_title(column, _("Filter"));
2685 gtk_tree_view_column_set_resizable(column, TRUE);
2687 renderer = gtk_cell_renderer_toggle_new();
2688 g_signal_connect(G_OBJECT(renderer), "toggled",
2689 G_CALLBACK(filter_store_enable_cb), filter_store);
2690 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2691 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2692 GINT_TO_POINTER(FE_ENABLE), NULL);
2694 renderer = gtk_cell_renderer_text_new();
2695 g_signal_connect(G_OBJECT(renderer), "edited",
2696 G_CALLBACK(filter_store_ext_edit_cb), filter_store);
2697 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2698 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2699 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2700 GINT_TO_POINTER(FE_EXTENSION), NULL);
2701 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2703 column = gtk_tree_view_column_new();
2704 gtk_tree_view_column_set_title(column, _("Description"));
2705 gtk_tree_view_column_set_resizable(column, TRUE);
2706 gtk_tree_view_column_set_fixed_width(column, 200);
2707 gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
2709 renderer = gtk_cell_renderer_text_new();
2710 g_signal_connect(G_OBJECT(renderer), "edited",
2711 G_CALLBACK(filter_store_desc_edit_cb), filter_store);
2712 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE, NULL);
2713 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2714 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2715 GINT_TO_POINTER(FE_DESCRIPTION), NULL);
2716 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2718 column = gtk_tree_view_column_new();
2719 gtk_tree_view_column_set_title(column, _("Class"));
2720 gtk_tree_view_column_set_resizable(column, TRUE);
2721 renderer = gtk_cell_renderer_combo_new();
2722 g_object_set(G_OBJECT(renderer), "editable", (gboolean)TRUE,
2723 "model", create_class_model(),
2728 g_signal_connect(G_OBJECT(renderer), "edited",
2729 G_CALLBACK(filter_store_class_edit_cb), filter_store);
2730 gtk_tree_view_column_pack_start(column, renderer, TRUE);
2731 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2732 GINT_TO_POINTER(FE_CLASS), NULL);
2733 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2735 column = gtk_tree_view_column_new();
2736 gtk_tree_view_column_set_title(column, _("Writable"));
2737 gtk_tree_view_column_set_resizable(column, FALSE);
2738 renderer = gtk_cell_renderer_toggle_new();
2739 g_signal_connect(G_OBJECT(renderer), "toggled",
2740 G_CALLBACK(filter_store_writable_cb), filter_store);
2741 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2742 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2743 GINT_TO_POINTER(FE_WRITABLE), NULL);
2744 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2746 column = gtk_tree_view_column_new();
2747 gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
2748 gtk_tree_view_column_set_resizable(column, FALSE);
2749 renderer = gtk_cell_renderer_toggle_new();
2750 g_signal_connect(G_OBJECT(renderer), "toggled",
2751 G_CALLBACK(filter_store_sidecar_cb), filter_store);
2752 gtk_tree_view_column_pack_start(column, renderer, FALSE);
2753 gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
2754 GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
2755 gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
2758 filter_store_populate();
2759 gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
2760 gtk_widget_show(filter_view);
2762 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
2764 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
2765 G_CALLBACK(filter_default_cb), filter_view);
2766 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2767 gtk_widget_show(button);
2769 button = pref_button_new(NULL, GTK_STOCK_REMOVE, NULL, FALSE,
2770 G_CALLBACK(filter_remove_cb), filter_view);
2771 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2772 gtk_widget_show(button);
2774 button = pref_button_new(NULL, GTK_STOCK_ADD, NULL, FALSE,
2775 G_CALLBACK(filter_add_cb), filter_view);
2776 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
2777 gtk_widget_show(button);
2781 static void config_tab_metadata(GtkWidget *notebook)
2786 GtkWidget *ct_button;
2790 vbox = scrolled_notebook_page(notebook, _("Metadata"));
2793 group = pref_group_new(vbox, FALSE, _("Metadata writing process"), GTK_ORIENTATION_VERTICAL);
2795 label = pref_label_new(group, _("Warning: Geeqie is built without Exiv2. Some options are disabled."));
2797 label = pref_label_new(group, _("Metadata are written in the following order. The process ends after first success."));
2798 #if GTK_CHECK_VERSION(3,16,0)
2799 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2800 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2802 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2805 ct_button = pref_checkbox_new_int(group, _("1) Save metadata in image files, or sidecar files, according to the XMP standard"),
2806 options->metadata.save_in_image_file, &c_options->metadata.save_in_image_file);
2808 gtk_widget_set_sensitive(ct_button, FALSE);
2811 pref_checkbox_new_int(group, _("2) Save metadata in '.metadata' folder, local to image folder (non-standard)"),
2812 options->metadata.enable_metadata_dirs, &c_options->metadata.enable_metadata_dirs);
2814 text = g_strdup_printf(_("3) Save metadata in Geeqie private directory '%s'"), get_metadata_cache_dir());
2815 label = pref_label_new(group, text);
2816 #if GTK_CHECK_VERSION(3,16,0)
2817 gtk_label_set_xalign(GTK_LABEL(label), 0.0);
2818 gtk_label_set_yalign(GTK_LABEL(label), 0.5);
2820 gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
2822 gtk_misc_set_padding(GTK_MISC(label), 22, 0);
2825 group = pref_group_new(vbox, FALSE, _("Step 1: Write to image files"), GTK_ORIENTATION_VERTICAL);
2827 gtk_widget_set_sensitive(group, FALSE);
2830 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
2831 pref_checkbox_link_sensitivity(ct_button, hbox);
2833 pref_checkbox_new_int(hbox, _("Store metadata also in legacy IPTC tags (converted according to IPTC4XMP standard)"),
2834 options->metadata.save_legacy_IPTC, &c_options->metadata.save_legacy_IPTC);
2836 pref_checkbox_new_int(hbox, _("Warn if the image files are unwritable"),
2837 options->metadata.warn_on_write_problems, &c_options->metadata.warn_on_write_problems);
2839 pref_checkbox_new_int(hbox, _("Ask before writing to image files"),
2840 options->metadata.confirm_write, &c_options->metadata.confirm_write);
2842 pref_checkbox_new_int(hbox, _("Create sidecar files named image.ext.xmp (as opposed to image.xmp)"),
2843 options->metadata.sidecar_extended_name, &c_options->metadata.sidecar_extended_name);
2845 group = pref_group_new(vbox, FALSE, _("Step 2 and 3: write to Geeqie private files"), GTK_ORIENTATION_VERTICAL);
2847 gtk_widget_set_sensitive(group, FALSE);
2850 pref_checkbox_new_int(group, _("Use GQview legacy metadata format (supports only keywords and comments) instead of XMP"),
2851 options->metadata.save_legacy_format, &c_options->metadata.save_legacy_format);
2854 group = pref_group_new(vbox, FALSE, _("Miscellaneous"), GTK_ORIENTATION_VERTICAL);
2855 pref_checkbox_new_int(group, _("Write the same description tags (keywords, comment, etc.) to all grouped sidecars"),
2856 options->metadata.sync_grouped_files, &c_options->metadata.sync_grouped_files);
2858 pref_checkbox_new_int(group, _("Allow keywords to differ only in case"),
2859 options->metadata.keywords_case_sensitive, &c_options->metadata.keywords_case_sensitive);
2861 ct_button = pref_checkbox_new_int(group, _("Write altered image orientation to the metadata"),
2862 options->metadata.write_orientation, &c_options->metadata.write_orientation);
2864 gtk_widget_set_sensitive(ct_button, FALSE);
2867 group = pref_group_new(vbox, FALSE, _("Auto-save options"), GTK_ORIENTATION_VERTICAL);
2869 ct_button = pref_checkbox_new_int(group, _("Write metadata after timeout"),
2870 options->metadata.confirm_after_timeout, &c_options->metadata.confirm_after_timeout);
2872 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
2873 pref_checkbox_link_sensitivity(ct_button, hbox);
2875 pref_spin_new_int(hbox, _("Timeout (seconds):"), NULL, 0, 900, 1,
2876 options->metadata.confirm_timeout, &c_options->metadata.confirm_timeout);
2878 pref_checkbox_new_int(group, _("Write metadata on image change"),
2879 options->metadata.confirm_on_image_change, &c_options->metadata.confirm_on_image_change);
2881 pref_checkbox_new_int(group, _("Write metadata on directory change"),
2882 options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
2884 group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
2886 ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
2887 options->read_metadata_in_idle, &c_options->read_metadata_in_idle);
2888 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");
2893 typedef struct _KeywordFindData KeywordFindData;
2894 struct _KeywordFindData
2901 GtkWidget *button_close;
2902 GtkWidget *button_stop;
2903 GtkWidget *button_start;
2904 GtkWidget *progress;
2912 guint idle_id; /* event source id */
2915 #define KEYWORD_DIALOG_WIDTH 400
2917 static void keywords_find_folder(KeywordFindData *kfd, FileData *dir_fd)
2919 GList *list_d = NULL;
2920 GList *list_f = NULL;
2924 filelist_read(dir_fd, &list_f, &list_d);
2928 filelist_read(dir_fd, &list_f, NULL);
2931 list_f = filelist_filter(list_f, FALSE);
2932 list_d = filelist_filter(list_d, TRUE);
2934 kfd->list = g_list_concat(list_f, kfd->list);
2935 kfd->list_dir = g_list_concat(list_d, kfd->list_dir);
2938 static void keywords_find_reset(KeywordFindData *kfd)
2940 filelist_free(kfd->list);
2943 filelist_free(kfd->list_dir);
2944 kfd->list_dir = NULL;
2947 static void keywords_find_close_cb(GenericDialog *fd, gpointer data)
2949 KeywordFindData *kfd = data;
2951 if (!gtk_widget_get_sensitive(kfd->button_close)) return;
2953 keywords_find_reset(kfd);
2954 generic_dialog_close(kfd->gd);
2958 static void keywords_find_finish(KeywordFindData *kfd)
2960 keywords_find_reset(kfd);
2962 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("done"));
2963 spinner_set_interval(kfd->spinner, -1);
2965 gtk_widget_set_sensitive(kfd->group, TRUE);
2966 gtk_widget_set_sensitive(kfd->button_start, TRUE);
2967 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
2968 gtk_widget_set_sensitive(kfd->button_close, TRUE);
2971 static void keywords_find_stop_cb(GenericDialog *fd, gpointer data)
2973 KeywordFindData *kfd = data;
2975 g_idle_remove_by_data(kfd);
2977 keywords_find_finish(kfd);
2980 static gboolean keywords_find_file(gpointer data)
2982 KeywordFindData *kfd = data;
2984 GtkTextBuffer *buffer;
2992 fd = kfd->list->data;
2993 kfd->list = g_list_remove(kfd->list, fd);
2995 keywords = metadata_read_list(fd, KEYWORD_KEY, METADATA_PLAIN);
2996 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3000 gtk_text_buffer_get_end_iter(buffer, &iter);
3001 tmp = g_strconcat(keywords->data, "\n", NULL);
3002 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3004 keywords = keywords->next;
3007 gtk_entry_set_text(GTK_ENTRY(kfd->progress), fd->path);
3008 file_data_unref(fd);
3009 string_list_free(keywords);
3013 else if (kfd->list_dir)
3017 fd = kfd->list_dir->data;
3018 kfd->list_dir = g_list_remove(kfd->list_dir, fd);
3020 keywords_find_folder(kfd, fd);
3022 file_data_unref(fd);
3027 keywords_find_finish(kfd);
3032 static void keywords_find_start_cb(GenericDialog *fd, gpointer data)
3034 KeywordFindData *kfd = data;
3037 if (kfd->list || !gtk_widget_get_sensitive(kfd->button_start)) return;
3039 path = remove_trailing_slash((gtk_entry_get_text(GTK_ENTRY(kfd->entry))));
3040 parse_out_relatives(path);
3044 warning_dialog(_("Invalid folder"),
3045 _("The specified folder can not be found."),
3046 GTK_STOCK_DIALOG_WARNING, kfd->gd->dialog);
3052 gtk_widget_set_sensitive(kfd->group, FALSE);
3053 gtk_widget_set_sensitive(kfd->button_start, FALSE);
3054 gtk_widget_set_sensitive(kfd->button_stop, TRUE);
3055 gtk_widget_set_sensitive(kfd->button_close, FALSE);
3056 spinner_set_interval(kfd->spinner, SPINNER_SPEED);
3058 dir_fd = file_data_new_dir(path);
3059 keywords_find_folder(kfd, dir_fd);
3060 file_data_unref(dir_fd);
3061 kfd->idle_id = g_idle_add(keywords_find_file, kfd);
3067 static void keywords_find_dialog(GtkWidget *widget, const gchar *path)
3069 KeywordFindData *kfd;
3073 kfd = g_new0(KeywordFindData, 1);
3075 kfd->gd = generic_dialog_new(_("Search for keywords"),
3076 "search_for_keywords",
3079 gtk_window_set_default_size(GTK_WINDOW(kfd->gd->dialog), KEYWORD_DIALOG_WIDTH, -1);
3080 kfd->gd->cancel_cb = keywords_find_close_cb;
3081 kfd->button_close = generic_dialog_add_button(kfd->gd, GTK_STOCK_CLOSE, NULL,
3082 keywords_find_close_cb, FALSE);
3083 kfd->button_start = generic_dialog_add_button(kfd->gd, GTK_STOCK_OK, _("S_tart"),
3084 keywords_find_start_cb, FALSE);
3085 kfd->button_stop = generic_dialog_add_button(kfd->gd, GTK_STOCK_STOP, NULL,
3086 keywords_find_stop_cb, FALSE);
3087 gtk_widget_set_sensitive(kfd->button_stop, FALSE);
3089 generic_dialog_add_message(kfd->gd, NULL, _("Search for keywords"), NULL, FALSE);
3091 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, 0);
3092 pref_spacer(hbox, PREF_PAD_INDENT);
3093 kfd->group = pref_box_new(hbox, TRUE, GTK_ORIENTATION_VERTICAL, PREF_PAD_GAP);
3095 hbox = pref_box_new(kfd->group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3096 pref_label_new(hbox, _("Folder:"));
3098 label = tab_completion_new(&kfd->entry, path, NULL, NULL, NULL, NULL);
3099 tab_completion_add_select_button(kfd->entry,_("Select folder") , TRUE);
3100 gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
3101 gtk_widget_show(label);
3103 pref_checkbox_new_int(kfd->group, _("Include subfolders"), FALSE, &kfd->recurse);
3105 pref_line(kfd->gd->vbox, PREF_PAD_SPACE);
3106 hbox = pref_box_new(kfd->gd->vbox, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3108 kfd->progress = gtk_entry_new();
3109 gtk_widget_set_can_focus(kfd->progress, FALSE);
3110 gtk_editable_set_editable(GTK_EDITABLE(kfd->progress), FALSE);
3111 gtk_entry_set_text(GTK_ENTRY(kfd->progress), _("click start to begin"));
3112 gtk_box_pack_start(GTK_BOX(hbox), kfd->progress, TRUE, TRUE, 0);
3113 gtk_widget_show(kfd->progress);
3115 kfd->spinner = spinner_new(NULL, -1);
3116 gtk_box_pack_start(GTK_BOX(hbox), kfd->spinner, FALSE, FALSE, 0);
3117 gtk_widget_show(kfd->spinner);
3121 gtk_widget_show(kfd->gd->dialog);
3124 static void keywords_find_cb(GtkWidget *widget, gpointer data)
3126 const gchar *path = layout_get_path(NULL);
3128 if (!path || !*path) path = homedir();
3129 keywords_find_dialog(widget, path);
3132 static void config_tab_keywords_save()
3134 GtkTextIter start, end;
3135 GtkTextBuffer *buffer;
3136 GList *kw_list = NULL;
3142 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3143 gtk_text_buffer_get_bounds(buffer, &start, &end);
3145 buffer_text = gtk_text_buffer_get_text(buffer, &start, &end, FALSE);
3147 kw_split = strtok(buffer_text, "\n");
3148 while (kw_split != NULL)
3154 if (g_strcmp0(work->data, kw_split) == 0)
3163 kw_list = g_list_append(kw_list, g_strdup(kw_split));
3165 kw_split = strtok(NULL, "\n");
3168 keyword_list_set(kw_list);
3170 string_list_free(kw_list);
3171 g_free(buffer_text);
3174 static void config_tab_keywords(GtkWidget *notebook)
3180 GtkWidget *scrolled;
3182 GtkTextBuffer *buffer;
3185 vbox = scrolled_notebook_page(notebook, _("Keywords"));
3187 group = pref_group_new(vbox, TRUE, _("Edit keywords autocompletion list"), GTK_ORIENTATION_VERTICAL);
3189 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3191 button = pref_button_new(hbox, GTK_STOCK_EXECUTE, _("Search"), FALSE,
3192 G_CALLBACK(keywords_find_cb), keyword_text);
3193 gtk_widget_set_tooltip_text(button, "Search for existing keywords");
3196 keyword_text = gtk_text_view_new();
3197 gtk_widget_set_size_request(keyword_text, 20, 20);
3198 scrolled = gtk_scrolled_window_new(NULL, NULL);
3199 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3200 gtk_widget_show(scrolled);
3202 gtk_container_add(GTK_CONTAINER(scrolled), keyword_text);
3203 gtk_widget_show(keyword_text);
3205 gtk_text_view_set_editable(GTK_TEXT_VIEW(keyword_text), TRUE);
3207 buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(keyword_text));
3208 gtk_text_buffer_create_tag(buffer, "monospace",
3209 "family", "monospace", NULL);
3211 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(keyword_text), GTK_WRAP_WORD);
3212 gtk_text_buffer_get_start_iter(buffer, &iter);
3213 gtk_text_buffer_create_mark(buffer, "end", &iter, FALSE);
3216 path = g_build_filename(get_rc_dir(), "keywords", NULL);
3218 GList *kwl = keyword_list_get();
3219 kwl = g_list_first(kwl);
3222 gtk_text_buffer_get_end_iter (buffer, &iter);
3223 tmp = g_strconcat(kwl->data, "\n", NULL);
3224 gtk_text_buffer_insert(buffer, &iter, tmp, -1);
3229 gtk_text_buffer_set_modified(buffer, FALSE);
3236 static void intent_menu_cb(GtkWidget *combo, gpointer data)
3238 gint *option = data;
3240 switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
3244 *option = INTENT_PERCEPTUAL;
3247 *option = INTENT_RELATIVE_COLORIMETRIC;
3250 *option = INTENT_SATURATION;
3253 *option = INTENT_ABSOLUTE_COLORIMETRIC;
3258 static void add_intent_menu(GtkWidget *table, gint column, gint row, const gchar *text,
3259 gint option, gint *option_c)
3266 pref_table_label(table, column, row, text, 0.0);
3268 combo = gtk_combo_box_text_new();
3270 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Perceptual"));
3271 if (option == INTENT_PERCEPTUAL) current = 0;
3272 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Relative Colorimetric"));
3273 if (option == INTENT_RELATIVE_COLORIMETRIC) current = 1;
3274 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Saturation"));
3275 if (option == INTENT_SATURATION) current = 2;
3276 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Absolute Colorimetric"));
3277 if (option == INTENT_ABSOLUTE_COLORIMETRIC) current = 3;
3279 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
3281 gtk_widget_set_tooltip_text(combo,"Refer to the lcms documentation for the defaults used when the selected Intent is not available");
3283 g_signal_connect(G_OBJECT(combo), "changed",
3284 G_CALLBACK(intent_menu_cb), option_c);
3286 gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
3287 gtk_widget_show(combo);
3291 static void config_tab_color(GtkWidget *notebook)
3300 vbox = scrolled_notebook_page(notebook, _("Color management"));
3302 group = pref_group_new(vbox, FALSE, _("Input profiles"), GTK_ORIENTATION_VERTICAL);
3304 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3307 table = pref_table_new(group, 3, COLOR_PROFILE_INPUTS + 1, FALSE, FALSE);
3308 gtk_table_set_col_spacings(GTK_TABLE(table), PREF_PAD_GAP);
3310 label = pref_table_label(table, 0, 0, _("Type"), 0.0);
3311 pref_label_bold(label, TRUE, FALSE);
3313 label = pref_table_label(table, 1, 0, _("Menu name"), 0.0);
3314 pref_label_bold(label, TRUE, FALSE);
3316 label = pref_table_label(table, 2, 0, _("File"), 0.0);
3317 pref_label_bold(label, TRUE, FALSE);
3319 for (i = 0; i < COLOR_PROFILE_INPUTS; i++)
3324 buf = g_strdup_printf(_("Input %d:"), i + COLOR_PROFILE_FILE);
3325 pref_table_label(table, 0, i + 1, buf, 1.0);
3328 entry = gtk_entry_new();
3329 gtk_entry_set_max_length(GTK_ENTRY(entry), EDITOR_NAME_MAX_LENGTH);
3330 if (options->color_profile.input_name[i])
3332 gtk_entry_set_text(GTK_ENTRY(entry), options->color_profile.input_name[i]);
3334 gtk_table_attach(GTK_TABLE(table), entry, 1, 2, i + 1, i + 2,
3335 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3336 gtk_widget_show(entry);
3337 color_profile_input_name_entry[i] = entry;
3339 tabcomp = tab_completion_new(&entry, options->color_profile.input_file[i], NULL, ".icc", "ICC Files", NULL);
3340 tab_completion_add_select_button(entry, _("Select color profile"), FALSE);
3341 gtk_widget_set_size_request(entry, 160, -1);
3342 gtk_table_attach(GTK_TABLE(table), tabcomp, 2, 3, i + 1, i + 2,
3343 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3344 gtk_widget_show(tabcomp);
3345 color_profile_input_file_entry[i] = entry;
3348 group = pref_group_new(vbox, FALSE, _("Screen profile"), GTK_ORIENTATION_VERTICAL);
3350 gtk_widget_set_sensitive(pref_group_parent(group), FALSE);
3352 pref_checkbox_new_int(group, _("Use system screen profile if available"),
3353 options->color_profile.use_x11_screen_profile, &c_options->color_profile.use_x11_screen_profile);
3355 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3357 pref_table_label(table, 0, 0, _("Screen:"), 1.0);
3358 tabcomp = tab_completion_new(&color_profile_screen_file_entry,
3359 options->color_profile.screen_file, NULL, ".icc", "ICC Files", NULL);
3360 tab_completion_add_select_button(color_profile_screen_file_entry, _("Select color profile"), FALSE);
3361 gtk_widget_set_size_request(color_profile_screen_file_entry, 160, -1);
3363 add_intent_menu(table, 0, 1, _("Render Intent:"), options->color_profile.render_intent, &c_options->color_profile.render_intent);
3365 gtk_table_attach(GTK_TABLE(table), tabcomp, 1, 2,
3367 GTK_FILL | GTK_EXPAND, 0, 0, 0);
3369 gtk_widget_show(tabcomp);
3372 /* advanced entry tab */
3373 static void use_geeqie_trash_cb(GtkWidget *widget, gpointer data)
3375 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3377 c_options->file_ops.use_system_trash = FALSE;
3378 c_options->file_ops.no_trash = FALSE;
3382 static void use_system_trash_cb(GtkWidget *widget, gpointer data)
3384 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3386 c_options->file_ops.use_system_trash = TRUE;
3387 c_options->file_ops.no_trash = FALSE;
3391 static void use_no_cache_cb(GtkWidget *widget, gpointer data)
3393 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
3395 c_options->file_ops.no_trash = TRUE;
3399 static void config_tab_behavior(GtkWidget *notebook)
3406 GtkWidget *ct_button;
3410 GtkWidget *with_rename;
3411 GtkWidget *collections_on_top;
3412 GtkWidget *hide_window_in_fullscreen;
3413 GtkWidget *checkbox;
3416 vbox = scrolled_notebook_page(notebook, _("Behavior"));
3418 group = pref_group_new(vbox, FALSE, _("Delete"), GTK_ORIENTATION_VERTICAL);
3420 pref_checkbox_new_int(group, _("Confirm permanent file delete"),
3421 options->file_ops.confirm_delete, &c_options->file_ops.confirm_delete);
3422 pref_checkbox_new_int(group, _("Confirm move file to Trash"),
3423 options->file_ops.confirm_move_to_trash, &c_options->file_ops.confirm_move_to_trash);
3424 pref_checkbox_new_int(group, _("Enable Delete key"),
3425 options->file_ops.enable_delete_key, &c_options->file_ops.enable_delete_key);
3427 ct_button = pref_radiobutton_new(group, NULL, _("Use Geeqie trash location"),
3428 !options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_geeqie_trash_cb),NULL);
3430 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
3431 pref_checkbox_link_sensitivity(ct_button, hbox);
3433 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_SPACE);
3434 pref_label_new(hbox, _("Folder:"));
3436 tabcomp = tab_completion_new(&safe_delete_path_entry, options->file_ops.safe_delete_path, NULL, NULL, NULL, NULL);
3437 tab_completion_add_select_button(safe_delete_path_entry, NULL, TRUE);
3438 gtk_box_pack_start(GTK_BOX(hbox), tabcomp, TRUE, TRUE, 0);
3439 gtk_widget_show(tabcomp);
3441 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3442 pref_checkbox_link_sensitivity(ct_button, hbox);
3444 pref_spacer(hbox, PREF_PAD_INDENT - PREF_PAD_GAP);
3445 spin = pref_spin_new_int(hbox, _("Maximum size:"), _("MiB"),
3446 0, 2048, 1, options->file_ops.safe_delete_folder_maxsize, &c_options->file_ops.safe_delete_folder_maxsize);
3447 gtk_widget_set_tooltip_markup(spin, _("Set to 0 for unlimited size"));
3448 button = pref_button_new(NULL, NULL, _("View"), FALSE,
3449 G_CALLBACK(safe_delete_view_cb), NULL);
3450 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3451 gtk_widget_show(button);
3453 button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
3454 G_CALLBACK(safe_delete_clear_cb), NULL);
3455 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3456 pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
3457 options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
3459 pref_radiobutton_new(group, ct_button, _("Use no trash at all"),
3460 options->file_ops.no_trash, G_CALLBACK(use_no_cache_cb), NULL);
3462 gtk_widget_show(button);
3464 pref_spacer(group, PREF_PAD_GROUP);
3467 group = pref_group_new(vbox, FALSE, _("Behavior"), GTK_ORIENTATION_VERTICAL);
3469 pref_checkbox_new_int(group, _("Descend folders in tree view"),
3470 options->tree_descend_subdirs, &c_options->tree_descend_subdirs);
3472 pref_checkbox_new_int(group, _("In place renaming"),
3473 options->file_ops.enable_in_place_rename, &c_options->file_ops.enable_in_place_rename);
3475 pref_checkbox_new_int(group, _("List directory view uses single click to enter"),
3476 options->view_dir_list_single_click_enter, &c_options->view_dir_list_single_click_enter);
3478 tmp = pref_checkbox_new_int(group, _("Circular selection lists"),
3479 options->circular_selection_lists, &c_options->circular_selection_lists);
3480 gtk_widget_set_tooltip_text(tmp, _("Traverse selection lists in a circular manner"));
3482 marks = pref_checkbox_new_int(group, _("Save marks on exit"),
3483 options->marks_save, &c_options->marks_save);
3484 gtk_widget_set_tooltip_text(marks,"Note that marks linked to a keyword will be saved irrespective of this setting");
3486 with_rename = pref_checkbox_new_int(group, _("Use \"With Rename\" as default for Copy/Move dialogs"),
3487 options->with_rename, &c_options->with_rename);
3488 gtk_widget_set_tooltip_text(with_rename,"Change the default button for Copy/Move dialogs");
3490 collections_on_top = pref_checkbox_new_int(group, _("Open collections on top"),
3491 options->collections_on_top, &c_options->collections_on_top);
3492 gtk_widget_set_tooltip_text(collections_on_top,"Open collections window on top");
3494 hide_window_in_fullscreen = pref_checkbox_new_int(group, _("Hide window in fullscreen"),
3495 options->hide_window_in_fullscreen, &c_options->hide_window_in_fullscreen);
3496 gtk_widget_set_tooltip_text(hide_window_in_fullscreen,"When alt-tabbing, prevent Geeqie window showing twice");
3498 pref_spin_new_int(group, _("Recent folder list maximum size"), NULL,
3499 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize);
3501 pref_spin_new_int(group, _("Drag'n drop icon size"), NULL,
3502 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size);
3504 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3505 add_dnd_default_action_selection_menu(table, 0, 0, _("Drag`n drop default action:"), options->dnd_default_action, &c_options->dnd_default_action);
3507 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3508 add_clipboard_selection_menu(table, 0, 0, _("Copy path clipboard selection:"), options->clipboard_selection, &c_options->clipboard_selection);
3510 pref_spacer(group, PREF_PAD_GROUP);
3512 group = pref_group_new(vbox, FALSE, _("Navigation"), GTK_ORIENTATION_VERTICAL);
3514 pref_checkbox_new_int(group, _("Progressive keyboard scrolling"),
3515 options->progressive_key_scrolling, &c_options->progressive_key_scrolling);
3516 pref_spin_new_int(group, _("Keyboard scrolling step multiplier:"), NULL,
3517 1, 32, 1, options->keyboard_scroll_step, (int *)&c_options->keyboard_scroll_step);
3518 pref_checkbox_new_int(group, _("Mouse wheel scrolls image"),
3519 options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
3520 pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
3521 options->image_lm_click_nav, &c_options->image_lm_click_nav);
3522 pref_checkbox_new_int(group, _("Open archive by left click on image"),
3523 options->image_l_click_archive, &c_options->image_l_click_archive);
3524 pref_checkbox_new_int(group, _("Play video by left click on image"),
3525 options->image_l_click_video, &c_options->image_l_click_video);
3526 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3527 add_video_menu(table, 0, 0, _("Play with:"), options->image_l_click_video_editor, &c_options->image_l_click_video_editor);
3529 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3530 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3531 add_mouse_selection_menu(table, 0, 0, _("Mouse button Back:"), options->mouse_button_8, &c_options->mouse_button_8);
3532 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3533 add_mouse_selection_menu(table, 0, 0, _("Mouse button Forward:"), options->mouse_button_9, &c_options->mouse_button_9);
3535 pref_spacer(group, PREF_PAD_GROUP);
3537 group = pref_group_new(vbox, FALSE, _("GPU"), GTK_ORIENTATION_VERTICAL);
3539 checkbox = pref_checkbox_new_int(group, _("Override disable GPU"),
3540 options->override_disable_gpu, &c_options->override_disable_gpu);
3541 gtk_widget_set_tooltip_text(checkbox, "Contact the developers for usage");
3544 pref_spacer(group, PREF_PAD_GROUP);
3546 group = pref_group_new(vbox, FALSE, _("Debugging"), GTK_ORIENTATION_VERTICAL);
3548 pref_spin_new_int(group, _("Debug level:"), NULL,
3549 DEBUG_LEVEL_MIN, DEBUG_LEVEL_MAX, 1, get_debug_level(), &debug_c);
3551 pref_checkbox_new_int(group, _("Timer data"),
3552 options->log_window.timer_data, &c_options->log_window.timer_data);
3554 pref_spin_new_int(group, _("Log Window max. lines:"), NULL,
3555 1, 99999, 1, options->log_window_lines, &options->log_window_lines);
3559 /* accelerators tab */
3560 static void config_tab_accelerators(GtkWidget *notebook)
3566 GtkWidget *scrolled;
3567 GtkWidget *accel_view;
3568 GtkCellRenderer *renderer;
3569 GtkTreeSelection *selection;
3570 GtkTreeViewColumn *column;
3572 vbox = scrolled_notebook_page(notebook, _("Keyboard"));
3574 group = pref_group_new(vbox, TRUE, _("Accelerators"), GTK_ORIENTATION_VERTICAL);
3576 scrolled = gtk_scrolled_window_new(NULL, NULL);
3577 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled), GTK_SHADOW_IN);
3578 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
3579 gtk_box_pack_start(GTK_BOX(group), scrolled, TRUE, TRUE, 0);
3580 gtk_widget_show(scrolled);
3582 accel_store = gtk_tree_store_new(4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
3584 accel_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(accel_store));
3585 g_object_unref(accel_store);
3586 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(accel_view));
3587 gtk_tree_selection_set_mode(GTK_TREE_SELECTION(selection), GTK_SELECTION_MULTIPLE);
3589 gtk_tree_view_set_enable_search(GTK_TREE_VIEW(accel_view), FALSE);
3591 renderer = gtk_cell_renderer_text_new();
3593 column = gtk_tree_view_column_new_with_attributes(_("Action"),
3598 gtk_tree_view_column_set_sort_column_id(column, AE_ACTION);
3599 gtk_tree_view_column_set_resizable(column, TRUE);
3600 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3603 renderer = gtk_cell_renderer_accel_new();
3604 g_signal_connect(G_OBJECT(renderer), "accel-cleared",
3605 G_CALLBACK(accel_store_cleared_cb), accel_store);
3606 g_signal_connect(G_OBJECT(renderer), "accel-edited",
3607 G_CALLBACK(accel_store_edited_cb), accel_store);
3610 g_object_set (renderer,
3612 "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
3615 column = gtk_tree_view_column_new_with_attributes(_("KEY"),
3620 gtk_tree_view_column_set_sort_column_id(column, AE_KEY);
3621 gtk_tree_view_column_set_resizable(column, TRUE);
3622 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3624 renderer = gtk_cell_renderer_text_new();
3626 column = gtk_tree_view_column_new_with_attributes(_("Tooltip"),
3631 gtk_tree_view_column_set_sort_column_id(column, AE_TOOLTIP);
3632 gtk_tree_view_column_set_resizable(column, TRUE);
3633 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3635 renderer = gtk_cell_renderer_text_new();
3637 column = gtk_tree_view_column_new_with_attributes("Accel",
3642 gtk_tree_view_column_set_sort_column_id(column, AE_ACCEL);
3643 gtk_tree_view_column_set_resizable(column, TRUE);
3644 gtk_tree_view_append_column(GTK_TREE_VIEW(accel_view), column);
3646 accel_store_populate();
3647 gtk_container_add(GTK_CONTAINER(scrolled), accel_view);
3648 gtk_widget_show(accel_view);
3650 hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_BUTTON_GAP);
3652 button = pref_button_new(NULL, NULL, _("Defaults"), FALSE,
3653 G_CALLBACK(accel_default_cb), accel_view);
3654 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3655 gtk_widget_show(button);
3657 button = pref_button_new(NULL, NULL, _("Reset selected"), FALSE,
3658 G_CALLBACK(accel_reset_cb), accel_view);
3659 gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
3660 gtk_widget_show(button);
3663 /* toolbar main tab */
3664 static void config_tab_toolbar_main(GtkWidget *notebook)
3667 GtkWidget *toolbardata;
3670 lw = layout_window_list->data;
3672 vbox = scrolled_notebook_page(notebook, _("Toolbar Main"));
3674 toolbardata = toolbar_select_new(lw, TOOLBAR_MAIN);
3675 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3676 gtk_widget_show(vbox);
3679 /* toolbar status tab */
3680 static void config_tab_toolbar_status(GtkWidget *notebook)
3683 GtkWidget *toolbardata;
3686 lw = layout_window_list->data;
3688 vbox = scrolled_notebook_page(notebook, _("Toolbar Status"));
3690 toolbardata = toolbar_select_new(lw, TOOLBAR_STATUS);
3691 gtk_box_pack_start(GTK_BOX(vbox), toolbardata, TRUE, TRUE, 0);
3692 gtk_widget_show(vbox);
3696 static gint extension_sort_cb(gconstpointer a, gconstpointer b)
3698 return g_strcmp0((gchar *)a, (gchar *)b);
3701 static void config_tab_advanced(GtkWidget *notebook)
3705 GSList *formats_list;
3706 GList *extensions_list = NULL;
3709 GdkPixbufFormat *fm;
3711 GString *types_string = g_string_new(NULL);
3712 GtkWidget *types_string_label;
3713 GtkWidget *threads_string_label;
3714 GtkWidget *dupes_threads_spin;
3716 vbox = scrolled_notebook_page(notebook, _("Advanced"));
3717 group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
3719 pref_checkbox_new_int(group, _("Use external preview extraction - Requires restart"), options->external_preview.enable, &c_options->external_preview.enable);
3721 pref_spacer(group, PREF_PAD_GROUP);
3723 formats_list = gdk_pixbuf_get_formats();
3725 while (formats_list)
3727 fm = formats_list->data;
3728 extensions = gdk_pixbuf_format_get_extensions(fm);
3731 while (extensions[i])
3733 extensions_list = g_list_insert_sorted(extensions_list, g_strdup(extensions[i]), extension_sort_cb);
3737 g_strfreev(extensions);
3738 formats_list = formats_list->next;
3741 while (extensions_list)
3743 if (types_string->len == 0)
3745 types_string = g_string_append(types_string, extensions_list->data);
3749 types_string = g_string_append(types_string, ", ");
3750 types_string = g_string_append(types_string, extensions_list->data);
3753 extensions_list = extensions_list->next;
3756 types_string = g_string_prepend(types_string, _("Usable file types:\n"));
3757 types_string_label = pref_label_new(group, types_string->str);
3758 gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
3760 pref_spacer(group, PREF_PAD_GROUP);
3762 group = pref_group_new(vbox, FALSE, _("File identification tool"), GTK_ORIENTATION_VERTICAL);
3763 external_preview_select_entry = gtk_entry_new();
3764 tabcomp = tab_completion_new(&external_preview_select_entry, options->external_preview.select, NULL, NULL, NULL, NULL);
3765 tab_completion_add_select_button(external_preview_select_entry, _("Select file identification tool"), FALSE);
3766 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3767 gtk_widget_show(tabcomp);
3769 group = pref_group_new(vbox, FALSE, _("Preview extraction tool"), GTK_ORIENTATION_VERTICAL);
3770 external_preview_extract_entry = gtk_entry_new();
3771 tabcomp = tab_completion_new(&external_preview_extract_entry, options->external_preview.extract, NULL, NULL, NULL, NULL);
3772 tab_completion_add_select_button(external_preview_extract_entry, _("Select preview extraction tool"), FALSE);
3773 gtk_box_pack_start(GTK_BOX(group), tabcomp, TRUE, TRUE, 0);
3774 gtk_widget_show(tabcomp);
3776 gtk_widget_show(vbox);
3778 g_slist_free(formats_list);
3779 string_list_free(extensions_list);
3780 g_string_free(types_string, TRUE);
3782 pref_spacer(group, PREF_PAD_GROUP);
3784 pref_line(vbox, PREF_PAD_SPACE);
3785 group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
3787 threads_string_label = pref_label_new(group, "This option limits the number of threads (or cpu cores)\nthat Geeqie will use when running duplicate checks. The default value is 0, which means all available cores will be used.");
3788 gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
3790 pref_spacer(vbox, PREF_PAD_GROUP);
3792 dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
3793 gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
3797 static void config_tab_stereo(GtkWidget *notebook)
3805 GtkWidget *fs_button;
3806 vbox = scrolled_notebook_page(notebook, _("Stereo"));
3808 group = pref_group_new(vbox, FALSE, _("Windowed stereo mode"), GTK_ORIENTATION_VERTICAL);
3810 table = pref_table_new(group, 2, 1, FALSE, FALSE);
3811 add_stereo_mode_menu(table, 0, 0, _("Windowed stereo mode"), options->stereo.mode, &c_options->stereo.mode, FALSE);
3813 table = pref_table_new(group, 2, 2, TRUE, FALSE);
3814 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3815 pref_checkbox_new_int(box, _("Mirror left image"),
3816 options->stereo.mode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.mirror_left);
3817 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3818 pref_checkbox_new_int(box, _("Flip left image"),
3819 options->stereo.mode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.flip_left);
3820 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3821 pref_checkbox_new_int(box, _("Mirror right image"),
3822 options->stereo.mode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.mirror_right);
3823 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3824 pref_checkbox_new_int(box, _("Flip right image"),
3825 options->stereo.mode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.flip_right);
3826 pref_checkbox_new_int(group, _("Swap left and right images"),
3827 options->stereo.mode & PR_STEREO_SWAP, &c_options->stereo.tmp.swap);
3828 pref_checkbox_new_int(group, _("Disable stereo mode on single image source"),
3829 options->stereo.mode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.temp_disable);
3831 group = pref_group_new(vbox, FALSE, _("Fullscreen stereo mode"), GTK_ORIENTATION_VERTICAL);
3832 fs_button = pref_checkbox_new_int(group, _("Use different settings for fullscreen"),
3833 options->stereo.enable_fsmode, &c_options->stereo.enable_fsmode);
3834 box2 = pref_box_new(group, FALSE, GTK_ORIENTATION_VERTICAL, PREF_PAD_SPACE);
3835 pref_checkbox_link_sensitivity(fs_button, box2);
3836 table = pref_table_new(box2, 2, 1, FALSE, FALSE);
3837 add_stereo_mode_menu(table, 0, 0, _("Fullscreen stereo mode"), options->stereo.fsmode, &c_options->stereo.fsmode, TRUE);
3838 table = pref_table_new(box2, 2, 2, TRUE, FALSE);
3839 box = pref_table_box(table, 0, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3840 pref_checkbox_new_int(box, _("Mirror left image"),
3841 options->stereo.fsmode & PR_STEREO_MIRROR_LEFT, &c_options->stereo.tmp.fs_mirror_left);
3842 box = pref_table_box(table, 1, 0, GTK_ORIENTATION_HORIZONTAL, NULL);
3843 pref_checkbox_new_int(box, _("Flip left image"),
3844 options->stereo.fsmode & PR_STEREO_FLIP_LEFT, &c_options->stereo.tmp.fs_flip_left);
3845 box = pref_table_box(table, 0, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3846 pref_checkbox_new_int(box, _("Mirror right image"),
3847 options->stereo.fsmode & PR_STEREO_MIRROR_RIGHT, &c_options->stereo.tmp.fs_mirror_right);
3848 box = pref_table_box(table, 1, 1, GTK_ORIENTATION_HORIZONTAL, NULL);
3849 pref_checkbox_new_int(box, _("Flip right image"),
3850 options->stereo.fsmode & PR_STEREO_FLIP_RIGHT, &c_options->stereo.tmp.fs_flip_right);
3851 pref_checkbox_new_int(box2, _("Swap left and right images"),
3852 options->stereo.fsmode & PR_STEREO_SWAP, &c_options->stereo.tmp.fs_swap);
3853 pref_checkbox_new_int(box2, _("Disable stereo mode on single image source"),
3854 options->stereo.fsmode & PR_STEREO_TEMP_DISABLE, &c_options->stereo.tmp.fs_temp_disable);
3856 group2 = pref_group_new(box2, FALSE, _("Fixed position"), GTK_ORIENTATION_VERTICAL);
3857 table = pref_table_new(group2, 5, 3, FALSE, FALSE);
3858 pref_table_spin_new_int(table, 0, 0, _("Width"), NULL,
3859 1, 5000, 1, options->stereo.fixed_w, &c_options->stereo.fixed_w);
3860 pref_table_spin_new_int(table, 3, 0, _("Height"), NULL,
3861 1, 5000, 1, options->stereo.fixed_h, &c_options->stereo.fixed_h);
3862 pref_table_spin_new_int(table, 0, 1, _("Left X"), NULL,
3863 0, 5000, 1, options->stereo.fixed_x1, &c_options->stereo.fixed_x1);
3864 pref_table_spin_new_int(table, 3, 1, _("Left Y"), NULL,
3865 0, 5000, 1, options->stereo.fixed_y1, &c_options->stereo.fixed_y1);
3866 pref_table_spin_new_int(table, 0, 2, _("Right X"), NULL,
3867 0, 5000, 1, options->stereo.fixed_x2, &c_options->stereo.fixed_x2);
3868 pref_table_spin_new_int(table, 3, 2, _("Right Y"), NULL,
3869 0, 5000, 1, options->stereo.fixed_y2, &c_options->stereo.fixed_y2);
3873 /* Main preferences window */
3874 static void config_window_create(LayoutWindow *lw)
3876 GtkWidget *win_vbox;
3878 GtkWidget *notebook;
3880 GtkWidget *ct_button;
3882 if (!c_options) c_options = init_options(NULL);
3884 configwindow = window_new(GTK_WINDOW_TOPLEVEL, "preferences", PIXBUF_INLINE_ICON_CONFIG, NULL, _("Preferences"));
3885 DEBUG_NAME(configwindow);
3886 gtk_window_set_type_hint(GTK_WINDOW(configwindow), GDK_WINDOW_TYPE_HINT_DIALOG);
3887 g_signal_connect(G_OBJECT(configwindow), "delete_event",
3888 G_CALLBACK(config_window_delete), NULL);
3889 if (options->save_dialog_window_positions)
3891 gtk_window_resize(GTK_WINDOW(configwindow), lw->options.preferences_window.w, lw->options.preferences_window.h);
3892 gtk_window_move(GTK_WINDOW(configwindow), lw->options.preferences_window.x, lw->options.preferences_window.y);
3896 gtk_window_set_default_size(GTK_WINDOW(configwindow), CONFIG_WINDOW_DEF_WIDTH, CONFIG_WINDOW_DEF_HEIGHT);
3898 gtk_window_set_resizable(GTK_WINDOW(configwindow), TRUE);
3899 gtk_container_set_border_width(GTK_CONTAINER(configwindow), PREF_PAD_BORDER);
3901 win_vbox = gtk_vbox_new(FALSE, PREF_PAD_SPACE);
3902 gtk_container_add(GTK_CONTAINER(configwindow), win_vbox);
3903 gtk_widget_show(win_vbox);
3905 notebook = gtk_notebook_new();
3906 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook), GTK_POS_LEFT);
3907 gtk_notebook_set_scrollable(GTK_NOTEBOOK(notebook), TRUE);
3908 gtk_box_pack_start(GTK_BOX(win_vbox), notebook, TRUE, TRUE, 0);
3910 config_tab_general(notebook);
3911 config_tab_image(notebook);
3912 config_tab_osd(notebook);
3913 config_tab_windows(notebook);
3914 config_tab_accelerators(notebook);
3915 config_tab_files(notebook);
3916 config_tab_metadata(notebook);
3917 config_tab_keywords(notebook);
3918 config_tab_color(notebook);
3919 config_tab_stereo(notebook);
3920 config_tab_behavior(notebook);
3921 config_tab_toolbar_main(notebook);
3922 config_tab_toolbar_status(notebook);
3923 config_tab_advanced(notebook);
3925 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), lw->options.preferences_window.page_number);
3927 hbox = gtk_hbutton_box_new();
3928 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbox), GTK_BUTTONBOX_END);
3929 gtk_box_set_spacing(GTK_BOX(hbox), PREF_PAD_BUTTON_GAP);
3930 gtk_box_pack_end(GTK_BOX(win_vbox), hbox, FALSE, FALSE, 0);
3931 gtk_widget_show(hbox);
3933 button = pref_button_new(NULL, GTK_STOCK_HELP, NULL, FALSE,
3934 G_CALLBACK(config_window_help_cb), notebook);
3935 gtk_container_add(GTK_CONTAINER(hbox), button);
3936 gtk_widget_set_can_default(button, TRUE);
3937 gtk_widget_show(button);
3939 button = pref_button_new(NULL, GTK_STOCK_OK, NULL, FALSE,
3940 G_CALLBACK(config_window_ok_cb), notebook);
3941 gtk_container_add(GTK_CONTAINER(hbox), button);
3942 gtk_widget_set_can_default(button, TRUE);
3943 gtk_widget_grab_default(button);
3944 gtk_widget_show(button);
3948 button = pref_button_new(NULL, GTK_STOCK_CANCEL, NULL, FALSE,
3949 G_CALLBACK(config_window_close_cb), NULL);
3950 gtk_container_add(GTK_CONTAINER(hbox), button);
3951 gtk_widget_set_can_default(button, TRUE);
3952 gtk_widget_show(button);
3954 if (!generic_dialog_get_alternative_button_order(configwindow))
3956 gtk_box_reorder_child(GTK_BOX(hbox), ct_button, -1);
3959 gtk_widget_show(notebook);
3961 gtk_widget_show(configwindow);
3965 *-----------------------------------------------------------------------------
3966 * config window show (public)
3967 *-----------------------------------------------------------------------------
3970 void show_config_window(LayoutWindow *lw)
3974 gtk_window_present(GTK_WINDOW(configwindow));
3978 config_window_create(lw);
3987 void show_about_window(LayoutWindow *lw)
3989 GdkPixbuf *pixbuf_logo;
3990 GdkPixbuf *pixbuf_icon;
3991 gchar *authors[1000];
3996 gchar *timezone_path;
4000 #define LINE_LENGTH 1000
4001 gchar line[LINE_LENGTH];
4003 copyright = g_string_new(NULL);
4004 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");
4006 path = path_from_utf8(TIMEZONE_DATABASE);
4007 basename = g_path_get_basename(path);
4008 timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
4009 if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
4011 cd = ZDOpenDatabase(timezone_path);
4014 copyright = g_string_append(copyright, ZDGetNotice(cd));
4015 ZDCloseDatabase(cd);
4019 g_free(timezone_path);
4023 path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
4024 fp = fopen(path, "r");
4027 while(fgets(line, LINE_LENGTH, fp))
4029 /* get rid of ending \n from fgets */
4030 line[strlen(line) - 1] = '\0';
4031 authors[i_authors] = g_strdup(line);
4034 authors[i_authors] = NULL;
4039 comment = g_strconcat("Development and bug reports:\n", GQ_EMAIL_ADDRESS,
4040 "\nhttps://github.com/BestImageViewer/geeqie/issues",NULL);
4042 pixbuf_logo = pixbuf_inline(PIXBUF_INLINE_LOGO);
4043 pixbuf_icon = pixbuf_inline(PIXBUF_INLINE_ICON);
4044 gtk_show_about_dialog(GTK_WINDOW(lw->window),
4045 "title", _("About Geeqie"),
4047 "program-name", GQ_APPNAME,
4049 "logo", pixbuf_logo,
4050 "icon", pixbuf_icon,
4051 "website", GQ_WEBSITE,
4052 "website-label", "Website",
4053 "comments", comment,
4055 "translator-credits", _("translator-credits"),
4056 "wrap-license", TRUE,
4057 "license", copyright->str,
4060 g_string_free(copyright, TRUE);
4063 while(n < i_authors)
4073 static void image_overlay_set_text_colours()
4075 c_options->image_overlay.text_red = options->image_overlay.text_red;
4076 c_options->image_overlay.text_green = options->image_overlay.text_green;
4077 c_options->image_overlay.text_blue = options->image_overlay.text_blue;
4078 c_options->image_overlay.text_alpha = options->image_overlay.text_alpha;
4079 c_options->image_overlay.background_red = options->image_overlay.background_red;
4080 c_options->image_overlay.background_green = options->image_overlay.background_green;
4081 c_options->image_overlay.background_blue = options->image_overlay.background_blue;
4082 c_options->image_overlay.background_alpha = options->image_overlay.background_alpha;
4086 *-----------------------------------------------------------------------------
4087 * timezone database routines
4088 *-----------------------------------------------------------------------------
4091 static void timezone_async_ready_cb(GObject *source_object, GAsyncResult *res, gpointer data)
4093 GError *error = NULL;
4095 gchar *tmp_filename;
4097 if (!g_cancellable_is_cancelled(tz->cancellable))
4099 generic_dialog_close(tz->gd);
4103 if (g_file_copy_finish(G_FILE(source_object), res, &error))
4105 tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
4106 move_file(tmp_filename, tz->timezone_database_user);
4107 g_free(tmp_filename);
4111 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4114 g_file_delete(tz->tmp_g_file, NULL, &error);
4115 g_object_unref(tz->tmp_g_file);
4116 tz->tmp_g_file = NULL;
4117 g_object_unref(tz->cancellable);
4118 g_object_unref(tz->timezone_database_gq);
4121 static void timezone_progress_cb(goffset current_num_bytes, goffset total_num_bytes, gpointer data)
4125 if (!g_cancellable_is_cancelled(tz->cancellable))
4127 gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(tz->progress), (gdouble)current_num_bytes / total_num_bytes);
4131 static void timezone_cancel_button_cb(GenericDialog *gd, gpointer data)
4135 g_cancellable_cancel(tz->cancellable);
4138 static void timezone_database_install_cb(GtkWidget *widget, gpointer data)
4141 GError *error = NULL;
4142 GFileIOStream *io_stream;
4149 tz->tmp_g_file = g_file_new_tmp("geeqie_timezone_XXXXXX", &io_stream, &error);
4153 file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
4154 log_printf("Error: Download timezone database failed:\n%s", error->message);
4155 g_error_free(error);
4156 g_object_unref(tz->tmp_g_file);
4160 tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
4162 tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);
4164 generic_dialog_add_message(tz->gd, GTK_STOCK_DIALOG_INFO, _("Downloading timezone database"), NULL, FALSE);
4166 tz->progress = gtk_progress_bar_new();
4167 gtk_box_pack_start(GTK_BOX(tz->gd->vbox), tz->progress, FALSE, FALSE, 0);
4168 gtk_widget_show(tz->progress);
4170 gtk_widget_show(tz->gd->dialog);
4171 tz->cancellable = g_cancellable_new();
4172 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);
4174 gtk_button_set_label(GTK_BUTTON(widget), _("Update"));
4177 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */