X-Git-Url: https://www.fi.muni.cz/~kas/git//home/kas/public_html/git/?a=blobdiff_plain;ds=sidebyside;f=shell%2Fev-view.c;h=3eed46a803bfe54a2ab76bfe2052c0387c25f9a9;hb=e5fc6f779c049d73ba6387cabe4ef4a4d9109e51;hp=9925d5abc072fb1dbc12bddb41c83c4f717d48ce;hpb=7dca53f0824e2e24079a000289120c55540272ed;p=evince.git diff --git a/shell/ev-view.c b/shell/ev-view.c index 9925d5ab..3eed46a8 100644 --- a/shell/ev-view.c +++ b/shell/ev-view.c @@ -33,6 +33,7 @@ #include "ev-view-private.h" #include "ev-utils.h" #include "ev-selection.h" +#include "ev-document-links.h" #include "ev-document-find.h" #include "ev-document-misc.h" #include "ev-debug.h" @@ -205,7 +206,8 @@ static void draw_one_page (EvView gint page, GdkRectangle *page_area, GtkBorder *border, - GdkRectangle *expose_area); + GdkRectangle *expose_area, + gboolean *page_ready); static void draw_loading_text (EvView *view, GdkRectangle *page_area, GdkRectangle *expose_area); @@ -384,6 +386,7 @@ view_set_adjustment_values (EvView *view, factor = 1.0; switch (view->pending_scroll) { case SCROLL_TO_KEEP_POSITION: + case SCROLL_TO_FIND_LOCATION: factor = (adjustment->value) / adjustment->upper; break; case SCROLL_TO_PAGE_POSITION: @@ -404,6 +407,7 @@ view_set_adjustment_values (EvView *view, */ switch (view->pending_scroll) { case SCROLL_TO_KEEP_POSITION: + case SCROLL_TO_FIND_LOCATION: new_value = CLAMP (adjustment->upper * factor + 0.5, 0, adjustment->upper - adjustment->page_size); gtk_adjustment_set_value (adjustment, (int)new_value); break; @@ -426,9 +430,6 @@ view_update_range_and_current_page (EvView *view) gint current_page; gint best_current_page = -1; - if (view->pending_scroll != SCROLL_TO_KEEP_POSITION) - return; - /* Presentation trumps all other modes */ if (view->presentation) { view->start_page = view->current_page; @@ -437,7 +438,7 @@ view_update_range_and_current_page (EvView *view) GdkRectangle current_area, unused, page_area; GtkBorder border; gboolean found = FALSE; - gint area_max, area; + gint area_max = -1, area; int i; if (!(view->vadjustment && view->hadjustment)) @@ -494,7 +495,7 @@ view_update_range_and_current_page (EvView *view) best_current_page = MAX (best_current_page, view->start_page); current_page = ev_page_cache_get_current_page (view->page_cache); - if (current_page != best_current_page) { + if ((current_page != best_current_page) && (view->pending_scroll == SCROLL_TO_KEEP_POSITION)) { view->current_page = best_current_page; ev_page_cache_set_current_page (view->page_cache, best_current_page); } @@ -580,7 +581,7 @@ ev_view_scroll (EvView *view, view->jump_to_find_result = FALSE; - if (view->presentation) { + if (view->presentation || view->sizing_mode == EV_SIZING_BEST_FIT) { switch (scroll) { case EV_SCROLL_PAGE_BACKWARD: case EV_SCROLL_STEP_BACKWARD: @@ -665,7 +666,7 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect) GtkAdjustment *adjustment; int value; - view->pending_scroll = SCROLL_TO_KEEP_POSITION; + view->pending_scroll = SCROLL_TO_FIND_LOCATION; adjustment = view->vadjustment; @@ -690,6 +691,8 @@ ensure_rectangle_is_visible (EvView *view, GdkRectangle *rect) widget->allocation.width + MARGIN); gtk_adjustment_set_value (view->hadjustment, value); } + + gtk_widget_queue_resize (GTK_WIDGET (view)); } /*** Geometry computations ***/ @@ -1075,25 +1078,23 @@ ev_view_get_link_at_location (EvView *view, } static void -goto_fitr_link (EvView *view, EvLink *link) +goto_fitr_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; - int page; double zoom; - zoom = zoom_for_size_best_fit (ev_link_get_right (link) - ev_link_get_left (link), - ev_link_get_top (link) - ev_link_get_bottom (link), + zoom = zoom_for_size_best_fit (ev_link_dest_get_right (dest) - ev_link_dest_get_left (dest), + ev_link_dest_get_bottom (dest) - ev_link_dest_get_top (dest), ev_view_get_width (view), ev_view_get_height (view), 0, 0); ev_view_set_sizing_mode (view, EV_SIZING_FREE); ev_view_set_zoom (view, zoom, FALSE); - page = ev_link_get_page (link); - doc_point.x = ev_link_get_left (link); - doc_point.y = ev_link_get_top (link); + doc_point.x = ev_link_dest_get_left (dest); + doc_point.y = ev_link_dest_get_top (dest); - view->current_page = page; + view->current_page = ev_link_dest_get_page (dest); view->pending_point = doc_point; view->pending_scroll = SCROLL_TO_PAGE_POSITION; @@ -1101,16 +1102,16 @@ goto_fitr_link (EvView *view, EvLink *link) } static void -goto_fitv_link (EvView *view, EvLink *link) +goto_fitv_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; int doc_width, doc_height, page; double zoom; - page = ev_link_get_page (link); + page = ev_link_dest_get_page (dest); ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height); - doc_point.x = ev_link_get_left (link); + doc_point.x = ev_link_dest_get_left (dest); doc_point.y = 0; zoom = zoom_for_size_fit_height (doc_width - doc_point.x , doc_height, @@ -1128,23 +1129,23 @@ goto_fitv_link (EvView *view, EvLink *link) } static void -goto_fith_link (EvView *view, EvLink *link) +goto_fith_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; int doc_width, doc_height, page; double zoom; - page = ev_link_get_page (link); + page = ev_link_dest_get_page (dest); ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height); doc_point.x = 0; - doc_point.y = doc_height - ev_link_get_top (link); + doc_point.y = ev_link_dest_get_top (dest); - zoom = zoom_for_size_fit_width (doc_width, ev_link_get_top (link), + zoom = zoom_for_size_fit_width (doc_width, ev_link_dest_get_top (dest), ev_view_get_width (view), ev_view_get_height (view), 0); - ev_view_set_sizing_mode (view, EV_SIZING_FREE); + ev_view_set_sizing_mode (view, EV_SIZING_FIT_WIDTH); ev_view_set_zoom (view, zoom, FALSE); view->current_page = page; @@ -1155,19 +1156,19 @@ goto_fith_link (EvView *view, EvLink *link) } static void -goto_fit_link (EvView *view, EvLink *link) +goto_fit_dest (EvView *view, EvLinkDest *dest) { double zoom; int doc_width, doc_height; int page; - page = ev_link_get_page (link); + page = ev_link_dest_get_page (dest); ev_page_cache_get_size (view->page_cache, page, 0, 1.0, &doc_width, &doc_height); zoom = zoom_for_size_best_fit (doc_width, doc_height, ev_view_get_width (view), ev_view_get_height (view), 0, 0); - ev_view_set_sizing_mode (view, EV_SIZING_FREE); + ev_view_set_sizing_mode (view, EV_SIZING_BEST_FIT); ev_view_set_zoom (view, zoom, FALSE); view->current_page = page; @@ -1177,23 +1178,22 @@ goto_fit_link (EvView *view, EvLink *link) } static void -goto_xyz_link (EvView *view, EvLink *link) +goto_xyz_dest (EvView *view, EvLinkDest *dest) { EvPoint doc_point; - int height, page; + gint page; double zoom; - zoom = ev_link_get_zoom (link); - page = ev_link_get_page (link); - ev_page_cache_get_size (view->page_cache, page, 0, 1.0, NULL, &height); + zoom = ev_link_dest_get_zoom (dest); + page = ev_link_dest_get_page (dest); - if (zoom != 0) { + if (zoom > 1) { ev_view_set_sizing_mode (view, EV_SIZING_FREE); ev_view_set_zoom (view, zoom, FALSE); } - doc_point.x = ev_link_get_left (link); - doc_point.y = height - ev_link_get_top (link); + doc_point.x = ev_link_dest_get_left (dest); + doc_point.y = ev_link_dest_get_top (dest); view->current_page = page; view->pending_point = doc_point; @@ -1202,70 +1202,205 @@ goto_xyz_link (EvView *view, EvLink *link) gtk_widget_queue_resize (GTK_WIDGET (view)); } -void -ev_view_goto_link (EvView *view, EvLink *link) +static void +goto_dest (EvView *view, EvLinkDest *dest) { - EvLinkType type; - int page; + EvLinkDestType type; + int page, n_pages; - type = ev_link_get_link_type (link); + page = ev_link_dest_get_page (dest); + n_pages = ev_page_cache_get_n_pages (view->page_cache); + + if (page < 0 || page >= n_pages) + return; + + type = ev_link_dest_get_dest_type (dest); switch (type) { - case EV_LINK_TYPE_TITLE: - break; - case EV_LINK_TYPE_PAGE: - page = ev_link_get_page (link); + case EV_LINK_DEST_TYPE_PAGE: ev_page_cache_set_current_page (view->page_cache, page); break; - case EV_LINK_TYPE_PAGE_FIT: - goto_fit_link (view, link); + case EV_LINK_DEST_TYPE_FIT: + goto_fit_dest (view, dest); break; - case EV_LINK_TYPE_PAGE_FITH: - goto_fith_link (view, link); + case EV_LINK_DEST_TYPE_FITH: + goto_fith_dest (view, dest); break; - case EV_LINK_TYPE_PAGE_FITV: - goto_fitv_link (view, link); + case EV_LINK_DEST_TYPE_FITV: + goto_fitv_dest (view, dest); break; - case EV_LINK_TYPE_PAGE_FITR: - goto_fitr_link (view, link); + case EV_LINK_DEST_TYPE_FITR: + goto_fitr_dest (view, dest); break; - case EV_LINK_TYPE_PAGE_XYZ: - goto_xyz_link (view, link); + case EV_LINK_DEST_TYPE_XYZ: + goto_xyz_dest (view, dest); break; - case EV_LINK_TYPE_EXTERNAL_URI: - case EV_LINK_TYPE_LAUNCH: - g_signal_emit (view, signals[SIGNAL_EXTERNAL_LINK], 0, link); + case EV_LINK_DEST_TYPE_PAGE_LABEL: + ev_page_cache_set_page_label (view->page_cache, ev_link_dest_get_page_label (dest)); break; + default: + g_assert_not_reached (); + } +} + +void +ev_view_goto_dest (EvView *view, EvLinkDest *dest) +{ + EvLinkDestType type; + + type = ev_link_dest_get_dest_type (dest); + + if (type == EV_LINK_DEST_TYPE_NAMED) { + EvLinkDest *dest2; + const gchar *named_dest; + + named_dest = ev_link_dest_get_named_dest (dest); + dest2 = ev_document_links_find_link_dest (EV_DOCUMENT_LINKS (view->document), + named_dest); + if (dest2) { + goto_dest (view, dest2); + g_object_unref (dest2); + } + + return; + } + + goto_dest (view, dest); +} + +void +ev_view_handle_link (EvView *view, EvLink *link) +{ + EvLinkAction *action = NULL; + EvLinkActionType type; + + action = ev_link_get_action (link); + if (!action) + return; + + type = ev_link_action_get_action_type (action); + + switch (type) { + case EV_LINK_ACTION_TYPE_GOTO_DEST: { + EvLinkDest *dest; + + dest = ev_link_action_get_dest (action); + ev_view_goto_dest (view, dest); + } + break; + case EV_LINK_ACTION_TYPE_GOTO_REMOTE: + case EV_LINK_ACTION_TYPE_EXTERNAL_URI: + case EV_LINK_ACTION_TYPE_LAUNCH: + case EV_LINK_ACTION_TYPE_NAMED: + g_signal_emit (view, signals[SIGNAL_EXTERNAL_LINK], 0, action); + break; + } +} + +static gchar * +page_label_from_dest (EvView *view, EvLinkDest *dest) +{ + EvLinkDestType type; + gchar *msg = NULL; + + type = ev_link_dest_get_dest_type (dest); + + switch (type) { + case EV_LINK_DEST_TYPE_NAMED: { + EvLinkDest *dest2; + const gchar *named_dest; + + named_dest = ev_link_dest_get_named_dest (dest); + dest2 = ev_document_links_find_link_dest (EV_DOCUMENT_LINKS (view->document), + named_dest); + if (dest2) { + msg = ev_page_cache_get_page_label (view->page_cache, + ev_link_dest_get_page (dest2)); + g_object_unref (dest2); + } + } + + break; + default: + msg = ev_page_cache_get_page_label (view->page_cache, + ev_link_dest_get_page (dest)); + } + + return msg; +} + +static char * +tip_from_action_named (EvLinkAction *action) +{ + const gchar *name = ev_link_action_get_name (action); + + if (g_ascii_strcasecmp (name, "FirstPage") == 0) { + return g_strdup (_("Go to first page")); + } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) { + return g_strdup (_("Go to previous page")); + } else if (g_ascii_strcasecmp (name, "NextPage") == 0) { + return g_strdup (_("Go to next page")); + } else if (g_ascii_strcasecmp (name, "LastPage") == 0) { + return g_strdup (_("Go to last page")); + } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) { + return g_strdup (_("Go to page")); + } else if (g_ascii_strcasecmp (name, "Find") == 0) { + return g_strdup (_("Find")); } + + return NULL; } static char * tip_from_link (EvView *view, EvLink *link) { - EvLinkType type; + EvLinkAction *action; + EvLinkActionType type; char *msg = NULL; char *page_label; + const char *title; - type = ev_link_get_link_type (link); + action = ev_link_get_action (link); + title = ev_link_get_title (link); + + if (!action) + return title ? g_strdup (title) : NULL; + + type = ev_link_action_get_action_type (action); switch (type) { - case EV_LINK_TYPE_TITLE: - if (ev_link_get_title (link)) - msg = g_strdup (ev_link_get_title (link)); - break; - case EV_LINK_TYPE_PAGE: - case EV_LINK_TYPE_PAGE_XYZ: - page_label = ev_page_cache_get_page_label (view->page_cache, ev_link_get_page (link)); + case EV_LINK_ACTION_TYPE_GOTO_DEST: + page_label = page_label_from_dest (view, + ev_link_action_get_dest (action)); msg = g_strdup_printf (_("Go to page %s"), page_label); g_free (page_label); break; - case EV_LINK_TYPE_EXTERNAL_URI: - msg = g_strdup (ev_link_get_uri (link)); + case EV_LINK_ACTION_TYPE_GOTO_REMOTE: + if (title) { + msg = g_strdup_printf (_("Go to %s on file “%s”"), title, + ev_link_action_get_filename (action)); + } else { + msg = g_strdup_printf (_("Go to file “%s”"), + ev_link_action_get_filename (action)); + } + + break; + case EV_LINK_ACTION_TYPE_EXTERNAL_URI: + msg = g_strdup (ev_link_action_get_uri (action)); + break; + case EV_LINK_ACTION_TYPE_LAUNCH: + msg = g_strdup_printf (_("Launch %s"), + ev_link_action_get_filename (action)); + break; + case EV_LINK_ACTION_TYPE_NAMED: + msg = tip_from_action_named (action); break; - default: + default: + if (title) + msg = g_strdup (title); break; } - + return msg; } @@ -1476,12 +1611,12 @@ ev_view_size_allocate (GtkWidget *widget, view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL); view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL); - view->pending_scroll = SCROLL_TO_KEEP_POSITION; - view->pending_resize = FALSE; - if (view->document) view_update_range_and_current_page (view); + view->pending_scroll = SCROLL_TO_KEEP_POSITION; + view->pending_resize = FALSE; + GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation); } @@ -1570,14 +1705,14 @@ ev_view_scroll_event (GtkWidget *widget, GdkEventScroll *event) if (state == 0 && view->presentation) { switch (event->direction) { - case GDK_SCROLL_DOWN: - case GDK_SCROLL_RIGHT: - ev_view_next_page (view); - break; - case GDK_SCROLL_UP: - case GDK_SCROLL_LEFT: - ev_view_previous_page (view); - break; + case GDK_SCROLL_DOWN: + case GDK_SCROLL_RIGHT: + ev_view_next_page (view); + break; + case GDK_SCROLL_UP: + case GDK_SCROLL_LEFT: + ev_view_previous_page (view); + break; } return TRUE; @@ -1628,6 +1763,7 @@ ev_view_expose_event (GtkWidget *widget, for (i = view->start_page; i <= view->end_page; i++) { GdkRectangle page_area; GtkBorder border; + gboolean page_ready = TRUE; if (!get_page_extents (view, i, &page_area, &border)) continue; @@ -1635,9 +1771,9 @@ ev_view_expose_event (GtkWidget *widget, page_area.x -= view->scroll_x; page_area.y -= view->scroll_y; - draw_one_page (view, i, &page_area, &border, &(event->area)); + draw_one_page (view, i, &page_area, &border, &(event->area), &page_ready); - if (EV_IS_DOCUMENT_FIND (view->document)) + if (page_ready && EV_IS_DOCUMENT_FIND (view->document)) highlight_find_results (view, i); } @@ -1898,7 +2034,7 @@ ev_view_button_release_event (GtkWidget *widget, ev_view_set_cursor (view, EV_VIEW_CURSOR_NORMAL); } - if (view->document) { + if (view->document && view->pressed_button == 1) { link = ev_view_get_link_at_location (view, event->x, event->y); } else { link = NULL; @@ -1926,15 +2062,15 @@ ev_view_button_release_event (GtkWidget *widget, view->selection_info.in_drag = FALSE; } else if (link) { - ev_view_goto_link (view, link); + ev_view_handle_link (view, link); } else if (view->presentation) { switch (event->button) { - case 1: - ev_view_next_page (view); - return TRUE; - case 3: - ev_view_previous_page (view); - return TRUE; + case 1: + ev_view_next_page (view); + return TRUE; + case 3: + ev_view_previous_page (view); + return TRUE; } } @@ -2092,6 +2228,12 @@ draw_loading_text (EvView *view, double real_scale; int target_width; + /* Don't annoy users with loading messages during presentations. + * FIXME: Temporary "workaround" for + * http://bugzilla.gnome.org/show_bug.cgi?id=320352 */ + if (view->presentation) + return; + const char *loading_text = _("Loading..."); layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text); @@ -2131,7 +2273,8 @@ draw_one_page (EvView *view, gint page, GdkRectangle *page_area, GtkBorder *border, - GdkRectangle *expose_area) + GdkRectangle *expose_area, + gboolean *page_ready) { gint width, height; GdkPixbuf *current_pixbuf; @@ -2141,7 +2284,7 @@ draw_one_page (EvView *view, gint current_page; g_assert (view->document); - + if (! gdk_rectangle_intersect (page_area, expose_area, &overlap)) return; @@ -2158,6 +2301,7 @@ draw_one_page (EvView *view, real_page_area.y += border->top; real_page_area.width -= (border->left + border->right); real_page_area.height -= (border->top + border->bottom); + *page_ready = TRUE; ev_document_misc_paint_one_page (GTK_WIDGET(view)->window, GTK_WIDGET (view), @@ -2217,6 +2361,7 @@ draw_one_page (EvView *view, draw_loading_text (view, &real_page_area, expose_area); + *page_ready = FALSE; } if (scaled_selection) { @@ -2268,6 +2413,7 @@ ev_view_destroy (GtkObject *object) if (view->link_tooltip) { gtk_widget_destroy (view->link_tooltip); + view->link_tooltip = NULL; } if (view->selection_scroll_id) { @@ -2293,31 +2439,30 @@ ev_view_set_property (GObject *object, { EvView *view = EV_VIEW (object); - switch (prop_id) - { - case PROP_CONTINUOUS: - ev_view_set_continuous (view, g_value_get_boolean (value)); - break; - case PROP_DUAL_PAGE: - ev_view_set_dual_page (view, g_value_get_boolean (value)); - break; - case PROP_FULLSCREEN: - ev_view_set_fullscreen (view, g_value_get_boolean (value)); - break; - case PROP_PRESENTATION: - ev_view_set_presentation (view, g_value_get_boolean (value)); - break; - case PROP_SIZING_MODE: - ev_view_set_sizing_mode (view, g_value_get_enum (value)); - break; - case PROP_ZOOM: - ev_view_set_zoom (view, g_value_get_double (value), FALSE); - break; - case PROP_ROTATION: - ev_view_set_rotation (view, g_value_get_int (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) { + case PROP_CONTINUOUS: + ev_view_set_continuous (view, g_value_get_boolean (value)); + break; + case PROP_DUAL_PAGE: + ev_view_set_dual_page (view, g_value_get_boolean (value)); + break; + case PROP_FULLSCREEN: + ev_view_set_fullscreen (view, g_value_get_boolean (value)); + break; + case PROP_PRESENTATION: + ev_view_set_presentation (view, g_value_get_boolean (value)); + break; + case PROP_SIZING_MODE: + ev_view_set_sizing_mode (view, g_value_get_enum (value)); + break; + case PROP_ZOOM: + ev_view_set_zoom (view, g_value_get_double (value), FALSE); + break; + case PROP_ROTATION: + ev_view_set_rotation (view, g_value_get_int (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } @@ -2360,41 +2505,40 @@ ev_view_get_property (GObject *object, { EvView *view = EV_VIEW (object); - switch (prop_id) - { - case PROP_STATUS: - g_value_set_string (value, view->status); - break; - case PROP_FIND_STATUS: - g_value_set_string (value, view->status); - break; - case PROP_CONTINUOUS: - g_value_set_boolean (value, view->continuous); - break; - case PROP_DUAL_PAGE: - g_value_set_boolean (value, view->dual_page); - break; - case PROP_FULLSCREEN: - g_value_set_boolean (value, view->fullscreen); - break; - case PROP_PRESENTATION: - g_value_set_boolean (value, view->presentation); - break; - case PROP_SIZING_MODE: - g_value_set_enum (value, view->sizing_mode); - break; - case PROP_ZOOM: - g_value_set_double (value, view->scale); - break; - case PROP_ROTATION: - g_value_set_int (value, view->rotation); - break; - case PROP_HAS_SELECTION: - g_value_set_boolean (value, - view->selection_info.selections != NULL); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + switch (prop_id) { + case PROP_STATUS: + g_value_set_string (value, view->status); + break; + case PROP_FIND_STATUS: + g_value_set_string (value, view->status); + break; + case PROP_CONTINUOUS: + g_value_set_boolean (value, view->continuous); + break; + case PROP_DUAL_PAGE: + g_value_set_boolean (value, view->dual_page); + break; + case PROP_FULLSCREEN: + g_value_set_boolean (value, view->fullscreen); + break; + case PROP_PRESENTATION: + g_value_set_boolean (value, view->presentation); + break; + case PROP_SIZING_MODE: + g_value_set_enum (value, view->sizing_mode); + break; + case PROP_ZOOM: + g_value_set_double (value, view->scale); + break; + case PROP_ROTATION: + g_value_set_int (value, view->rotation); + break; + case PROP_HAS_SELECTION: + g_value_set_boolean (value, + view->selection_info.selections != NULL); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } @@ -3993,6 +4137,9 @@ ev_view_next_page (EvView *view) int page; g_return_val_if_fail (EV_IS_VIEW (view), FALSE); + + if (!view->page_cache) + return FALSE; page = ev_page_cache_get_current_page (view->page_cache); @@ -4019,6 +4166,9 @@ ev_view_previous_page (EvView *view) g_return_val_if_fail (EV_IS_VIEW (view), FALSE); + if (!view->page_cache) + return FALSE; + page = ev_page_cache_get_current_page (view->page_cache); if (view->dual_page && !view->presentation)