#include "layout_config.h"
#include "layout_util.h"
#include "metadata.h"
+#include "misc.h"
#include "osd.h"
#include "pixbuf_util.h"
#include "rcfile.h"
AE_ACCEL
};
+enum {
+ FILETYPES_COLUMN_FILTER = 0,
+ FILETYPES_COLUMN_DESCRIPTION,
+ FILETYPES_COLUMN_CLASS,
+ FILETYPES_COLUMN_WRITABLE,
+ FILETYPES_COLUMN_SIDECAR,
+ FILETYPES_COLUMN_COUNT
+};
+
gchar *format_class_list[] = {
N_("Unknown"),
N_("Image"),
N_("Metadata"),
N_("Video"),
N_("Collection"),
- N_("Document")
+ N_("Document"),
+ N_("Archive")
};
/* config memory values */
options->image.max_autofit_size = c_options->image.max_autofit_size;
options->image.max_enlargement_size = c_options->image.max_enlargement_size;
options->image.use_clutter_renderer = c_options->image.use_clutter_renderer;
+ options->image.tile_size = c_options->image.tile_size;
options->progressive_key_scrolling = c_options->progressive_key_scrolling;
options->keyboard_scroll_step = c_options->keyboard_scroll_step;
options->mousewheel_scrolls = c_options->mousewheel_scrolls;
options->image_lm_click_nav = c_options->image_lm_click_nav;
+ options->image_l_click_archive = c_options->image_l_click_archive;
options->image_l_click_video = c_options->image_l_click_video;
options->image_l_click_video_editor = c_options->image_l_click_video_editor;
options->image.zoom_increment = c_options->image.zoom_increment;
+ options->image.zoom_style = c_options->image.zoom_style;
+
options->image.enable_read_ahead = c_options->image.enable_read_ahead;
options->image_overlay.background_blue = c_options->image_overlay.background_blue;
options->image_overlay.background_alpha = c_options->image_overlay.background_alpha;
options->update_on_time_change = c_options->update_on_time_change;
- options->image.exif_proof_rotate_enable = c_options->image.exif_proof_rotate_enable;
options->duplicates_similarity_threshold = c_options->duplicates_similarity_threshold;
options->rot_invariant_sim = c_options->rot_invariant_sim;
options->metadata.confirm_on_dir_change = c_options->metadata.confirm_on_dir_change;
options->metadata.keywords_case_sensitive = c_options->metadata.keywords_case_sensitive;
options->metadata.write_orientation = c_options->metadata.write_orientation;
+ options->metadata.check_spelling = c_options->metadata.check_spelling;
options->stereo.mode = (c_options->stereo.mode & (PR_STEREO_HORIZ | PR_STEREO_VERT | PR_STEREO_FIXED | PR_STEREO_ANAGLYPH | PR_STEREO_HALF)) |
(c_options->stereo.tmp.mirror_right ? PR_STEREO_MIRROR_RIGHT : 0) |
(c_options->stereo.tmp.flip_right ? PR_STEREO_FLIP_RIGHT : 0) |
options->star_rating.star = c_options->star_rating.star;
options->star_rating.rejected = c_options->star_rating.rejected;
+
+ options->threads.duplicates = c_options->threads.duplicates > 0 ? c_options->threads.duplicates : -1;
+
#ifdef DEBUG
set_debug_level(debug_c);
#endif
gtk_widget_show(combo);
}
+static void zoom_style_selection_menu_cb(GtkWidget *combo, gpointer data)
+{
+ gint *option = data;
+
+ switch (gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+ {
+ case 0:
+ *option = ZOOM_GEOMETRIC;
+ break;
+ case 1:
+ *option = ZOOM_ARITHMETIC;
+ break;
+ default:
+ *option = ZOOM_GEOMETRIC;
+ }
+}
+
+static void add_zoom_style_selection_menu(GtkWidget *table, gint column, gint row, const gchar *text, ZoomStyle option, ZoomStyle *option_c)
+{
+ GtkWidget *combo;
+ gint current = 0;
+
+ *option_c = option;
+
+ pref_table_label(table, column, row, text, 0.0);
+
+ combo = gtk_combo_box_text_new();
+
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Geometric"));
+ if (option == ZOOM_GEOMETRIC) current = 0;
+ gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(combo), _("Arithmetic"));
+ if (option == ZOOM_ARITHMETIC) current = 1;
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), current);
+
+ g_signal_connect(G_OBJECT(combo), "changed", G_CALLBACK(zoom_style_selection_menu_cb), option_c);
+
+ gtk_table_attach(GTK_TABLE(table), combo, column + 1, column + 2, row, row + 1, GTK_SHRINK, 0, 0, 0);
+ gtk_widget_show(combo);
+}
+
typedef struct _UseableMouseItems UseableMouseItems;
struct _UseableMouseItems
{
gchar *rating_symbol;
gchar *path;
gchar *basename;
+ gchar *download_locn;
GNetworkMonitor *net_mon;
- GSocketConnectable *geeqie_org;
- gboolean internet_available;
+ GSocketConnectable *tz_org;
+ gboolean internet_available = FALSE;
TZData *tz;
vbox = scrolled_notebook_page(notebook, _("General"));
pref_spacer(group, PREF_PAD_GROUP);
- group = pref_group_new(vbox, FALSE, _("Info sidebar heights"), GTK_ORIENTATION_VERTICAL);
- pref_label_new(group, _("NOTE! Geeqie must be restarted for changes to take effect"));
- hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
- pref_spin_new_int(hbox, _("Keywords:"), NULL,
- 1, 9999, 1,
- options->info_keywords.height, &c_options->info_keywords.height);
- pref_spin_new_int(hbox, _("Title:"), NULL,
- 1, 9999, 1,
- options->info_title.height, &c_options->info_title.height);
- pref_spin_new_int(hbox, _("Comment:"), NULL,
- 1, 9999, 1,
- options->info_comment.height, &c_options->info_comment.height);
- pref_spin_new_int(hbox, _("Rating:"), NULL,
- 1, 9999, 1,
- options->info_rating.height, &c_options->info_rating.height);
-
- pref_spacer(group, PREF_PAD_GROUP);
-
- group = pref_group_new(vbox, FALSE, _("Show predefined keyword tree"), GTK_ORIENTATION_VERTICAL);
-
- pref_checkbox_new_int(group, _("Show predefined keyword tree (NOTE! Geeqie must be restarted for change to take effect)"),
- options->show_predefined_keyword_tree, &c_options->show_predefined_keyword_tree);
-
- pref_spacer(group, PREF_PAD_GROUP);
-
net_mon = g_network_monitor_get_default();
- geeqie_org = g_network_address_parse_uri(GQ_WEBSITE, 80, NULL);
- internet_available = g_network_monitor_can_reach(net_mon, geeqie_org, NULL, NULL);
- g_object_unref(geeqie_org);
+ tz_org = g_network_address_parse_uri(TIMEZONE_DATABASE_WEB, 80, NULL);
+ if (tz_org)
+ {
+ internet_available = g_network_monitor_can_reach(net_mon, tz_org, NULL, NULL);
+ g_object_unref(tz_org);
+ }
group = pref_group_new(vbox, FALSE, _("Timezone database"), GTK_ORIENTATION_VERTICAL);
hbox = pref_box_new(group, TRUE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
tz = g_new0(TZData, 1);
- path = path_from_utf8(TIMEZONE_DATABASE);
+ path = path_from_utf8(TIMEZONE_DATABASE_WEB);
basename = g_path_get_basename(path);
- tz->timezone_database_user = g_build_filename(get_rc_dir(), basename, NULL);
+ tz->timezone_database_user = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
g_free(path);
g_free(basename);
button = pref_button_new(GTK_WIDGET(hbox), NULL, _("Install"), FALSE, G_CALLBACK(timezone_database_install_cb), tz);
}
+ download_locn = g_strconcat(_("Download database from: "), TIMEZONE_DATABASE_WEB, NULL);
+ pref_label_new(GTK_WIDGET(hbox), download_locn);
+ g_free(download_locn);
+
if (!internet_available)
{
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"));
G_CALLBACK(zoom_increment_cb), NULL);
gtk_spin_button_set_update_policy(GTK_SPIN_BUTTON(spin), GTK_UPDATE_ALWAYS);
+ c_options->image.zoom_style = options->image.zoom_style;
+ table = pref_table_new(group, 2, 1, FALSE, FALSE);
+ add_zoom_style_selection_menu(table, 0, 0, _("Zoom style:"), options->image.zoom_style, &c_options->image.zoom_style);
+
group = pref_group_new(vbox, FALSE, _("Fit image to window"), GTK_ORIENTATION_VERTICAL);
hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
pref_checkbox_link_sensitivity(ct_button, spin);
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."));
+ group = pref_group_new(vbox, FALSE, _("Tile size"), GTK_ORIENTATION_VERTICAL);
+ gtk_widget_set_sensitive(group, !options->image.use_clutter_renderer);
+
+ hbox = pref_box_new(group, FALSE, GTK_ORIENTATION_HORIZONTAL, PREF_PAD_SPACE);
+ spin = pref_spin_new_int(hbox, _("Pixels"), _("(Requires restart)"),
+ 128, 4096, 128,
+ options->image.tile_size, &c_options->image.tile_size);
+ 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."));
+
group = pref_group_new(vbox, FALSE, _("Appearance"), GTK_ORIENTATION_VERTICAL);
pref_checkbox_new_int(group, _("Use custom border color in window mode"),
c_options->image.alpha_color_1 = options->image.alpha_color_1;
c_options->image.alpha_color_2 = options->image.alpha_color_2;
-
- group = pref_group_new(vbox, FALSE, _("Convenience"), GTK_ORIENTATION_VERTICAL);
-
- pref_checkbox_new_int(group, _("Auto rotate proofs using Exif information"),
- options->image.exif_proof_rotate_enable, &c_options->image.exif_proof_rotate_enable);
}
/* windows tab */
/* filtering tab */
+static gint filter_table_sort_cb(GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer data)
+{
+ gint n = GPOINTER_TO_INT(data);
+ gint ret = 0;
+ FilterEntry *filter_a;
+ FilterEntry *filter_b;
+
+ gtk_tree_model_get(model, a, 0, &filter_a, -1);
+ gtk_tree_model_get(model, b, 0, &filter_b, -1);
+
+ switch (n)
+ {
+ case FILETYPES_COLUMN_DESCRIPTION:
+ {
+ ret = g_utf8_collate(filter_a->description, filter_b->description);
+ break;
+ }
+ case FILETYPES_COLUMN_CLASS:
+ {
+ ret = g_strcmp0(format_class_list[filter_a->file_class], format_class_list[filter_b->file_class]);
+ break;
+ }
+ case FILETYPES_COLUMN_WRITABLE:
+ {
+ ret = filter_a->writable - filter_b->writable;
+ break;
+ }
+ case FILETYPES_COLUMN_SIDECAR:
+ {
+ ret = filter_a->allow_sidecar - filter_b->allow_sidecar;
+ break;
+ }
+ default:
+ g_return_val_if_reached(0);
+ }
+
+ return ret;
+}
+
+static gboolean search_function_cb(GtkTreeModel *model, gint column, const gchar *key, GtkTreeIter *iter, gpointer search_data)
+{
+ FilterEntry *fe;
+ gboolean ret = TRUE;
+
+ gtk_tree_model_get(model, iter, 0, &fe, -1);
+
+ if (g_strstr_len(fe->extensions, -1, key))
+ {
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
static void config_tab_files(GtkWidget *notebook)
{
GtkWidget *hbox;
GINT_TO_POINTER(FE_EXTENSION), NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
+ gtk_tree_view_set_enable_search(GTK_TREE_VIEW(filter_view), TRUE);
+ gtk_tree_view_set_search_column(GTK_TREE_VIEW(filter_view), FILETYPES_COLUMN_FILTER);
+ gtk_tree_view_set_search_equal_func(GTK_TREE_VIEW(filter_view), search_function_cb, NULL, NULL);
+
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Description"));
gtk_tree_view_column_set_resizable(column, TRUE);
gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
GINT_TO_POINTER(FE_DESCRIPTION), NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_DESCRIPTION, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_DESCRIPTION), NULL);
+ gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_DESCRIPTION);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Class"));
gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
GINT_TO_POINTER(FE_CLASS), NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_CLASS, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_CLASS), NULL);
+ gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_CLASS);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Writable"));
gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
GINT_TO_POINTER(FE_WRITABLE), NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_WRITABLE, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_WRITABLE), NULL);
+ gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_WRITABLE);
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title(column, _("Sidecar is allowed"));
gtk_tree_view_column_set_cell_data_func(column, renderer, filter_set_func,
GINT_TO_POINTER(FE_ALLOW_SIDECAR), NULL);
gtk_tree_view_append_column(GTK_TREE_VIEW(filter_view), column);
-
+ gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(filter_store), FILETYPES_COLUMN_SIDECAR, filter_table_sort_cb, GINT_TO_POINTER(FILETYPES_COLUMN_SIDECAR), NULL);
+ gtk_tree_view_column_set_sort_column_id(column, FILETYPES_COLUMN_SIDECAR);
filter_store_populate();
gtk_container_add(GTK_CONTAINER(scrolled), filter_view);
pref_checkbox_new_int(group, _("Write metadata on directory change"),
options->metadata.confirm_on_dir_change, &c_options->metadata.confirm_on_dir_change);
+#ifdef HAVE_SPELL
+#if GTK_CHECK_VERSION(3,20,0)
+ group = pref_group_new(vbox, FALSE, _("Spelling checks"), GTK_ORIENTATION_VERTICAL);
+
+ ct_button = pref_checkbox_new_int(group, _("Check spelling -Requires restart"), options->metadata.check_spelling, &c_options->metadata.check_spelling);
+#endif
+#endif
+
group = pref_group_new(vbox, FALSE, _("Pre-load metadata"), GTK_ORIENTATION_VERTICAL);
ct_button = pref_checkbox_new_int(group, _("Read metadata in background"),
button = pref_button_new(NULL, GTK_STOCK_CLEAR, NULL, FALSE,
G_CALLBACK(safe_delete_clear_cb), NULL);
gtk_box_pack_end(GTK_BOX(hbox), button, FALSE, FALSE, 0);
+
+ c_options->file_ops.no_trash = options->file_ops.no_trash;
+ c_options->file_ops.use_system_trash = options->file_ops.use_system_trash;
+
pref_radiobutton_new(group, ct_button, _("Use system Trash bin"),
options->file_ops.use_system_trash && !options->file_ops.no_trash, G_CALLBACK(use_system_trash_cb), NULL);
options->mousewheel_scrolls, &c_options->mousewheel_scrolls);
pref_checkbox_new_int(group, _("Navigation by left or middle click on image"),
options->image_lm_click_nav, &c_options->image_lm_click_nav);
+ pref_checkbox_new_int(group, _("Open archive by left click on image"),
+ options->image_l_click_archive, &c_options->image_l_click_archive);
pref_checkbox_new_int(group, _("Play video by left click on image"),
options->image_l_click_video, &c_options->image_l_click_video);
table = pref_table_new(group, 2, 1, FALSE, FALSE);
GdkPixbufFormat *fm;
gint i;
GString *types_string = g_string_new(NULL);
+ GtkWidget *types_string_label;
+ GtkWidget *threads_string_label;
+ GtkWidget *dupes_threads_spin;
vbox = scrolled_notebook_page(notebook, _("Advanced"));
group = pref_group_new(vbox, FALSE, _("External preview extraction"), GTK_ORIENTATION_VERTICAL);
}
types_string = g_string_prepend(types_string, _("Usable file types:\n"));
- pref_label_new(group, types_string->str);
- GtkWidget *types_string_label = gtk_label_new(types_string->str);
+ types_string_label = pref_label_new(group, types_string->str);
gtk_label_set_line_wrap(GTK_LABEL(types_string_label), TRUE);
pref_spacer(group, PREF_PAD_GROUP);
g_slist_free(formats_list);
string_list_free(extensions_list);
g_string_free(types_string, TRUE);
+
+ pref_spacer(group, PREF_PAD_GROUP);
+
+ pref_line(vbox, PREF_PAD_SPACE);
+ group = pref_group_new(vbox, FALSE, _("Thread pool limits"), GTK_ORIENTATION_VERTICAL);
+
+ 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.");
+ gtk_label_set_line_wrap(GTK_LABEL(threads_string_label), TRUE);
+
+ pref_spacer(vbox, PREF_PAD_GROUP);
+
+ dupes_threads_spin = pref_spin_new_int(vbox, _("Duplicate check:"), _("max. threads"), 0, get_cpu_cores(), 1, options->threads.duplicates, &c_options->threads.duplicates);
+ gtk_widget_set_tooltip_markup(dupes_threads_spin, _("Set to 0 for unlimited"));
}
/* stereo tab */
gchar *path;
GString *copyright;
gchar *timezone_path;
- gchar *basename;
ZoneDetect *cd;
FILE *fp = NULL;
#define LINE_LENGTH 1000
copyright = g_string_new(NULL);
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");
- path = path_from_utf8(TIMEZONE_DATABASE);
- basename = g_path_get_basename(path);
- timezone_path = g_build_filename(get_rc_dir(), basename, NULL);
+ timezone_path = g_build_filename(get_rc_dir(), TIMEZONE_DATABASE_FILE, NULL);
if (g_file_test(timezone_path, G_FILE_TEST_EXISTS))
{
cd = ZDOpenDatabase(timezone_path);
if (cd)
{
copyright = g_string_append(copyright, ZDGetNotice(cd));
- ZDCloseDatabase(cd);
}
+ else
+ {
+ log_printf("Error: Init of timezone database %s failed\n", timezone_path);
+ }
+ ZDCloseDatabase(cd);
}
- g_free(path);
g_free(timezone_path);
- g_free(basename);
authors[0] = NULL;
path = g_build_filename(gq_helpdir, "AUTHORS", NULL);
GError *error = NULL;
TZData *tz = data;
gchar *tmp_filename;
+ gchar *timezone_bin;
+ gchar *tmp_dir = NULL;
+ FileData *fd;
if (!g_cancellable_is_cancelled(tz->cancellable))
{
if (g_file_copy_finish(G_FILE(source_object), res, &error))
{
- tmp_filename = g_file_get_parse_name(tz->tmp_g_file);
- move_file(tmp_filename, tz->timezone_database_user);
+ tmp_filename = g_file_get_path(tz->tmp_g_file);
+ fd = file_data_new_simple(tmp_filename);
+ tmp_dir = open_archive(fd);
+
+ if (tmp_dir)
+ {
+ timezone_bin = g_build_filename(tmp_dir, TIMEZONE_DATABASE_VERSION, TIMEZONE_DATABASE_FILE, NULL);
+ if (isfile(timezone_bin))
+ {
+ move_file(timezone_bin, tz->timezone_database_user);
+ }
+ else
+ {
+ warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+ }
+
+ g_free(timezone_bin);
+ g_free(tmp_dir); // The folder in /tmp is deleted in exit_program_final()
+ }
+ else
+ {
+ warning_dialog(_("Warning: Cannot open timezone database file"), _("See the Log Window"), GTK_STOCK_DIALOG_WARNING, NULL);
+ }
g_free(tmp_filename);
+ file_data_unref(fd);
}
else
{
- file_util_warning_dialog(_("Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
+ file_util_warning_dialog(_("Error: Timezone database download failed"), error->message, GTK_STOCK_DIALOG_ERROR, NULL);
}
g_file_delete(tz->tmp_g_file, NULL, &error);
}
else
{
- tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE);
+ tz->timezone_database_gq = g_file_new_for_uri(TIMEZONE_DATABASE_WEB);
tz->gd = generic_dialog_new(_("Timezone database"), "download_timezone_database", NULL, TRUE, timezone_cancel_button_cb, tz);