From fda118466258c26f7934dd2067680c42b5e2042e Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 25 Jan 2012 18:52:38 +0530 Subject: [PATCH] E-book viewer: Preserve the current position more accurately when changing font size/other preferences. Fixes #912406 (Preserve reading position when changing font magnification or in preferences changing font or size) --- src/calibre/ebooks/oeb/display/cfi.coffee | 2 + src/calibre/gui2/viewer/documentview.py | 22 ++++++--- src/calibre/gui2/viewer/main.py | 6 +-- src/calibre/gui2/viewer/position.py | 60 +++++++++++++++++++++++ 4 files changed, 78 insertions(+), 12 deletions(-) create mode 100644 src/calibre/gui2/viewer/position.py diff --git a/src/calibre/ebooks/oeb/display/cfi.coffee b/src/calibre/ebooks/oeb/display/cfi.coffee index 260c0b71f1..8efc6866b5 100644 --- a/src/calibre/ebooks/oeb/display/cfi.coffee +++ b/src/calibre/ebooks/oeb/display/cfi.coffee @@ -166,6 +166,8 @@ class CanonicalFragmentIdentifier ### constructor: () -> # {{{ + if not this instanceof arguments.callee + throw new Error('CFI constructor called as function') this.CREATE_RANGE_ERR = "Your browser does not support the createRange function. Update it to a newer version." this.IE_ERR = "Your browser is too old. You need Internet Explorer version 9 or newer." div = document.createElement('div') diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index 9009182cb5..710b7722a7 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -24,6 +24,7 @@ from calibre.constants import iswindows from calibre import prints, guess_type from calibre.gui2.viewer.keys import SHORTCUTS from calibre.gui2.viewer.javascript import JavaScriptLoader +from calibre.gui2.viewer.position import PagePosition # }}} @@ -170,14 +171,16 @@ class Document(QWebPage): # {{{ settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family) settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family) settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family) + settings.setAttribute(QWebSettings.ZoomTextOnly, True) def do_config(self, parent=None): d = ConfigDialog(self.shortcuts, parent) if d.exec_() == QDialog.Accepted: - self.set_font_settings() - self.set_user_stylesheet() - self.misc_config() - self.after_load() + with self.page_position: + self.set_font_settings() + self.set_user_stylesheet() + self.misc_config() + self.after_load() def __init__(self, shortcuts, parent=None, resize_callback=lambda: None, debug_javascript=False): @@ -196,6 +199,7 @@ class Document(QWebPage): # {{{ pal = self.palette() pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee)) self.setPalette(pal) + self.page_position = PagePosition(self) settings = self.settings() @@ -895,23 +899,25 @@ class DocumentView(QWebView): # {{{ @dynamic_property def multiplier(self): def fget(self): - return self.document.mainFrame().textSizeMultiplier() + return self.zoomFactor() def fset(self, val): - self.document.mainFrame().setTextSizeMultiplier(val) + self.setZoomFactor(val) self.magnification_changed.emit(val) return property(fget=fget, fset=fset) def magnify_fonts(self, amount=None): if amount is None: amount = self.document.font_magnification_step - self.multiplier += amount + with self.document.page_position: + self.multiplier += amount return self.document.scroll_fraction def shrink_fonts(self, amount=None): if amount is None: amount = self.document.font_magnification_step if self.multiplier >= amount: - self.multiplier -= amount + with self.document.page_position: + self.multiplier -= amount return self.document.scroll_fraction def changeEvent(self, event): diff --git a/src/calibre/gui2/viewer/main.py b/src/calibre/gui2/viewer/main.py index 2cf53824c4..f37465d02a 100644 --- a/src/calibre/gui2/viewer/main.py +++ b/src/calibre/gui2/viewer/main.py @@ -481,16 +481,14 @@ class EbookViewer(MainWindow, Ui_EbookViewer): self.load_ebook(action.path) def font_size_larger(self): - frac = self.view.magnify_fonts() + self.view.magnify_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2) - self.set_page_number(frac) def font_size_smaller(self): - frac = self.view.shrink_fonts() + self.view.shrink_fonts() self.action_font_size_larger.setEnabled(self.view.multiplier < 3) self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2) - self.set_page_number(frac) def magnification_changed(self, val): tt = _('Make font size %(which)s\nCurrent magnification: %(mag).1f') diff --git a/src/calibre/gui2/viewer/position.py b/src/calibre/gui2/viewer/position.py new file mode 100644 index 0000000000..cd2f9d2975 --- /dev/null +++ b/src/calibre/gui2/viewer/position.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2012, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +import json + +class PagePosition(object): + + def __init__(self, document): + self.document = document + + @property + def viewport_cfi(self): + ans = None + res = self.document.mainFrame().evaluateJavaScript(''' + ans = 'undefined'; + try { + ans = window.cfi.at_current(); + if (!ans) ans = 'undefined'; + } catch (err) { + window.console.log(err); + } + window.console.log("Viewport cfi: " + ans); + ans; + ''') + if res.isValid() and not res.isNull() and res.type() == res.String: + c = unicode(res.toString()) + if c != 'undefined': + ans = c + return ans + + def scroll_to_cfi(self, cfi): + if cfi: + cfi = json.dumps(cfi) + self.document.mainFrame().evaluateJavaScript(''' + window.cfi.scroll_to(%s); + '''%cfi) + + @property + def current_pos(self): + ans = self.viewport_cfi + if not ans: + ans = self.document.scroll_fraction + return ans + + def __enter__(self): + self._cpos = self.current_pos + + def __exit__(self, *args): + if isinstance(self._cpos, (int, float)): + self.document.scroll_fraction = self._cpos + else: + self.scroll_to_cfi(self._cpos) + self._cpos = None +