Add printing to tab API

This fixes printing for QtWebKit, and hopefully will make printing to
PDF work with QtWebEngine with Qt >= 5.7
This commit is contained in:
Florian Bruhin 2016-07-12 12:54:11 +02:00
parent 7a39021d41
commit cd4eff364a
5 changed files with 107 additions and 26 deletions

View File

@ -24,6 +24,7 @@ import itertools
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QUrl, QObject, QPoint
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QLayout
from PyQt5.QtPrintSupport import QPrinter
from qutebrowser.keyinput import modeman
from qutebrowser.config import config
@ -105,6 +106,27 @@ class TabData:
self.inspector = None
class AbstractPrinting:
"""Attribute of AbstractTab for printing the page."""
def __init__(self):
self._widget = None
def check_pdf_support(self):
raise NotImplementedError
def check_printer_support(self):
raise NotImplementedError
def to_pdf(self, filename):
raise NotImplementedError
@pyqtSlot(QPrinter)
def to_printer(self, printer):
raise NotImplementedError
class AbstractSearch(QObject):
"""Attribute of AbstractTab for doing searches.
@ -468,6 +490,7 @@ class AbstractTab(QWidget):
# parent=self)
# self.zoom = AbstractZoom(win_id=win_id)
# self.search = AbstractSearch(parent=self)
# self.printing = AbstractPrinting()
self.data = TabData()
self._layout = None
self._widget = None
@ -485,6 +508,7 @@ class AbstractTab(QWidget):
self.caret._widget = widget
self.zoom._widget = widget
self.search._widget = widget
self.printing._widget = widget
widget.mouse_wheel_zoom.connect(self.zoom._on_mouse_wheel_zoom)
widget.setParent(self)
self.setFocusProxy(widget)

View File

@ -28,7 +28,7 @@ import functools
from PyQt5.QtWidgets import QApplication, QTabBar
from PyQt5.QtCore import Qt, QUrl, QEvent
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter, QPrintPreviewDialog
from PyQt5.QtPrintSupport import QPrintDialog, QPrintPreviewDialog
from PyQt5.QtWebKitWidgets import QWebPage
try:
from PyQt5.QtWebEngineWidgets import QWebEnginePage
@ -308,33 +308,37 @@ class CommandDispatcher:
count: The tab index to print, or None.
pdf: The file path to write the PDF to.
"""
if not qtutils.check_print_compat():
# WORKAROUND (remove this when we bump the requirements to 5.3.0)
raise cmdexc.CommandError(
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
tab = self._cntwidget(count)
if tab is not None:
if preview:
diag = QPrintPreviewDialog()
diag.setAttribute(Qt.WA_DeleteOnClose)
diag.setWindowFlags(diag.windowFlags() |
Qt.WindowMaximizeButtonHint |
Qt.WindowMinimizeButtonHint)
diag.paintRequested.connect(tab.print)
diag.exec_()
elif pdf:
pdf = os.path.expanduser(pdf)
directory = os.path.dirname(pdf)
if directory and not os.path.exists(directory):
os.mkdir(directory)
printer = QPrinter()
printer.setOutputFileName(pdf)
tab.print(printer)
log.misc.debug("Print to file: {}".format(pdf))
if tab is None:
return
try:
if pdf:
tab.printing.check_pdf_support()
else:
diag = QPrintDialog()
diag.setAttribute(Qt.WA_DeleteOnClose)
diag.open(lambda: tab.print(diag.printer()))
tab.printing.check_printer_support()
except browsertab.WebTabError as e:
raise cmdexc.CommandError(e)
if preview:
diag = QPrintPreviewDialog()
diag.setAttribute(Qt.WA_DeleteOnClose)
diag.setWindowFlags(diag.windowFlags() |
Qt.WindowMaximizeButtonHint |
Qt.WindowMinimizeButtonHint)
diag.paintRequested.connect(tab.printing.to_printer)
diag.exec_()
elif pdf:
pdf = os.path.expanduser(pdf)
directory = os.path.dirname(pdf)
if directory and not os.path.exists(directory):
os.mkdir(directory)
tab.printing.to_pdf(pdf)
log.misc.debug("Print to file: {}".format(pdf))
else:
diag = QPrintDialog()
diag.setAttribute(Qt.WA_DeleteOnClose)
diag.open(lambda: tab.printing.to_printer(diag.printer()))
@cmdutils.register(instance='command-dispatcher', scope='window')
def tab_clone(self, bg=False, window=False):

View File

@ -25,6 +25,7 @@
from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QPoint
from PyQt5.QtGui import QKeyEvent, QIcon
from PyQt5.QtWidgets import QApplication
from PyQt5.QtPrintSupport import QPrinter
# pylint: disable=no-name-in-module,import-error,useless-suppression
from PyQt5.QtWebEngineWidgets import QWebEnginePage
# pylint: enable=no-name-in-module,import-error,useless-suppression
@ -34,6 +35,28 @@ from qutebrowser.browser.webengine import webview
from qutebrowser.utils import usertypes, qtutils, log
class WebEnginePrinting(browsertab.AbstractPrinting):
"""QtWebEngine implementations related to printing."""
def check_pdf_support(self):
if not hasattr(self._widget.page(), 'printToPdf'):
raise browsertab.WebTabError(
"Printing to PDF is unsupported with QtWebEngine on Qt > 5.7")
def check_printer_support(self):
raise browsertab.WebTabError(
"Printing is unsupported with QtWebEngine")
def to_pdf(self, filename):
self._widget.page().printToPdf(filename)
@pyqtSlot(QPrinter)
def to_printer(self, printer):
# Should never be called
assert False
class WebEngineSearch(browsertab.AbstractSearch):
"""QtWebEngine implementations related to searching on the page."""
@ -256,6 +279,7 @@ class WebEngineTab(browsertab.AbstractTab):
tab=self, parent=self)
self.zoom = WebEngineZoom(win_id=win_id, parent=self)
self.search = WebEngineSearch(parent=self)
self.printing = WebEnginePrinting()
self._set_widget(widget)
self._connect_signals()
self.backend = usertypes.Backend.QtWebEngine

View File

@ -27,12 +27,39 @@ from PyQt5.QtCore import pyqtSlot, Qt, QEvent, QUrl, QPoint, QTimer
from PyQt5.QtGui import QKeyEvent
from PyQt5.QtWebKitWidgets import QWebPage
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtPrintSupport import QPrinter
from qutebrowser.browser import browsertab
from qutebrowser.browser.webkit import webview, tabhistory
from qutebrowser.utils import qtutils, objreg, usertypes, utils
class WebKitPrinting(browsertab.AbstractPrinting):
"""QtWebKit implementations related to printing."""
def _do_check(self):
if not qtutils.check_print_compat():
# WORKAROUND (remove this when we bump the requirements to 5.3.0)
raise browsertab.WebTabError(
"Printing on Qt < 5.3.0 on Windows is broken, please upgrade!")
def check_pdf_support(self):
self._do_check()
def check_printer_support(self):
self._do_check()
def to_pdf(self, filename):
printer = QPrinter()
printer.setOutputFileName(filename)
self.to_printer(printer)
@pyqtSlot(QPrinter)
def to_printer(self, printer):
self._widget.print(printer)
class WebKitSearch(browsertab.AbstractSearch):
"""QtWebKit implementations related to searching on the page."""
@ -461,6 +488,7 @@ class WebKitTab(browsertab.AbstractTab):
tab=self, parent=self)
self.zoom = WebKitZoom(win_id=win_id, parent=self)
self.search = WebKitSearch(parent=self)
self.printing = WebKitPrinting()
self._set_widget(widget)
self._connect_signals()
self.zoom.set_default()

View File

@ -77,6 +77,7 @@ def test_tab(qtbot, view, config_stub, tab_registry):
tab=tab_w, parent=tab_w)
tab_w.zoom = browsertab.AbstractZoom(win_id=tab_w.win_id)
tab_w.search = browsertab.AbstractSearch(parent=tab_w)
tab_w.printing = browsertab.AbstractPrinting()
tab_w._set_widget(w)
assert tab_w._widget is w