E-book viewer: Make bookmark positioning (and remembering last read location) more robust. Fixes #4812 (E-book viewer not correctly remembering reading position on reopen)

This commit is contained in:
Kovid Goyal 2010-02-08 11:48:15 -07:00
parent 80ad1fa467
commit cf5ca45531
2 changed files with 46 additions and 33 deletions

View File

@ -20,37 +20,8 @@ function selector(elem) {
return sel; return sel;
} }
function find_closest_enclosing_block(top) { function calculate_bookmark(y, node) {
var START = top-1000; var elem = $(node);
var STOP = top;
var matches = [];
var elem, temp;
var width = 1000;
for (y = START; y < STOP; y += 20) {
for ( x = 0; x < width; x += 20) {
elem = document.elementFromPoint(x, y);
try {
elem = $(elem);
temp = elem.offset().top
matches.push(elem);
if (Math.abs(temp - START) < 25) { y = STOP; break}
} catch(error) {}
}
}
var miny = Math.abs(matches[0].offset().top - START), min_elem = matches[0];
for (i = 1; i < matches.length; i++) {
elem = matches[i];
temp = Math.abs(elem.offset().top - START);
if ( temp < miny ) { miny = temp; min_elem = elem; }
}
return min_elem;
}
function calculate_bookmark(y) {
var elem = find_closest_enclosing_block(y);
var sel = selector(elem); var sel = selector(elem);
var ratio = (y - elem.offset().top)/elem.height(); var ratio = (y - elem.offset().top)/elem.height();
if (ratio > 1) { ratio = 1; } if (ratio > 1) { ratio = 1; }

View File

@ -5,7 +5,7 @@ __docformat__ = 'restructuredtext en'
''' '''
''' '''
import os, math, re, glob import os, math, re, glob, sys
from base64 import b64encode from base64 import b64encode
from PyQt4.Qt import QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \ from PyQt4.Qt import QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \ QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
@ -295,8 +295,50 @@ class Document(QWebPage):
if r > 0: if r > 0:
self.javascript('document.body.style.paddingBottom = "%dpx"'%r) self.javascript('document.body.style.paddingBottom = "%dpx"'%r)
def element_ypos(self, elem):
ans, ok = elem.evaluateJavaScript('$(this).offset().top').toInt()
if not ok:
raise ValueError('No ypos found')
return ans
def elem_outer_xml(self, elem):
return unicode(elem.toOuterXml())
def find_bookmark_element(self):
mf = self.mainFrame()
doc_pos = self.ypos
min_delta, min_elem = sys.maxint, None
for y in range(10, -500, -10):
for x in range(-50, 500, 10):
pos = QPoint(x, y)
result = mf.hitTestContent(pos)
if result.isNull(): continue
elem = result.enclosingBlockElement()
if elem.isNull(): continue
try:
ypos = self.element_ypos(elem)
except:
continue
delta = abs(ypos - doc_pos)
if delta < 25:
return elem
if delta < min_delta:
min_elem, min_delta = elem, delta
return min_elem
def bookmark(self): def bookmark(self):
return self.javascript('calculate_bookmark(%d)'%(self.ypos+25), 'string') elem = self.find_bookmark_element()
if elem is None or self.element_ypos(elem) < 100:
print elem, self.element_ypos(elem)
bm = 'body|%f'%(float(self.ypos)/(self.height*0.7))
else:
bm = unicode(elem.evaluateJavaScript(
'calculate_bookmark(%d, this)'%self.ypos).toString())
if not bm:
bm = 'body|%f'%(float(self.ypos)/(self.height*0.7))
return bm
@property @property
def at_bottom(self): def at_bottom(self):