From 417c2b44b60d99f423bfed1beb7571284bce4574 Mon Sep 17 00:00:00 2001 From: Colin Clark Date: Thu, 26 Sep 2019 11:21:35 +0100 Subject: [PATCH] Fix #712: ability to return to previous image if home/end was pressed occasionally https://github.com/BestImageViewer/geeqie/issues/712 Additional Go menu items - Image Back, Image Forward Remove key bindings for multi-page navigation - they conflict with other usage. The user can set their own key bindings. Remove enable/disable multi-page navigation items. The parameter fd->page_total is set in another thread which causes problems. It is easiest to leave them always enabled. --- doc/docbook/GuideMainWindowMenus.xml | 20 +++++++ src/history_list.c | 73 +++++++++++++++++++++++ src/history_list.h | 4 ++ src/image.c | 6 ++ src/layout_image.c | 5 ++ src/layout_util.c | 88 ++++++++++++++-------------- src/toolbar.c | 2 + 7 files changed, 153 insertions(+), 45 deletions(-) diff --git a/doc/docbook/GuideMainWindowMenus.xml b/doc/docbook/GuideMainWindowMenus.xml index 3f1f93b4..07e9b1d6 100644 --- a/doc/docbook/GuideMainWindowMenus.xml +++ b/doc/docbook/GuideMainWindowMenus.xml @@ -301,6 +301,26 @@ Goes to the last image + + + + Image Back + + + + Each image you view is appended to a chain. You may traverse forwards and backwards through this chain using this and the following key. Move to the previous image in the chain. + + + + + + Image Forward + + + + Move to the next image in the chain. + + diff --git a/src/history_list.c b/src/history_list.c index e1fafbf6..d03ee055 100644 --- a/src/history_list.c +++ b/src/history_list.c @@ -98,6 +98,79 @@ void history_chain_append_end(const gchar *path) } } +/* + *----------------------------------------------------------------------------- + * Implements an image history chain. Whenever an image is displayed it is + * appended to a chain. + * Pressing the Image Back and Image Forward buttons moves along the chain, + * but does not make additions to the chain. + * The chain always increases and is deleted at the end of the session + *----------------------------------------------------------------------------- + */ +static GList *image_chain = NULL; +static guint image_chain_index = G_MAXUINT; +static gboolean image_nav_button = FALSE; /** Used to prevent the nav buttons making entries to the chain **/ +const gchar *image_chain_back() +{ + image_nav_button = TRUE; + + image_chain_index = image_chain_index > 0 ? image_chain_index - 1 : 0; + + return g_list_nth_data(image_chain, image_chain_index); +} + +const gchar *image_chain_forward() +{ + image_nav_button= TRUE; + guint last = g_list_length(image_chain) - 1; + + image_chain_index = image_chain_index < last ? image_chain_index + 1 : last; + + return g_list_nth_data(image_chain, image_chain_index); +} + +/** + * @brief Appends a path to the image history chain + * @param path Image path selected + * + * 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 + */ +void image_chain_append_end(const gchar *path) +{ + GList *work; + + if (!image_nav_button) + { + if(image_chain_index == G_MAXUINT) + { + image_chain = g_list_append(image_chain, g_strdup(path)); + image_chain_index = 0; + } + else + { + work = g_list_last(image_chain); + gchar *tmp; + tmp = work->data; + if (g_strcmp0(work->data , path) != 0) + { + image_chain = g_list_append(image_chain, g_strdup(path)); + image_chain_index = g_list_length(image_chain) - 1; + DEBUG_3("%d %s", image_chain_index, path); + } + else + { + image_chain_index = g_list_length(image_chain) - 1; + } + } + } + else + { + image_nav_button = FALSE; + } +} + /* *----------------------------------------------------------------------------- * history lists diff --git a/src/history_list.h b/src/history_list.h index da10b8e2..f9040de4 100644 --- a/src/history_list.h +++ b/src/history_list.h @@ -40,6 +40,10 @@ const gchar *history_chain_back(); const gchar *history_chain_forward(); void history_chain_append_end(const gchar *path); +const gchar *image_chain_back(); +const gchar *image_chain_forward(); +void image_chain_append_end(const gchar *path); + /* the returned GList is internal, don't free it */ GList *history_list_get_by_key(const gchar *key); diff --git a/src/image.c b/src/image.c index 23d2a204..a36f21d3 100644 --- a/src/image.c +++ b/src/image.c @@ -29,6 +29,7 @@ #include "exif.h" #include "metadata.h" #include "histogram.h" +#include "history_list.h" #include "image-load.h" #include "image-overlay.h" #include "layout.h" @@ -1384,6 +1385,11 @@ void image_change_from_collection(ImageWindow *imd, CollectionData *cd, CollectI collection_table_unselect_all(cw->table); collection_table_select(cw->table,info); } + + if (info->fd) + { + image_chain_append_end(info->fd->path); + } } CollectionData *image_get_collection(ImageWindow *imd, CollectInfo **info) diff --git a/src/layout_image.c b/src/layout_image.c index ee26fd46..a87e9f8c 100644 --- a/src/layout_image.c +++ b/src/layout_image.c @@ -1400,6 +1400,11 @@ void layout_image_set_fd(LayoutWindow *lw, FileData *fd) layout_image_slideshow_continue_check(lw); layout_bars_new_image(lw); layout_image_animate_new_file(lw); + + if (fd) + { + image_chain_append_end(fd->path); + } } void layout_image_set_with_ahead(LayoutWindow *lw, FileData *fd, FileData *read_ahead_fd) diff --git a/src/layout_util.c b/src/layout_util.c index 83db36c3..40a32535 100644 --- a/src/layout_util.c +++ b/src/layout_util.c @@ -1546,7 +1546,10 @@ static void layout_menu_page_first_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; FileData *fd = layout_image_get_fd(lw); - file_data_set_page_num(fd, 1); + if (fd->page_total > 0) + { + file_data_set_page_num(fd, 1); + } } static void layout_menu_page_last_cb(GtkAction *action, gpointer data) @@ -1554,7 +1557,10 @@ static void layout_menu_page_last_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; FileData *fd = layout_image_get_fd(lw); - file_data_set_page_num(fd, -1); + if (fd->page_total > 0) + { + file_data_set_page_num(fd, -1); + } } static void layout_menu_page_next_cb(GtkAction *action, gpointer data) @@ -1562,7 +1568,10 @@ static void layout_menu_page_next_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; FileData *fd = layout_image_get_fd(lw); - file_data_inc_page_num(fd); + if (fd->page_total > 0) + { + file_data_inc_page_num(fd); + } } static void layout_menu_page_previous_cb(GtkAction *action, gpointer data) @@ -1570,7 +1579,28 @@ static void layout_menu_page_previous_cb(GtkAction *action, gpointer data) LayoutWindow *lw = data; FileData *fd = layout_image_get_fd(lw); - file_data_dec_page_num(fd); + if (fd->page_total > 0) + { + file_data_dec_page_num(fd); + } +} + +static void layout_menu_image_forward_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + FileData *dir_fd; + + /* Obtain next image */ + layout_set_path(lw, image_chain_forward()); +} + +static void layout_menu_image_back_cb(GtkAction *action, gpointer data) +{ + LayoutWindow *lw = data; + FileData *dir_fd; + + /* Obtain previous image */ + layout_set_path(lw, image_chain_back()); } static void layout_menu_split_pane_next_cb(GtkAction *action, gpointer data) @@ -1922,10 +1952,13 @@ static GtkActionEntry menu_entries[] = { { "NextImage", GTK_STOCK_GO_DOWN, N_("_Next Image"), "space", N_("Next Image"), CB(layout_menu_image_next_cb) }, { "NextImageAlt1", GTK_STOCK_GO_DOWN, N_("_Next Image"), "Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) }, - { "FirstPage", GTK_STOCK_MEDIA_PREVIOUS, N_("_First Page"), "Home", N_( "First Page"), CB(layout_menu_page_first_cb) }, - { "LastPage", GTK_STOCK_MEDIA_NEXT, N_("_Last Page"), "End", N_("Last Page"), CB(layout_menu_page_last_cb) }, - { "NextPage", GTK_STOCK_MEDIA_FORWARD, N_("_Next Page"), "Page_Down", N_("Next Page"), CB(layout_menu_page_next_cb) }, - { "PrevPage", GTK_STOCK_MEDIA_REWIND, N_("_Previous Page"), "Page_Up", N_("Previous Page"), CB(layout_menu_page_previous_cb) }, + { "ImageForward", GTK_STOCK_GOTO_LAST, N_("Image Forward"), NULL, N_("Image Forward"), CB(layout_menu_image_forward_cb) }, + { "ImageBack", GTK_STOCK_GOTO_FIRST, N_("Image Back"), NULL, N_("Image Back"), CB(layout_menu_image_back_cb) }, + + { "FirstPage", GTK_STOCK_MEDIA_PREVIOUS, N_("_First Page"), NULL, N_( "First Page"), CB(layout_menu_page_first_cb) }, + { "LastPage", GTK_STOCK_MEDIA_NEXT, N_("_Last Page"), NULL, N_("Last Page"), CB(layout_menu_page_last_cb) }, + { "NextPage", GTK_STOCK_MEDIA_FORWARD, N_("_Next Page"), NULL, N_("Next Page"), CB(layout_menu_page_next_cb) }, + { "PrevPage", GTK_STOCK_MEDIA_REWIND, N_("_Previous Page"), NULL, N_("Previous Page"), CB(layout_menu_page_previous_cb) }, { "NextImageAlt2", GTK_STOCK_GO_DOWN, N_("_Next Image"), "KP_Page_Down", N_("Next Image"), CB(layout_menu_image_next_cb) }, @@ -2154,6 +2187,8 @@ static const gchar *menu_ui_description = " " " " " " +" " +" " " " " " " " @@ -2641,39 +2676,6 @@ static void layout_actions_setup_editors(LayoutWindow *lw) g_list_free(editors_list); } -static gboolean go_menu_select(GtkWidget *widget, gpointer data) -{ - GtkAction *action; - LayoutWindow *lw = data; - - action = gtk_action_group_get_action(lw->action_group, "FirstPage"); - gtk_action_set_sensitive(action, FALSE); - action = gtk_action_group_get_action(lw->action_group, "PrevPage"); - gtk_action_set_sensitive(action, FALSE); - action = gtk_action_group_get_action(lw->action_group, "LastPage"); - gtk_action_set_sensitive(action, FALSE); - action = gtk_action_group_get_action(lw->action_group, "NextPage"); - gtk_action_set_sensitive(action, FALSE); - - if (lw->image && lw->image->image_fd && lw->image->image_fd->page_total > 0) - { - if (lw->image->image_fd->page_num > 0) - { - action = gtk_action_group_get_action(lw->action_group, "FirstPage"); - gtk_action_set_sensitive(action, TRUE); - action = gtk_action_group_get_action(lw->action_group, "PrevPage"); - gtk_action_set_sensitive(action, TRUE); - } - if (lw->image->image_fd->page_num < (lw->image->image_fd->page_total - 1)) - { - action = gtk_action_group_get_action(lw->action_group, "LastPage"); - gtk_action_set_sensitive(action, TRUE); - action = gtk_action_group_get_action(lw->action_group, "NextPage"); - gtk_action_set_sensitive(action, TRUE); - } - } -} - void layout_actions_setup(LayoutWindow *lw) { GError *error; @@ -2688,10 +2690,6 @@ void layout_actions_setup(LayoutWindow *lw) gtk_action_group_add_actions(lw->action_group, menu_entries, G_N_ELEMENTS(menu_entries), lw); - - action = gtk_action_group_get_action(lw->action_group, "GoMenu"); - g_signal_connect(G_OBJECT(action), "activate", G_CALLBACK(go_menu_select), lw); - gtk_action_group_add_toggle_actions(lw->action_group, menu_toggle_entries, G_N_ELEMENTS(menu_toggle_entries), lw); gtk_action_group_add_radio_actions(lw->action_group, diff --git a/src/toolbar.c b/src/toolbar.c index e77b51ae..472429d0 100644 --- a/src/toolbar.c +++ b/src/toolbar.c @@ -83,6 +83,8 @@ static const UseableToolbarItems useable_toolbar_items[] = { {"LastPage", N_("Last Page"), GTK_STOCK_MEDIA_NEXT}, {"NextPage", N_("Next page"), GTK_STOCK_MEDIA_FORWARD}, {"PrevPage", N_("Previous Page"), GTK_STOCK_MEDIA_REWIND}, + {"ImageForward", N_("Image Forward"), GTK_STOCK_GOTO_LAST}, + {"ImageBack", N_("Image Back"), GTK_STOCK_GOTO_FIRST}, {"NewWindow", N_("New _window"), GTK_STOCK_NEW}, {"NewCollection", N_("New collection"), GTK_STOCK_INDEX}, {"OpenCollection", N_("Open collection"), GTK_STOCK_OPEN}, -- 2.20.1