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;
}
function find_closest_enclosing_block(top) {
var START = top-1000;
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);
function calculate_bookmark(y, node) {
var elem = $(node);
var sel = selector(elem);
var ratio = (y - elem.offset().top)/elem.height();
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 PyQt4.Qt import QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, \
QPainter, QPalette, QBrush, QFontDatabase, QDialog, \
@ -295,8 +295,50 @@ class Document(QWebPage):
if r > 0:
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):
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
def at_bottom(self):