|
-- 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