def __init__(self, opts, log, cover_data=None, toc=None): from calibre.gui2 import is_ok_to_use_qt from calibre.utils.podofo import get_podofo if not is_ok_to_use_qt(): raise Exception('Not OK to use Qt') QObject.__init__(self) self.logger = self.log = log self.podofo = get_podofo() self.doc = self.podofo.PDFDoc() self.loop = QEventLoop() self.view = QWebView() self.page = Page(opts, self.log) self.view.setPage(self.page) self.view.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform) self.view.loadFinished.connect(self._render_html, type=Qt.QueuedConnection) for x in (Qt.Horizontal, Qt.Vertical): self.view.page().mainFrame().setScrollBarPolicy( x, Qt.ScrollBarAlwaysOff) self.render_queue = [] self.combine_queue = [] self.tmp_path = PersistentTemporaryDirectory(u'_pdf_output_parts') self.opts = opts self.cover_data = cover_data self.paged_js = None self.toc = toc
def render_html(path_to_html, width=590, height=750, as_xhtml=True): from PyQt4.QtWebKit import QWebPage from PyQt4.Qt import QEventLoop, QPalette, Qt, QUrl, QSize from calibre.gui2 import is_ok_to_use_qt if not is_ok_to_use_qt(): return None path_to_html = os.path.abspath(path_to_html) with CurrentDir(os.path.dirname(path_to_html)): page = QWebPage() pal = page.palette() pal.setBrush(QPalette.Background, Qt.white) page.setPalette(pal) page.setViewportSize(QSize(width, height)) page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) loop = QEventLoop() renderer = HTMLRenderer(page, loop) page.loadFinished.connect(renderer, type=Qt.QueuedConnection) if as_xhtml: page.mainFrame().setContent(open(path_to_html, 'rb').read(), 'application/xhtml+xml', QUrl.fromLocalFile(path_to_html)) else: page.mainFrame().load(QUrl.fromLocalFile(path_to_html)) loop.exec_() renderer.loop = renderer.page = None page.loadFinished.disconnect() del page del loop if isinstance(renderer.exception, ParserError) and as_xhtml: return render_html(path_to_html, width=width, height=height, as_xhtml=False) return renderer
def __init__(self, opts, log, cover_data=None, toc=None): from calibre.gui2 import is_ok_to_use_qt if not is_ok_to_use_qt(): raise Exception('Not OK to use Qt') QObject.__init__(self) self.logger = self.log = log self.opts = opts self.cover_data = cover_data self.paged_js = None self.toc = toc self.loop = QEventLoop() self.view = QWebView() self.page = Page(opts, self.log) self.view.setPage(self.page) self.view.setRenderHints(QPainter.Antialiasing | QPainter.TextAntialiasing | QPainter.SmoothPixmapTransform) self.view.loadFinished.connect(self.render_html, type=Qt.QueuedConnection) for x in (Qt.Horizontal, Qt.Vertical): self.view.page().mainFrame().setScrollBarPolicy( x, Qt.ScrollBarAlwaysOff) self.report_progress = lambda x, y: x self.current_section = ''
def __init__(self, container, do_embed=False): self.container = container self.log = self.logger = container.log self.do_embed = do_embed must_use_qt() self.parser = CSSParser(loglevel=logging.CRITICAL, log=logging.getLogger('calibre.css')) self.loop = QEventLoop() self.view = QWebView() self.page = Page(self.log) self.view.setPage(self.page) self.page.setViewportSize(QSize(1200, 1600)) self.view.loadFinished.connect(self.collect, type=Qt.QueuedConnection) self.render_queue = list(container.spine_items) self.font_stats = {} self.font_usage_map = {} self.font_spec_map = {} self.font_rule_map = {} self.all_font_rules = {} QTimer.singleShot(0, self.render_book) if self.loop.exec_() == 1: raise Exception( 'Failed to gather statistics from book, see log for details')
def _wait_for_replies(self, reply_count, timeout): final_time = time.time() + (self.default_timeout if timeout is default_timeout else timeout) loop = QEventLoop(self) while (time.time() < final_time and self.nam.reply_count < reply_count): loop.processEvents() time.sleep(0.1) if self.nam.reply_count < reply_count: raise Timeout('Waiting for replies took longer than %d seconds' % timeout)
def _wait_for_load(self, timeout, url=None): loop = QEventLoop(self) start_time = time.time() end_time = start_time + timeout lw = LoadWatcher(self.page, parent=self) while lw.is_loading and end_time > time.time(): if not loop.processEvents(): time.sleep(0.01) if lw.is_loading: raise Timeout('Loading of %r took longer than %d seconds' % (url, timeout)) return lw.loaded_ok
def download_file(self, url_or_selector_or_qwe, timeout=60): ''' Download unsupported content: i.e. files the browser cannot handle itself or files marked for saving as files by the website. Useful if you want to download something like an epub file after authentication. You can pass in either the url to the file to be downloaded, or a selector that points to an element to be clicked on the current page which will cause the file to be downloaded. ''' ans = [False, None, []] loop = QEventLoop(self) start_time = time.time() end_time = start_time + timeout self.page.unsupportedContent.disconnect(self.page.on_unsupported_content) try: def download(reply): if ans[0]: reply.abort() # We only handle the first unsupported download return ans[0] = True while not reply.isFinished() and end_time > time.time(): if not loop.processEvents(): time.sleep(0.01) raw = bytes(bytearray(reply.readAll())) if raw: ans[-1].append(raw) if not reply.isFinished(): ans[1] = Timeout('Loading of %r took longer than %d seconds'%(url_or_selector_or_qwe, timeout)) ans[-1].append(bytes(bytearray(reply.readAll()))) self.page.unsupportedContent.connect(download) if hasattr(url_or_selector_or_qwe, 'rstrip') and re.match('[a-z]+://', url_or_selector_or_qwe) is not None: # We have a URL self.page.mainFrame().load(QUrl(url_or_selector_or_qwe)) else: self.click(url_or_selector_or_qwe, wait_for_load=False) lw = LoadWatcher(self.page) while not ans[0] and lw.is_loading and end_time > time.time(): if not loop.processEvents(): time.sleep(0.01) if not ans[0]: raise NotAFile('%r does not point to a downloadable file. You can only' ' use this method to download files that the browser cannot handle' ' natively. Or files that are marked with the ' ' content-disposition: attachment header' % url_or_selector_or_qwe) if ans[1] is not None: raise ans[1] return b''.join(ans[-1]) finally: self.page.unsupportedContent.disconnect() self.page.unsupportedContent.connect(self.page.on_unsupported_content)
def __init__(self, html, base_dir, width, height, dpi, factor): ''' `width, height`: page width and height in pixels `base_dir`: The directory in which the HTML file that contains the table resides ''' QObject.__init__(self) self.app = None self.width, self.height, self.dpi = width, height, dpi self.base_dir = base_dir self.images = [] self.tdir = tempfile.mkdtemp(prefix='calibre_render_table') self.loop = QEventLoop() self.page = QWebPage() self.page.loadFinished.connect(self.render_html) self.page.mainFrame().setTextSizeMultiplier(factor) self.page.mainFrame().setHtml( html, QUrl('file:' + os.path.abspath(self.base_dir)))
def do_print(self, printer): painter = QPainter(printer) zoomx = printer.logicalDpiX() / self.view.logicalDpiX() zoomy = printer.logicalDpiY() / self.view.logicalDpiY() painter.scale(zoomx, zoomy) pr = printer.pageRect() self.view.page().setViewportSize( QSize(pr.width() / zoomx, pr.height() / zoomy)) evaljs = self.mf.evaluateJavaScript loop = QEventLoop(self) first = True for path in self.iterator.spine: self.loaded_ok = None load_html(path, self.view, codec=getattr(path, 'encoding', 'utf-8'), mime_type=getattr(path, 'mime_type', None)) while self.loaded_ok is None: loop.processEvents(loop.ExcludeUserInputEvents) if not self.loaded_ok: return error_dialog(self.parent(), _('Failed to render'), _('Failed to render document %s') % path, show=True) evaljs(self.paged_js) evaljs(''' document.body.style.backgroundColor = "white"; paged_display.set_geometry(1, 0, 0, 0); paged_display.layout(); paged_display.fit_images(); ''') while True: if not first: printer.newPage() first = False self.mf.render(painter) nsl = evaljs('paged_display.next_screen_location()').toInt() if not nsl[1] or nsl[0] <= 0: break evaljs('window.scrollTo(%d, 0)' % nsl[0]) painter.end()
def __init__(self, container): self.container = container self.log = self.logger = container.log must_use_qt() self.loop = QEventLoop() self.view = QWebView() self.page = Page(self.log) self.view.setPage(self.page) self.page.setViewportSize(QSize(1200, 1600)) self.view.loadFinished.connect(self.collect, type=Qt.QueuedConnection) self.render_queue = list(container.spine_items) self.font_stats = {} QTimer.singleShot(0, self.render_book) if self.loop.exec_() == 1: raise Exception( 'Failed to gather statistics from book, see log for details')
def run_for_a_time(self, timeout): final_time = time.time() + timeout loop = QEventLoop(self) while (time.time() < final_time): if not loop.processEvents(): time.sleep(0.1)