From: Colin Clark Date: Fri, 22 Apr 2022 12:42:03 +0000 (+0100) Subject: Fix #934: Request to add image bookmarking/tagging within a folder X-Git-Tag: gtk2final~22 X-Git-Url: http://geeqie.org/cgi-bin/gitweb.cgi?p=geeqie.git;a=commitdiff_plain;h=8552b6786d67b5712bc5cd45830cdbd48e18769b Fix #934: Request to add image bookmarking/tagging within a folder https://github.com/BestImageViewer/geeqie/issues/934 The last image viewed in a folder is stored in a list. If the folder is re-opened, focus moves to the last image viewed. An option on Preferences/Behavior sets the maximum size of the list. --- diff --git a/doc/docbook/GuideOptionsBehavior.xml b/doc/docbook/GuideOptionsBehavior.xml index 03a89d32..9fb2a7b9 100644 --- a/doc/docbook/GuideOptionsBehavior.xml +++ b/doc/docbook/GuideOptionsBehavior.xml @@ -177,7 +177,15 @@ Recent folder list maximum size - This is the number of entries to be saved from the recent open folder list drop-down box. The number of entries displayed in the current session is unlimited. + This is the maximum number of entries to be displayed in the recent open folder list drop-down box. + + + + + Recent folder-image list maximum size + + + The last image viewed in a folder is stored in a list. This value is the maximum number of entries in the list. When a folder is subsequently re-opened, focus moves to the last image viewed in that folder. diff --git a/src/history_list.c b/src/history_list.c index eb624c4f..d9770bc9 100644 --- a/src/history_list.c +++ b/src/history_list.c @@ -24,6 +24,7 @@ #include "secure_save.h" #include "ui_fileops.h" +static void update_recent_viewed_folder_image_list(const gchar *path); /** * @file @@ -140,6 +141,8 @@ const gchar *image_chain_forward() * Each time the user selects a new image it is appended to the chain * except when it is identical to the current last entry * The pointer is always moved to the end of the chain + * + * Updates the recent viewed image_list */ void image_chain_append_end(const gchar *path) { @@ -166,6 +169,8 @@ void image_chain_append_end(const gchar *path) image_chain_index = g_list_length(image_chain) - 1; } } + + update_recent_viewed_folder_image_list(path); } else { @@ -307,7 +312,11 @@ gboolean history_list_save(const gchar *path) list_count = g_list_position(hd->list, g_list_last(hd->list)) + 1; while (work && secsave_errno == SS_ERR_NONE) { - if ((!(strcmp(hd->key, "path_list") == 0 && list_count > options->open_recent_list_maxsize)) && (!(strcmp(hd->key, "recent") == 0 && (!isfile(work->data))))) + if ((!(strcmp(hd->key, "path_list") == 0 && list_count > options->open_recent_list_maxsize)) + && + (!(strcmp(hd->key, "recent") == 0 && (!isfile(work->data)))) + && + (!(strcmp(hd->key, "image_list") == 0 && list_count > options->recent_folder_image_list_maxsize))) { secure_fprintf(ssi, "\"%s\"\n", (gchar *)work->data); } @@ -509,4 +518,105 @@ GList *history_list_get_by_key(const gchar *key) return hd->list; } + +/** + * @brief Get image last viewed in a folder + * @param path Must be a folder + * @returns Last image viewed in folder or NULL + * + * Returned string should be freed + */ +gchar *get_recent_viewed_folder_image(gchar *path) +{ + HistoryData *hd; + GList *work; + gchar *dirname; + gchar *ret = NULL; + + if (options->recent_folder_image_list_maxsize == 0) + { + return NULL; + } + + hd = history_list_find_by_key("image_list"); + + if (!hd) + { + hd = g_new(HistoryData, 1); + hd->key = g_strdup("image_list"); + hd->list = NULL; + history_list = g_list_prepend(history_list, hd); + } + + work = hd->list; + + while (work) + { + dirname = g_path_get_dirname(work->data); + + if (g_strcmp0(dirname, path) == 0) + { + ret = g_strdup(work->data); + g_free(dirname); + break; + } + + g_free(dirname); + work = work->next; + } + + return ret; +} + +static void update_recent_viewed_folder_image_list(const gchar *path) +{ + HistoryData *hd; + GList *work; + gchar *image_dir = NULL; + gchar *list_dir = NULL; + gboolean found = FALSE; + + if (options->recent_folder_image_list_maxsize == 0) + { + return; + } + + image_dir = g_path_get_dirname(path); + hd = history_list_find_by_key("image_list"); + if (!hd) + { + hd = g_new(HistoryData, 1); + hd->key = g_strdup("image_list"); + hd->list = NULL; + history_list = g_list_prepend(history_list, hd); + } + + work = hd->list; + + while (work) + { + list_dir = g_path_get_dirname(work->data); + + /* If folder already in list, update and move to start of list */ + if (g_strcmp0(list_dir, image_dir) == 0) + { + g_free(work->data); + work->data = g_strdup(path); + hd->list = g_list_remove_link(hd->list, work); + hd->list = g_list_concat(work, hd->list); + found = TRUE; + g_free(list_dir); + break; + } + g_free(list_dir); + work = work->next; + } + + g_free(image_dir); + + if (!found) + { + hd->list = g_list_prepend(hd->list, g_strdup(path)); + } +} /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ diff --git a/src/history_list.h b/src/history_list.h index 0ba4f476..d184770a 100644 --- a/src/history_list.h +++ b/src/history_list.h @@ -33,6 +33,7 @@ void history_list_add_to_key(const gchar *key, const gchar *path, gint max); void history_list_item_change(const gchar *key, const gchar *oldpath, const gchar *newpath); void history_list_item_move(const gchar *key, const gchar *path, gint direction); void history_list_item_remove(const gchar *key, const gchar *path); +gchar *get_recent_viewed_folder_image(gchar *path); const gchar *history_list_find_last_path_by_key(const gchar *key); diff --git a/src/layout.c b/src/layout.c index 338b05c2..c411d9af 100644 --- a/src/layout.c +++ b/src/layout.c @@ -1184,6 +1184,7 @@ gboolean layout_set_fd(LayoutWindow *lw, FileData *fd) { gboolean have_file = FALSE; gboolean dir_changed = TRUE; + gchar *last_image; if (!layout_valid(&lw)) return FALSE; @@ -1202,6 +1203,16 @@ gboolean layout_set_fd(LayoutWindow *lw, FileData *fd) } lw->dir_fd = file_data_ref(fd); file_data_register_real_time_monitor(fd); + + last_image = get_recent_viewed_folder_image(fd->path); + if (last_image) + { + fd = file_data_new_group(last_image); + g_free(last_image); + + if (isfile(fd->path)) have_file = TRUE; + } + } else { @@ -2977,6 +2988,8 @@ static void layout_config_startup_path(LayoutOptions *lop, gchar **path) static void layout_config_commandline(LayoutOptions *lop, gchar **path) { + gchar *last_image; + if (command_line->startup_blank) { *path = NULL; @@ -2991,6 +3004,16 @@ static void layout_config_commandline(LayoutOptions *lop, gchar **path) } else layout_config_startup_path(lop, path); + if (isdir(*path)) + { + last_image = get_recent_viewed_folder_image(*path); + if (last_image) + { + g_free(*path); + *path = last_image; + } + } + if (command_line->tools_show) { lop->tools_float = FALSE; diff --git a/src/options.c b/src/options.c index 995a329e..3819532b 100644 --- a/src/options.c +++ b/src/options.c @@ -145,6 +145,7 @@ ConfOptions *init_options(ConfOptions *options) options->image_l_click_video = FALSE; options->image_l_click_video_editor = NULL; options->open_recent_list_maxsize = 10; + options->recent_folder_image_list_maxsize = 10; options->place_dialogs_under_mouse = FALSE; options->progressive_key_scrolling = TRUE; diff --git a/src/options.h b/src/options.h index 41fd01f8..003e988e 100644 --- a/src/options.h +++ b/src/options.h @@ -58,6 +58,7 @@ struct _ConfOptions gboolean sort_totals; gint open_recent_list_maxsize; + gint recent_folder_image_list_maxsize; gint dnd_icon_size; DnDAction dnd_default_action; gint clipboard_selection; diff --git a/src/preferences.c b/src/preferences.c index dce9e05c..214765ba 100644 --- a/src/preferences.c +++ b/src/preferences.c @@ -402,6 +402,7 @@ static void config_window_apply(void) options->circular_selection_lists = c_options->circular_selection_lists; options->open_recent_list_maxsize = c_options->open_recent_list_maxsize; + options->recent_folder_image_list_maxsize = c_options->recent_folder_image_list_maxsize; options->dnd_icon_size = c_options->dnd_icon_size; options->clipboard_selection = c_options->clipboard_selection; options->dnd_default_action = c_options->dnd_default_action; @@ -3610,6 +3611,9 @@ static void config_tab_behavior(GtkWidget *notebook) pref_spin_new_int(group, _("Recent folder list maximum size"), NULL, 1, 50, 1, options->open_recent_list_maxsize, &c_options->open_recent_list_maxsize); + tmp = pref_spin_new_int(group, _("Recent folder-image list maximum size"), NULL, 0, 50, 1, options->recent_folder_image_list_maxsize, &c_options->recent_folder_image_list_maxsize); + gtk_widget_set_tooltip_text(tmp, _("List of the last image viewed in each recent folder.\nRe-opening a folder will set focus to the last image viewed.")); + pref_spin_new_int(group, _("Drag'n drop icon size"), NULL, 16, 256, 16, options->dnd_icon_size, &c_options->dnd_icon_size); diff --git a/src/rcfile.c b/src/rcfile.c index 1e98e4cd..56dc0d03 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -335,6 +335,7 @@ static void write_global_attributes(GString *outstr, gint indent) WRITE_NL(); WRITE_BOOL(*options, image_l_click_video); WRITE_NL(); WRITE_CHAR(*options, image_l_click_video_editor); WRITE_NL(); WRITE_INT(*options, open_recent_list_maxsize); + WRITE_NL(); WRITE_INT(*options, recent_folder_image_list_maxsize); WRITE_NL(); WRITE_INT(*options, dnd_icon_size); WRITE_NL(); WRITE_UINT(*options, dnd_default_action); WRITE_NL(); WRITE_BOOL(*options, place_dialogs_under_mouse); @@ -834,6 +835,7 @@ static gboolean load_global_params(const gchar **attribute_names, const gchar ** if (READ_CHAR(*options, image_l_click_video_editor)) continue; if (READ_INT(*options, open_recent_list_maxsize)) continue; + if (READ_INT(*options, recent_folder_image_list_maxsize)) continue; if (READ_INT(*options, dnd_icon_size)) continue; if (READ_UINT(*options, dnd_default_action)) continue; if (READ_BOOL(*options, place_dialogs_under_mouse)) continue;