class Html2PdfConverter(QObject): def __init__(self, inputPath: str, outputPath: str) -> None: super().__init__() self.m_inputPath = inputPath self.m_outputPath = outputPath self.m_page = QWebEnginePage() self.m_page.loadFinished.connect(self.loadFinished) self.m_page.pdfPrintingFinished.connect(self.pdfPrintingFinished) def run(self) -> bool: self.m_page.load(QUrl.fromUserInput(self.m_inputPath)) return QApplication.exec_() @pyqtSlot(bool) def loadFinished(self, ok: bool): if not ok: sys.stderr.write("failed to load URL '%s'" % (self.m_inputPath,)) QCoreApplication.exit(1) return self.m_page.printToPdf(self.m_outputPath) @pyqtSlot(str, bool) def pdfPrintingFinished(self, filePath: str, success: bool): if not success: sys.stderr.write("failed to print to output file '%s'" % (filePath,)) QCoreApplication.exit(1) else: QCoreApplication.quit()
class PdfExport(): def __init__(self, filename, book, status_bar): QApplication.setOverrideCursor(Qt.WaitCursor) self.filename = filename self.status_bar = status_bar html = "<html>\n<head>\n" html += "<link href=\"../css/pastie.css\" rel=\"stylesheet\" type=\"text/css\"/>\n" html += "<link href=\"../css/stylesheet.css\" rel=\"stylesheet\" type=\"text/css\"/>\n" html += "</head>\n<body>\n" for part in book._parts: self.status_bar.showMessage("Processing " + part.name) with open(os.path.join(book.source_path, "parts", part.src), "r") as i: text = i.read() htm = markdown(text, html4tags=False, extras=[ "fenced-code-blocks", "wiki-tables", "tables", "header-ids" ]) htm = addLineNumbers(htm) html += htm html += "\n</body>\n</html>" self.status_bar.showMessage("Loading HTML") self.page = QWebEnginePage() self.page.loadFinished.connect(self.loadFinished) self.page.pdfPrintingFinished.connect(self.printFinished) self.page.setHtml( html, QUrl( Path(os.path.join(book.source_path, "parts", "index.html")).as_uri())) def loadFinished(self, ok): if ok: self.status_bar.showMessage("Printing PDF") self.page.printToPdf(self.filename, pageLayout=QPageLayout( QPageSize(QPageSize.A5), QPageLayout.Portrait, QMarginsF(30.0, 30.0, 30.0, 30.0))) else: self.status_bar.showMessage("There was an error printing the PDF") def printFinished(self, filename, success): QApplication.restoreOverrideCursor() if success: self.status_bar.showMessage("PDF created") else: self.status_bar.showMessage("There was an error printing the PDF")
def test_qt(self): from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import QApplication from PyQt5.QtWebEngineWidgets import QWebEnginePage from PyQt5.QtGui import QImageReader, QFontDatabase from PyQt5.QtNetwork import QNetworkAccessManager from calibre.utils.img import image_from_data, image_to_data, test # Ensure that images can be read before QApplication is constructed. # Note that this requires QCoreApplication.libraryPaths() to return the # path to the Qt plugins which it always does in the frozen build, # because Qt is patched to know the layout of the calibre application # package. On non-frozen builds, it should just work because the # hard-coded paths of the Qt installation should work. If they do not, # then it is a distro problem. fmts = set(map(lambda x: x.data().decode('utf-8'), QImageReader.supportedImageFormats())) # no2to3 testf = {'jpg', 'png', 'svg', 'ico', 'gif'} self.assertEqual(testf.intersection(fmts), testf, "Qt doesn't seem to be able to load some of its image plugins. Available plugins: %s" % fmts) data = P('images/blank.png', allow_user_override=False, data=True) img = image_from_data(data) image_from_data(P('catalog/mastheadImage.gif', allow_user_override=False, data=True)) for fmt in 'png bmp jpeg'.split(): d = image_to_data(img, fmt=fmt) image_from_data(d) # Run the imaging tests test() from calibre.gui2 import ensure_app, destroy_app display_env_var = os.environ.pop('DISPLAY', None) try: ensure_app() self.assertGreaterEqual(len(QFontDatabase().families()), 5, 'The QPA headless plugin is not able to locate enough system fonts via fontconfig') from calibre.ebooks.covers import create_cover create_cover('xxx', ['yyy']) na = QNetworkAccessManager() self.assertTrue(hasattr(na, 'sslErrors'), 'Qt not compiled with openssl') if iswindows: from PyQt5.Qt import QtWin QtWin p = QWebEnginePage() def callback(result): callback.result = result if hasattr(print_callback, 'result'): QApplication.instance().quit() def print_callback(result): print_callback.result = result if hasattr(callback, 'result'): QApplication.instance().quit() p.runJavaScript('1 + 1', callback) p.printToPdf(print_callback) QTimer.singleShot(5000, lambda: QApplication.instance().quit()) QApplication.instance().exec_() test_flaky = ismacos and not is_ci if not test_flaky: self.assertEqual(callback.result, 2, 'Simple JS computation failed') self.assertIn(b'Skia/PDF', bytes(print_callback.result), 'Print to PDF failed') del p del na destroy_app() del QWebEnginePage finally: if display_env_var is not None: os.environ['DISPLAY'] = display_env_var