From d13195584e3ec4b3c30b626c360e81e437757427 Mon Sep 17 00:00:00 2001 From: John Layt Date: Wed, 11 Dec 2013 16:37:03 +0100 Subject: QPrintEngine - Switch Cups to QPlaformPrintDevice Use QPlatformPrintDevice in the Cups print engine for all device specific code. Change-Id: Ic1f5f8b4010a9958c320f3c0c727cf1bd1a70c65 Reviewed-by: Lars Knoll --- src/plugins/printsupport/cups/qcupsprintengine.cpp | 272 ++++++++------------- 1 file changed, 98 insertions(+), 174 deletions(-) (limited to 'src/plugins/printsupport/cups/qcupsprintengine.cpp') diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index c41ee4373c..2c05a76084 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -43,13 +43,17 @@ #ifndef QT_NO_PRINTER +#include +#include + #include #include #include #include -#include "private/qcups_p.h" -#include "qprinterinfo.h" +#include "private/qcups_p.h" // Only needed for PPK_CupsOptions +#include +#include #include #include @@ -63,22 +67,7 @@ QCupsPrintEngine::QCupsPrintEngine(QPrinter::PrinterMode m) : QPdfPrintEngine(*new QCupsPrintEnginePrivate(m)) { Q_D(QCupsPrintEngine); - - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - const cups_dest_t* printers = cups.availablePrinters(); - int prnCount = cups.availablePrintersCount(); - - for (int i = 0; i < prnCount; ++i) { - if (printers[i].is_default) { - d->printerName = QString::fromLocal8Bit(printers[i].name); - d->setCupsDefaults(); - break; - } - } - - } - + d->setupDefaultPrinter(); state = QPrinter::Idle; } @@ -92,27 +81,20 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v switch (int(key)) { case PPK_PageSize: - d->setPageSize(QPageSize::PageSizeId(value.toInt())); - break; - case PPK_CupsPageRect: - d->cupsPageRect = value.toRect(); - break; - case PPK_CupsPaperRect: - d->cupsPaperRect = value.toRect(); + d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); break; - case PPK_CupsOptions: - d->cupsOptions = value.toStringList(); + case PPK_CustomPaperSize: + d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); break; - case PPK_CupsStringPageSize: case PPK_PaperName: - d->setPaperName(value.toString()); + // Get the named page size from the printer if supported + d->setPageSize(d->m_printDevice.supportedPageSize(value.toString())); break; case PPK_PrinterName: - // prevent setting the defaults again for the same printer - if (d->printerName != value.toString()) { - d->printerName = value.toString(); - d->setCupsDefaults(); - } + d->changePrinter(value.toString()); + break; + case PPK_CupsOptions: + d->cupsOptions = value.toStringList(); break; default: QPdfPrintEngine::setProperty(key, value); @@ -127,24 +109,15 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const QVariant ret; switch (int(key)) { case PPK_SupportsMultipleCopies: + // CUPS server always supports multiple copies, even if individual m_printDevice doesn't ret = true; break; case PPK_NumberOfCopies: ret = 1; break; - case PPK_CupsPageRect: - ret = d->cupsPageRect; - break; - case PPK_CupsPaperRect: - ret = d->cupsPaperRect; - break; case PPK_CupsOptions: ret = d->cupsOptions; break; - case PPK_CupsStringPageSize: - case PPK_PaperName: - ret = d->m_pageLayout.pageSize().name(); - break; default: ret = QPdfPrintEngine::property(key); break; @@ -173,17 +146,16 @@ bool QCupsPrintEnginePrivate::openPrintDevice() return false; } outDevice = file; - } else if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QPair ret = cups.tempFd(); - if (ret.first < 0) { + } else { + char filename[512]; + fd = cupsTempFd(filename, 512); + if (fd < 0) { qWarning("QPdfPrinter: Could not open temporary file to print"); return false; } - cupsTempFile = ret.second; + cupsTempFile = QString::fromLocal8Bit(filename); outDevice = new QFile(); - static_cast(outDevice)->open(ret.first, QIODevice::WriteOnly); - fd = ret.first; + static_cast(outDevice)->open(fd, QIODevice::WriteOnly); } return true; @@ -196,25 +168,18 @@ void QCupsPrintEnginePrivate::closePrintDevice() if (!cupsTempFile.isEmpty()) { QString tempFile = cupsTempFile; cupsTempFile.clear(); - QCUPSSupport cups; + + // Should never have got here without a printer, but check anyway + if (printerName.isEmpty()) { + qWarning("Could not determine printer to print to"); + QFile::remove(tempFile); + return; + } // Set up print options. - QByteArray prnName; QList > options; QVector cupsOptStruct; - if (!printerName.isEmpty()) { - prnName = printerName.toLocal8Bit(); - } else { - QPrinterInfo def = QPrinterInfo::defaultPrinter(); - if (def.isNull()) { - qWarning("Could not determine printer to print to"); - QFile::remove(tempFile); - return; - } - prnName = def.printerName().toLocal8Bit(); - } - options.append(QPair("media", m_pageLayout.pageSize().key().toLocal8Bit())); if (copies > 1) @@ -224,24 +189,24 @@ void QCupsPrintEnginePrivate::closePrintDevice() options.append(QPair("Collate", "True")); switch (duplex) { - case QPrinter::DuplexNone: + case QPrint::DuplexNone: options.append(QPair("sides", "one-sided")); break; - case QPrinter::DuplexAuto: + case QPrint::DuplexAuto: if (m_pageLayout.orientation() == QPageLayout::Portrait) options.append(QPair("sides", "two-sided-long-edge")); else options.append(QPair("sides", "two-sided-short-edge")); break; - case QPrinter::DuplexLongSide: + case QPrint::DuplexLongSide: options.append(QPair("sides", "two-sided-long-edge")); break; - case QPrinter::DuplexShortSide: + case QPrint::DuplexShortSide: options.append(QPair("sides", "two-sided-short-edge")); break; } - if (QCUPSSupport::cupsVersion() >= 10300 && m_pageLayout.orientation() == QPageLayout::Landscape) + if (m_pageLayout.orientation() == QPageLayout::Landscape) options.append(QPair("landscape", "")); QStringList::const_iterator it = cupsOptions.constBegin(); @@ -259,124 +224,83 @@ void QCupsPrintEnginePrivate::closePrintDevice() // Print the file. cups_option_t* optPtr = cupsOptStruct.size() ? &cupsOptStruct.first() : 0; - cups.printFile(prnName.constData(), tempFile.toLocal8Bit().constData(), - title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr); + cupsPrintFile(printerName.toLocal8Bit().constData(), tempFile.toLocal8Bit().constData(), + title.toLocal8Bit().constData(), cupsOptStruct.size(), optPtr); QFile::remove(tempFile); } } -void QCupsPrintEnginePrivate::setPageSize(QPageSize::PageSizeId pageSizeId) +void QCupsPrintEnginePrivate::setupDefaultPrinter() { - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QSize size = QPageSize(pageSizeId).sizePoints(); - - if (cups.currentPPD()) { - const ppd_option_t* pageSizes = cups.pageSizes(); - for (int i = 0; i < pageSizes->num_choices; ++i) { - QByteArray cupsPageSize = pageSizes->choices[i].choice; - QRect tmpCupsPaperRect = cups.paperRect(cupsPageSize); - QRect tmpCupsPageRect = cups.pageRect(cupsPageSize); - - if (qAbs(size.width() - tmpCupsPaperRect.width()) < 5 && qAbs(size.height() - tmpCupsPaperRect.height()) < 5) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = tmpCupsPaperRect; - cupsPageRect = tmpCupsPageRect; - setPageSize(key, name); - break; - } - } - } + // Should never have reached here if no plugin available, but check just in case + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return; + + // Get default printer id, if no default then use the first available + // TODO Find way to remove printerName from base class? + printerName = ps->defaultPrintDeviceId(); + if (printerName.isEmpty()) { + QStringList list = ps->availablePrintDeviceIds(); + if (list.size() > 0) + printerName = list.at(0); } -} -void QCupsPrintEnginePrivate::setPaperName(const QString &paperName) -{ - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - if (cups.currentPPD()) { - const ppd_option_t* pageSizes = cups.pageSizes(); - for (int i = 0; i < pageSizes->num_choices; ++i) { - if (pageSizes->choices[i].text == paperName) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); - cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); - setPageSize(key, name); - break; - } - } - } - } -} + // Should never have reached here if no printers available, but check just in case + if (printerName.isEmpty()) + return; -void QCupsPrintEnginePrivate::setCupsDefaults() -{ - if (QCUPSSupport::isAvailable()) { - int cupsPrinterIndex = -1; - QCUPSSupport cups; - - const cups_dest_t* printers = cups.availablePrinters(); - int prnCount = cups.availablePrintersCount(); - for (int i = 0; i < prnCount; ++i) { - QString name = QString::fromLocal8Bit(printers[i].name); - if (name == printerName) { - cupsPrinterIndex = i; - break; - } - } + m_printDevice = ps->createPrintDevice(printerName); + if (!m_printDevice.isValid()) + return; - if (cupsPrinterIndex < 0) - return; + // Setup the printer defaults + duplex = m_printDevice.defaultDuplexMode(); + grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; + // CUPS server always supports collation, even if individual m_printDevice doesn't + collate = true; + setPageSize(m_printDevice.defaultPageSize()); +} - cups.setCurrentPrinter(cupsPrinterIndex); - - if (cups.currentPPD()) { - const ppd_option_t *ppdDuplex = cups.ppdOption("Duplex"); - if (ppdDuplex) { - if (qstrcmp(ppdDuplex->defchoice, "DuplexTumble") == 0) - duplex = QPrinter::DuplexShortSide; - else if (qstrcmp(ppdDuplex->defchoice, "DuplexNoTumble") == 0) - duplex = QPrinter::DuplexLongSide; - else - duplex = QPrinter::DuplexNone; - } - - grayscale = !cups.currentPPD()->color_device; - - const ppd_option_t *ppdCollate = cups.ppdOption("Collate"); - if (ppdCollate) - collate = qstrcmp(ppdCollate->defchoice, "True") == 0; - - const ppd_option_t* pageSizes = cups.pageSizes(); - QByteArray cupsPageSize; - for (int i = 0; i < pageSizes->num_choices; ++i) { - if (static_cast(pageSizes->choices[i].marked) == 1) { - QString key = QString::fromLocal8Bit(pageSizes->choices[i].choice); - QString name = QString::fromLocal8Bit(pageSizes->choices[i].text); - cupsPaperRect = cups.paperRect(pageSizes->choices[i].choice); - cupsPageRect = cups.pageRect(pageSizes->choices[i].choice); - setPageSize(key, name); - } - } - - cupsOptions = cups.options(); - } - } +void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter) +{ + // Don't waste time if same printer name + if (newPrinter == printerName) + return; + + // Should never have reached here if no plugin available, but check just in case + QPlatformPrinterSupport *ps = QPlatformPrinterSupportPlugin::get(); + if (!ps) + return; + + // Try create the printer, only use it if it returns valid + QPrintDevice printDevice = ps->createPrintDevice(newPrinter); + if (!m_printDevice.isValid()) + return; + m_printDevice.swap(printDevice); + printerName = m_printDevice.id(); + + // Check if new printer supports current settings, otherwise us defaults + if (duplex != QPrint::DuplexAuto && !m_printDevice.supportedDuplexModes().contains(duplex)) + duplex = m_printDevice.defaultDuplexMode(); + QPrint::ColorMode colorMode = grayscale ? QPrint::GrayScale : QPrint::Color; + if (!m_printDevice.supportedColorModes().contains(colorMode)) + grayscale = m_printDevice.defaultColorMode() == QPrint::GrayScale; + + // Get the equivalent page size for this printer as supported names may be different + setPageSize(m_pageLayout.pageSize()); } -void QCupsPrintEnginePrivate::setPageSize(const QString &key, const QString &name) +void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize) { - QSize size = QSize(cupsPaperRect.width(), cupsPaperRect.height()); - const qreal left = cupsPageRect.x() - cupsPaperRect.x(); - const qreal top = cupsPageRect.y() - cupsPaperRect.y(); - const qreal right = cupsPaperRect.right() - cupsPageRect.right(); - const qreal bottom = cupsPaperRect.bottom() - cupsPageRect.bottom(); - QMarginsF printable = qt_convertMargins(QMarginsF(left, top, right, bottom), - QPageLayout::Point, m_pageLayout.units()); - m_pageLayout.setPageSize(QPageSize(key, size, name), printable); + if (pageSize.isValid()) { + // Find if the requested page size has a matching printer page size, if so use its defined name instead + QPageSize printerPageSize = m_printDevice.supportedPageSize(pageSize); + QPageSize usePageSize = printerPageSize.isValid() ? printerPageSize : pageSize; + QMarginsF printable = m_printDevice.printableMargins(usePageSize, m_pageLayout.orientation(), resolution); + m_pageLayout.setPageSize(usePageSize, qt_convertMargins(printable, QPageLayout::Point, m_pageLayout.units())); + } } QT_END_NAMESPACE -- cgit v1.2.3