diff --git a/resources/viewer/bookmarks.js b/resources/viewer/bookmarks.js new file mode 100644 index 0000000000..c6f59414ab --- /dev/null +++ b/resources/viewer/bookmarks.js @@ -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()}}); +} + diff --git a/resources/viewer/hyphenation.js b/resources/viewer/hyphenation.js new file mode 100644 index 0000000000..a0ba6d1f34 --- /dev/null +++ b/resources/viewer/hyphenation.js @@ -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); +} + diff --git a/resources/viewer/referencing.js b/resources/viewer/referencing.js new file mode 100644 index 0000000000..6de1a06be9 --- /dev/null +++ b/resources/viewer/referencing.js @@ -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('
Paragraph

None

') + 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()}}); +} + + diff --git a/setup/installer/osx/freeze.py b/setup/installer/osx/freeze.py index f30a037703..281432fcf3 100644 --- a/setup/installer/osx/freeze.py +++ b/setup/installer/osx/freeze.py @@ -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', diff --git a/src/calibre/gui2/viewer/documentview.py b/src/calibre/gui2/viewer/documentview.py index aeaf8e2c4f..8e86604603 100644 --- a/src/calibre/gui2/viewer/documentview.py +++ b/src/calibre/gui2/viewer/documentview.py @@ -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) diff --git a/src/calibre/gui2/viewer/js.py b/src/calibre/gui2/viewer/js.py deleted file mode 100644 index 68768829bb..0000000000 --- a/src/calibre/gui2/viewer/js.py +++ /dev/null @@ -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('
Paragraph

None

') - 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); -} -'''