Started to implement real printing support for the new web browser and Qt >= 5.7.0.

Wed, 28 Sep 2016 20:04:44 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 28 Sep 2016 20:04:44 +0200
changeset 5182
e2782c9a43d4
parent 5181
1948b27d7b21
child 5184
79b3922094ba

Started to implement real printing support for the new web browser and Qt >= 5.7.0.

WebBrowser/Tools/FilePrinter.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserTabWidget.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebBrowser/Tools/FilePrinter.py	Wed Sep 28 20:04:44 2016 +0200
@@ -0,0 +1,576 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing an object for printing of files.
+"""
+
+#
+# This code is inspired by and ported from Qupzilla.
+# Original Copyright (C) 2016 by Kevin Kofler <kevin.kofler@chello.at>
+#
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import qVersion, QFile, QStandardPaths, QProcess
+from PyQt5.QtPrintSupport import QPrinter, QPrintEngine
+
+import Globals
+
+
+_FilePrintJobs = []
+
+class FilePrinter(object):
+    """
+    Class implementing methods for printing on *nix systems.
+    """
+    #
+    # Whether file(s) get deleted by the application or by the print system.
+    #
+    ApplicationDeletesFiles = 0
+    SystemDeletesFiles = 1
+    
+    #
+    # Whether pages to be printed are selected by the application or the print
+    # system.
+    #
+    # If application side, then the generated file will only contain those
+    # pages selected by the user, so FilePrinter will print all the pages in
+    # the file.
+    #
+    #  If system side, then the file will contain all the pages in the
+    # document, and the print system will print the users selected print range
+    # from out of the file.
+    #
+    # Note: system side only works in CUPS, not LPR.
+    #
+    ApplicationSelectsPages = 0
+    SystemSelectsPages = 1
+    
+    def __init__(self):
+        """
+        Constructor
+        """
+        self.__paperSizesMap = {
+            QPrinter.A0: "A0",
+            QPrinter.A1: "A1",
+            QPrinter.A2: "A2",
+            QPrinter.A3: "A3",
+            QPrinter.A4: "A4",
+            QPrinter.A5: "A5",
+            QPrinter.A6: "A6",
+            QPrinter.A7: "A7",
+            QPrinter.A8: "A8",
+            QPrinter.A9: "A9",
+            QPrinter.B0: "B0",
+            QPrinter.B1: "B1",
+            QPrinter.B2: "B2",
+            QPrinter.B3: "B3",
+            QPrinter.B4: "B4",
+            QPrinter.B5: "B5",
+            QPrinter.B6: "B6",
+            QPrinter.B7: "B7",
+            QPrinter.B8: "B8",
+            QPrinter.B9: "B9",
+            QPrinter.B10: "B10",
+            QPrinter.C5E: "C5",
+            QPrinter.Comm10E: "Comm10",
+            QPrinter.DLE: "DL",
+            QPrinter.Executive: "Executive",
+            QPrinter.Folio: "Folio",
+            QPrinter.Ledger: "Ledger",
+            QPrinter.Legal: "Legal",
+            QPrinter.Letter: "Letter",
+            QPrinter.Tabloid: "Tabloid",
+        }
+        
+        self.__paperSourcesMap = {
+            QPrinter.Auto: "",
+            QPrinter.Cassette: "Cassette",
+            QPrinter.Envelope: "Envelope",
+            QPrinter.EnvelopeManual: "EnvelopeManual",
+            QPrinter.FormSource: "FormSource",
+            QPrinter.LargeCapacity: "LargeCapacity",
+            QPrinter.LargeFormat: "LargeFormat",
+            QPrinter.Lower: "Lower",
+            QPrinter.MaxPageSource: "MaxPageSource",
+            QPrinter.Middle: "Middle",
+            QPrinter.Manual: "Manual",
+            QPrinter.OnlyOne: "OnlyOne",
+            QPrinter.Tractor: "Tractor",
+            QPrinter.SmallFormat: "SmallFormat",
+        }
+        
+        self.__process = None
+        self.__doDeleteFile = FilePrinter.ApplicationDeletesFiles
+        self.__fileName = ""
+    
+    def _doPrintFile(self, printer, fileName, fileDeletePolicy,
+                     pageSelectPolicy, pageRange):
+        """
+        Protected method to print a file
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param fileName name (path) of the file to be printed
+        @type str
+        @param fileDeletePolicy policy determining who deletes the file to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param pageSelectPolicy policy determining who selects the pages to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param pageRange string determining the page range(s) to be printed, if
+            SystemSelectsPages was given for pageSelectPolicy and user chose
+            Selection in print dialog
+        @type str
+        @return flag indicating successful print job submission
+        @rtype bool
+        """
+        if not QFile.exists(fileName):
+            return False
+        
+        self.__fileName = fileName
+        self.__doDeleteFile = (
+            fileDeletePolicy == FilePrinter.SystemDeletesFiles)
+        
+        if printer.printerState() in [QPrinter.Aborted, QPrinter.Error]:
+            if self.__doDeleteFile:
+                QFile.remove(fileName)
+            return False
+        
+        #
+        # Print via lpr/lp command
+        #
+        
+        #
+        # Decide what executable to use to print with, need the CUPS version
+        # of lpr if available. Some distros name the CUPS version of lpr as
+        # lpr-cups or lpr.cups so try those first before default to lpr, or
+        # failing that to lp.
+        if QStandardPaths.findExecutable("lpr-cups"):
+            exe = "lpr-cups"
+        elif QStandardPaths.findExecutable("lpr.cups"):
+            exe = "lpr.cups"
+        elif QStandardPaths.findExecutable("lpr"):
+            exe = "lpr"
+        elif QStandardPaths.findExecutable("lp"):
+            exe = "lp"
+        else:
+            if self.__doDeleteFile:
+                QFile.remove(fileName)
+            return False
+        
+        useCupsOptions = isCupsAvailable()
+        argsList = self._printArguments(
+            printer, fileDeletePolicy, pageSelectPolicy, useCupsOptions,
+            pageRange, exe)
+        argsList.append(fileName)
+        
+        self.__process = QProcess()
+        if qVersion() < "5.6.0":
+            self.__process.error.connect(self.__processError)
+        else:
+            self.__process.errorOccurred.connect(self.__processError)
+        self.__process.finished.connect(self.__processFinished)
+        self.__process.start(exe, argsList)
+        if not self.__process.waitForStarted(10000):
+            # it failed to start
+            self.__doCleanup(self.__doDeleteFile)
+            return False
+        
+        return True
+    
+    def __doCleanup(self, deleteFile):
+        """
+        Private method to perform some internal cleanup actions.
+        
+        @param deleteFile flag indicating to delete the print file
+        @type bool
+        """
+        if deleteFile:
+            QFile.remove(self.__fileName)
+        
+        self.__process.deleteLater()
+        self.__process = None
+        
+        if self in _FilePrintJobs:
+            _FilePrintJobs.remove(self)
+    
+    def __processError(self, error):
+        """
+        Private slot handling process errors.
+        
+        @param error error value
+        @type QProcess.ProcessError
+        """
+        self.__doCleanup(self.__doDeleteFile)
+    
+    def __processFinished(self, exitCode, exitStatus):
+        """
+        Private slot handling the end of the process.
+        
+        @param exitCode exit code of the process
+        @type int
+        @param exitStatus exit status of the process
+        @type QProcess.ExitStatus
+        """
+        self.__doCleanup(self.__doDeleteFile and (
+            exitStatus != QProcess.NormalExit or exitCode != 0))
+    
+    def _printArguments(self, printer, fileDeletePolicy, pageSelectPolicy,
+                        useCupsOptions, pageRange, variant):
+        """
+        Protected method to assemble the command line arguments for the print
+        command.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param fileDeletePolicy policy determining who deletes the file to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param pageSelectPolicy policy determining who selects the pages to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param useCupsOptions flag indicating to assemble the arguments for
+            CUPS
+        @type bool
+        @param pageRange string determining the page range(s) to be printed, if
+            SystemSelectsPages was given for pageSelectPolicy and user chose
+            Selection in print dialog
+        @type str
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled command line arguments for the print command
+        @rtype list of str
+        """
+        if variant.startswith("lpr"):
+            variant = "lpr"
+        
+        args = []
+        args.extend(self._destination(printer, variant))
+        args.extend(self._copies(printer, variant))
+        args.extend(self._jobname(printer, variant))
+        args.extend(self._pages(printer, pageSelectPolicy, pageRange,
+                    useCupsOptions, variant))
+        if useCupsOptions:
+            args.extend(self._cupsOptions(printer))
+        args.extend(self._deleteFile(printer, fileDeletePolicy, variant))
+        if variant == "lp":
+            args.append("--")
+        
+        return args
+    
+    def _destination(self, printer, variant):
+        """
+        Protected method to assemble the printer destination arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled printer destination arguments
+        @rtype list of str
+        """
+        if variant == "lp":
+            return ["-d", printer.printerName()]
+        elif variant == "lpr":
+            return ["-P", printer.printerName()]
+        else:
+            return []
+    
+    def _copies(self, printer, variant):
+        """
+        Protected method to assemble the number of copies arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled number of copies arguments
+        @rtype list of str
+        """
+        copies = printer.copyCount()
+        if variant == "lp":
+            return ["-n", str(copies)]
+        elif variant == "lpr":
+            return ["-#{0}".format(copies)]
+        else:
+            return []
+    
+    def _jobname(self, printer, variant):
+        """
+        Protected method to assemble the jobname arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled jobname arguments
+        @rtype list of str
+        """
+        if printer.docName():
+            if variant == "lp":
+                return ["-t", printer.docName()]
+            elif variant == "lpr":
+                shortenedDocName = printer.docName()[:255]
+                return ["-J", shortenedDocName]
+        
+        return []
+    
+    def _deleteFile(self, printer, fileDeletePolicy, variant):
+        """
+        Protected method to assemble the jobname arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param fileDeletePolicy policy determining who deletes the file to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled jobname arguments
+        @rtype list of str
+        """
+        if fileDeletePolicy == FilePrinter.SystemDeletesFiles and \
+                variant == "lpr":
+            return ["-r"]
+        else:
+            return []
+    
+    def _pages(self, printer, pageSelectPolicy, pageRange, useCupsOptions,
+               variant):
+        """
+        Protected method to assemble the page range(s) arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @param pageSelectPolicy policy determining who selects the pages to be
+            printed (application or system)
+        @type int (0 or 1)
+        @param pageRange string determining the page range(s) to be printed, if
+            SystemSelectsPages was given for pageSelectPolicy and user chose
+            Selection in print dialog
+        @type str
+        @param useCupsOptions flag indicating to assemble the arguments for
+            CUPS
+        @type bool
+        @param variant string identifying the print command variant
+        @type str
+        @return assembled page range(s) arguments
+        @rtype list of str
+        """
+        if pageSelectPolicy == FilePrinter.SystemSelectsPages:
+            if printer.printRange() == QPrinter.Selection and bool(pageRange):
+                if variant == "lp":
+                    return ["-P", pageRange]
+                elif variant == "lpr":
+                    return ["-o", "page-ranges={0}".format(pageRange)]
+            
+            if printer.printRange() == QPrinter.PageRange:
+                if variant == "lp":
+                    return ["-P", "{0}-{1}".format(
+                        printer.fromPage(), printer.toPage())]
+                elif variant == "lpr":
+                    return ["-o", "page-ranges={0}-{1}".format(
+                        printer.fromPage(), printer.toPage())]
+        
+        return []       # all pages
+    
+    def _cupsOptions(self, printer):
+        """
+        Protected method to assemble the CUPS specific arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled CUPS arguments
+        @rtype list of str
+        """
+        options = []
+        options.extend(self._optionMedia(printer))
+        options.extend(self._optionDoubleSidedPrinting(printer))
+        options.extend(self._optionPageOrder(printer))
+        options.extend(self._optionCollateCopies(printer))
+        options.extend(self._optionCupsProperties(printer))
+        
+        return options
+    
+    def _optionMedia(self, printer):
+        """
+        Protected method to assemble the print media arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled print media arguments
+        @rtype list of str
+        """
+        pageSize = self._mediaPageSize(printer)
+        paperSource = self._mediaPaperSource(printer)
+        
+        if pageSize and paperSource:
+            return ["-o", "media={0},{1}".format(pageSize, paperSource)]
+        
+        elif pageSize:
+            return ["-o", "media={0}".format(pageSize)]
+        
+        elif paperSource:
+            return ["-o", "media={0}".format(paperSource)]
+        
+        return []
+    
+    def _mediaPageSize(self, printer):
+        """
+        Protected method to get the page size argument.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return page size argument
+        @rtype str
+        """
+        pageSize = printer.pageSize()
+        if pageSize in self.__paperSizesMap:
+            return self.__paperSizesMap[pageSize]
+        else:
+            return ""
+    
+    def _mediaPaperSource(self, printer):
+        """
+        Protected method to get the paper source argument.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return paper source argument
+        @rtype str
+        """
+        paperSource = printer.paperSource()
+        if paperSource in self.__paperSourcesMap:
+            return self.__paperSourcesMap[paperSource]
+        else:
+            return ""
+    
+    def _optionDoubleSidedPrinting(self, printer):
+        """
+        Protected method to assemble the double sided printing arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled double sided printing arguments
+        @rtype list of str
+        """
+        duplex = printer.duplex()
+        
+        if duplex == QPrinter.DuplexNone:
+            return ["-o", "sides=one-sided"]
+        elif duplex == QPrinter.DuplexAuto:
+            if printer.orientation() == QPrinter.Landscape:
+                return ["-o", "sides=two-sided-short-edge"]
+            else:
+                return ["-o", "sides=two-sided-long-edge"]
+        elif duplex == QPrinter.DuplexLongSide:
+            return ["-o", "sides=two-sided-long-edge"]
+        elif duplex == QPrinter.DuplexShortSide:
+            return ["-o", "sides=two-sided-short-edge"]
+        else:
+            return []       # use printer default
+    
+    def _optionPageOrder(self, printer):
+        """
+        Protected method to assemble the page order arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled page order arguments
+        @rtype list of str
+        """
+        if printer.pageOrder() == QPrinter.LastPageFirst:
+            return ["-o", "outputorder=reverse"]
+        else:
+            return ["-o", "outputorder=normal"]
+    
+    def _optionCollateCopies(self, printer):
+        """
+        Protected method to assemble the collate copies arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled collate copies arguments
+        @rtype list of str
+        """
+        if printer.collateCopies():
+            return ["-o", "Collate=True"]
+        else:
+            return ["-o", "Collate=False"]
+    
+    def _optionCupsProperties(self, printer):
+        """
+        Protected method to assemble the CUPS properties arguments.
+        
+        @param printer reference to the printer to print to
+        @type QPrinter
+        @return assembled CUPS properties arguments
+        @rtype list of str
+        """
+        options = Globals.toList(printer.printEngine().property(
+            QPrintEngine.PrintEnginePropertyKey(0xfe00)))
+        
+        cupsOptions = []
+        index = 0
+        while index < len(options):
+            if options[index + 1]:
+                cupsOptions.extend(["-o", "{0}={1}".format(
+                    options[index], options[index + 1])])
+            else:
+                cupsOptions.extend(["-o", options[index]])
+            index += 2
+        
+        return cupsOptions
+
+
+def isCupsAvailable():
+    """
+    Static method to test the availability of CUPS.
+    
+    @return flag indicating the availability of CUPS
+    @rtype bool
+    """
+    if Globals.isMacPlatform():
+        # OS X/MacOS always have CUPS
+        return True
+    elif Globals.isLinuxPlatform():
+        testPrinter = QPrinter()
+        return testPrinter.supportsMultipleCopies()
+    else:
+        return False
+
+
+def printFile(printer, fileName,
+              fileDeletePolicy=FilePrinter.ApplicationDeletesFiles,
+              pageSelectPolicy=FilePrinter.ApplicationSelectsPages,
+              pageRange=""):
+    """
+    Static method to print a file.
+    
+    Note: Only CUPS and LPR on *nix systems is supported.
+    
+    @param printer reference to the printer to print to
+    @type QPrinter
+    @param fileName name (path) of the file to be printed
+    @type str
+    @param fileDeletePolicy policy determining who deletes the file to be
+        printed (application or system)
+    @type int (0 or 1)
+    @param pageSelectPolicy policy determining who selects the pages to be
+        printed (application or system)
+    @type int (0 or 1)
+    @param pageRange string determining the page range(s) to be printed, if
+        SystemSelectsPages was given for pageSelectPolicy and user chose
+        Selection in print dialog
+    @type str
+    """
+    fp = FilePrinter()
+    if fp._doPrintFile(printer, fileName, fileDeletePolicy, pageSelectPolicy,
+                       pageRange):
+        _FilePrintJobs.append(fp)
+
--- a/WebBrowser/WebBrowserTabWidget.py	Tue Sep 27 19:41:11 2016 +0200
+++ b/WebBrowser/WebBrowserTabWidget.py	Wed Sep 28 20:04:44 2016 +0200
@@ -11,10 +11,11 @@
 
 import os
 
-from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl, QFile, qVersion
+from PyQt5.QtCore import pyqtSignal, pyqtSlot, Qt, QUrl, QDir, QFile, \
+    QFileDevice, QTemporaryFile, qVersion
 from PyQt5.QtGui import QIcon, QPixmap, QPainter
 from PyQt5.QtWidgets import QWidget, QHBoxLayout, QMenu, QToolButton, QDialog
-from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
+from PyQt5.QtPrintSupport import QPrinter, QPrintDialog, QAbstractPrintDialog
 
 from E5Gui.E5TabWidget import E5TabWidget
 from E5Gui import E5MessageBox
@@ -23,6 +24,7 @@
 from .WebBrowserView import WebBrowserView
 from .WebBrowserPage import WebBrowserPage
 from .Tools import WebBrowserTools
+from .Tools import FilePrinter
 from . import WebInspector
 
 import UI.PixmapCache
@@ -150,6 +152,8 @@
         self.__initTabContextMenu()
         
         self.__historyCompleter = None
+        
+        self.__pdfPrinter = None
     
     def __initTabContextMenu(self):
         """
@@ -179,11 +183,11 @@
         self.__tabContextMenu.addAction(
             self.tr('Close All'), self.closeAllBrowsers)
         self.__tabContextMenu.addSeparator()
-        if not Globals.isWindowsPlatform():
-            # TODO: implement printing based on printToPdf()
+        if not Globals.isWindowsPlatform() and qVersion() < "5.7.0":
             self.__tabContextMenu.addAction(
                 UI.PixmapCache.getIcon("printPreview.png"),
                 self.tr('Print Preview'), self.__tabContextMenuPrintPreview)
+        if not Globals.isWindowsPlatform() or qVersion() >= "5.7.0":
             self.__tabContextMenu.addAction(
                 UI.PixmapCache.getIcon("print.png"),
                 self.tr('Print'), self.__tabContextMenuPrint)
@@ -624,10 +628,32 @@
         if printerName:
             printer.setPrinterName(printerName)
         printer.setResolution(Preferences.getPrinter("Resolution"))
+        documentName = WebBrowserTools.getFileNameFromUrl(browser.url())
+        printer.setDocName(documentName)
         
         printDialog = QPrintDialog(printer, self)
+        printDialog.setOptions(QAbstractPrintDialog.PrintToFile |
+                               QAbstractPrintDialog.PrintShowPageSize)
+        if not Globals.isWindowsPlatform():
+            if FilePrinter.isCupsAvailable():
+                printDialog.setOption(QAbstractPrintDialog.PrintCollateCopies)
+            printDialog.setOption(QAbstractPrintDialog.PrintPageRange)
         if printDialog.exec_() == QDialog.Accepted:
-            browser.render(printer)
+            if not hasattr(browser.page(), "printToPdf"):
+                browser.render(printer)
+            else:
+                if printer.outputFormat() == QPrinter.PdfFormat:
+                    # print to PDF file selected
+                    browser.page().printToPdf(
+                        lambda pdf: self.__pdfGeneratedForSave(
+                            printer.outputFileName(), pdf),
+                        printer.pageLayout())
+                else:
+                    # print to printer
+                    self.__pdfPrinter = printer
+                    browser.page().printToPdf(
+                        self.__pdfGeneratedForPrinting,
+                        printer.pageLayout())
     
     @pyqtSlot()
     def printBrowserPdf(self, browser=None):
@@ -652,20 +678,20 @@
                 filePath, pageLayout = dlg.getData()
                 if filePath:
                     if os.path.exists(filePath):
-                        res = E5MessageBox.warning(
-                            self,
-                            self.tr("Print to PDF"),
+                        res = E5MessageBox.warning(
+                            self,
+                            self.tr("Print to PDF"),
                             self.tr("""<p>The file <b>{0}</b> exists"""
                                     """ already. Shall it be"""
-                                    """ overwritten?</p>""").format(filePath),
-                            E5MessageBox.StandardButtons(
-                                E5MessageBox.No |
-                                E5MessageBox.Yes),
-                            E5MessageBox.No)
+                                    """ overwritten?</p>""").format(filePath),
+                            E5MessageBox.StandardButtons(
+                                E5MessageBox.No |
+                                E5MessageBox.Yes),
+                            E5MessageBox.No)
                         if res == E5MessageBox.No:
                             return
                     browser.page().printToPdf(
-                        lambda p: self.__pdfGenerated(filePath, p),
+                        lambda pdf: self.__pdfGeneratedForSave(filePath, pdf),
                         pageLayout)
         elif Globals.isLinuxPlatform():
             printer = QPrinter(mode=QPrinter.HighResolution)
@@ -685,9 +711,9 @@
             if printDialog.exec_() == QDialog.Accepted:
                 browser.render(printer)
     
-    def __pdfGenerated(self, filePath, pdfData):
+    def __pdfGeneratedForSave(self, filePath, pdfData):
         """
-        Private slot handling the generated PDF data.
+        Private slot to save the generated PDF data to a file.
         
         @param filePath path to save the PDF to
         @type str
@@ -698,11 +724,50 @@
             return
         
         pdfFile = QFile(filePath)
-        if not pdfFile.open(QFile.WriteOnly):
+        if pdfFile.open(QFile.WriteOnly):
+            pdfFile.write(pdfData)
+            pdfFile.close()
+        if pdfFile.error() != QFileDevice.NoError:
+            E5MessageBox.critical(
+                self,
+                self.tr("Print to PDF"),
+                self.tr("""<p>The PDF could not be written to file <b>{0}"""
+                        """</b>.</p><p><b>Error:</b> {1}</p>""").format(
+                    filePath, pdfFile.errorString()),
+                E5MessageBox.StandardButtons(
+                    E5MessageBox.Ok))
+    
+    def __pdfGeneratedForPrinting(self, pdfData):
+        """
+        Private slot to print the generated PDF data.
+        
+        @param pdfData generated PDF document
+        @type QByteArray
+        """
+        if self.__pdfPrinter is None or pdfData.isEmpty():
             return
         
-        pdfFile.write(pdfData)
-        pdfFile.close()
+        tempFile = QTemporaryFile(QDir.tempPath() + "/ericBrowserXXXXXX.pdf")
+        tempFile.setAutoRemove(False)
+        if tempFile.open():
+            bytesWritten = tempFile.write(pdfData)
+            tempFile.close()
+            if bytesWritten == pdfData.size():
+                if Globals.isWindowsPlatform():
+                    printerName = self.__pdfPrinter.printerName()
+                    import ctypes
+                    ctypes.windll.shell32.ShellExecuteW(
+                        self.winId(), "printto", tempFile.fileName(),
+                        '"{0}"'.format(printerName), None, 0)
+                else:
+                    FilePrinter.printFile(
+                        self.__pdfPrinter, tempFile.fileName(),
+                        FilePrinter.FilePrinter.SystemDeletesFiles,
+                        FilePrinter.FilePrinter.SystemSelectsPages)
+            else:
+                tempFile.remove()
+        
+        self.__pdfPrinter = None
     
     @pyqtSlot()
     def printPreviewBrowser(self, browser=None):
--- a/WebBrowser/WebBrowserWindow.py	Tue Sep 27 19:41:11 2016 +0200
+++ b/WebBrowser/WebBrowserWindow.py	Wed Sep 28 20:04:44 2016 +0200
@@ -701,8 +701,8 @@
                 bookmarksManager.exportBookmarks)
         self.__actions.append(self.exportBookmarksAct)
         
-        if not Globals.isWindowsPlatform():
-            # TODO: implement printing based on printToPdf()
+        if not Globals.isWindowsPlatform() or \
+                qVersion() >= "5.7.0":
             self.printAct = E5Action(
                 self.tr('Print'),
                 UI.PixmapCache.getIcon("print.png"),
@@ -739,7 +739,7 @@
         else:
             self.printPdfAct = None
         
-        if not Globals.isWindowsPlatform():
+        if not Globals.isWindowsPlatform() and qVersion() < "5.7.0":
             self.printPreviewAct = E5Action(
                 self.tr('Print Preview'),
                 UI.PixmapCache.getIcon("printPreview.png"),
@@ -1956,7 +1956,8 @@
             filetb.addAction(self.printAct)
         if self.printPdfAct:
             filetb.addAction(self.printPdfAct)
-        filetb.addSeparator()
+        if self.printPreviewAct or self.printAct or self.printPdfAct:
+            filetb.addSeparator()
         filetb.addAction(self.closeAct)
         filetb.addAction(self.exitAct)
         
--- a/eric6.e4p	Tue Sep 27 19:41:11 2016 +0200
+++ b/eric6.e4p	Wed Sep 28 20:04:44 2016 +0200
@@ -1424,6 +1424,7 @@
     <Source>WebBrowser/TabManager/TabManagerWidget.py</Source>
     <Source>WebBrowser/TabManager/__init__.py</Source>
     <Source>WebBrowser/Tools/DelayedFileWatcher.py</Source>
+    <Source>WebBrowser/Tools/FilePrinter.py</Source>
     <Source>WebBrowser/Tools/PrintToPdfDialog.py</Source>
     <Source>WebBrowser/Tools/Scripts.py</Source>
     <Source>WebBrowser/Tools/WebBrowserTools.py</Source>

eric ide

mercurial