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)

This commit is contained in:
Kovid Goyal 2012-01-25 18:52:38 +05:30
parent ceb0638ccd
commit fda1184662
4 changed files with 78 additions and 12 deletions

View File

@ -166,6 +166,8 @@ class CanonicalFragmentIdentifier
### ###
constructor: () -> # {{{ 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.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." this.IE_ERR = "Your browser is too old. You need Internet Explorer version 9 or newer."
div = document.createElement('div') div = document.createElement('div')

View File

@ -24,6 +24,7 @@ from calibre.constants import iswindows
from calibre import prints, guess_type from calibre import prints, guess_type
from calibre.gui2.viewer.keys import SHORTCUTS from calibre.gui2.viewer.keys import SHORTCUTS
from calibre.gui2.viewer.javascript import JavaScriptLoader 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.SerifFont, opts.serif_family)
settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family) settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family)
settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family) settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family)
settings.setAttribute(QWebSettings.ZoomTextOnly, True)
def do_config(self, parent=None): def do_config(self, parent=None):
d = ConfigDialog(self.shortcuts, parent) d = ConfigDialog(self.shortcuts, parent)
if d.exec_() == QDialog.Accepted: if d.exec_() == QDialog.Accepted:
self.set_font_settings() with self.page_position:
self.set_user_stylesheet() self.set_font_settings()
self.misc_config() self.set_user_stylesheet()
self.after_load() self.misc_config()
self.after_load()
def __init__(self, shortcuts, parent=None, resize_callback=lambda: None, def __init__(self, shortcuts, parent=None, resize_callback=lambda: None,
debug_javascript=False): debug_javascript=False):
@ -196,6 +199,7 @@ class Document(QWebPage): # {{{
pal = self.palette() pal = self.palette()
pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee)) pal.setBrush(QPalette.Background, QColor(0xee, 0xee, 0xee))
self.setPalette(pal) self.setPalette(pal)
self.page_position = PagePosition(self)
settings = self.settings() settings = self.settings()
@ -895,23 +899,25 @@ class DocumentView(QWebView): # {{{
@dynamic_property @dynamic_property
def multiplier(self): def multiplier(self):
def fget(self): def fget(self):
return self.document.mainFrame().textSizeMultiplier() return self.zoomFactor()
def fset(self, val): def fset(self, val):
self.document.mainFrame().setTextSizeMultiplier(val) self.setZoomFactor(val)
self.magnification_changed.emit(val) self.magnification_changed.emit(val)
return property(fget=fget, fset=fset) return property(fget=fget, fset=fset)
def magnify_fonts(self, amount=None): def magnify_fonts(self, amount=None):
if amount is None: if amount is None:
amount = self.document.font_magnification_step amount = self.document.font_magnification_step
self.multiplier += amount with self.document.page_position:
self.multiplier += amount
return self.document.scroll_fraction return self.document.scroll_fraction
def shrink_fonts(self, amount=None): def shrink_fonts(self, amount=None):
if amount is None: if amount is None:
amount = self.document.font_magnification_step amount = self.document.font_magnification_step
if self.multiplier >= amount: if self.multiplier >= amount:
self.multiplier -= amount with self.document.page_position:
self.multiplier -= amount
return self.document.scroll_fraction return self.document.scroll_fraction
def changeEvent(self, event): def changeEvent(self, event):

View File

@ -481,16 +481,14 @@ class EbookViewer(MainWindow, Ui_EbookViewer):
self.load_ebook(action.path) self.load_ebook(action.path)
def font_size_larger(self): 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_larger.setEnabled(self.view.multiplier < 3)
self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2) self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2)
self.set_page_number(frac)
def font_size_smaller(self): 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_larger.setEnabled(self.view.multiplier < 3)
self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2) self.action_font_size_smaller.setEnabled(self.view.multiplier > 0.2)
self.set_page_number(frac)
def magnification_changed(self, val): def magnification_changed(self, val):
tt = _('Make font size %(which)s\nCurrent magnification: %(mag).1f') tt = _('Make font size %(which)s\nCurrent magnification: %(mag).1f')

View File

@ -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 <kovid@kovidgoyal.net>'
__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