Fix #934: Request to add image bookmarking/tagging within a folder
authorColin Clark <colin.clark@cclark.uk>
Fri, 22 Apr 2022 12:42:03 +0000 (13:42 +0100)
committerColin Clark <colin.clark@cclark.uk>
Fri, 22 Apr 2022 12:42:03 +0000 (13:42 +0100)
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.

doc/docbook/GuideOptionsBehavior.xml
src/history_list.c
src/history_list.h
src/layout.c
src/options.c
src/options.h
src/preferences.c
src/rcfile.c

index 03a89d3..9fb2a7b 100644 (file)
           <guilabel>Recent folder list maximum size</guilabel>
         </term>
         <listitem>
-          <para>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.</para>
+          <para>This is the maximum number of entries to be displayed in the recent open folder list drop-down box.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>
+          <guilabel>Recent folder-image list maximum size</guilabel>
+        </term>
+        <listitem>
+          <para>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.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
index eb624c4..d9770bc 100644 (file)
@@ -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: */
index 0ba4f47..d184770 100644 (file)
@@ -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);
 
index 338b05c..c411d9a 100644 (file)
@@ -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;
index 995a329..3819532 100644 (file)
@@ -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;
index 41fd01f..003e988 100644 (file)
@@ -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;
index dce9e05..214765b 100644 (file)
@@ -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);
 
index 1e98e4c..56dc0d0 100644 (file)
@@ -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;