diff options
author | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-24 16:10:15 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-24 16:10:15 +0100 |
commit | 3b5c0bc0780f1749fed7c07bd8b691400a0282b7 (patch) | |
tree | 1022f5553ad5a0aca9b5f3b49ca38a01c2329d20 /src/plugins/printsupport/cups | |
parent | c79918733a194ebbe5a2fe1617c884659f3e4b9f (diff) | |
parent | 21f1738a94fc8544ece04b3b1ee03a11986fe59b (diff) |
Merge remote-tracking branch 'origin/stable' into dev
Conflicts:
src/gui/image/qjpeghandler.cpp
Change-Id: I9db3acea7d5c82f5da679c8eaeb29431136665f0
Diffstat (limited to 'src/plugins/printsupport/cups')
-rw-r--r-- | src/plugins/printsupport/cups/cups.pro | 4 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qcupsprintengine.cpp | 328 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qcupsprintengine_p.h | 16 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qcupsprintersupport.cpp | 109 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qcupsprintersupport_p.h | 37 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qppdprintdevice.cpp | 503 | ||||
-rw-r--r-- | src/plugins/printsupport/cups/qppdprintdevice.h | 124 |
7 files changed, 792 insertions, 329 deletions
diff --git a/src/plugins/printsupport/cups/cups.pro b/src/plugins/printsupport/cups/cups.pro index f617738a94..cdbb08b10a 100644 --- a/src/plugins/printsupport/cups/cups.pro +++ b/src/plugins/printsupport/cups/cups.pro @@ -6,13 +6,17 @@ load(qt_plugin) QT += core-private gui-private printsupport printsupport-private +LIBS_PRIVATE += -lcups + INCLUDEPATH += ../../../printsupport/kernel SOURCES += main.cpp \ + qppdprintdevice.cpp \ qcupsprintersupport.cpp \ qcupsprintengine.cpp HEADERS += qcupsprintersupport_p.h \ + qppdprintdevice.h \ qcupsprintengine_p.h OTHER_FILES += cups.json diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 2fecdc00e9..ec9963197c 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -43,13 +43,17 @@ #ifndef QT_NO_PRINTER +#include <qpa/qplatformprintplugin.h> +#include <qpa/qplatformprintersupport.h> + #include <qiodevice.h> #include <qfile.h> #include <qdebug.h> #include <qbuffer.h> -#include "private/qcups_p.h" -#include "qprinterinfo.h" +#include "private/qcups_p.h" // Only needed for PPK_CupsOptions +#include <QtGui/qpagelayout.h> +#include <cups/cups.h> #include <limits.h> #include <math.h> @@ -57,26 +61,13 @@ QT_BEGIN_NAMESPACE +extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit fromUnits, QPageLayout::Unit toUnits); + 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; } @@ -89,31 +80,37 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v Q_D(QCupsPrintEngine); switch (int(key)) { - case PPK_PaperSize: - d->printerPaperSize = QPrinter::PaperSize(value.toInt()); - d->setPaperSize(); + case PPK_PageSize: + d->setPageSize(QPageSize(QPageSize::PageSizeId(value.toInt()))); + break; + case PPK_WindowsPageSize: + d->setPageSize(QPageSize(QPageSize::id(value.toInt()))); break; - case PPK_CupsPageRect: - d->cupsPageRect = value.toRect(); + case PPK_CustomPaperSize: + d->setPageSize(QPageSize(value.toSizeF(), QPageSize::Point)); + break; + case PPK_PaperName: + // Get the named page size from the printer if supported + d->setPageSize(d->m_printDevice.supportedPageSize(value.toString())); break; - case PPK_CupsPaperRect: - d->cupsPaperRect = value.toRect(); + case PPK_PrinterName: + d->changePrinter(value.toString()); break; case PPK_CupsOptions: d->cupsOptions = value.toStringList(); break; - case PPK_CupsStringPageSize: - case PPK_PaperName: - d->cupsStringPageSize = value.toString(); - d->setPaperName(); + case PPK_QPageSize: + d->setPageSize(value.value<QPageSize>()); break; - case PPK_PrinterName: - // prevent setting the defaults again for the same printer - if (d->printerName != value.toString()) { - d->printerName = value.toString(); - d->setCupsDefaults(); + case PPK_QPageLayout: { + QPageLayout pageLayout = value.value<QPageLayout>(); + if (pageLayout.isValid() && d->m_printDevice.isValidPageLayout(pageLayout, d->resolution)) { + d->m_pageLayout = pageLayout; + // Replace the page size with the CUPS page size + d->setPageSize(d->m_printDevice.supportedPageSize(pageLayout.pageSize())); } break; + } default: QPdfPrintEngine::setProperty(key, value); break; @@ -127,24 +124,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->cupsStringPageSize; - break; default: ret = QPdfPrintEngine::property(key); break; @@ -173,17 +161,16 @@ bool QCupsPrintEnginePrivate::openPrintDevice() return false; } outDevice = file; - } else if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QPair<int, QString> 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<QFile *>(outDevice)->open(ret.first, QIODevice::WriteOnly); - fd = ret.first; + static_cast<QFile *>(outDevice)->open(fd, QIODevice::WriteOnly); } return true; @@ -196,27 +183,19 @@ 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<QPair<QByteArray, QByteArray> > options; QVector<cups_option_t> 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(); - } - - if (!cupsStringPageSize.isEmpty()) - options.append(QPair<QByteArray, QByteArray>("media", cupsStringPageSize.toLocal8Bit())); + options.append(QPair<QByteArray, QByteArray>("media", m_pageLayout.pageSize().key().toLocal8Bit())); if (copies > 1) options.append(QPair<QByteArray, QByteArray>("copies", QString::number(copies).toLocal8Bit())); @@ -225,24 +204,24 @@ void QCupsPrintEnginePrivate::closePrintDevice() options.append(QPair<QByteArray, QByteArray>("Collate", "True")); switch (duplex) { - case QPrinter::DuplexNone: + case QPrint::DuplexNone: options.append(QPair<QByteArray, QByteArray>("sides", "one-sided")); break; - case QPrinter::DuplexAuto: - if (!landscape) + case QPrint::DuplexAuto: + if (m_pageLayout.orientation() == QPageLayout::Portrait) options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge")); else options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge")); break; - case QPrinter::DuplexLongSide: + case QPrint::DuplexLongSide: options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-long-edge")); break; - case QPrinter::DuplexShortSide: + case QPrint::DuplexShortSide: options.append(QPair<QByteArray, QByteArray>("sides", "two-sided-short-edge")); break; } - if (QCUPSSupport::cupsVersion() >= 10300 && landscape) + if (m_pageLayout.orientation() == QPageLayout::Landscape) options.append(QPair<QByteArray, QByteArray>("landscape", "")); QStringList::const_iterator it = cupsOptions.constBegin(); @@ -260,164 +239,85 @@ 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::updatePaperSize() +void QCupsPrintEnginePrivate::setupDefaultPrinter() { - if (printerPaperSize == QPrinter::Custom) { - paperSize = customPaperSize; - } else if (!cupsPaperRect.isNull()) { - QRect r = cupsPaperRect; - paperSize = r.size(); - } else { - QPdf::PaperSize s = QPdf::paperSize(printerPaperSize); - paperSize = QSize(s.width, s.height); + // 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::setPaperSize() -{ - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(printerPaperSize)); - - if (cups.currentPPD()) { - cupsStringPageSize = QLatin1String("Custom"); - 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) { - cupsPaperRect = tmpCupsPaperRect; - cupsPageRect = tmpCupsPageRect; - cupsStringPageSize = pageSizes->choices[i].text; - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - - updatePaperSize(); - break; - } - } - } - } + // Should never have reached here if no printers available, but check just in case + if (printerName.isEmpty()) + return; + + m_printDevice = ps->createPrintDevice(printerName); + if (!m_printDevice.isValid()) + 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()); } -void QCupsPrintEnginePrivate::setPaperName() +void QCupsPrintEnginePrivate::changePrinter(const QString &newPrinter) { - if (QCUPSSupport::isAvailable()) { - QCUPSSupport cups; - if (cups.currentPPD()) { - const ppd_option_t* pageSizes = cups.pageSizes(); - bool foundPaperName = false; - for (int i = 0; i < pageSizes->num_choices; ++i) { - if (cupsStringPageSize == pageSizes->choices[i].text) { - foundPaperName = true; - QByteArray cupsPageSize = pageSizes->choices[i].choice; - cupsPaperRect = cups.paperRect(cupsPageSize); - cupsPageRect = cups.pageRect(cupsPageSize); - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - printerPaperSize = QPrinter::Custom; - customPaperSize = cupsPaperRect.size(); - for (int ps = 0; ps < QPrinter::NPageSize; ++ps) { - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps)); - if (qAbs(size.width - cupsPaperRect.width()) < 5 && qAbs(size.height - cupsPaperRect.height()) < 5) { - printerPaperSize = static_cast<QPrinter::PaperSize>(ps); - customPaperSize = QSize(); - break; - } - } - updatePaperSize(); - break; - } - } - if (!foundPaperName) - cupsStringPageSize = QString(); - } - } + // 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::setCupsDefaults() +void QCupsPrintEnginePrivate::setPageSize(const QPageSize &pageSize) { - 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; - } - } - - if (cupsPrinterIndex < 0) - return; - - 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<int>(pageSizes->choices[i].marked) == 1) { - cupsPageSize = pageSizes->choices[i].choice; - cupsStringPageSize = pageSizes->choices[i].text; - } - } - - cupsOptions = cups.options(); - cupsPaperRect = cups.paperRect(cupsPageSize); - cupsPageRect = cups.pageRect(cupsPageSize); - - for (int ps = 0; ps < QPrinter::NPageSize; ++ps) { - QPdf::PaperSize size = QPdf::paperSize(QPrinter::PaperSize(ps)); - if (qAbs(size.width - cupsPaperRect.width()) < 5 && qAbs(size.height - cupsPaperRect.height()) < 5) { - printerPaperSize = static_cast<QPrinter::PaperSize>(ps); - - leftMargin = cupsPageRect.x() - cupsPaperRect.x(); - topMargin = cupsPageRect.y() - cupsPaperRect.y(); - rightMargin = cupsPaperRect.right() - cupsPageRect.right(); - bottomMargin = cupsPaperRect.bottom() - cupsPageRect.bottom(); - - updatePaperSize(); - break; - } - } - } + 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 #endif // QT_NO_PRINTER diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h index db947a0232..393fef42a3 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine_p.h +++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h @@ -61,9 +61,8 @@ #include <QtGui/qpaintengine.h> #include <private/qpaintengine_p.h> +#include <private/qprintdevice_p.h> #include <private/qprintengine_pdf_p.h> -#include <QtPrintSupport/qprintengine.h> -#include <private/qcups_p.h> QT_BEGIN_NAMESPACE @@ -95,18 +94,15 @@ public: bool openPrintDevice(); void closePrintDevice(); - void updatePaperSize(); - void setPaperSize(); - void setPaperName(); - void setCupsDefaults(); - private: Q_DISABLE_COPY(QCupsPrintEnginePrivate) + void setupDefaultPrinter(); + void changePrinter(const QString &newPrinter); + void setPageSize(const QPageSize &pageSize); + + QPrintDevice m_printDevice; QStringList cupsOptions; - QString cupsStringPageSize; - QRect cupsPaperRect; - QRect cupsPageRect; QString cupsTempFile; }; diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp index b9f0c394f8..b2abb07fc7 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp +++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 John Layt <jlayt@kde.org> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -44,7 +45,9 @@ #ifndef QT_NO_PRINTER #include "qcupsprintengine_p.h" +#include "qppdprintdevice.h" #include <private/qprinterinfo_p.h> +#include <private/qprintdevice_p.h> #include <QtPrintSupport/QPrinterInfo> @@ -55,18 +58,13 @@ QT_BEGIN_NAMESPACE -QCupsPrinterSupport::QCupsPrinterSupport() : QPlatformPrinterSupport(), - m_cups(QLatin1String("cups"), 2), - m_cupsPrinters(0), - m_cupsPrintersCount(0) +QCupsPrinterSupport::QCupsPrinterSupport() + : QPlatformPrinterSupport() { - loadCups(); - loadCupsPrinters(); } QCupsPrinterSupport::~QCupsPrinterSupport() { - freeCupsPrinters(); } QPrintEngine *QCupsPrinterSupport::createNativePrintEngine(QPrinter::PrinterMode printerMode) @@ -80,85 +78,42 @@ QPaintEngine *QCupsPrinterSupport::createPaintEngine(QPrintEngine *engine, QPrin return static_cast<QCupsPrintEngine *>(engine); } -QList<QPrinter::PaperSize> QCupsPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const +QPrintDevice QCupsPrinterSupport::createPrintDevice(const QString &id) { - return QCUPSSupport::getCupsPrinterPaperSizes(printerIndex(printerInfo)); + return QPlatformPrinterSupport::createPrintDevice(new QPpdPrintDevice(id)); } -QList<QPair<QString, QSizeF> > QCupsPrinterSupport::supportedSizesWithNames(const QPrinterInfo &printerInfo) const +QStringList QCupsPrinterSupport::availablePrintDeviceIds() const { - return QCUPSSupport::getCupsPrinterPaperSizesWithNames(printerIndex(printerInfo)); -} - -void QCupsPrinterSupport::loadCups() -{ - cupsGetDests = (CupsGetDests) m_cups.resolve("cupsGetDests"); - cupsFreeDests = (CupsFreeDests) m_cups.resolve("cupsFreeDests"); - cupsGetOption = (CupsGetOption) m_cups.resolve("cupsGetOption"); -} - -void QCupsPrinterSupport::freeCupsPrinters() -{ - if (cupsFreeDests && m_cupsPrintersCount) { - cupsFreeDests(m_cupsPrintersCount, m_cupsPrinters); - m_cupsPrintersCount = 0; - m_cupsPrinters = 0; + QStringList list; + cups_dest_t *dests; + int count = cupsGetDests(&dests); + for (int i = 0; i < count; ++i) { + QString printerId = QString::fromLocal8Bit(dests[i].name); + if (dests[i].instance) + printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance); + list.append(printerId); } + cupsFreeDests(count, dests); + return list; } -void QCupsPrinterSupport::loadCupsPrinters() -{ - freeCupsPrinters(); - m_printers.clear(); - - if (cupsGetDests) - m_cupsPrintersCount = cupsGetDests(&m_cupsPrinters); - - for (int i = 0; i < m_cupsPrintersCount; ++i) { - QString printerName = QString::fromLocal8Bit(m_cupsPrinters[i].name); - if (m_cupsPrinters[i].instance) - printerName += QLatin1Char('/') + QString::fromLocal8Bit(m_cupsPrinters[i].instance); - QString description = cupsOption(i, "printer-info"); - QString location = cupsOption(i, "printer-location"); - QString makeAndModel = cupsOption(i, "printer-make-and-model"); - QPrinterInfo printer = createPrinterInfo(printerName, description, location, makeAndModel, - m_cupsPrinters[i].is_default, i); - m_printers.append(printer); - } -} - -QList<QPrinterInfo> QCupsPrinterSupport::availablePrinters() -{ - loadCupsPrinters(); - return QPlatformPrinterSupport::availablePrinters(); -} - -QString QCupsPrinterSupport::printerOption(const QPrinterInfo &printer, const QString &key) const -{ - return cupsOption(printerIndex(printer), key); -} - -QString QCupsPrinterSupport::cupsOption(int i, const QString &key) const -{ - QString value; - if (i > -1 && i < m_cupsPrintersCount && cupsGetOption) - value = cupsGetOption(key.toLocal8Bit(), m_cupsPrinters[i].num_options, m_cupsPrinters[i].options); - return value; -} - -PrinterOptions QCupsPrinterSupport::printerOptions(const QPrinterInfo &printer) const +QString QCupsPrinterSupport::defaultPrintDeviceId() const { - PrinterOptions options; - int p = printerIndex(printer); - if (p <= -1 || p >= m_cupsPrintersCount) - return options; - int numOptions = m_cupsPrinters[p].num_options; - for (int i = 0; i < numOptions; ++i) { - QString name = m_cupsPrinters[p].options[i].name; - QString value = m_cupsPrinters[p].options[i].value; - options.insert(name, value); + QString printerId; + cups_dest_t *dests; + int count = cupsGetDests(&dests); + for (int i = 0; i < count; ++i) { + if (dests[i].is_default) { + printerId = QString::fromLocal8Bit(dests[i].name); + if (dests[i].instance) { + printerId += QLatin1Char('/') + QString::fromLocal8Bit(dests[i].instance); + break; + } + } } - return options; + cupsFreeDests(count, dests); + return printerId; } QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintersupport_p.h b/src/plugins/printsupport/cups/qcupsprintersupport_p.h index d42c0d2630..1cba4e997b 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport_p.h +++ b/src/plugins/printsupport/cups/qcupsprintersupport_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 John Layt <jlayt@kde.org> ** Contact: http://www.qt-project.org/legal ** ** This file is part of the plugins of the Qt Toolkit. @@ -42,49 +43,29 @@ #ifndef QCUPSPRINTERSUPPORT_H #define QCUPSPRINTERSUPPORT_H -#include <QtCore/qfeatures.h> // Some feature dependencies might define QT_NO_PRINTER -#ifndef QT_NO_PRINTER - #include <qpa/qplatformprintersupport.h> -#include <QtCore/qlibrary.h> -#include <QtCore/qlist.h> +#ifndef QT_NO_PRINTER -#include <cups/cups.h> +#include <QtCore/qstringlist.h> QT_BEGIN_NAMESPACE -typedef int (*CupsGetDests)(cups_dest_t **dests); -typedef void (*CupsFreeDests)(int num_dests, cups_dest_t *dests); -typedef const char* (*CupsGetOption)(const char *name, int num_options, cups_option_t *options); - class QCupsPrinterSupport : public QPlatformPrinterSupport { public: QCupsPrinterSupport(); ~QCupsPrinterSupport(); - virtual QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode); - virtual QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode); - virtual QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const; - virtual QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const; - virtual QList<QPrinterInfo> availablePrinters(); - virtual QString printerOption(const QPrinterInfo &printer, const QString &key) const; - virtual PrinterOptions printerOptions(const QPrinterInfo &printer) const; + QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; + QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) Q_DECL_OVERRIDE; + + QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; + QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; + QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; private: - void loadCups(); - void loadCupsPrinters(); - void freeCupsPrinters(); QString cupsOption(int i, const QString &key) const; - - QLibrary m_cups; - cups_dest_t *m_cupsPrinters; - int m_cupsPrintersCount; - - CupsGetDests cupsGetDests; - CupsFreeDests cupsFreeDests; - CupsGetOption cupsGetOption; }; QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp new file mode 100644 index 0000000000..56ae5600c4 --- /dev/null +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -0,0 +1,503 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt <jlayt@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qppdprintdevice.h" + +#include <QtCore/QMimeDatabase> +#include <qdebug.h> + +#ifndef QT_LINUXBASE // LSB merges everything into cups.h +#include <cups/language.h> +#endif + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_PRINTER + +QPpdPrintDevice::QPpdPrintDevice() + : QPlatformPrintDevice(), + m_cupsDest(0), + m_ppd(0) +{ +} + +QPpdPrintDevice::QPpdPrintDevice(const QString &id) + : QPlatformPrintDevice(id), + m_cupsDest(0), + m_ppd(0) +{ + if (!id.isEmpty()) { + + // TODO For now each dest is an individual device + QStringList parts = id.split(QLatin1Char('/')); + m_cupsName = parts.at(0).toUtf8(); + if (parts.size() > 1) + m_cupsInstance = parts.at(1).toUtf8(); + loadPrinter(); + + if (m_cupsDest && m_ppd) { + m_name = printerOption("printer-info"); + m_location = printerOption("printer-location"); + m_makeAndModel = printerOption("printer-make-and-model"); + cups_ptype_e type = printerTypeFlags(); + m_isRemote = type & CUPS_PRINTER_REMOTE; + // Note this is if the hardware does multiple copies, not if Cups can + m_supportsMultipleCopies = type & CUPS_PRINTER_COPIES; + // Note this is if the hardware does collation, not if Cups can + m_supportsCollateCopies = type & CUPS_PRINTER_COLLATE; + + // Custom Page Size support + // Cups cups_ptype_e CUPS_PRINTER_VARIABLE + // Cups ppd_file_t variable_sizes custom_min custom_max + // PPD MaxMediaWidth MaxMediaHeight + m_supportsCustomPageSizes = type & CUPS_PRINTER_VARIABLE; + m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]); + m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]); + m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3], + m_ppd->custom_margins[2], m_ppd->custom_margins[1]); + } + } +} + +QPpdPrintDevice::QPpdPrintDevice(const QPpdPrintDevice &other) + : QPlatformPrintDevice(other), + m_cupsDest(0), + m_ppd(0) +{ + m_cupsName = other.m_cupsName; + m_cupsInstance = other.m_cupsInstance; + loadPrinter(); +} + +QPpdPrintDevice::~QPpdPrintDevice() +{ + if (m_ppd) + ppdClose(m_ppd); + if (m_cupsDest) + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + m_ppd = 0; +} + +QPpdPrintDevice &QPpdPrintDevice::operator=(const QPpdPrintDevice &other) +{ + m_cupsName = other.m_cupsName; + m_cupsInstance = other.m_cupsInstance; + if (other.m_cupsDest && other.m_ppd) + loadPrinter(); + return *this; +} + +bool QPpdPrintDevice::operator==(const QPpdPrintDevice &other) const +{ + return (m_id == other.m_id); +} + +bool QPpdPrintDevice::isValid() const +{ + return m_cupsDest && m_ppd; +} + +bool QPpdPrintDevice::isDefault() const +{ + return printerTypeFlags() & CUPS_PRINTER_DEFAULT; +} + +QPrint::DeviceState QPpdPrintDevice::state() const +{ + // 3 = idle, 4 = printing, 5 = stopped + // More details available from printer-state-message and printer-state-reasons + int state = printerOption(QStringLiteral("printer-state")).toInt(); + if (state == 3) + return QPrint::Idle; + else if (state == 4) + return QPrint::Active; + else + return QPrint::Error; +} + +void QPpdPrintDevice::loadPageSizes() const +{ + m_pageSizes.clear(); + m_printableMargins.clear(); + + ppd_option_t *pageSizes = ppdFindOption(m_ppd, "PageSize"); + if (pageSizes) { + for (int i = 0; i < pageSizes->num_choices; ++i) { + const ppd_size_t *ppdSize = ppdPageSize(m_ppd, pageSizes->choices[i].choice); + if (ppdSize) { + // Returned size is in points + QString key = QString::fromUtf8(ppdSize->name); + QSize size = QSize(qRound(ppdSize->width), qRound(ppdSize->length)); + QString name = QString::fromUtf8(pageSizes->choices[i].text); + if (!size.isEmpty()) { + QPageSize ps = createPageSize(key, size, name); + if (ps.isValid()) { + m_pageSizes.append(ps); + m_printableMargins.insert(key, QMarginsF(ppdSize->left, ppdSize->length - ppdSize->top, + ppdSize->width - ppdSize->right, ppdSize->bottom)); + } + } + } + } + m_havePageSizes = true; + } +} + +QPageSize QPpdPrintDevice::defaultPageSize() const +{ + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "PageSize"); + if (defaultChoice) { + ppd_size_t *ppdSize = ppdPageSize(m_ppd, defaultChoice->choice); + if (ppdSize) { + // Returned size is in points + QString key = QString::fromUtf8(ppdSize->name); + QSize size = QSize(qRound(ppdSize->width), qRound(ppdSize->length)); + QString name = QString::fromUtf8(defaultChoice->text); + return createPageSize(key, size, name); + } + } + return QPageSize(); +} + +QMarginsF QPpdPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + Q_UNUSED(orientation) + Q_UNUSED(resolution) + if (!m_havePageSizes) + loadPageSizes(); + // TODO Orientation? + if (m_printableMargins.contains(pageSize.key())) + return m_printableMargins.value(pageSize.key()); + return m_customMargins; +} + +void QPpdPrintDevice::loadResolutions() const +{ + m_resolutions.clear(); + + // Try load standard PPD options first + ppd_option_t *resolutions = ppdFindOption(m_ppd, "Resolution"); + if (resolutions) { + for (int i = 0; i < resolutions->num_choices; ++i) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[i].choice); + if (res > 0) + m_resolutions.append(res); + } + } + // If no result, try just the default + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "DefaultResolution"); + if (resolutions) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[0].choice); + if (res > 0) + m_resolutions.append(res); + } + } + // If still no result, then try HP's custom options + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "HPPrintQuality"); + if (resolutions) { + for (int i = 0; i < resolutions->num_choices; ++i) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[i].choice); + if (res > 0) + m_resolutions.append(res); + } + } + } + if (m_resolutions.size() == 0) { + resolutions = ppdFindOption(m_ppd, "DefaultHPPrintQuality"); + if (resolutions) { + int res = QPrintUtils::parsePpdResolution(resolutions->choices[0].choice); + if (res > 0) + m_resolutions.append(res); + } + } + m_haveResolutions = true; +} + +int QPpdPrintDevice::defaultResolution() const +{ + // Try load standard PPD option first + ppd_option_t *resolution = ppdFindOption(m_ppd, "DefaultResolution"); + if (resolution) { + int res = QPrintUtils::parsePpdResolution(resolution->choices[0].choice); + if (res > 0) + return res; + } + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "Resolution"); + if (defaultChoice) { + int res = QPrintUtils::parsePpdResolution(defaultChoice->choice); + if (res > 0) + return res; + } + // If still no result, then try HP's custom options + resolution = ppdFindOption(m_ppd, "DefaultHPPrintQuality"); + if (resolution) { + int res = QPrintUtils::parsePpdResolution(resolution->choices[0].choice); + if (res > 0) + return res; + } + defaultChoice = ppdFindMarkedChoice(m_ppd, "HPPrintQuality"); + if (defaultChoice) { + int res = QPrintUtils::parsePpdResolution(defaultChoice->choice); + if (res > 0) + return res; + } + // Otherwise return a sensible default. + // TODO What is sensible? 150? 300? + return 72; +} + +void QPpdPrintDevice::loadInputSlots() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // TODO Deal with concatenated names like Tray1Manual or Tray1_Man, + // will currently show as CustomInputSlot + // TODO Deal with separate ManualFeed key + // Try load standard PPD options first + m_inputSlots.clear(); + if (m_ppd) { + ppd_option_t *inputSlots = ppdFindOption(m_ppd, "InputSlot"); + if (inputSlots) { + for (int i = 0; i < inputSlots->num_choices; ++i) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i])); + } + // If no result, try just the default + if (m_inputSlots.size() == 0) { + inputSlots = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlots) + m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0])); + } + } + // If still no result, just use Auto + if (m_inputSlots.size() == 0) + m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot()); + m_haveInputSlots = true; +} + +QPrint::InputSlot QPpdPrintDevice::defaultInputSlot() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultInputSlot"); + if (inputSlot) + return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "InputSlot"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice); + } + // Otherwise return Auto + return QPlatformPrintDevice::defaultInputSlot(); +} + +void QPpdPrintDevice::loadOutputBins() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + m_outputBins.clear(); + if (m_ppd) { + ppd_option_t *outputBins = ppdFindOption(m_ppd, "OutputBin"); + if (outputBins) { + for (int i = 0; i < outputBins->num_choices; ++i) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i])); + } + // If no result, try just the default + if (m_outputBins.size() == 0) { + outputBins = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBins) + m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0])); + } + } + // If still no result, just use Auto + if (m_outputBins.size() == 0) + m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); + m_haveOutputBins = true; +} + +QPrint::OutputBin QPpdPrintDevice::defaultOutputBin() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *outputBin = ppdFindOption(m_ppd, "DefaultOutputBin"); + if (outputBin) + return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "OutputBin"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice); + } + // Otherwise return AutoBin + return QPlatformPrintDevice::defaultOutputBin(); +} + +void QPpdPrintDevice::loadDuplexModes() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Try load standard PPD options first + m_duplexModes.clear(); + if (m_ppd) { + ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex"); + if (duplexModes) { + for (int i = 0; i < duplexModes->num_choices; ++i) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice)); + } + // If no result, try just the default + if (m_duplexModes.size() == 0) { + duplexModes = ppdFindOption(m_ppd, "DefaultDuplex"); + if (duplexModes) + m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice)); + } + } + // 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); + m_haveDuplexModes = true; +} + +QPrint::DuplexMode QPpdPrintDevice::defaultDuplexMode() const +{ + // Try load standard PPD option first + if (m_ppd) { + ppd_option_t *inputSlot = ppdFindOption(m_ppd, "DefaultDuplex"); + if (inputSlot) + return QPrintUtils::ppdChoiceToDuplexMode(inputSlot->choices[0].choice); + // If no result, then try a marked option + ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd, "Duplex"); + if (defaultChoice) + return QPrintUtils::ppdChoiceToDuplexMode(defaultChoice->choice); + } + // Otherwise return None + return QPrint::DuplexNone; +} + +void QPpdPrintDevice::loadColorModes() const +{ + // Cups cups_ptype_e CUPS_PRINTER_BW CUPS_PRINTER_COLOR + // Cups ppd_file_t color_device + // PPD ColorDevice + m_colorModes.clear(); + cups_ptype_e type = printerTypeFlags(); + if (type & CUPS_PRINTER_BW) + m_colorModes.append(QPrint::GrayScale); + if (type & CUPS_PRINTER_COLOR) + m_colorModes.append(QPrint::Color); + m_haveColorModes = true; +} + +QPrint::ColorMode QPpdPrintDevice::defaultColorMode() const +{ + // NOTE: Implemented in both CUPS and Mac plugins, please keep in sync + // Not a proper option, usually only know if supports color or not, but some + // users known to abuse ColorModel to always force GrayScale. + if (m_ppd && supportedColorModes().contains(QPrint::Color)) { + ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel"); + if (!colorModel) + colorModel = ppdFindOption(m_ppd, "ColorModel"); + if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray"))) + return QPrint::Color; + } + return QPrint::GrayScale; +} + +void QPpdPrintDevice::loadMimeTypes() const +{ + // TODO No CUPS api? Need to manually load CUPS mime.types file? + // For now hard-code most common support types + QMimeDatabase db; + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/pdf"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("application/postscript"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/gif"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/png"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/jpeg"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("image/tiff"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/html"))); + m_mimeTypes.append(db.mimeTypeForName(QStringLiteral("text/plain"))); + m_haveMimeTypes = true; +} + +void QPpdPrintDevice::loadPrinter() +{ + // Just to be safe, check if existing printer needs closing + if (m_ppd) { + ppdClose(m_ppd); + m_ppd = 0; + } + if (m_cupsDest) { + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + } + + // Get the print instance and PPD file + m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance); + if (m_cupsDest) { + const char *ppdFile = cupsGetPPD(m_cupsName); + if (ppdFile) + m_ppd = ppdOpenFile(ppdFile); + unlink(ppdFile); + if (m_ppd) { + ppdMarkDefaults(m_ppd); + } else { + cupsFreeDests(1, m_cupsDest); + m_cupsDest = 0; + m_ppd = 0; + } + } +} + +QString QPpdPrintDevice::printerOption(const QString &key) const +{ + return cupsGetOption(key.toUtf8(), m_cupsDest->num_options, m_cupsDest->options); +} + +cups_ptype_e QPpdPrintDevice::printerTypeFlags() const +{ + return static_cast<cups_ptype_e>(printerOption("printer-type").toUInt()); +} + +#endif // QT_NO_PRINTER + +QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h new file mode 100644 index 0000000000..982f46d71f --- /dev/null +++ b/src/plugins/printsupport/cups/qppdprintdevice.h @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2014 John Layt <jlayt@kde.org> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPPDPRINTDEVICE_H +#define QPPDPRINTDEVICE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of internal files. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include <qpa/qplatformprintdevice.h> + +#ifndef QT_NO_PRINTER + +#include <cups/cups.h> +#include <cups/ppd.h> + +QT_BEGIN_NAMESPACE + +class QPpdPrintDevice : public QPlatformPrintDevice +{ +public: + QPpdPrintDevice(); + explicit QPpdPrintDevice(const QString &id); + QPpdPrintDevice(const QPpdPrintDevice &other); + virtual ~QPpdPrintDevice(); + + QPpdPrintDevice &operator=(const QPpdPrintDevice &other); + + QPpdPrintDevice *clone(); + + bool operator==(const QPpdPrintDevice &other) const; + + bool isValid() const Q_DECL_OVERRIDE; + bool isDefault() const Q_DECL_OVERRIDE; + + QPrint::DeviceState state() const Q_DECL_OVERRIDE; + + QPageSize defaultPageSize() const Q_DECL_OVERRIDE; + + QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, + int resolution) const Q_DECL_OVERRIDE; + + int defaultResolution() const Q_DECL_OVERRIDE; + + QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE; + + QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE; + + QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE; + + QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE; + +protected: + void loadPageSizes() const Q_DECL_OVERRIDE; + void loadResolutions() const Q_DECL_OVERRIDE; + void loadInputSlots() const Q_DECL_OVERRIDE; + void loadOutputBins() const Q_DECL_OVERRIDE; + void loadDuplexModes() const Q_DECL_OVERRIDE; + void loadColorModes() const Q_DECL_OVERRIDE; + void loadMimeTypes() const Q_DECL_OVERRIDE; + +private: + void loadPrinter(); + QString printerOption(const QString &key) const; + cups_ptype_e printerTypeFlags() const; + + cups_dest_t *m_cupsDest; + ppd_file_t *m_ppd; + QByteArray m_cupsName; + QByteArray m_cupsInstance; + QMarginsF m_customMargins; + mutable QHash<QString, QMarginsF> m_printableMargins; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER +#endif // QPPDPRINTDEVICE_H |