src/eric7/WebBrowser/WebBrowserView.py

branch
eric7
changeset 10240
cbd566d49a88
parent 10069
435cc5875135
child 10334
24300d16a154
equal deleted inserted replaced
10239:63fe209a1e71 10240:cbd566d49a88
16 from PyQt6.QtCore import ( 16 from PyQt6.QtCore import (
17 QByteArray, 17 QByteArray,
18 QDataStream, 18 QDataStream,
19 QDateTime, 19 QDateTime,
20 QEvent, 20 QEvent,
21 QEventLoop,
21 QIODevice, 22 QIODevice,
23 QMarginsF,
22 QPoint, 24 QPoint,
23 QPointF, 25 QPointF,
24 QStandardPaths, 26 QStandardPaths,
25 Qt, 27 Qt,
26 QTimer, 28 QTimer,
27 QUrl, 29 QUrl,
28 pyqtSignal, 30 pyqtSignal,
29 pyqtSlot, 31 pyqtSlot,
30 ) 32 )
31 from PyQt6.QtGui import QClipboard, QCursor, QDesktopServices, QIcon, QPixmap 33 from PyQt6.QtGui import (
34 QClipboard,
35 QCursor,
36 QDesktopServices,
37 QIcon,
38 QPageLayout,
39 QPixmap,
40 )
41 from PyQt6.QtPrintSupport import (
42 QAbstractPrintDialog,
43 QPrintDialog,
44 QPrinter,
45 QPrintPreviewDialog,
46 )
32 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage 47 from PyQt6.QtWebEngineCore import QWebEngineDownloadRequest, QWebEnginePage
33 from PyQt6.QtWebEngineWidgets import QWebEngineView 48 from PyQt6.QtWebEngineWidgets import QWebEngineView
34 from PyQt6.QtWidgets import QApplication, QDialog, QMenu, QStyle 49 from PyQt6.QtWidgets import QApplication, QDialog, QMenu, QStyle
35 50
36 from eric7 import Preferences 51 from eric7 import Preferences
37 from eric7.EricGui import EricPixmapCache 52 from eric7.EricGui import EricPixmapCache
38 from eric7.EricWidgets import EricFileDialog, EricMessageBox 53 from eric7.EricWidgets import EricFileDialog, EricMessageBox
39 from eric7.EricWidgets.EricApplication import ericApp 54 from eric7.EricWidgets.EricApplication import ericApp
40 from eric7.SystemUtilities import FileSystemUtilities, OSUtilities 55 from eric7.SystemUtilities import FileSystemUtilities, OSUtilities
56 from eric7.UI.Info import Homepage, VersionOnly
41 from eric7.WebBrowser.WebBrowserWindow import WebBrowserWindow 57 from eric7.WebBrowser.WebBrowserWindow import WebBrowserWindow
42 from eric7.WebBrowser.ZoomManager import ZoomManager 58 from eric7.WebBrowser.ZoomManager import ZoomManager
43 59
44 from . import WebInspector 60 from . import WebInspector
45 from .Tools import Scripts 61 from .Tools import Scripts, WebBrowserTools
46 from .Tools.WebBrowserTools import getHtmlPage, pixmapToDataUrl 62 from .Tools.WebBrowserTools import getHtmlPage, pixmapToDataUrl
47 from .Tools.WebIconLoader import WebIconLoader 63 from .Tools.WebIconLoader import WebIconLoader
48 from .WebBrowserPage import WebBrowserPage 64 from .WebBrowserPage import WebBrowserPage
65
66
67 def isCupsAvailable():
68 """
69 Static method to test the availability of CUPS.
70
71 @return flag indicating the availability of CUPS
72 @rtype bool
73 """
74 if OSUtilities.isMacPlatform():
75 # OS X/MacOS always have CUPS
76 return True
77 elif OSUtilities.isLinuxPlatform():
78 testPrinter = QPrinter()
79 return testPrinter.supportsMultipleCopies()
80 else:
81 return False
49 82
50 83
51 class WebBrowserView(QWebEngineView): 84 class WebBrowserView(QWebEngineView):
52 """ 85 """
53 Class implementing the web browser view widget. 86 Class implementing the web browser view widget.
128 self.__siteIcon = QIcon() 161 self.__siteIcon = QIcon()
129 self.__menu = QMenu(self) 162 self.__menu = QMenu(self)
130 self.__clickedPos = QPoint() 163 self.__clickedPos = QPoint()
131 self.__firstLoad = False 164 self.__firstLoad = False
132 self.__preview = QPixmap() 165 self.__preview = QPixmap()
166 self.__currentPrinter = None
167 self.__printPreviewLoop = None
133 168
134 self.__currentZoom = 100 169 self.__currentZoom = 100
135 self.__zoomLevels = WebBrowserView.ZoomLevels[:] 170 self.__zoomLevels = WebBrowserView.ZoomLevels[:]
136 171
137 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) 172 self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
144 self.loadStarted.connect(self.__loadStarted) 179 self.loadStarted.connect(self.__loadStarted)
145 self.loadProgress.connect(self.__loadProgress) 180 self.loadProgress.connect(self.__loadProgress)
146 self.loadFinished.connect(self.__loadFinished) 181 self.loadFinished.connect(self.__loadFinished)
147 self.renderProcessTerminated.connect(self.__renderProcessTerminated) 182 self.renderProcessTerminated.connect(self.__renderProcessTerminated)
148 183
184 self.printRequested.connect(self.printPage)
185 self.printFinished.connect(self.__printPageFinished)
186 self.pdfPrintingFinished.connect(self.__printPageToPdfFinished)
187
149 self.__mw.openSearchManager().currentEngineChanged.connect( 188 self.__mw.openSearchManager().currentEngineChanged.connect(
150 self.__currentEngineChanged 189 self.__currentEngineChanged
151 ) 190 )
152 191
153 self.setAcceptDrops(True) 192 self.setAcceptDrops(True)
175 self.__page = WebBrowserPage(self, self) 214 self.__page = WebBrowserPage(self, self)
176 self.setPage(self.__page) 215 self.setPage(self.__page)
177 216
178 self.__page.safeBrowsingAbort.connect(self.safeBrowsingAbort) 217 self.__page.safeBrowsingAbort.connect(self.safeBrowsingAbort)
179 self.__page.safeBrowsingBad.connect(self.safeBrowsingBad) 218 self.__page.safeBrowsingBad.connect(self.safeBrowsingBad)
180 self.__page.printPageRequested.connect(self.__printPage)
181 with contextlib.suppress(AttributeError): 219 with contextlib.suppress(AttributeError):
182 # deprecated with Qt 6.5+ 220 # deprecated with Qt 6.5+
183 self.__page.quotaRequested.connect(self.__quotaRequested) 221 self.__page.quotaRequested.connect(self.__quotaRequested)
184 with contextlib.suppress(AttributeError): 222 with contextlib.suppress(AttributeError):
185 # Qt 6.4+ 223 # Qt 6.4+
2297 return self.__page.getSafeBrowsingStatus() 2335 return self.__page.getSafeBrowsingStatus()
2298 else: 2336 else:
2299 return True 2337 return True
2300 2338
2301 ########################################################################### 2339 ###########################################################################
2302 ## Methods below implement print support from the page 2340 ## Methods below implement print support
2303 ########################################################################### 2341 ###########################################################################
2304 2342
2343 def __setupPrinter(self, filePath=None):
2344 """
2345 Private method to create and initialize a QPrinter object.
2346
2347 @param filePath name of the output file for the printer (defaults to None)
2348 @type str (optional)
2349 @return initialized QPrinter object
2350 @rtype QPrinter
2351 """
2352 printer = QPrinter(mode=QPrinter.PrinterMode.HighResolution)
2353 if Preferences.getPrinter("ColorMode"):
2354 printer.setColorMode(QPrinter.ColorMode.Color)
2355 else:
2356 printer.setColorMode(QPrinter.ColorMode.GrayScale)
2357 if Preferences.getPrinter("FirstPageFirst"):
2358 printer.setPageOrder(QPrinter.PageOrder.FirstPageFirst)
2359 else:
2360 printer.setPageOrder(QPrinter.PageOrder.LastPageFirst)
2361 printer.setPageMargins(
2362 QMarginsF(
2363 Preferences.getPrinter("LeftMargin") * 10,
2364 Preferences.getPrinter("TopMargin") * 10,
2365 Preferences.getPrinter("RightMargin") * 10,
2366 Preferences.getPrinter("BottomMargin") * 10,
2367 ),
2368 QPageLayout.Unit.Millimeter,
2369 )
2370 printerName = Preferences.getPrinter("PrinterName")
2371 if printerName:
2372 printer.setPrinterName(printerName)
2373 printer.setResolution(Preferences.getPrinter("Resolution"))
2374 documentName = WebBrowserTools.getFileNameFromUrl(self.url())
2375 printer.setDocName(documentName)
2376 documentsPath = QStandardPaths.writableLocation(
2377 QStandardPaths.StandardLocation.DocumentsLocation
2378 )
2379 if filePath is None:
2380 filePath = "{0}.pdf".format(documentName)
2381 filePath = (
2382 os.path.join(documentsPath, filePath)
2383 if documentsPath
2384 else os.path.abspath(filePath)
2385 )
2386 printer.setOutputFileName(filePath)
2387 printer.setCreator(self.tr("eric7 {0} ({1})").format(VersionOnly, Homepage))
2388 return printer
2389
2305 @pyqtSlot() 2390 @pyqtSlot()
2306 def __printPage(self): 2391 def printPage(self):
2307 """ 2392 """
2308 Private slot to support printing from the web page. 2393 Public slot to print the current page.
2309 """ 2394 """
2310 self.__mw.tabWidget.printBrowser(browser=self) 2395 if self.__currentPrinter is not None:
2396 EricMessageBox.warning(
2397 self,
2398 self.tr("Print Page"),
2399 self.tr(
2400 "There is already a print job in progress. Printing is temporarily"
2401 " disabled until the current job is finished."
2402 ),
2403 )
2404 return
2405
2406 printer = self.__setupPrinter()
2407
2408 printDialog = QPrintDialog(printer, self)
2409 printDialog.setOptions(
2410 QAbstractPrintDialog.PrintDialogOption.PrintToFile
2411 | QAbstractPrintDialog.PrintDialogOption.PrintShowPageSize
2412 )
2413 if not OSUtilities.isWindowsPlatform():
2414 if isCupsAvailable():
2415 printDialog.setOption(
2416 QAbstractPrintDialog.PrintDialogOption.PrintCollateCopies
2417 )
2418 printDialog.setOption(QAbstractPrintDialog.PrintDialogOption.PrintPageRange)
2419 if printDialog.exec() == QDialog.DialogCode.Accepted:
2420 if printer.outputFormat() == QPrinter.OutputFormat.PdfFormat:
2421 self.printToPdf(
2422 printer.outputFileName(), printer.pageLayout(), printer.pageRanges()
2423 )
2424 else:
2425 self.__currentPrinter = printer
2426 self.print(printer)
2427
2428 @pyqtSlot()
2429 def printPageToPdf(self):
2430 """
2431 Public slot to save the current page as a PDF file.
2432 """
2433 from .Tools.PrintToPdfDialog import PrintToPdfDialog
2434
2435 name = WebBrowserTools.getFileNameFromUrl(self.url())
2436 name = name.rsplit(".", 1)[0] + ".pdf" if name else "printout.pdf"
2437 dlg = PrintToPdfDialog(self.__setupPrinter(filePath=name), self)
2438 if dlg.exec() == QDialog.DialogCode.Accepted:
2439 filePath, pageLayout = dlg.getData()
2440 if filePath:
2441 if os.path.exists(filePath):
2442 res = EricMessageBox.warning(
2443 self,
2444 self.tr("Print to PDF"),
2445 self.tr(
2446 """<p>The file <b>{0}</b> exists"""
2447 """ already. Shall it be"""
2448 """ overwritten?</p>"""
2449 ).format(filePath),
2450 EricMessageBox.No | EricMessageBox.Yes,
2451 EricMessageBox.No,
2452 )
2453 if res == EricMessageBox.No:
2454 return
2455 self.printToPdf(filePath, pageLayout)
2456
2457 @pyqtSlot()
2458 def printPreviewPage(self):
2459 """
2460 Public slot to create a print preview of the current page.
2461 """
2462 printer = self.__setupPrinter()
2463 preview = QPrintPreviewDialog(printer, self)
2464 preview.resize(800, 750)
2465 preview.paintRequested.connect(self.__printPreviewRequested)
2466 preview.exec()
2467
2468 @pyqtSlot(QPrinter)
2469 def __printPreviewRequested(self, printer):
2470 """
2471 Private slot to generate the print preview.
2472
2473 @param printer reference to the printer object
2474 @type QPrinter
2475 """
2476 # This needs to run its own event loop to prevent a premature return from
2477 # the method.
2478 self.__printPreviewLoop = QEventLoop()
2479
2480 self.print(printer)
2481
2482 self.__printPreviewLoop.exec()
2483 self.__printPreviewLoop = None
2484
2485 @pyqtSlot(bool)
2486 def __printPageFinished(self, success):
2487 """
2488 Private slot to handle the finishing of a print job.
2489
2490 @param success flag indicating success (not used)
2491 @type bool
2492 """
2493 if self.__printPreviewLoop is not None:
2494 # The print preview was created, now stop the print preview loop.
2495 self.__printPreviewLoop.quit()
2496 return
2497
2498 # we printed to a real printer
2499 self.__currentPrinter = None
2500
2501 @pyqtSlot(str, bool)
2502 def __printPageToPdfFinished(self, filepath, success):
2503 """
2504 Private slot to handle the finishing of a PDF print job.
2505
2506 @param filepath path of the output PDF file
2507 @type str
2508 @param success flag indicating success
2509 @type bool
2510 """
2511 if not success:
2512 EricMessageBox.critical(
2513 self,
2514 self.tr("Print to PDF"),
2515 self.tr(
2516 """<p>The PDF file <b>{0}</b> could not be generated.</p>"""
2517 ).format(filepath),
2518 )
2311 2519
2312 ########################################################################### 2520 ###########################################################################
2313 ## Methods below implement slots for Qt 6.0 to 6.4 2521 ## Methods below implement slots for Qt 6.0 to 6.4
2314 ########################################################################### 2522 ###########################################################################
2315 2523

eric ide

mercurial