home *** CD-ROM | disk | FTP | other *** search
- # Source Generated with Decompyle++
- # File: in.pyc (Python 2.6)
-
- __license__ = 'GPL v3'
- __copyright__ = '2008, Kovid Goyal kovid@kovidgoyal.net'
- __docformat__ = 'restructuredtext en'
- import os
- import math
- import re
- import glob
- import sys
- from base64 import b64encode
- from functools import partial
- from PyQt4.Qt import QSize, QSizePolicy, QUrl, SIGNAL, Qt, QTimer, QPainter, QPalette, QBrush, QFontDatabase, QDialog, QColor, QPoint, QImage, QRegion, QVariant, QIcon, QFont, pyqtSignature, QAction, QByteArray, QMenu
- 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.shortcuts import Shortcuts, ShortcutConfig
- from calibre.constants import iswindows
- from calibre import prints, guess_type
- from calibre.gui2.viewer.keys import SHORTCUTS
- bookmarks = referencing = hyphenation = jquery = jquery_scrollTo = hyphenator = images = None
-
- def load_builtin_fonts():
- base = P('fonts/liberation/*.ttf')
- for f in glob.glob(base):
- QFontDatabase.addApplicationFont(f)
-
- return ('Liberation Serif', 'Liberation Sans', 'Liberation Mono')
-
-
- def config(defaults = None):
- desc = _('Options to customize the ebook viewer')
- if defaults is None:
- c = Config('viewer', desc)
- else:
- c = StringConfig(defaults, desc)
- c.add_opt('remember_window_size', default = False, help = _('Remember last used window size'))
- c.add_opt('user_css', default = '', help = _('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
- c.add_opt('max_view_width', default = 6000, help = _('Maximum width of the viewer window, in pixels.'))
- c.add_opt('fit_images', default = True, help = _('Resize images larger than the viewer window to fit inside it'))
- c.add_opt('hyphenate', default = False, help = _('Hyphenate text'))
- c.add_opt('hyphenate_default_lang', default = 'en', help = _('Default language for hyphenation rules'))
- fonts = c.add_group('FONTS', _('Font options'))
- None(fonts, serif_family = 'default' if iswindows else 'Liberation Serif', help = _('The serif font family'))
- None(fonts, sans_family = 'default' if iswindows else 'Liberation Sans', help = _('The sans-serif font family'))
- None(fonts, mono_family = 'default' if iswindows else 'Liberation Mono', help = _('The monospaced font family'))
- fonts('default_font_size', default = 20, help = _('The standard font size in px'))
- fonts('mono_font_size', default = 16, help = _('The monospaced font size in px'))
- fonts('standard_font', default = 'serif', help = _('The standard font type'))
- return c
-
-
- class ConfigDialog(QDialog, Ui_Dialog):
-
- def __init__(self, shortcuts, parent = None):
- QDialog.__init__(self, parent)
- self.setupUi(self)
- opts = config().parse()
- self.opt_remember_window_size.setChecked(opts.remember_window_size)
- self.serif_family.setCurrentFont(QFont(opts.serif_family))
- self.sans_family.setCurrentFont(QFont(opts.sans_family))
- self.mono_family.setCurrentFont(QFont(opts.mono_family))
- self.default_font_size.setValue(opts.default_font_size)
- self.mono_font_size.setValue(opts.mono_font_size)
- self.standard_font.setCurrentIndex({
- 'serif': 0,
- 'sans': 1,
- 'mono': 2 }[opts.standard_font])
- self.css.setPlainText(opts.user_css)
- self.css.setToolTip(_('Set the user CSS stylesheet. This can be used to customize the look of all books.'))
- self.max_view_width.setValue(opts.max_view_width)
- pats = [ os.path.basename(x).split('.')[0] for x in glob.glob(P('viewer/hyphenate/patterns/*.js', allow_user_override = False)) ]
- names = list(map(get_language, pats))
- pmap = { }
- for i in range(len(pats)):
- pmap[names[i]] = pats[i]
-
- for x in sorted(names):
- self.hyphenate_default_lang.addItem(x, QVariant(pmap[x]))
-
-
- try:
- idx = pats.index(opts.hyphenate_default_lang)
- except ValueError:
- []
- []
- []
- idx = pats.index('en')
- except:
- []
-
- idx = self.hyphenate_default_lang.findText(names[idx])
- self.hyphenate_default_lang.setCurrentIndex(idx)
- self.hyphenate.setChecked(opts.hyphenate)
- self.hyphenate_default_lang.setEnabled(opts.hyphenate)
- self.shortcuts = shortcuts
- self.shortcut_config = ShortcutConfig(shortcuts, parent = self)
- p = self.tabs.widget(1)
- p.layout().addWidget(self.shortcut_config)
- self.opt_fit_images.setChecked(opts.fit_images)
-
-
- def accept(self, *args):
- c = config()
- c.set('serif_family', unicode(self.serif_family.currentFont().family()))
- c.set('sans_family', unicode(self.sans_family.currentFont().family()))
- c.set('mono_family', unicode(self.mono_family.currentFont().family()))
- c.set('default_font_size', self.default_font_size.value())
- c.set('mono_font_size', self.mono_font_size.value())
- c.set('standard_font', {
- 0: 'serif',
- 1: 'sans',
- 2: 'mono' }[self.standard_font.currentIndex()])
- c.set('user_css', unicode(self.css.toPlainText()))
- c.set('remember_window_size', self.opt_remember_window_size.isChecked())
- c.set('fit_images', self.opt_fit_images.isChecked())
- c.set('max_view_width', int(self.max_view_width.value()))
- c.set('hyphenate', self.hyphenate.isChecked())
- idx = self.hyphenate_default_lang.currentIndex()
- c.set('hyphenate_default_lang', str(self.hyphenate_default_lang.itemData(idx).toString()))
- return QDialog.accept(self, *args)
-
-
-
- class Document(QWebPage):
-
- def set_font_settings(self):
- opts = config().parse()
- settings = self.settings()
- settings.setFontSize(QWebSettings.DefaultFontSize, opts.default_font_size)
- settings.setFontSize(QWebSettings.DefaultFixedFontSize, opts.mono_font_size)
- settings.setFontSize(QWebSettings.MinimumLogicalFontSize, 8)
- settings.setFontSize(QWebSettings.MinimumFontSize, 8)
- settings.setFontFamily(QWebSettings.StandardFont, {
- 'serif': opts.serif_family,
- 'sans': opts.sans_family,
- 'mono': opts.mono_family }[opts.standard_font])
- settings.setFontFamily(QWebSettings.SerifFont, opts.serif_family)
- settings.setFontFamily(QWebSettings.SansSerifFont, opts.sans_family)
- settings.setFontFamily(QWebSettings.FixedFont, opts.mono_family)
-
-
- def do_config(self, parent = None):
- d = ConfigDialog(self.shortcuts, parent)
- if d.exec_() == QDialog.Accepted:
- self.set_font_settings()
- self.set_user_stylesheet()
- self.misc_config()
- self.triggerAction(QWebPage.Reload)
-
-
-
- def __init__(self, shortcuts, parent = None):
- QWebPage.__init__(self, parent)
- self.setObjectName('py_bridge')
- self.debug_javascript = False
- self.current_language = None
- self.loaded_javascript = False
- self.setLinkDelegationPolicy(self.DelegateAllLinks)
- self.scroll_marks = []
- self.shortcuts = shortcuts
- pal = self.palette()
- pal.setBrush(QPalette.Background, QColor(238, 238, 238))
- self.setPalette(pal)
- settings = self.settings()
- load_builtin_fonts()
- self.set_font_settings()
- settings.setAttribute(QWebSettings.JavaEnabled, False)
- settings.setAttribute(QWebSettings.PluginsEnabled, False)
- settings.setAttribute(QWebSettings.JavascriptCanOpenWindows, False)
- settings.setAttribute(QWebSettings.JavascriptCanAccessClipboard, False)
- settings.setAttribute(QWebSettings.LinksIncludedInFocusChain, True)
- self.set_user_stylesheet()
- self.misc_config()
- self.mainFrame().javaScriptWindowObjectCleared.connect(self.add_window_objects)
-
-
- def set_user_stylesheet(self):
- raw = config().parse().user_css
- raw = '::selection {background:#ffff00; color:#000;}\nbody {background-color: white;}\n' + raw
- data = 'data:text/css;charset=utf-8;base64,'
- data += b64encode(raw.encode('utf-8'))
- self.settings().setUserStyleSheetUrl(QUrl(data))
-
-
- def misc_config(self):
- opts = config().parse()
- self.hyphenate = opts.hyphenate
- self.hyphenate_default_lang = opts.hyphenate_default_lang
- self.do_fit_images = opts.fit_images
-
-
- def fit_images(self):
- if self.do_fit_images:
- self.javascript('setup_image_scaling_handlers()')
-
-
-
- def add_window_objects(self):
- self.mainFrame().addToJavaScriptWindowObject('py_bridge', self)
- self.loaded_javascript = False
-
-
- def load_javascript_libraries(self):
- global jquery, jquery_scrollTo, bookmarks, referencing, images, hyphenation, hyphenator
- if self.loaded_javascript:
- return None
- self.loaded_javascript = True
- if jquery is None:
- jquery = P('content_server/jquery.js', data = True)
-
- self.javascript(jquery)
- if jquery_scrollTo is None:
- jquery_scrollTo = P('viewer/jquery_scrollTo.js', data = True)
-
- 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 images is None:
- images = P('viewer/images.js', data = True)
-
- self.javascript(images)
- if hyphenation is None:
- hyphenation = P('viewer/hyphenation.js', data = True)
-
- self.javascript(hyphenation)
- default_lang = self.hyphenate_default_lang
- lang = self.current_language
- if not lang:
- lang = default_lang
-
- lang = lang.lower()[:2]
- if hyphenator is None:
- hyphenator = P('viewer/hyphenate/Hyphenator.js', data = True).decode('utf-8')
-
- self.javascript(hyphenator)
- p = P('viewer/hyphenate/patterns/%s.js' % lang)
- if not os.path.exists(p):
- lang = default_lang
- p = P('viewer/hyphenate/patterns/%s.js' % lang)
-
- self.javascript(open(p, 'rb').read().decode('utf-8'))
- self.loaded_lang = lang
-
-
- def animated_scroll_done(self):
- self.emit(SIGNAL('animated_scroll_done()'))
-
- animated_scroll_done = pyqtSignature('')(animated_scroll_done)
-
- def init_hyphenate(self):
- if self.hyphenate:
- self.javascript('do_hyphenation("%s")' % self.loaded_lang)
-
-
- init_hyphenate = pyqtSignature('')(init_hyphenate)
-
- def debug(self, msg):
- prints(msg)
-
- debug = pyqtSignature('QString')(debug)
-
- def reference_mode(self, enable):
- None(self.javascript if enable else 'leave' + '_reference_mode()')
-
-
- def set_reference_prefix(self, prefix):
- self.javascript('reference_prefix = "%s"' % prefix)
-
-
- def goto(self, ref):
- self.javascript('goto_reference("%s")' % ref)
-
-
- def goto_bookmark(self, bm):
- bm = bm.strip()
- if bm.startswith('>'):
- bm = bm[1:].strip()
-
- self.javascript('scroll_to_bookmark("%s")' % bm)
-
-
- def javascript(self, string, typ = None):
- ans = self.mainFrame().evaluateJavaScript(string)
- if typ == 'int':
- ans = ans.toInt()
- if ans[1]:
- return ans[0]
- return 0
- if typ == 'string':
- return unicode(ans.toString())
- return ans
-
-
- def javaScriptConsoleMessage(self, msg, lineno, msgid):
- if self.debug_javascript:
- prints('JS:', msgid, lineno)
- prints(msg)
- prints(' ')
- else:
- return QWebPage.javaScriptConsoleMessage(self, msg, lineno, msgid)
- return self.debug_javascript
-
-
- def javaScriptAlert(self, frame, msg):
- if self.debug_javascript:
- prints(msg)
- else:
- return QWebPage.javaScriptAlert(self, frame, msg)
- return self.debug_javascript
-
-
- def scroll_by(self, dx = 0, dy = 0):
- self.mainFrame().scroll(dx, dy)
-
-
- def scroll_to(self, x = 0, y = 0):
- self.mainFrame().setScrollPosition(QPoint(x, y))
-
-
- def jump_to_anchor(self, anchor):
- self.javascript('document.location.hash = "%s"' % anchor)
-
-
- def quantize(self):
- if self.height > self.window_height:
- r = self.height % self.window_height
- 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')
- ok
- 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 = sys.maxint
- min_elem = 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 = elem
- min_delta = delta
- continue
- delta < 25
-
-
- return min_elem
-
-
- def bookmark(self):
- elem = self.find_bookmark_element()
- if elem is None or self.element_ypos(elem) < 100:
- 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
-
-
- def at_bottom(self):
- return self.height - self.ypos <= self.window_height
-
- at_bottom = property(at_bottom)
-
- def at_top(self):
- return self.ypos <= 0
-
- at_top = property(at_top)
-
- def test(self):
- pass
-
-
- def ypos(self):
- return self.mainFrame().scrollPosition().y()
-
- ypos = property(ypos)
-
- def window_height(self):
- return self.javascript('window.innerHeight', 'int')
-
- window_height = property(window_height)
-
- def window_width(self):
- return self.javascript('window.innerWidth', 'int')
-
- window_width = property(window_width)
-
- def xpos(self):
- return self.mainFrame().scrollPosition().x()
-
- xpos = property(xpos)
-
- def scroll_fraction(self):
-
- try:
- return float(self.ypos) / (self.height - self.window_height)
- except ZeroDivisionError:
- return 0
-
-
- scroll_fraction = property(scroll_fraction)
-
- def hscroll_fraction(self):
-
- try:
- return float(self.xpos) / self.width
- except ZeroDivisionError:
- return 0
-
-
- hscroll_fraction = property(hscroll_fraction)
-
- def height(self):
- j = self.javascript('document.body.offsetHeight', 'int')
- q = self.mainFrame().contentsSize().height()
- if q == j:
- return j
- if min(j, q) <= 0:
- return max(j, q)
- window_height = self.window_height
- if j == window_height:
- if q < 1.2 * j:
- return j
- return q
- return j
-
- height = property(height)
-
- def width(self):
- return self.mainFrame().contentsSize().width()
-
- width = property(width)
-
- def set_bottom_padding(self, amount):
- s = None if amount == 0 else QSize(self.width, self.height + amount)
- self.setPreferredContentsSize(s)
-
-
-
- class EntityDeclarationProcessor(object):
-
- def __init__(self, html):
- self.declared_entities = { }
- for match in re.finditer('<!\\s*ENTITY\\s+([^>]+)>', html):
- tokens = match.group(1).split()
- if len(tokens) > 1:
- self.declared_entities[tokens[0].strip()] = tokens[1].strip().replace('"', '')
- continue
-
- self.processed_html = html
- for key, val in self.declared_entities.iteritems():
- self.processed_html = self.processed_html.replace('&%s;' % key, val)
-
-
-
-
- class DocumentView(QWebView):
- DISABLED_BRUSH = QBrush(Qt.lightGray, Qt.Dense5Pattern)
-
- def __init__(self, *args):
- QWebView.__init__(self, *args)
- self.debug_javascript = False
- self.shortcuts = Shortcuts(SHORTCUTS, 'shortcuts/viewer')
- self.self_closing_pat = re.compile('<([a-z1-6]+)\\s+([^>]+)/>', re.IGNORECASE)
- self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
- self._size_hint = QSize(510, 680)
- self.initial_pos = 0
- self.to_bottom = False
- self.document = Document(self.shortcuts, parent = self)
- self.setPage(self.document)
- self.manager = None
- self._reference_mode = False
- self._ignore_scrollbar_signals = False
- self.loading_url = None
- self.loadFinished.connect(self.load_finished)
- self.connect(self.document, SIGNAL('linkClicked(QUrl)'), self.link_clicked)
- self.connect(self.document, SIGNAL('linkHovered(QString,QString,QString)'), self.link_hovered)
- self.connect(self.document, SIGNAL('selectionChanged()'), self.selection_changed)
- self.connect(self.document, SIGNAL('animated_scroll_done()'), self.animated_scroll_done, Qt.QueuedConnection)
- copy_action = self.pageAction(self.document.Copy)
- copy_action.setIcon(QIcon(I('convert.png')))
- d = self.document
- self.unimplemented_actions = list(map(self.pageAction, [
- d.DownloadImageToDisk,
- d.OpenLinkInNewWindow,
- d.DownloadLinkToDisk,
- d.OpenImageInNewWindow,
- d.OpenLink]))
- self.dictionary_action = QAction(QIcon(I('dictionary.png')), _('&Lookup in dictionary'), self)
- self.dictionary_action.setShortcut(Qt.CTRL + Qt.Key_L)
- self.dictionary_action.triggered.connect(self.lookup)
- self.goto_location_action = QAction(_('Go to...'), self)
- self.goto_location_menu = m = QMenu(self)
- self.goto_location_actions = a = {
- 'Next Page': self.next_page,
- 'Previous Page': self.previous_page,
- 'Section Top': partial(self.scroll_to, 0),
- 'Document Top': self.goto_document_start,
- 'Section Bottom': partial(self.scroll_to, 1),
- 'Document Bottom': self.goto_document_end,
- 'Next Section': self.goto_next_section,
- 'Previous Section': self.goto_previous_section }
- for name, key in [
- (_('Next Section'), 'Next Section'),
- (_('Previous Section'), 'Previous Section'),
- (None, None),
- (_('Document Start'), 'Document Top'),
- (_('Document End'), 'Document Bottom'),
- (None, None),
- (_('Section Start'), 'Section Top'),
- (_('Section End'), 'Section Bottom'),
- (None, None),
- (_('Next Page'), 'Next Page'),
- (_('Previous Page'), 'Previous Page')]:
- if key is None:
- m.addSeparator()
- continue
- m.addAction(name, a[key], self.shortcuts.get_sequences(key)[0])
-
- self.goto_location_action.setMenu(self.goto_location_menu)
-
-
- def goto_next_section(self, *args):
- if self.manager is not None:
- self.manager.goto_next_section()
-
-
-
- def goto_previous_section(self, *args):
- if self.manager is not None:
- self.manager.goto_previous_section()
-
-
-
- def goto_document_start(self, *args):
- if self.manager is not None:
- self.manager.goto_start()
-
-
-
- def goto_document_end(self, *args):
- if self.manager is not None:
- self.manager.goto_end()
-
-
-
- def copy_action(self):
- return self.pageAction(self.document.Copy)
-
- copy_action = property(copy_action)
-
- def animated_scroll_done(self):
- if self.manager is not None:
- self.manager.scrolled(self.document.scroll_fraction)
-
-
-
- def reference_mode(self, enable):
- self._reference_mode = enable
- self.document.reference_mode(enable)
-
-
- def goto(self, ref):
- self.document.goto(ref)
-
-
- def goto_bookmark(self, bm):
- self.document.goto_bookmark(bm)
-
-
- def config(self, parent = None):
- self.document.do_config(parent)
- if self.manager is not None:
- self.manager.set_max_width()
-
- self.setFocus(Qt.OtherFocusReason)
-
-
- def bookmark(self):
- return self.document.bookmark()
-
-
- def selection_changed(self):
- if self.manager is not None:
- self.manager.selection_changed(unicode(self.document.selectedText()))
-
-
-
- def contextMenuEvent(self, ev):
- menu = self.document.createStandardContextMenu()
- for action in self.unimplemented_actions:
- menu.removeAction(action)
-
- text = unicode(self.selectedText())
- if text:
- menu.insertAction(list(menu.actions())[0], self.dictionary_action)
-
- menu.addSeparator()
- menu.addAction(self.goto_location_action)
- menu.exec_(ev.globalPos())
-
-
- def lookup(self, *args):
- if self.manager is not None:
- t = unicode(self.selectedText()).strip()
- if t:
- self.manager.lookup(t.split()[0])
-
-
-
-
- def set_manager(self, manager):
- self.manager = manager
- self.scrollbar = manager.horizontal_scrollbar
- self.connect(self.scrollbar, SIGNAL('valueChanged(int)'), self.scroll_horizontally)
-
-
- def scroll_horizontally(self, amount):
- self.document.scroll_to(y = self.document.ypos, x = amount)
-
-
- def link_hovered(self, link, text, context):
- link = unicode(link)
- text = unicode(text)
- if link:
- self.setCursor(Qt.PointingHandCursor)
- else:
- self.unsetCursor()
-
-
- def link_clicked(self, url):
- if self.manager is not None:
- self.manager.link_clicked(url)
-
-
-
- def sizeHint(self):
- return self._size_hint
-
-
- def scroll_fraction(self):
- return self.document.scroll_fraction
-
- scroll_fraction = property(scroll_fraction)
-
- def hscroll_fraction(self):
- return self.document.hscroll_fraction
-
- hscroll_fraction = property(hscroll_fraction)
-
- def content_size(self):
- return (self.document.width, self.document.height)
-
- content_size = property(content_size)
-
- def current_language(self):
-
- def fget(self):
- return self.document.current_language
-
-
- def fset(self, val):
- self.document.current_language = val
-
- return property(fget = fget, fset = fset)
-
- current_language = dynamic_property(current_language)
-
- def search(self, text, backwards = False):
- if backwards:
- return self.findText(text, self.document.FindBackwards)
- return self.findText(text)
-
-
- def path(self):
- return os.path.abspath(unicode(self.url().toLocalFile()))
-
-
- def self_closing_sub(self, match):
- tag = match.group(1)
- if tag.lower().strip() == 'br':
- return match.group()
- return '<%s %s></%s>' % (match.group(1), match.group(2), match.group(1))
-
-
- def load_path(self, path, pos = 0):
- self.initial_pos = pos
- mt = getattr(path, 'mime_type', None)
- if mt is None:
- mt = guess_type(path)[0]
-
- html = open(path, 'rb').read().decode(path.encoding, 'replace')
- html = EntityDeclarationProcessor(html).processed_html
- has_svg = re.search('<[:a-zA-Z]*svg', html) is not None
- if 'xhtml' in mt:
- html = self.self_closing_pat.sub(self.self_closing_sub, html)
-
- if self.manager is not None:
- self.manager.load_started()
-
- self.loading_url = QUrl.fromLocalFile(path)
- if has_svg:
- prints('Rendering as XHTML...')
- self.setContent(QByteArray(html.encode(path.encoding)), mt, QUrl.fromLocalFile(path))
- else:
- self.setHtml(html, self.loading_url)
- self.turn_off_internal_scrollbars()
-
-
- def initialize_scrollbar(self):
- if getattr(self, 'scrollbar', None) is not None:
- delta = self.document.width - self.size().width()
- if delta > 0:
- self._ignore_scrollbar_signals = True
- self.scrollbar.blockSignals(True)
- self.scrollbar.setRange(0, delta)
- self.scrollbar.setValue(0)
- self.scrollbar.setSingleStep(1)
- self.scrollbar.setPageStep(int(delta / 10))
-
- self.scrollbar.setVisible(delta > 0)
- self.scrollbar.blockSignals(False)
- self._ignore_scrollbar_signals = False
-
-
-
- def load_finished(self, ok):
- if self.loading_url is None:
- return None
- self.loading_url = None
- self.document.load_javascript_libraries()
- self.document.set_bottom_padding(0)
- self.document.fit_images()
- self._size_hint = self.document.mainFrame().contentsSize()
- scrolled = False
- if self.to_bottom:
- self.to_bottom = False
- self.initial_pos = 1
-
- if self.initial_pos > 0:
- scrolled = True
-
- self.scroll_to(self.initial_pos, notify = False)
- self.initial_pos = 0
- self.update()
- self.initialize_scrollbar()
- self.document.reference_mode(self._reference_mode)
- if self.manager is not None:
- spine_index = self.manager.load_finished(bool(ok))
- if spine_index > -1:
- self.document.set_reference_prefix('%d.' % (spine_index + 1))
-
- if scrolled:
- self.manager.scrolled(self.document.scroll_fraction)
-
-
- self.turn_off_internal_scrollbars()
-
-
- def turn_off_internal_scrollbars(self):
- self.document.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff)
- self.document.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff)
-
-
- def test_line(cls, img, y):
- start = img.pixel(0, y)
- for i in range(1, img.width()):
- if img.pixel(i, y) != start:
- return False
-
- return True
-
- test_line = classmethod(test_line)
-
- def find_next_blank_line(self, overlap):
- img = QImage(self.width(), overlap, QImage.Format_ARGB32)
- painter = QPainter(img)
- self.document.mainFrame().render(painter, QRegion(0, 0, self.width(), overlap))
- painter.end()
- for i in range(overlap - 1, -1, -1):
- if self.test_line(img, i):
- self.scroll_by(y = i, notify = False)
- return None
-
- self.scroll_by(y = overlap)
-
-
- def previous_page(self):
- delta_y = self.document.window_height - 25
- if self.document.at_top:
- if self.manager is not None:
- self.to_bottom = True
- self.manager.previous_document()
-
- else:
- opos = self.document.ypos
- upper_limit = opos - delta_y
- if upper_limit < 0:
- upper_limit = 0
-
- if upper_limit < opos:
- self.document.scroll_to(self.document.xpos, upper_limit)
-
- if self.manager is not None:
- self.manager.scrolled(self.scroll_fraction)
-
-
-
- def next_page(self):
- window_height = self.document.window_height
- document_height = self.document.height
- ddelta = document_height - window_height
- delta_y = window_height - 25
- if self.document.at_bottom or ddelta <= 0:
- if self.manager is not None:
- self.manager.next_document()
-
- elif ddelta < 25:
- self.scroll_by(y = ddelta)
- return None
- oopos = self.document.ypos
- self.document.set_bottom_padding(0)
- opos = self.document.ypos
- if opos < oopos:
- if self.manager is not None:
- self.manager.next_document()
-
- return None
- lower_limit = opos + delta_y
- max_y = self.document.height - 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)
-
- 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)
-
-
-
- def scroll_by(self, x = 0, y = 0, notify = True):
- old_pos = self.document.ypos
- self.document.scroll_by(x, y)
- if notify and self.manager is not None and self.document.ypos != old_pos:
- self.manager.scrolled(self.scroll_fraction)
-
-
-
- def scroll_to(self, pos, notify = True):
- if self._ignore_scrollbar_signals:
- return None
- old_pos = self.document.ypos
- if isinstance(pos, basestring):
- self.document.jump_to_anchor(pos)
- elif pos >= 1:
- self.document.scroll_to(0, self.document.height)
- else:
- y = int(math.ceil(pos * (self.document.height - self.document.window_height)))
- self.document.scroll_to(0, y)
- if notify and self.manager is not None and self.document.ypos != old_pos:
- self.manager.scrolled(self.scroll_fraction)
-
-
-
- def multiplier(self):
- return self.document.mainFrame().textSizeMultiplier()
-
-
- def magnify_fonts(self):
- self.document.mainFrame().setTextSizeMultiplier(self.multiplier() + 0.2)
- return self.document.scroll_fraction
-
-
- def shrink_fonts(self):
- self.document.mainFrame().setTextSizeMultiplier(max(self.multiplier() - 0.2, 0))
- return self.document.scroll_fraction
-
-
- def changeEvent(self, event):
- if event.type() == event.EnabledChange:
- self.update()
-
- return QWebView.changeEvent(self, event)
-
-
- def paintEvent(self, event):
- self.turn_off_internal_scrollbars()
- painter = QPainter(self)
- self.document.mainFrame().render(painter, event.region())
- if not self.isEnabled():
- painter.fillRect(event.region().boundingRect(), self.DISABLED_BRUSH)
-
- painter.end()
-
-
- def wheelEvent(self, event):
- if event.delta() < -14:
- if self.document.at_bottom:
- self.scroll_by(y = 15)
- if self.manager is not None:
- self.manager.next_document()
- event.accept()
- return None
-
- elif event.delta() > 14:
- if self.document.at_top:
- if self.manager is not None:
- self.manager.previous_document()
- event.accept()
- return None
-
-
- ret = QWebView.wheelEvent(self, event)
- scroll_amount = (event.delta() / 120) * 0.2 * -1
- if event.orientation() == Qt.Vertical:
- self.scroll_by(0, self.document.viewportSize().height() * scroll_amount)
- else:
- self.scroll_by(self.document.viewportSize().width() * scroll_amount, 0)
- if self.manager is not None:
- self.manager.scrolled(self.scroll_fraction)
-
- return ret
-
-
- def keyPressEvent(self, event):
- key = self.shortcuts.get_match(event)
- func = self.goto_location_actions.get(key, None)
- if func is not None:
- func()
- elif key == 'Down':
- self.scroll_by(y = 15)
- elif key == 'Up':
- self.scroll_by(y = -15)
- elif key == 'Left':
- self.scroll_by(x = -15)
- elif key == 'Right':
- self.scroll_by(x = 15)
- else:
- return QWebView.keyPressEvent(self, event)
- return func is not None
-
-
- def resizeEvent(self, event):
- ret = QWebView.resizeEvent(self, event)
- QTimer.singleShot(10, self.initialize_scrollbar)
- if self.manager is not None:
- self.manager.viewport_resized(self.scroll_fraction)
-
- return ret
-
-
- def mouseReleaseEvent(self, ev):
- opos = self.document.ypos
- ret = QWebView.mouseReleaseEvent(self, ev)
- if self.manager is not None and opos != self.document.ypos:
- self.manager.internal_link_clicked(opos)
- self.manager.scrolled(self.scroll_fraction)
-
- return ret
-
-
-