mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
IGN:Cleanup of ebook viewer code
This commit is contained in:
parent
c6853892d0
commit
ceace20197
71
resources/viewer/bookmarks.js
Normal file
71
resources/viewer/bookmarks.js
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* bookmarks management
|
||||
* Copyright 2008 Kovid Goyal
|
||||
* License: GNU GPL v3
|
||||
*/
|
||||
|
||||
function selector_in_parent(elem) {
|
||||
var num = elem.prevAll().length;
|
||||
var sel = " > *:eq("+num+") ";
|
||||
return sel;
|
||||
}
|
||||
|
||||
function selector(elem) {
|
||||
var obj = elem;
|
||||
var sel = "";
|
||||
while (obj[0] != document) {
|
||||
sel = selector_in_parent(obj) + sel;
|
||||
obj = obj.parent();
|
||||
}
|
||||
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);
|
||||
var sel = selector(elem);
|
||||
var ratio = (y - elem.offset().top)/elem.height();
|
||||
if (ratio > 1) { ratio = 1; }
|
||||
if (ratio < 0) { ratio = 0; }
|
||||
return sel + "|" + ratio;
|
||||
}
|
||||
|
||||
function animated_scrolling_done() {
|
||||
window.py_bridge.animated_scroll_done();
|
||||
}
|
||||
|
||||
function scroll_to_bookmark(bookmark) {
|
||||
bm = bookmark.split("|");
|
||||
var ratio = 0.7 * parseFloat(bm[1]);
|
||||
$.scrollTo($(bm[0]), 1000,
|
||||
{over:ratio, onAfter:function(){window.py_bridge.animated_scroll_done()}});
|
||||
}
|
||||
|
26
resources/viewer/hyphenation.js
Normal file
26
resources/viewer/hyphenation.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* bookmarks management
|
||||
* Copyright 2008 Kovid Goyal
|
||||
* License: GNU GPL v3
|
||||
*/
|
||||
|
||||
function init_hyphenate() {
|
||||
window.py_bridge.init_hyphenate();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", init_hyphenate, false);
|
||||
|
||||
function do_hyphenation(lang) {
|
||||
Hyphenator.config(
|
||||
{
|
||||
'minwordlength' : 6,
|
||||
//'hyphenchar' : '|',
|
||||
'displaytogglebox' : false,
|
||||
'remoteloading' : false,
|
||||
'onerrorhandler' : function (e) {
|
||||
window.py_bridge.debug(e);
|
||||
}
|
||||
});
|
||||
Hyphenator.hyphenate(document.body, lang);
|
||||
}
|
||||
|
62
resources/viewer/referencing.js
Normal file
62
resources/viewer/referencing.js
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* reference management
|
||||
* Copyright 2008 Kovid Goyal
|
||||
* License: GNU GPL v3
|
||||
*/
|
||||
|
||||
|
||||
|
||||
var reference_old_bgcol = "transparent";
|
||||
var reference_prefix = "1.";
|
||||
|
||||
function show_reference_panel(ref) {
|
||||
panel = $("#calibre_reference_panel");
|
||||
if (panel.length < 1) {
|
||||
$(document.body).append('<div id="calibre_reference_panel" style="top:20px; left:20px; padding-left:30px; padding-right:30px; font:monospace normal;text-align:center; z-index:10000; background: beige; border:red ridge 2px; position:absolute;"><h5>Paragraph</h5><p style="text-indent:0pt">None</p></div>')
|
||||
panel = $("#calibre_reference_panel");
|
||||
}
|
||||
$("> p", panel).text(ref);
|
||||
panel.css({top:(window.pageYOffset+20)+"px"});
|
||||
panel.fadeIn(500);
|
||||
}
|
||||
|
||||
function toggle_reference(e) {
|
||||
p = $(this);
|
||||
if (e.type == "mouseenter") {
|
||||
reference_old_bgcol = p.css("background-color");
|
||||
p.css({backgroundColor:"beige"});
|
||||
var i = 0;
|
||||
var paras = $("p");
|
||||
for (j = 0; j < paras.length; j++,i++) {
|
||||
if (paras[j] == p[0]) break;
|
||||
}
|
||||
show_reference_panel(reference_prefix+(i+1) );
|
||||
} else {
|
||||
p.css({backgroundColor:reference_old_bgcol});
|
||||
panel = $("#calibre_reference_panel").hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function enter_reference_mode() {
|
||||
$("p").bind("mouseenter mouseleave", toggle_reference);
|
||||
}
|
||||
|
||||
function leave_reference_mode() {
|
||||
$("p").unbind("mouseenter mouseleave", toggle_reference);
|
||||
}
|
||||
|
||||
function goto_reference(ref) {
|
||||
var tokens = ref.split(".");
|
||||
if (tokens.length != 2) {alert("Invalid reference: "+ref); return;}
|
||||
var num = parseInt(tokens[1]);
|
||||
if (isNaN(num)) {alert("Invalid reference: "+ref); return;}
|
||||
num -= 1;
|
||||
if (num < 0) {alert("Invalid reference: "+ref); return;}
|
||||
var p = $("p");
|
||||
if (num >= p.length) {alert("Reference not found: "+ref); return;}
|
||||
$.scrollTo($(p[num]), 1000,
|
||||
{onAfter:function(){window.py_bridge.animated_scroll_done()}});
|
||||
}
|
||||
|
||||
|
@ -386,7 +386,7 @@ def main():
|
||||
{
|
||||
'optimize' : 2,
|
||||
'dist_dir' : 'build/py2app',
|
||||
'argv_emulation' : False,
|
||||
'argv_emulation' : True,
|
||||
'iconfile' : icon,
|
||||
'frameworks': ['libusb.dylib', 'libunrar.dylib'],
|
||||
'includes' : ['sip', 'pkg_resources', 'PyQt4.QtXml',
|
||||
|
@ -15,11 +15,12 @@ from PyQt4.QtWebKit import QWebPage, QWebView, QWebSettings
|
||||
from calibre.utils.config import Config, StringConfig
|
||||
from calibre.utils.localization import get_language
|
||||
from calibre.gui2.viewer.config_ui import Ui_Dialog
|
||||
from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation
|
||||
from calibre.ptempfile import PersistentTemporaryFile
|
||||
from calibre.constants import iswindows
|
||||
from calibre import prints, guess_type
|
||||
|
||||
bookmarks = referencing = hyphenation = jquery = jquery_scrollTo = hyphenator = None
|
||||
|
||||
def load_builtin_fonts():
|
||||
base = P('fonts/liberation/*.ttf')
|
||||
for f in glob.glob(base):
|
||||
@ -192,15 +193,24 @@ class Document(QWebPage):
|
||||
self.hyphenate_default_lang = opts.hyphenate_default_lang
|
||||
|
||||
def load_javascript_libraries(self):
|
||||
global bookmarks, referencing, hyphenation, jquery, jquery_scrollTo, hyphenator
|
||||
self.mainFrame().addToJavaScriptWindowObject("py_bridge", self)
|
||||
jquery = open(P('content_server/jquery.js'), 'rb').read()
|
||||
jquery_scrollTo = open(P('viewer/jquery_scrollTo.js'), 'rb').read()
|
||||
hyphenator = open(P('viewer/hyphenate/Hyphenator.js'),
|
||||
'rb').read().decode('utf-8')
|
||||
if jquery is None:
|
||||
jquery = P('content_server/jquery.js', data=True)
|
||||
if jquery_scrollTo is None:
|
||||
jquery_scrollTo = P('viewer/jquery_scrollTo.js', data=True)
|
||||
if hyphenator is None:
|
||||
hyphenator = P('viewer/hyphenate/Hyphenator.js', data=True).decode('utf-8')
|
||||
self.javascript(jquery)
|
||||
self.javascript(jquery_scrollTo)
|
||||
if bookmarks is None:
|
||||
bookmarks = P('viewer/bookmarks.js', data=True)
|
||||
self.javascript(bookmarks)
|
||||
if referencing is None:
|
||||
referencing = P('viewer/referencing.js', data=True)
|
||||
self.javascript(referencing)
|
||||
if hyphenation is None:
|
||||
hyphenation = P('viewer/hyphenation.js', data=True)
|
||||
self.javascript(hyphenation)
|
||||
default_lang = self.hyphenate_default_lang
|
||||
lang = self.current_language
|
||||
@ -333,6 +343,7 @@ class Document(QWebPage):
|
||||
def width(self):
|
||||
return self.mainFrame().contentsSize().width() # offsetWidth gives inaccurate results
|
||||
|
||||
|
||||
class EntityDeclarationProcessor(object):
|
||||
|
||||
def __init__(self, html):
|
||||
@ -508,6 +519,7 @@ class DocumentView(QWebView):
|
||||
|
||||
@classmethod
|
||||
def test_line(cls, img, y):
|
||||
'Test if line contains pixels of exactly the same color'
|
||||
start = img.pixel(0, y)
|
||||
for i in range(1, img.width()):
|
||||
if img.pixel(i, y) != start:
|
||||
@ -517,6 +529,7 @@ class DocumentView(QWebView):
|
||||
def find_next_blank_line(self, overlap):
|
||||
img = QImage(self.width(), overlap, QImage.Format_ARGB32)
|
||||
painter = QPainter(img)
|
||||
# Render a region of width x overlap pixels atthe bottom of the current viewport
|
||||
self.document.mainFrame().render(painter, QRegion(0, 0, self.width(), overlap))
|
||||
painter.end()
|
||||
for i in range(overlap-1, -1, -1):
|
||||
@ -542,18 +555,20 @@ class DocumentView(QWebView):
|
||||
self.manager.scrolled(self.scroll_fraction)
|
||||
|
||||
def next_page(self):
|
||||
delta_y = self.document.window_height - 25
|
||||
window_height = self.document.window_height
|
||||
delta_y = window_height - 25
|
||||
if self.document.at_bottom:
|
||||
if self.manager is not None:
|
||||
self.manager.next_document()
|
||||
else:
|
||||
opos = self.document.ypos
|
||||
lower_limit = opos + delta_y
|
||||
max_y = self.document.height - self.document.window_height
|
||||
max_y = self.document.height - window_height
|
||||
lower_limit = min(max_y, lower_limit)
|
||||
if lower_limit > opos:
|
||||
self.document.scroll_to(self.document.xpos, lower_limit)
|
||||
self.find_next_blank_line( self.height() - (self.document.ypos-opos) )
|
||||
actually_scrolled = self.document.ypos - opos
|
||||
self.find_next_blank_line(window_height - actually_scrolled)
|
||||
if self.manager is not None:
|
||||
self.manager.scrolled(self.scroll_fraction)
|
||||
|
||||
|
@ -1,156 +0,0 @@
|
||||
bookmarks = '''
|
||||
|
||||
function selector_in_parent(elem) {
|
||||
var num = elem.prevAll().length;
|
||||
var sel = " > *:eq("+num+") ";
|
||||
return sel;
|
||||
}
|
||||
|
||||
function selector(elem) {
|
||||
var obj = elem;
|
||||
var sel = "";
|
||||
while (obj[0] != document) {
|
||||
sel = selector_in_parent(obj) + sel;
|
||||
obj = obj.parent();
|
||||
}
|
||||
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);
|
||||
var sel = selector(elem);
|
||||
var ratio = (y - elem.offset().top)/elem.height();
|
||||
if (ratio > 1) { ratio = 1; }
|
||||
if (ratio < 0) { ratio = 0; }
|
||||
return sel + "|" + ratio;
|
||||
}
|
||||
|
||||
function animated_scrolling_done() {
|
||||
window.py_bridge.animated_scroll_done();
|
||||
}
|
||||
|
||||
function scroll_to_bookmark(bookmark) {
|
||||
bm = bookmark.split("|");
|
||||
var ratio = 0.7 * parseFloat(bm[1]);
|
||||
$.scrollTo($(bm[0]), 1000,
|
||||
{over:ratio, onAfter:function(){window.py_bridge.animated_scroll_done()}});
|
||||
}
|
||||
|
||||
'''
|
||||
|
||||
referencing = '''
|
||||
var reference_old_bgcol = "transparent";
|
||||
var reference_prefix = "1.";
|
||||
|
||||
function show_reference_panel(ref) {
|
||||
panel = $("#calibre_reference_panel");
|
||||
if (panel.length < 1) {
|
||||
$(document.body).append('<div id="calibre_reference_panel" style="top:20px; left:20px; padding-left:30px; padding-right:30px; font:monospace normal;text-align:center; z-index:10000; background: beige; border:red ridge 2px; position:absolute;"><h5>Paragraph</h5><p style="text-indent:0pt">None</p></div>')
|
||||
panel = $("#calibre_reference_panel");
|
||||
}
|
||||
$("> p", panel).text(ref);
|
||||
panel.css({top:(window.pageYOffset+20)+"px"});
|
||||
panel.fadeIn(500);
|
||||
}
|
||||
|
||||
function toggle_reference(e) {
|
||||
p = $(this);
|
||||
if (e.type == "mouseenter") {
|
||||
reference_old_bgcol = p.css("background-color");
|
||||
p.css({backgroundColor:"beige"});
|
||||
var i = 0;
|
||||
var paras = $("p");
|
||||
for (j = 0; j < paras.length; j++,i++) {
|
||||
if (paras[j] == p[0]) break;
|
||||
}
|
||||
show_reference_panel(reference_prefix+(i+1) );
|
||||
} else {
|
||||
p.css({backgroundColor:reference_old_bgcol});
|
||||
panel = $("#calibre_reference_panel").hide();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function enter_reference_mode() {
|
||||
$("p").bind("mouseenter mouseleave", toggle_reference);
|
||||
}
|
||||
|
||||
function leave_reference_mode() {
|
||||
$("p").unbind("mouseenter mouseleave", toggle_reference);
|
||||
}
|
||||
|
||||
function goto_reference(ref) {
|
||||
var tokens = ref.split(".");
|
||||
if (tokens.length != 2) {alert("Invalid reference: "+ref); return;}
|
||||
var num = parseInt(tokens[1]);
|
||||
if (isNaN(num)) {alert("Invalid reference: "+ref); return;}
|
||||
num -= 1;
|
||||
if (num < 0) {alert("Invalid reference: "+ref); return;}
|
||||
var p = $("p");
|
||||
if (num >= p.length) {alert("Reference not found: "+ref); return;}
|
||||
$.scrollTo($(p[num]), 1000,
|
||||
{onAfter:function(){window.py_bridge.animated_scroll_done()}});
|
||||
}
|
||||
|
||||
'''
|
||||
|
||||
test = '''
|
||||
$(document.body).click(function(e) {
|
||||
bm = calculate_bookmark(e.pageY);
|
||||
scroll_to_bookmark(bm);
|
||||
});
|
||||
|
||||
$(document).ready(enter_reference_mode);
|
||||
|
||||
'''
|
||||
|
||||
hyphenation = '''
|
||||
function init_hyphenate() {
|
||||
window.py_bridge.init_hyphenate();
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", init_hyphenate, false);
|
||||
|
||||
function do_hyphenation(lang) {
|
||||
Hyphenator.config(
|
||||
{
|
||||
'minwordlength' : 6,
|
||||
//'hyphenchar' : '|',
|
||||
'displaytogglebox' : false,
|
||||
'remoteloading' : false,
|
||||
'onerrorhandler' : function (e) {
|
||||
window.py_bridge.debug(e);
|
||||
}
|
||||
});
|
||||
Hyphenator.hyphenate(document.body, lang);
|
||||
}
|
||||
'''
|
Loading…
x
Reference in New Issue
Block a user