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