From 74a51d590f4acd189f8d0594a5a706cbf97c805b Mon Sep 17 00:00:00 2001 From: John Layt Date: Mon, 17 Mar 2014 17:59:55 +0100 Subject: QPrinter - Fix DuplexMode on all platforms Add support to get/set the DuplexMode on Windows and Mac, improve the CUPS duplex handling, ensure support is the same on all platforms. [ChangeLog][QtPrintSupport][QPrinter] Added duplex support for Windows and OS X. Task-number: QTBUG-11332 Change-Id: I9d61d63233d828c3b1fd6df54072c6049f3c6298 Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/plugins/platforms/cocoa/qcocoaprintdevice.mm | 3 ++ src/plugins/platforms/cocoa/qprintengine_mac.mm | 47 ++++++++++++++++--- src/plugins/printsupport/cups/qcupsprintengine.cpp | 6 +++ src/plugins/printsupport/cups/qppdprintdevice.cpp | 3 ++ .../printsupport/windows/qwindowsprintdevice.cpp | 1 + src/printsupport/kernel/qprintengine_win.cpp | 54 +++++++++++++++++++--- src/printsupport/kernel/qprinter.cpp | 12 +++-- src/printsupport/kernel/qprinterinfo.cpp | 27 +++++++++++ src/printsupport/kernel/qprinterinfo.h | 3 ++ .../printsupport/kernel/qprinter/tst_qprinter.cpp | 46 ++++++++++-------- .../kernel/qprinterinfo/tst_qprinterinfo.cpp | 8 ++++ 11 files changed, 172 insertions(+), 38 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index 7322025df6..2101b68769 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -391,6 +391,9 @@ void QCocoaPrintDevice::loadDuplexModes() const // If still no result, or not added in PPD, then add None if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) m_duplexModes.append(QPrint::DuplexNone); + // If have both modes, then can support DuplexAuto + if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide)) + m_duplexModes.append(QPrint::DuplexAuto); m_haveDuplexModes = true; } diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index fb968f31e9..f684fef233 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -457,9 +457,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va break; case PPK_CustomBase: break; - case PPK_Duplex: - // TODO Add support using PMSetDuplex / PMGetDuplex - break; case PPK_FontEmbedding: break; case PPK_PageOrder: @@ -503,6 +500,29 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va case PPK_DocumentName: PMPrintSettingsSetJobName(d->settings(), QCFString(value.toString())); break; + case PPK_Duplex: { + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); + if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice->supportedDuplexModes().contains(mode)) + break; + switch (mode) { + case QPrinter::DuplexNone: + PMSetDuplex(d->settings(), kPMDuplexNone); + break; + case QPrinter::DuplexAuto: + PMSetDuplex(d->settings(), d->m_pageLayout.orientation() == QPageLayout::Landscape ? kPMDuplexTumble : kPMDuplexNoTumble); + break; + case QPrinter::DuplexLongSide: + PMSetDuplex(d->settings(), kPMDuplexNoTumble); + break; + case QPrinter::DuplexShortSide: + PMSetDuplex(d->settings(), kPMDuplexTumble); + break; + default: + // Don't change + break; + } + break; + } case PPK_FullPage: if (value.toBool()) d->m_pageLayout.setMode(QPageLayout::FullPageMode); @@ -602,10 +622,6 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CustomBase: // Special case, leave null break; - case PPK_Duplex: - // TODO Add support using PMSetDuplex / PMGetDuplex - ret = QPrinter::DuplexNone; - break; case PPK_FontEmbedding: ret = false; break; @@ -647,6 +663,23 @@ QVariant QMacPrintEngine::property(PrintEnginePropertyKey key) const ret = QCFString::toQString(name); break; } + case PPK_Duplex: { + PMDuplexMode mode = kPMDuplexNone; + PMGetDuplex(d->settings(), &mode); + switch (mode) { + case kPMDuplexNoTumble: + ret = QPrinter::DuplexLongSide; + break; + case kPMDuplexTumble: + ret = QPrinter::DuplexShortSide; + break; + case kPMDuplexNone: + default: + ret = QPrinter::DuplexNone; + break; + } + break; + } case PPK_FullPage: ret = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 724ff5b98b..d7cd18f1d1 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -85,6 +85,12 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v // Get the named page size from the printer if supported d->setPageSize(d->m_printDevice.supportedPageSize(value.toString())); break; + case PPK_Duplex: { + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); + if (mode != d->duplex && d->m_printDevice.supportedDuplexModes().contains(mode)) + d->duplex = mode; + break; + } case PPK_PrinterName: d->changePrinter(value.toString()); break; diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index 75e8a8bf26..7a6acf8b78 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -387,6 +387,9 @@ void QPpdPrintDevice::loadDuplexModes() const // If still no result, or not added in PPD, then add None if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone)) m_duplexModes.append(QPrint::DuplexNone); + // If have both modes, then can support DuplexAuto + if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide)) + m_duplexModes.append(QPrint::DuplexAuto); m_haveDuplexModes = true; } diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index 0feea5ea74..a0a549da6f 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -378,6 +378,7 @@ void QWindowsPrintDevice::loadDuplexModes() const DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL); if (int(duplex) == 1) { // TODO Assume if duplex flag supports both modes + m_duplexModes.append(QPrint::DuplexAuto); m_duplexModes.append(QPrint::DuplexLongSide); m_duplexModes.append(QPrint::DuplexShortSide); } diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index a1a2f97abe..90b204eb0c 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -1003,9 +1003,6 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & // The following keys are settings that are unsupported by the Windows PrintEngine case PPK_CustomBase: break; - case PPK_Duplex: - // TODO Add support using DEVMODE.dmDuplex - break; case PPK_FontEmbedding: break; case PPK_PageOrder: @@ -1046,6 +1043,33 @@ void QWin32PrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant & d->docName = value.toString(); break; + case PPK_Duplex: { + if (!d->devMode) + break; + QPrint::DuplexMode mode = QPrint::DuplexMode(value.toInt()); + if (mode == property(PPK_Duplex).toInt() || !d->m_printDevice.supportedDuplexModes().contains(mode)) + break; + switch (mode) { + case QPrinter::DuplexNone: + d->devMode->dmDuplex = DMDUP_SIMPLEX; + break; + case QPrinter::DuplexAuto: + d->devMode->dmDuplex = d->m_pageLayout.orientation() == QPageLayout::Landscape ? DMDUP_HORIZONTAL : DMDUP_VERTICAL; + break; + case QPrinter::DuplexLongSide: + d->devMode->dmDuplex = DMDUP_VERTICAL; + break; + case QPrinter::DuplexShortSide: + d->devMode->dmDuplex = DMDUP_HORIZONTAL; + break; + default: + // Don't change + break; + } + d->doReinit(); + break; + } + case PPK_FullPage: if (value.toBool()) d->m_pageLayout.setMode(QPageLayout::FullPageMode); @@ -1260,10 +1284,6 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const // The following keys are settings that are unsupported by the Windows PrintEngine // Return sensible default values to ensure consistent behavior across platforms - case PPK_Duplex: - // TODO Add support using DEVMODE.dmDuplex - value = QPrinter::DuplexNone; - break; case PPK_FontEmbedding: value = false; break; @@ -1300,6 +1320,26 @@ QVariant QWin32PrintEngine::property(PrintEnginePropertyKey key) const value = d->docName; break; + case PPK_Duplex: { + if (!d->devMode) { + value = QPrinter::DuplexNone; + } else { + switch (d->devMode->dmDuplex) { + case DMDUP_VERTICAL: + value = QPrinter::DuplexLongSide; + break; + case DMDUP_HORIZONTAL: + value = QPrinter::DuplexShortSide; + break; + case DMDUP_SIMPLEX: + default: + value = QPrinter::DuplexNone; + break; + } + } + break; + } + case PPK_FullPage: value = d->m_pageLayout.mode() == QPageLayout::FullPageMode; break; diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp index 8d62580d67..c13b1574d0 100644 --- a/src/printsupport/kernel/qprinter.cpp +++ b/src/printsupport/kernel/qprinter.cpp @@ -1678,9 +1678,11 @@ bool QPrinter::fontEmbeddingEnabled() const /*! \since 4.2 + \obsolete Use setDuplex() instead. + Enables double sided printing if \a doubleSided is true; otherwise disables it. - Currently this option is only supported on X11. + \sa setDuplex() */ void QPrinter::setDoubleSidedPrinting(bool doubleSided) { @@ -1691,9 +1693,11 @@ void QPrinter::setDoubleSidedPrinting(bool doubleSided) /*! \since 4.2 + \obsolete Use duplex() instead. + Returns \c true if double side printing is enabled. - Currently this option is only supported on X11. + \sa duplex() */ bool QPrinter::doubleSidedPrinting() const { @@ -1705,7 +1709,7 @@ bool QPrinter::doubleSidedPrinting() const Enables double sided printing based on the \a duplex mode. - Currently this option is only supported on X11. + \sa duplex() */ void QPrinter::setDuplex(DuplexMode duplex) { @@ -1718,7 +1722,7 @@ void QPrinter::setDuplex(DuplexMode duplex) Returns the current duplex mode. - Currently this option is only supported on X11. + \sa setDuplex() */ QPrinter::DuplexMode QPrinter::duplex() const { diff --git a/src/printsupport/kernel/qprinterinfo.cpp b/src/printsupport/kernel/qprinterinfo.cpp index b1321bf57a..a17da3fdaa 100644 --- a/src/printsupport/kernel/qprinterinfo.cpp +++ b/src/printsupport/kernel/qprinterinfo.cpp @@ -352,6 +352,33 @@ QList QPrinterInfo::supportedResolutions() const return d->m_printDevice.supportedResolutions(); } +/*! + Returns the default duplex mode of this printer. + + \since 5.4 +*/ + +QPrinter::DuplexMode QPrinterInfo::defaultDuplexMode() const +{ + Q_D(const QPrinterInfo); + return QPrinter::DuplexMode(d->m_printDevice.defaultDuplexMode()); +} + +/*! + Returns a list of duplex modes supported by this printer. + + \since 5.4 +*/ + +QList QPrinterInfo::supportedDuplexModes() const +{ + Q_D(const QPrinterInfo); + QList list; + foreach (QPrint::DuplexMode mode, d->m_printDevice.supportedDuplexModes()) + list << QPrinter::DuplexMode(mode); + return list; +} + /*! Returns a list of all the available Printer Names on this system. diff --git a/src/printsupport/kernel/qprinterinfo.h b/src/printsupport/kernel/qprinterinfo.h index a4754c48dc..58d3873492 100644 --- a/src/printsupport/kernel/qprinterinfo.h +++ b/src/printsupport/kernel/qprinterinfo.h @@ -82,6 +82,9 @@ public: QList supportedResolutions() const; + QPrinter::DuplexMode defaultDuplexMode() const; + QList supportedDuplexModes() const; + static QStringList availablePrinterNames(); static QList availablePrinters(); diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index c42450607d..1be570e4b8 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -1022,9 +1022,9 @@ void tst_QPrinter::duplex() { // duplex()) / setDuplex() / PPK_Duplex // PdfFormat: Supported, default QPrinter::DuplexNone - // NativeFormat, Cups: Supported, default QPrinter::DuplexNone - // NativeFormat, Win: Unsupported, always QPrinter::DuplexNone - // NativeFormat, Mac: Unsupported, always QPrinter::DuplexNone + // NativeFormat, Cups: Supported, default to printer default + // NativeFormat, Win: Supported, default to printer default + // NativeFormat, Mac: Supported, default to printer default QPrinter pdf; pdf.setOutputFormat(QPrinter::PdfFormat); @@ -1035,15 +1035,17 @@ void tst_QPrinter::duplex() QPrinter native; if (native.outputFormat() == QPrinter::NativeFormat) { // Test default - // TODO Printer specific, need QPrinterInfo::duplex() - //QCOMPARE(native.duplex(), QPrinter::DuplexNone); - - // Test set/get - QPrinter::DuplexMode expected = QPrinter::DuplexAuto; + QPrinterInfo printerInfo = QPrinterInfo::defaultPrinter(); + QPrinter::DuplexMode expected = printerInfo.defaultDuplexMode(); + QCOMPARE(native.duplex(), expected); + // Test set/get (skipping Auto as that will return something different) + foreach (QPrinter::DuplexMode mode, printerInfo.supportedDuplexModes()) { + if (mode != expected && mode != QPrinter::DuplexAuto) { + expected = mode; + break; + } + } native.setDuplex(expected); -#if defined Q_OS_MAC || defined Q_OS_WIN - expected = QPrinter::DuplexNone; -#endif // Q_OS_MAC || Q_OS_WIN QCOMPARE(native.duplex(), expected); // Test value preservation @@ -1051,6 +1053,12 @@ void tst_QPrinter::duplex() QCOMPARE(native.duplex(), expected); native.setOutputFormat(QPrinter::NativeFormat); QCOMPARE(native.duplex(), expected); + + // Test setting invalid option + if (!printerInfo.supportedDuplexModes().contains(QPrinter::DuplexLongSide)) { + native.setDuplex(QPrinter::DuplexLongSide); + QCOMPARE(native.duplex(), expected); + } } else { QSKIP("No printers installed, cannot test NativeFormat, please install printers to test"); } @@ -1059,9 +1067,9 @@ void tst_QPrinter::duplex() void tst_QPrinter::doubleSidedPrinting() { // PdfFormat: Supported, default false - // NativeFormat, Cups: Supported, default false - // NativeFormat, Win: Unsupported, always false - // NativeFormat, Mac: Unsupported, always false + // NativeFormat, Cups: Supported, default to printer default + // NativeFormat, Win: Supported, default to printer default + // NativeFormat, Mac: Supported, default to printer default QPrinter pdf; pdf.setOutputFormat(QPrinter::PdfFormat); @@ -1072,15 +1080,13 @@ void tst_QPrinter::doubleSidedPrinting() QPrinter native; if (native.outputFormat() == QPrinter::NativeFormat) { // Test default - // TODO Printer specific, need QPrinterInfo::duplex() - //QCOMPARE(native.doubleSidedPrinting(), false); + QPrinterInfo printerInfo; + bool expected = (printerInfo.defaultDuplexMode() != QPrinter::DuplexNone); + QCOMPARE(native.doubleSidedPrinting(), false); // Test set/get - bool expected = true; + expected = (printerInfo.supportedDuplexModes().count() > 1); native.setDoubleSidedPrinting(expected); -#if defined Q_OS_MAC || defined Q_OS_WIN - expected = false; -#endif // Q_OS_MAC || Q_OS_WIN QCOMPARE(native.doubleSidedPrinting(), expected); // Test value preservation diff --git a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp index 88a526ba17..f3e8b9209d 100644 --- a/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp +++ b/tests/auto/printsupport/kernel/qprinterinfo/tst_qprinterinfo.cpp @@ -298,6 +298,8 @@ void tst_QPrinterInfo::testConstructors() QCOMPARE(copy1.supportedPaperSizes(), printers.at(i).supportedPaperSizes()); QCOMPARE(copy1.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames()); QCOMPARE(copy1.supportedResolutions(), printers.at(i).supportedResolutions()); + QCOMPARE(copy1.defaultDuplexMode(), printers.at(i).defaultDuplexMode()); + QCOMPARE(copy1.supportedDuplexModes(), printers.at(i).supportedDuplexModes()); QPrinter printer(printers.at(i)); QPrinterInfo copy2(printer); @@ -317,6 +319,8 @@ void tst_QPrinterInfo::testConstructors() QCOMPARE(copy2.supportedPaperSizes(), printers.at(i).supportedPaperSizes()); QCOMPARE(copy2.supportedSizesWithNames(), printers.at(i).supportedSizesWithNames()); QCOMPARE(copy2.supportedResolutions(), printers.at(i).supportedResolutions()); + QCOMPARE(copy2.defaultDuplexMode(), printers.at(i).defaultDuplexMode()); + QCOMPARE(copy2.supportedDuplexModes(), printers.at(i).supportedDuplexModes()); } } @@ -347,6 +351,8 @@ void tst_QPrinterInfo::testAssignment() QCOMPARE(copy.minimumPhysicalPageSize(), printers.at(i).minimumPhysicalPageSize()); QCOMPARE(copy.maximumPhysicalPageSize(), printers.at(i).maximumPhysicalPageSize()); QCOMPARE(copy.supportedResolutions(), printers.at(i).supportedResolutions()); + QCOMPARE(copy.defaultDuplexMode(), printers.at(i).defaultDuplexMode()); + QCOMPARE(copy.supportedDuplexModes(), printers.at(i).supportedDuplexModes()); } } @@ -371,6 +377,8 @@ void tst_QPrinterInfo::namedPrinter() QCOMPARE(pi2.minimumPhysicalPageSize(), pi.minimumPhysicalPageSize()); QCOMPARE(pi2.maximumPhysicalPageSize(), pi.maximumPhysicalPageSize()); QCOMPARE(pi2.supportedResolutions(), pi.supportedResolutions()); + QCOMPARE(pi2.defaultDuplexMode(), pi.defaultDuplexMode()); + QCOMPARE(pi2.supportedDuplexModes(), pi.supportedDuplexModes()); } } #endif // QT_NO_PRINTER -- cgit v1.2.3