def render_html(path_to_html, width=590, height=750, as_xhtml=True): from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.Qt import QEventLoop, QPalette, Qt, QUrl, QSize from calibre.gui2 import is_ok_to_use_qt, secure_web_page 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() settings = page.settings() secure_web_page(settings) 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 render_html(path_to_html, width=590, height=750, as_xhtml=True): from PyQt5.QtWebKitWidgets import QWebPage from PyQt5.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() settings = page.settings() settings.setAttribute(settings.PluginsEnabled, False) 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 test02_check_scene1_webpage(self): """render exported web page and check page capture""" html_path = outputPath("scene1.html") url = QUrl.fromLocalFile(html_path) url = QUrl(url.toString() + "#cx=-20&cy=16&cz=-34&tx=-2&ty=0&tz=8") loop = QEventLoop() page = QWebPage() page.setViewportSize(QSize(OUT_WIDTH, OUT_HEIGHT)) page.loadFinished.connect(loop.quit) page.mainFrame().setUrl(url) loop.exec_() page.mainFrame().evaluateJavaScript('document.getElementById("progress").style.display = "none";') timer = QTimer() timer.timeout.connect(loop.quit) timer.start(100) while page.mainFrame().evaluateJavaScript("app.loadingManager.isLoading"): loop.exec_() timer.stop() image = QImage(OUT_WIDTH, OUT_HEIGHT, QImage.Format_ARGB32_Premultiplied) painter = QPainter(image) page.mainFrame().render(painter) painter.end() filename = "scene1_qwebpage.png" image.save(outputPath(filename)) assert QImage(outputPath(filename)) == QImage(expectedDataPath(filename)), "captured image is different from expected."
class WebLoader(QObject): _finished = pyqtSignal(str) def __init__(self, key): super(WebLoader, self).__init__() # if platform.python_version() < '3.0.0': # self._key = unicode(key) self._key = key self._percent = 0 self._page = QWebPage() self._page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self._page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self._page.loadProgress.connect(self.printProgress) def printProgress(self, percent): if self._percent >= percent: cout("\n") return else: cout('#' * (percent - self._percent)) self._percent = percent def load(self, url): self._percent = 0 self._url = QUrl.fromUserInput(url) self._page.mainFrame().load(self._url) self._page.setViewportSize(QSize(1920, 10000)) print("Loading... %s" % url)
class HTMLTableRenderer(QObject): 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 ''' from calibre.gui2 import secure_web_page 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() secure_web_page(self.page.settings()) 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 render_html(self, ok): try: if not ok: return cwidth, cheight = self.page.mainFrame().contentsSize().width( ), self.page.mainFrame().contentsSize().height() self.page.setViewportSize(QSize(cwidth, cheight)) factor = float(self.width) / cwidth if cwidth > self.width else 1 cutoff_height = int(self.height / factor) - 3 image = QImage(self.page.viewportSize(), QImage.Format_ARGB32) image.setDotsPerMeterX(self.dpi * (100 / 2.54)) image.setDotsPerMeterY(self.dpi * (100 / 2.54)) painter = QPainter(image) self.page.mainFrame().render(painter) painter.end() cheight = image.height() cwidth = image.width() pos = 0 while pos < cheight: img = image.copy(0, pos, cwidth, min(cheight - pos, cutoff_height)) pos += cutoff_height - 20 if cwidth > self.width: img = img.scaledToWidth(self.width, Qt.SmoothTransform) f = os.path.join(self.tdir, '%d.png' % pos) img.save(f) self.images.append((f, img.width(), img.height())) finally: QApplication.quit()
class HTMLTableRenderer(QObject): 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 ''' from calibre.gui2 import secure_web_page 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() secure_web_page(self.page.settings()) 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 render_html(self, ok): try: if not ok: return cwidth, cheight = self.page.mainFrame().contentsSize().width(), self.page.mainFrame().contentsSize().height() self.page.setViewportSize(QSize(cwidth, cheight)) factor = float(self.width)/cwidth if cwidth > self.width else 1 cutoff_height = int(self.height/factor)-3 image = QImage(self.page.viewportSize(), QImage.Format_ARGB32) image.setDotsPerMeterX(self.dpi*(100/2.54)) image.setDotsPerMeterY(self.dpi*(100/2.54)) painter = QPainter(image) self.page.mainFrame().render(painter) painter.end() cheight = image.height() cwidth = image.width() pos = 0 while pos < cheight: img = image.copy(0, pos, cwidth, min(cheight-pos, cutoff_height)) pos += cutoff_height-20 if cwidth > self.width: img = img.scaledToWidth(self.width, Qt.SmoothTransform) f = os.path.join(self.tdir, '%d.png'%pos) img.save(f) self.images.append((f, img.width(), img.height())) finally: QApplication.quit()
class FrameCapture(QObject): finished = pyqtSignal() def __init__(self): super(FrameCapture, self).__init__() self._percent = 0 self._page = QWebPage() self._page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self._page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self._page.loadProgress.connect(self.printProgress) self._page.loadFinished.connect(self.saveResult) def load(self, url, outputFileName): cout("Loading %s\n" % url.toString()) self._percent = 0 index = outputFileName.rfind(".") self._fileName = index == -1 and outputFileName + ".png" or outputFileName self._page.mainFrame().load(url) self._page.setViewportSize(QSize(1024, 768)) def printProgress(self, percent): if self._percent >= percent: return self._percent += 1 while self._percent < percent: self._percent += 1 cout("#") def saveResult(self, ok): cout("\n") # Crude error-checking. if not ok: cerr("Failed loading %s\n" % self._page.mainFrame().url().toString()) self.finished.emit() return # Save each frame in different image files. self._frameCounter = 0 self.saveFrame(self._page.mainFrame()) self.finished.emit() def saveFrame(self, frame): fileName = self._fileName if self._frameCounter: index = fileName.rfind(".") fileName = "%s_frame%s%s" % ( fileName[:index], self._frameCounter, fileName[index:], ) image = QImage(frame.contentsSize(), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter(image) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) frame.documentElement().render(painter) painter.end() image.save(fileName) self._frameCounter += 1 for childFrame in frame.childFrames(): self.saveFrame(childFrame)
class FrameCapture(QObject): finished = pyqtSignal() def __init__(self): super(FrameCapture, self).__init__() self._percent = 0 self._page = QWebPage() self._page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) self._page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self._page.loadProgress.connect(self.printProgress) self._page.loadFinished.connect(self.saveResult) def load(self, url, outputFileName): cout("Loading %s\n" % url.toString()) self._percent = 0 index = outputFileName.rfind('.') self._fileName = index == -1 and outputFileName + ".png" or outputFileName self._page.mainFrame().load(url) self._page.setViewportSize(QSize(1024, 768)) def printProgress(self, percent): if self._percent >= percent: return self._percent += 1 while self._percent < percent: self._percent += 1 cout("#") def saveResult(self, ok): cout("\n") # Crude error-checking. if not ok: cerr("Failed loading %s\n" % self._page.mainFrame().url().toString()) self.finished.emit() return # Save each frame in different image files. self._frameCounter = 0 self.saveFrame(self._page.mainFrame()) self.finished.emit() def saveFrame(self, frame): fileName = self._fileName if self._frameCounter: index = fileName.rfind('.') fileName = "%s_frame%s%s" % (fileName[:index], self._frameCounter, fileName[index:]) image = QImage(frame.contentsSize(), QImage.Format_ARGB32_Premultiplied) image.fill(Qt.transparent) painter = QPainter(image) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.TextAntialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) frame.documentElement().render(painter) painter.end() image.save(fileName) self._frameCounter += 1 for childFrame in frame.childFrames(): self.saveFrame(childFrame)
class PageThumbnailer(QObject): """ Class implementing a thumbnail creator for web sites. @signal thumbnailCreated(QPixmap) emitted after the thumbnail has been created """ thumbnailCreated = pyqtSignal(QPixmap) def __init__(self, parent=None): """ Constructor @param parent reference to the parent object (QObject) """ super(PageThumbnailer, self).__init__(parent) self.__page = QWebPage(self) self.__size = QSize(231, 130) self.__loadTitle = False self.__title = "" self.__url = QUrl() self.__proxy = NetworkAccessManagerProxy(self) import Helpviewer.HelpWindow self.__proxy.setPrimaryNetworkAccessManager( Helpviewer.HelpWindow.HelpWindow.networkAccessManager()) self.__page.setNetworkAccessManager(self.__proxy) self.__page.mainFrame().setScrollBarPolicy( Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.__page.mainFrame().setScrollBarPolicy( Qt.Vertical, Qt.ScrollBarAlwaysOff) # Full HD # Every page should fit in this resolution self.__page.setViewportSize(QSize(1920, 1080)) def setSize(self, size): """ Public method to set the size of the image. @param size size of the image (QSize) """ if size.isValid(): self.__size = QSize(size) def setUrl(self, url): """ Public method to set the URL of the site to be thumbnailed. @param url URL of the web site (QUrl) """ if url.isValid(): self.__url = QUrl(url) def url(self): """ Public method to get the URL of the thumbnail. @return URL of the thumbnail (QUrl) """ return QUrl(self.__url) def loadTitle(self): """ Public method to check, if the title is loaded from the web site. @return flag indicating, that the title is loaded (boolean) """ return self.__loadTitle def setLoadTitle(self, load): """ Public method to set a flag indicating to load the title from the web site. @param load flag indicating to load the title (boolean) """ self.__loadTitle = load def title(self): """ Public method to get the title of the thumbnail. @return title of the thumbnail (string) """ return self.__title def start(self): """ Public method to start the thumbnailing action. """ self.__page.loadFinished.connect(self.__createThumbnail) self.__page.mainFrame().load(self.__url) def __createThumbnail(self, status): """ Private slot creating the thumbnail of the web site. @param status flag indicating a successful load of the web site (boolean) """ if not status: self.thumbnailCreated.emit(QPixmap()) return self.__title = self.__page.mainFrame().title() image = QImage(self.__page.viewportSize(), QImage.Format_ARGB32) painter = QPainter(image) self.__page.mainFrame().render(painter) painter.end() scaledImage = image.scaled(self.__size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) self.thumbnailCreated.emit(QPixmap.fromImage(scaledImage))
class PageThumbnailer(QObject): """ Class implementing a thumbnail creator for web sites. @signal thumbnailCreated(QPixmap) emitted after the thumbnail has been created """ thumbnailCreated = pyqtSignal(QPixmap) def __init__(self, parent=None): """ Constructor @param parent reference to the parent object (QObject) """ super(PageThumbnailer, self).__init__(parent) self.__page = QWebPage(self) self.__size = QSize(231, 130) self.__loadTitle = False self.__title = "" self.__url = QUrl() self.__proxy = NetworkAccessManagerProxy(self) import Helpviewer.HelpWindow self.__proxy.setPrimaryNetworkAccessManager( Helpviewer.HelpWindow.HelpWindow.networkAccessManager()) self.__page.setNetworkAccessManager(self.__proxy) self.__page.mainFrame().setScrollBarPolicy(Qt.Horizontal, Qt.ScrollBarAlwaysOff) self.__page.mainFrame().setScrollBarPolicy(Qt.Vertical, Qt.ScrollBarAlwaysOff) # Full HD # Every page should fit in this resolution self.__page.setViewportSize(QSize(1920, 1080)) def setSize(self, size): """ Public method to set the size of the image. @param size size of the image (QSize) """ if size.isValid(): self.__size = QSize(size) def setUrl(self, url): """ Public method to set the URL of the site to be thumbnailed. @param url URL of the web site (QUrl) """ if url.isValid(): self.__url = QUrl(url) def url(self): """ Public method to get the URL of the thumbnail. @return URL of the thumbnail (QUrl) """ return QUrl(self.__url) def loadTitle(self): """ Public method to check, if the title is loaded from the web site. @return flag indicating, that the title is loaded (boolean) """ return self.__loadTitle def setLoadTitle(self, load): """ Public method to set a flag indicating to load the title from the web site. @param load flag indicating to load the title (boolean) """ self.__loadTitle = load def title(self): """ Public method to get the title of the thumbnail. @return title of the thumbnail (string) """ return self.__title def start(self): """ Public method to start the thumbnailing action. """ self.__page.loadFinished.connect(self.__createThumbnail) self.__page.mainFrame().load(self.__url) def __createThumbnail(self, status): """ Private slot creating the thumbnail of the web site. @param status flag indicating a successful load of the web site (boolean) """ if not status: self.thumbnailCreated.emit(QPixmap()) return self.__title = self.__page.mainFrame().title() image = QImage(self.__page.viewportSize(), QImage.Format_ARGB32) painter = QPainter(image) self.__page.mainFrame().render(painter) painter.end() scaledImage = image.scaled(self.__size, Qt.KeepAspectRatioByExpanding, Qt.SmoothTransformation) self.thumbnailCreated.emit(QPixmap.fromImage(scaledImage))