[patch]: support viewed page history back/forward travelling



Hello evince folks:

The evince seems had no viewed pages go backward/forward travelling support, isn't it?

This is a useful feature in other pdf readers, so I write a patch to support it.

I had add 2 menuitems under menu Go:
* Ctrl+V for "Go Forward", and
* Ctrl+B for "Go Backward"

--
wucan
>From 6b8228b911ebb52711a988479aec0be9aa57a205 Mon Sep 17 00:00:00 2001
From: wucan <can_wu cnbvcom com>
Date: Sat, 3 Jul 2010 20:11:06 +0800
Subject: support viewed page history back/forward traveling

---
 data/evince-ui.xml          |    3 +
 libview/Makefile.am         |    4 +-
 libview/ev-document-model.c |   39 ++++++++++
 libview/ev-document-model.h |    5 ++
 libview/ev-page-history.c   |  162 +++++++++++++++++++++++++++++++++++++++++++
 libview/ev-page-history.h   |   48 +++++++++++++
 libview/ev-view.c           |   36 ++++++++++
 libview/ev-view.h           |    2 +
 shell/ev-window.c           |   35 +++++++++
 9 files changed, 333 insertions(+), 1 deletions(-)
 create mode 100644 libview/ev-page-history.c
 create mode 100644 libview/ev-page-history.h

diff --git a/data/evince-ui.xml b/data/evince-ui.xml
index 962e8b2..75879b2 100644
--- a/data/evince-ui.xml
+++ b/data/evince-ui.xml
@@ -55,6 +55,9 @@
       <separator/>
       <menuitem name="GoFirstPageMenu" action="GoFirstPage"/>
       <menuitem name="GoLastPageMenu" action="GoLastPage"/>
+      <separator/>
+      <menuitem name="GoBackwardPageMenu" action="GoBackwardPage"/>
+      <menuitem name="GoForwardPageMenu" action="GoForwardPage"/>
     </menu>
 
     <menu name="HelpMenu" action="Help">
diff --git a/libview/Makefile.am b/libview/Makefile.am
index 226a653..a2f58ae 100644
--- a/libview/Makefile.am
+++ b/libview/Makefile.am
@@ -10,7 +10,8 @@ NOINST_H_FILES =			\
 	ev-view-accessible.h		\
 	ev-view-cursor.h		\
 	ev-view-marshal.h		\
-	ev-view-private.h
+	ev-view-private.h		\
+	ev-page-history.h
 
 INST_H_SRC_FILES = 			\
 	ev-document-model.h		\
@@ -46,6 +47,7 @@ libevview_la_SOURCES = 			\
 	ev-view-cursor.c		\
 	ev-view-presentation.c		\
 	ev-view-type-builtins.c		\
+	ev-page-history.c		\
 	$(NOINST_H_FILES)		\
 	$(INST_H_FILES)
 
diff --git a/libview/ev-document-model.c b/libview/ev-document-model.c
index 727264a..be9c6a6 100644
--- a/libview/ev-document-model.c
+++ b/libview/ev-document-model.c
@@ -23,6 +23,8 @@
 #include "ev-document-model.h"
 #include "ev-view-type-builtins.h"
 #include "ev-view-marshal.h"
+#include "ev-page-history.h"
+
 
 struct _EvDocumentModel
 {
@@ -42,6 +44,8 @@ struct _EvDocumentModel
 
 	gdouble max_scale;
 	gdouble min_scale;
+
+	EvPageHistory *page_history;
 };
 
 struct _EvDocumentModelClass
@@ -86,6 +90,10 @@ ev_document_model_finalize (GObject *object)
 		g_object_unref (model->document);
 		model->document = NULL;
 	}
+	if (model->page_history) {
+		g_object_unref (model->page_history);
+		model->page_history = NULL;
+	}
 
 	G_OBJECT_CLASS (ev_document_model_parent_class)->finalize (object);
 }
@@ -269,6 +277,7 @@ ev_document_model_init (EvDocumentModel *model)
 	model->inverted_colors = FALSE;
 	model->min_scale = 0.;
 	model->max_scale = G_MAXDOUBLE;
+	model->page_history = ev_page_history_new();
 }
 
 EvDocumentModel *
@@ -329,6 +338,7 @@ ev_document_model_set_page (EvDocumentModel *model,
 
 	old_page = model->page;
 	model->page = page;
+	ev_document_model_page_history_add_page (model, page);
 	g_signal_emit (model, signals[PAGE_CHANGED], 0, old_page, page);
 
 	g_object_notify (G_OBJECT (model), "page");
@@ -569,3 +579,32 @@ ev_document_model_get_fullscreen (EvDocumentModel *model)
 
 	return model->fullscreen;
 }
+
+void
+ev_document_model_page_history_add_page (EvDocumentModel *model, gint page)
+{
+	ev_page_history_add_page(model->page_history, page);
+}
+
+gint
+ev_document_model_backward_page (EvDocumentModel *model)
+{
+	return ev_page_history_backward_page(model->page_history);
+}
+
+gint
+ev_document_model_forward_page (EvDocumentModel *model)
+{
+	return ev_page_history_forward_page(model->page_history);
+}
+
+gboolean ev_document_model_could_backward_page (EvDocumentModel *model)
+{
+	return ev_page_history_could_backward_page (model->page_history);
+}
+
+gboolean ev_document_model_could_forward_page (EvDocumentModel *model)
+{
+	return ev_page_history_could_forward_page (model->page_history);
+}
+
diff --git a/libview/ev-document-model.h b/libview/ev-document-model.h
index b283615..17c3c4b 100644
--- a/libview/ev-document-model.h
+++ b/libview/ev-document-model.h
@@ -81,6 +81,11 @@ gboolean         ev_document_model_get_dual_page     (EvDocumentModel *model);
 void             ev_document_model_set_fullscreen    (EvDocumentModel *model,
 						      gboolean         fullscreen);
 gboolean         ev_document_model_get_fullscreen    (EvDocumentModel *model);
+void             ev_document_model_page_history_add_page (EvDocumentModel *model, gint page);
+gint             ev_document_model_backward_page (EvDocumentModel *model);
+gint             ev_document_model_forward_page (EvDocumentModel *model);
+gboolean         ev_document_model_could_backward_page (EvDocumentModel *model);
+gboolean         ev_document_model_could_forward_page (EvDocumentModel *model);
 
 G_END_DECLS
 
diff --git a/libview/ev-page-history.c b/libview/ev-page-history.c
new file mode 100644
index 0000000..a3a6ac4
--- /dev/null
+++ b/libview/ev-page-history.c
@@ -0,0 +1,162 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2010 Can Wu
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <string.h>
+
+#include "ev-page-history.h"
+
+
+#define PAGE_HISTORY_MAX_PAGES		128
+struct _EvPageHistory {
+	GObject parent;
+
+	gint pages[PAGE_HISTORY_MAX_PAGES];
+	guint start_page_index;
+	guint end_page_index;
+	guint cur_page_index;
+	gint backwardable_npages;
+	gint npages;
+
+	gboolean travel_history;
+};
+
+struct _EvPageHistoryClass {
+	GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (EvPageHistory, ev_page_history, G_TYPE_OBJECT)
+
+static void
+ev_page_history_finalize (GObject *object)
+{
+	G_OBJECT_CLASS (ev_page_history_parent_class)->finalize (object);
+}
+
+static void
+ev_page_history_init (EvPageHistory *history)
+{
+}
+
+static void
+ev_page_history_class_init (EvPageHistoryClass *klass)
+{
+	GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
+
+	g_object_class->finalize = ev_page_history_finalize;
+}
+
+EvPageHistory *ev_page_history_new()
+{
+	EvPageHistory *his;
+
+	his = EV_PAGE_HISTORY (g_object_new (EV_TYPE_PAGE_HISTORY, NULL));
+	his->cur_page_index = 0;
+	his->start_page_index = 0;
+	his->end_page_index = 0;
+	his->backwardable_npages = 0;
+	his->npages = 0;
+	his->travel_history = FALSE;
+
+	return his;
+}
+
+void
+ev_page_history_add_page (EvPageHistory *his, gint page)
+{
+	g_return_if_fail (EV_IS_PAGE_HISTORY (his));
+
+	if (his->travel_history) {
+		his->travel_history = FALSE;
+		return;
+	}
+	if (his->npages == 0) {
+		his->pages[0] = page;
+		his->backwardable_npages = 0;
+	} else {
+		his->pages[(++his->cur_page_index) % PAGE_HISTORY_MAX_PAGES] = page;
+		his->backwardable_npages++;
+	}
+	if (his->backwardable_npages == PAGE_HISTORY_MAX_PAGES) {
+		his->backwardable_npages = PAGE_HISTORY_MAX_PAGES - 1;
+		his->start_page_index++;
+	}
+	his->npages = his->backwardable_npages + 1;
+	his->end_page_index = his->cur_page_index;
+
+	his->travel_history = FALSE;
+}
+
+gint
+ev_page_history_backward_page (EvPageHistory *his)
+{
+	gint page = -1;
+
+	g_return_val_if_fail (EV_IS_PAGE_HISTORY (his), -1);
+
+	if (his->backwardable_npages > 0) {
+		his->backwardable_npages--;
+		page = his->pages[(--his->cur_page_index) % PAGE_HISTORY_MAX_PAGES];
+		his->travel_history = TRUE;
+	}
+
+	return page;
+}
+
+gint
+ev_page_history_forward_page (EvPageHistory *his)
+{
+	gint page = -1;
+
+	g_return_val_if_fail (EV_IS_PAGE_HISTORY (his), -1);
+
+	if (his->backwardable_npages + 1 < his->npages) {
+		his->backwardable_npages++;
+		page = his->pages[(++his->cur_page_index) % PAGE_HISTORY_MAX_PAGES];
+		his->travel_history = TRUE;
+	}
+
+	return page;
+}
+
+gboolean
+ev_page_history_could_backward_page (EvPageHistory *his)
+{
+	g_return_val_if_fail (EV_IS_PAGE_HISTORY (his), FALSE);
+
+	if (his->backwardable_npages > 0) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+gboolean
+ev_page_history_could_forward_page (EvPageHistory *his)
+{
+	g_return_val_if_fail (EV_IS_PAGE_HISTORY (his), FALSE);
+
+	if (his->backwardable_npages + 1 < his->npages) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
diff --git a/libview/ev-page-history.h b/libview/ev-page-history.h
new file mode 100644
index 0000000..89b5d3c
--- /dev/null
+++ b/libview/ev-page-history.h
@@ -0,0 +1,48 @@
+/* this file is part of evince, a gnome document viewer
+ *
+ *  Copyright (C) 2010 Can Wu
+ *
+ * Evince is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef EV_PAGE_HISTORY_H
+#define EV_PAGE_HISTORY_H
+
+#include <config.h>
+#include <glib-object.h>
+
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_PAGE_HISTORY    (ev_page_history_get_type ())
+#define EV_PAGE_HISTORY(obj)    (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_PAGE_HISTORY, EvPageHistory))
+#define EV_IS_PAGE_HISTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_PAGE_HISTORY))
+
+typedef struct _EvPageHistory        EvPageHistory;
+typedef struct _EvPageHistoryClass   EvPageHistoryClass;
+
+GType ev_page_history_get_type (void) G_GNUC_CONST;
+
+EvPageHistory *ev_page_history_new();
+void ev_page_history_add_page (EvPageHistory *his, gint page);
+gint ev_page_history_backward_page (EvPageHistory *his);
+gint ev_page_history_forward_page (EvPageHistory *his);
+gboolean ev_page_history_could_backward_page (EvPageHistory *his);
+gboolean ev_page_history_could_forward_page (EvPageHistory *his);
+
+
+G_END_DECLS
+
+#endif /* EV_PAGE_HISTORY_H */
diff --git a/libview/ev-view.c b/libview/ev-view.c
index a473d0a..130bcf2 100644
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -5967,3 +5967,39 @@ ev_view_previous_page (EvView *view)
 	}
 }
 		
+gboolean
+ev_view_backward_page (EvView *view)
+{
+	int page;
+
+	g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+	if (!view->document)
+		return FALSE;
+
+	page = ev_document_model_backward_page (view->model);
+	if (page < 0) {
+		return FALSE;
+	}
+	ev_document_model_set_page (view->model, page);
+	return TRUE;
+}
+
+gboolean
+ev_view_forward_page (EvView *view)
+{
+	int page;
+
+	g_return_val_if_fail (EV_IS_VIEW (view), FALSE);
+
+	if (!view->document)
+		return FALSE;
+
+	page = ev_document_model_forward_page (view->model);
+	if (page < 0) {
+		return FALSE;
+	}
+	ev_document_model_set_page (view->model, page);
+	return TRUE;
+}
+
diff --git a/libview/ev-view.h b/libview/ev-view.h
index d4ee577..8e6d109 100644
--- a/libview/ev-view.h
+++ b/libview/ev-view.h
@@ -98,6 +98,8 @@ gboolean       ev_view_previous_page	  (EvView         *view);
 
 void	       ev_view_autoscroll_start   (EvView *view);
 void           ev_view_autoscroll_stop    (EvView *view);
+gboolean       ev_view_backward_page (EvView *view);
+gboolean       ev_view_forward_page (EvView *view);
 
 gboolean       ev_view_get_page_extents   (EvView       *view,
                                            gint          page,
diff --git a/shell/ev-window.c b/shell/ev-window.c
index fa7a16b..b75d790 100644
--- a/shell/ev-window.c
+++ b/shell/ev-window.c
@@ -456,6 +456,7 @@ ev_window_update_actions (EvWindow *ev_window)
 	EvView *view = EV_VIEW (ev_window->priv->view);
 	int n_pages = 0, page = -1;
 	gboolean has_pages = FALSE;
+	gboolean could_backward_page = FALSE, could_forward_page = FALSE;
 	gboolean presentation_mode;
 	gboolean can_find_in_page = FALSE;
 	EvSizingMode sizing_mode;
@@ -464,6 +465,10 @@ ev_window_update_actions (EvWindow *ev_window)
 		page = ev_document_model_get_page (ev_window->priv->model);
 		n_pages = ev_document_get_n_pages (ev_window->priv->document);
 		has_pages = n_pages > 0;
+		could_backward_page =
+			ev_document_model_could_backward_page (ev_window->priv->model);
+		could_forward_page =
+			ev_document_model_could_forward_page (ev_window->priv->model);
 	}
 
 	can_find_in_page = (ev_window->priv->find_job &&
@@ -496,11 +501,15 @@ ev_window_update_actions (EvWindow *ev_window)
 		ev_window_set_action_sensitive (ev_window, "GoNextPage", page < n_pages - 1);
 		ev_window_set_action_sensitive (ev_window, "GoFirstPage", page > 0);
 		ev_window_set_action_sensitive (ev_window, "GoLastPage", page < n_pages - 1);
+		ev_window_set_action_sensitive (ev_window, "GoBackwardPage", could_backward_page);
+		ev_window_set_action_sensitive (ev_window, "GoForwardPage", could_forward_page);
 	} else {
   		ev_window_set_action_sensitive (ev_window, "GoFirstPage", FALSE);
 		ev_window_set_action_sensitive (ev_window, "GoPreviousPage", FALSE);
 		ev_window_set_action_sensitive (ev_window, "GoNextPage", FALSE);
 		ev_window_set_action_sensitive (ev_window, "GoLastPage", FALSE);
+		ev_window_set_action_sensitive (ev_window, "GoBackwardPage", FALSE);
+		ev_window_set_action_sensitive (ev_window, "GoForwardPage", FALSE);
 	}
 
 	sizing_mode = ev_document_model_get_sizing_mode (ev_window->priv->model);
@@ -4040,6 +4049,22 @@ ev_window_cmd_go_backward (GtkAction *action, EvWindow *ev_window)
 }
 
 static void
+ev_window_cmd_go_forward_page (GtkAction *action, EvWindow *ev_window)
+{
+	g_return_if_fail (EV_IS_WINDOW (ev_window));
+
+	ev_view_forward_page (EV_VIEW (ev_window->priv->view));
+}
+
+static void
+ev_window_cmd_go_backward_page (GtkAction *action, EvWindow *ev_window)
+{
+	g_return_if_fail (EV_IS_WINDOW (ev_window));
+
+	ev_view_backward_page (EV_VIEW (ev_window->priv->view));
+}
+
+static void
 ev_window_cmd_view_reload (GtkAction *action, EvWindow *ev_window)
 {
 	ev_window_reload_document (ev_window, NULL);
@@ -5207,6 +5232,12 @@ static const GtkActionEntry entries[] = {
         { "GoLastPage", GTK_STOCK_GOTO_BOTTOM, N_("_Last Page"), "<control>End",
           N_("Go to the last page"),
           G_CALLBACK (ev_window_cmd_go_last_page) },
+        { "GoBackwardPage", GTK_STOCK_GOTO_BOTTOM, N_("_Backward Page"), "<control>B",
+          N_("Go to the backward page"),
+          G_CALLBACK (ev_window_cmd_go_backward_page) },
+        { "GoForwardPage", GTK_STOCK_GOTO_BOTTOM, N_("_Forward Page"), "<control>V",
+          N_("Go to the forward page"),
+          G_CALLBACK (ev_window_cmd_go_forward_page) },
 
 	/* Help menu */
 	{ "HelpContents", GTK_STOCK_HELP, N_("_Contents"), "F1", NULL,
@@ -5727,6 +5758,10 @@ do_action_named (EvWindow *window, EvLinkAction *action)
 		ev_window_cmd_go_next_page (NULL, window);
 	} else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
 		ev_window_cmd_go_last_page (NULL, window);
+	} else if (g_ascii_strcasecmp (name, "BackwardPage") == 0) {
+		ev_window_cmd_go_backward_page (NULL, window);
+	} else if (g_ascii_strcasecmp (name, "ForwardPage") == 0) {
+		ev_window_cmd_go_forward_page (NULL, window);
 	} else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
 		ev_window_cmd_focus_page_selector (NULL, window);
 	} else if (g_ascii_strcasecmp (name, "Find") == 0) {
-- 
1.6.4.GIT



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]