diff options
Diffstat (limited to 'src/plugins/printsupport')
8 files changed, 302 insertions, 75 deletions
diff --git a/src/plugins/printsupport/cups/qcupsprintengine.cpp b/src/plugins/printsupport/cups/qcupsprintengine.cpp index 6c29a99705..c9683eb99d 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine.cpp +++ b/src/plugins/printsupport/cups/qcupsprintengine.cpp @@ -104,7 +104,11 @@ void QCupsPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &v break; case PPK_QPageLayout: { QPageLayout pageLayout = value.value<QPageLayout>(); - if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution) || d->m_printDevice.supportsCustomPageSizes())) { + if (pageLayout.isValid() && (d->m_printDevice.isValidPageLayout(pageLayout, d->resolution) + || d->m_printDevice.supportsCustomPageSizes() + || d->m_printDevice.supportedPageSizes().isEmpty())) { + // supportedPageSizes().isEmpty() because QPageSetupWidget::initPageSizes says + // "If no available printer page sizes, populate with all page sizes" d->m_pageLayout = pageLayout; d->setPageSize(pageLayout.pageSize()); } @@ -132,6 +136,9 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const case PPK_CupsOptions: ret = d->cupsOptions; break; + case PPK_Duplex: + ret = d->duplex; + break; default: ret = QPdfPrintEngine::property(key); break; @@ -140,7 +147,9 @@ QVariant QCupsPrintEngine::property(PrintEnginePropertyKey key) const } -QCupsPrintEnginePrivate::QCupsPrintEnginePrivate(QPrinter::PrinterMode m) : QPdfPrintEnginePrivate(m) +QCupsPrintEnginePrivate::QCupsPrintEnginePrivate(QPrinter::PrinterMode m) + : QPdfPrintEnginePrivate(m) + , duplex(QPrint::DuplexNone) { } diff --git a/src/plugins/printsupport/cups/qcupsprintengine_p.h b/src/plugins/printsupport/cups/qcupsprintengine_p.h index d5363bb8cc..2a1a83b9d7 100644 --- a/src/plugins/printsupport/cups/qcupsprintengine_p.h +++ b/src/plugins/printsupport/cups/qcupsprintengine_p.h @@ -99,6 +99,7 @@ private: QPrintDevice m_printDevice; QStringList cupsOptions; QString cupsTempFile; + QPrint::DuplexMode duplex; }; QT_END_NAMESPACE diff --git a/src/plugins/printsupport/cups/qcupsprintersupport.cpp b/src/plugins/printsupport/cups/qcupsprintersupport.cpp index a9c992a2e1..19e1df31f6 100644 --- a/src/plugins/printsupport/cups/qcupsprintersupport.cpp +++ b/src/plugins/printsupport/cups/qcupsprintersupport.cpp @@ -47,6 +47,15 @@ #include <QtPrintSupport/QPrinterInfo> +#if QT_CONFIG(dialogbuttonbox) +#include <QGuiApplication> +#include <QDialog> +#include <QDialogButtonBox> +#include <QFormLayout> +#include <QLabel> +#include <QLineEdit> +#endif // QT_CONFIG(dialogbuttonbox) + #include <cups/ppd.h> #ifndef QT_LINUXBASE // LSB merges everything into cups.h # include <cups/language.h> @@ -54,9 +63,78 @@ QT_BEGIN_NAMESPACE +#if QT_CONFIG(dialogbuttonbox) +static const char *getPasswordCB(const char */*prompt*/, http_t *http, const char */*method*/, const char *resource, void */*user_data*/) +{ + // cups doesn't free the const char * we return so keep around + // the last password so we don't leak memory if called multiple times. + static QByteArray password; + + // prompt is always "Password for %s on %s? " but we can't use it since we allow the user to change the user. + // That is fine because cups always calls cupsUser after calling this callback. + // We build our own prompt with the hostname (if not localhost) and the resource that is being used + + char hostname[HTTP_MAX_HOST]; + httpGetHostname(http, hostname, HTTP_MAX_HOST); + + const QString username = QString::fromLocal8Bit(cupsUser()); + + QDialog dialog; + dialog.setWindowTitle(QCoreApplication::translate("QCupsPrinterSupport", "Authentication Needed")); + + QFormLayout *layout = new QFormLayout(&dialog); + layout->setSizeConstraint(QLayout::SetFixedSize); + + QLineEdit *usernameLE = new QLineEdit(); + usernameLE->setText(username); + + QLineEdit *passwordLE = new QLineEdit(); + passwordLE->setEchoMode(QLineEdit::Password); + + QString resourceString = QString::fromLocal8Bit(resource); + if (resourceString.startsWith(QStringLiteral("/printers/"))) + resourceString = resourceString.mid(QStringLiteral("/printers/").length()); + + QLabel *label = new QLabel(); + if (hostname == QStringLiteral("localhost")) { + label->setText(QCoreApplication::translate("QCupsPrinterSupport", "Authentication needed to use %1.").arg(resourceString)); + } else { + label->setText(QCoreApplication::translate("QCupsPrinterSupport", "Authentication needed to use %1 on %2.").arg(resourceString).arg(hostname)); + label->setWordWrap(true); + } + + layout->addRow(label); + layout->addRow(new QLabel(QCoreApplication::translate("QCupsPrinterSupport", "Username:")), usernameLE); + layout->addRow(new QLabel(QCoreApplication::translate("QCupsPrinterSupport", "Password:")), passwordLE); + + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + layout->addRow(buttonBox); + + QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + passwordLE->setFocus(); + + if (dialog.exec() != QDialog::Accepted) + return nullptr; + + if (usernameLE->text() != username) + cupsSetUser(usernameLE->text().toLocal8Bit().constData()); + + password = passwordLE->text().toLocal8Bit(); + + return password.constData(); +} +#endif // QT_CONFIG(dialogbuttonbox) + QCupsPrinterSupport::QCupsPrinterSupport() : QPlatformPrinterSupport() { +#if QT_CONFIG(dialogbuttonbox) + // Only show password dialog if GUI application + if (qobject_cast<QGuiApplication*>(QCoreApplication::instance())) + cupsSetPasswordCB2(getPasswordCB, nullptr /* user_data */ ); +#endif // QT_CONFIG(dialogbuttonbox) } QCupsPrinterSupport::~QCupsPrinterSupport() diff --git a/src/plugins/printsupport/cups/qppdprintdevice.cpp b/src/plugins/printsupport/cups/qppdprintdevice.cpp index 340b1a1ff4..d2ddc4144f 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.cpp +++ b/src/plugins/printsupport/cups/qppdprintdevice.cpp @@ -50,13 +50,6 @@ QT_BEGIN_NAMESPACE -QPpdPrintDevice::QPpdPrintDevice() - : QPlatformPrintDevice(), - m_cupsDest(0), - m_ppd(0) -{ -} - QPpdPrintDevice::QPpdPrintDevice(const QString &id) : QPlatformPrintDevice(id), m_cupsDest(0), @@ -69,9 +62,26 @@ QPpdPrintDevice::QPpdPrintDevice(const QString &id) m_cupsName = parts.at(0).toUtf8(); if (parts.size() > 1) m_cupsInstance = parts.at(1).toUtf8(); - loadPrinter(); - if (m_cupsDest && m_ppd) { + // Get the print instance and PPD file + m_cupsDest = cupsGetNamedDest(CUPS_HTTP_DEFAULT, m_cupsName, m_cupsInstance.isNull() ? nullptr : m_cupsInstance.constData()); + if (m_cupsDest) { + const char *ppdFile = cupsGetPPD(m_cupsName); + if (ppdFile) { + m_ppd = ppdOpenFile(ppdFile); + unlink(ppdFile); + } + if (m_ppd) { + ppdMarkDefaults(m_ppd); + cupsMarkOptions(m_ppd, m_cupsDest->num_options, m_cupsDest->options); + ppdLocalize(m_ppd); + + 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]); + } + m_name = printerOption("printer-info"); m_location = printerOption("printer-location"); m_makeAndModel = printerOption("printer-make-and-model"); @@ -87,10 +97,6 @@ QPpdPrintDevice::QPpdPrintDevice(const QString &id) // 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]); } } } @@ -107,7 +113,7 @@ QPpdPrintDevice::~QPpdPrintDevice() bool QPpdPrintDevice::isValid() const { - return m_cupsDest && m_ppd; + return m_cupsDest; } bool QPpdPrintDevice::isDefault() const @@ -152,8 +158,8 @@ void QPpdPrintDevice::loadPageSizes() const } } } - m_havePageSizes = true; } + m_havePageSizes = true; } QPageSize QPpdPrintDevice::defaultPageSize() const @@ -359,14 +365,18 @@ void QPpdPrintDevice::loadDuplexModes() const ppd_option_t *duplexModes = ppdFindOption(m_ppd, "Duplex"); if (duplexModes) { m_duplexModes.reserve(duplexModes->num_choices); - for (int i = 0; i < duplexModes->num_choices; ++i) - m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice)); + for (int i = 0; i < duplexModes->num_choices; ++i) { + if (ppdInstallableConflict(m_ppd, duplexModes->keyword, duplexModes->choices[i].choice) == 0) { + 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) + if (duplexModes && (ppdInstallableConflict(m_ppd, duplexModes->keyword, duplexModes->choices[0].choice) == 0)) { m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice)); + } } } // If still no result, or not added in PPD, then add None @@ -417,7 +427,7 @@ QPrint::ColorMode QPpdPrintDevice::defaultColorMode() const ppd_option_t *colorModel = ppdFindOption(m_ppd, "DefaultColorModel"); if (!colorModel) colorModel = ppdFindOption(m_ppd, "ColorModel"); - if (!colorModel || (colorModel && !qstrcmp(colorModel->defchoice, "Gray"))) + if (!colorModel || qstrcmp(colorModel->defchoice, "Gray") != 0) return QPrint::Color; } return QPrint::GrayScale; @@ -481,38 +491,6 @@ void QPpdPrintDevice::loadMimeTypes() const } #endif -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.isNull() ? nullptr : m_cupsInstance.constData()); - if (m_cupsDest) { - const char *ppdFile = cupsGetPPD(m_cupsName); - if (ppdFile) { - m_ppd = ppdOpenFile(ppdFile); - unlink(ppdFile); - } - if (m_ppd) { - ppdMarkDefaults(m_ppd); - cupsMarkOptions(m_ppd, m_cupsDest->num_options, m_cupsDest->options); - ppdLocalize(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); diff --git a/src/plugins/printsupport/cups/qppdprintdevice.h b/src/plugins/printsupport/cups/qppdprintdevice.h index 9867083bd7..90f90d6788 100644 --- a/src/plugins/printsupport/cups/qppdprintdevice.h +++ b/src/plugins/printsupport/cups/qppdprintdevice.h @@ -65,7 +65,6 @@ QT_BEGIN_NAMESPACE class QPpdPrintDevice : public QPlatformPrintDevice { public: - QPpdPrintDevice(); explicit QPpdPrintDevice(const QString &id); virtual ~QPpdPrintDevice(); @@ -105,7 +104,6 @@ protected: #endif private: - void loadPrinter(); QString printerOption(const QString &key) const; cups_ptype_e printerTypeFlags() const; diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp index b1589c0738..f01e93d611 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.cpp +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 John Layt <jlayt@kde.org> -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -49,6 +49,8 @@ QT_BEGIN_NAMESPACE QT_WARNING_DISABLE_GCC("-Wsign-compare") +typedef QVector<QWindowsPrinterInfo> WindowsPrinterLookup; +Q_GLOBAL_STATIC(WindowsPrinterLookup, windowsDeviceLookup); extern qreal qt_pointMultiplier(QPageLayout::Unit unit); @@ -110,7 +112,7 @@ QWindowsPrintDevice::QWindowsPrintDevice(const QString &id) { // First do a fast lookup to see if printer exists, if it does then open it if (!id.isEmpty() && QWindowsPrintDevice::availablePrintDeviceIds().contains(id)) { - if (OpenPrinter((LPWSTR)m_id.utf16(), &m_hPrinter, NULL)) { + if (OpenPrinter(const_cast<LPWSTR>(wcharId()), &m_hPrinter, nullptr)) { DWORD needed = 0; GetPrinter(m_hPrinter, 2, 0, 0, &needed); QScopedArrayPointer<BYTE> buffer(new BYTE[needed]); @@ -121,15 +123,39 @@ QWindowsPrintDevice::QWindowsPrintDevice(const QString &id) m_makeAndModel = QString::fromWCharArray(info->pDriverName); // TODO Check is not available elsewhere m_isRemote = info->Attributes & PRINTER_ATTRIBUTE_NETWORK; } - m_supportsMultipleCopies = (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COPIES, NULL, NULL) > 1); - m_supportsCollateCopies = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLLATE, NULL, NULL); - // Min/Max custom size is in tenths of a millimeter - const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); - DWORD min = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MINEXTENT, NULL, NULL); - m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier); - DWORD max = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_MAXEXTENT, NULL, NULL); - m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier); - m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0); + QWindowsPrinterInfo m_info; + m_info.m_id = m_id; + m_info.m_name = m_name; + m_info.m_location = m_location; + m_info.m_makeAndModel = m_makeAndModel; + m_info.m_isRemote = m_isRemote; + m_infoIndex = windowsDeviceLookup()->indexOf(m_info); + if (m_infoIndex != -1) { + m_info = windowsDeviceLookup()->at(m_infoIndex); + m_havePageSizes = m_info.m_havePageSizes; + m_pageSizes = m_info.m_pageSizes; + m_haveResolutions = m_info.m_haveResolutions; + m_resolutions = m_info.m_resolutions; + m_haveCopies = m_info.m_haveCopies; + m_supportsMultipleCopies = m_info.m_supportsMultipleCopies; + m_supportsCollateCopies = m_info.m_supportsCollateCopies; + m_haveMinMaxPageSizes = m_info.m_haveMinMaxPageSizes; + m_minimumPhysicalPageSize = m_info.m_minimumPhysicalPageSize; + m_maximumPhysicalPageSize = m_info.m_maximumPhysicalPageSize; + m_supportsCustomPageSizes = m_info.m_supportsCustomPageSizes; + m_haveInputSlots = m_info.m_haveInputSlots; + m_inputSlots = m_info.m_inputSlots; + m_haveOutputBins = m_info.m_haveOutputBins; + m_outputBins = m_info.m_outputBins; + m_haveDuplexModes = m_info.m_haveDuplexModes; + m_duplexModes = m_info.m_duplexModes; + m_haveColorModes = m_info.m_haveColorModes; + m_colorModes = m_info.m_colorModes; + m_infoIndex = windowsDeviceLookup()->indexOf(m_info); + } else { + windowsDeviceLookup()->append(m_info); + m_infoIndex = windowsDeviceLookup()->count() - 1; + } } } } @@ -184,7 +210,7 @@ void QWindowsPrintDevice::loadPageSizes() const && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_PAPERS, NULL, NULL) == paperCount) { QScopedArrayPointer<wchar_t> paperNames(new wchar_t[paperCount*64]); - QScopedArrayPointer<POINT> winSizes(new POINT[paperCount*sizeof(POINT)]); + QScopedArrayPointer<POINT> winSizes(new POINT[paperCount]); QScopedArrayPointer<wchar_t> papers(new wchar_t[paperCount]); // Get the details and match the default paper size @@ -205,6 +231,9 @@ void QWindowsPrintDevice::loadPageSizes() const } m_havePageSizes = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_havePageSizes = true; + info[m_infoIndex].m_pageSizes = m_pageSizes; } QPageSize QWindowsPrintDevice::defaultPageSize() const @@ -297,6 +326,9 @@ void QWindowsPrintDevice::loadResolutions() const } } m_haveResolutions = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveResolutions = true; + info[m_infoIndex].m_resolutions = m_resolutions; } int QWindowsPrintDevice::defaultResolution() const @@ -319,16 +351,19 @@ int QWindowsPrintDevice::defaultResolution() const void QWindowsPrintDevice::loadInputSlots() const { - DWORD binCount = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, NULL, NULL); + const auto printerId = wcharId(); + DWORD binCount = DeviceCapabilities(printerId, nullptr, DC_BINS, nullptr, nullptr); if (int(binCount) > 0 - && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, NULL, NULL) == binCount) { + && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, nullptr, nullptr) == binCount) { - QScopedArrayPointer<WORD> bins(new WORD[binCount*sizeof(WORD)]); + QScopedArrayPointer<WORD> bins(new WORD[binCount]); QScopedArrayPointer<wchar_t> binNames(new wchar_t[binCount*24]); // Get the details and match the default paper size - if (DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINS, (LPWSTR)bins.data(), NULL) == binCount - && DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_BINNAMES, binNames.data(), NULL) == binCount) { + if (DeviceCapabilities(printerId, nullptr, DC_BINS, + reinterpret_cast<LPWSTR>(bins.data()), nullptr) == binCount + && DeviceCapabilities(printerId, nullptr, DC_BINNAMES, binNames.data(), + nullptr) == binCount) { for (int i = 0; i < int(binCount); ++i) { wchar_t *binName = binNames.data() + (i * 24); @@ -340,6 +375,9 @@ void QWindowsPrintDevice::loadInputSlots() const } m_haveInputSlots = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveInputSlots = true; + info[m_infoIndex].m_inputSlots = m_inputSlots; } QPrint::InputSlot QWindowsPrintDevice::defaultInputSlot() const @@ -367,12 +405,15 @@ void QWindowsPrintDevice::loadOutputBins() const { m_outputBins.append(QPlatformPrintDevice::defaultOutputBin()); m_haveOutputBins = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveOutputBins = true; + info[m_infoIndex].m_outputBins = m_outputBins; } void QWindowsPrintDevice::loadDuplexModes() const { m_duplexModes.append(QPrint::DuplexNone); - DWORD duplex = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_DUPLEX, NULL, NULL); + DWORD duplex = DeviceCapabilities(wcharId(), nullptr, DC_DUPLEX, nullptr, nullptr); if (int(duplex) == 1) { // TODO Assume if duplex flag supports both modes m_duplexModes.append(QPrint::DuplexAuto); @@ -380,6 +421,9 @@ void QWindowsPrintDevice::loadDuplexModes() const m_duplexModes.append(QPrint::DuplexShortSide); } m_haveDuplexModes = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveDuplexModes = true; + info[m_infoIndex].m_duplexModes = m_duplexModes; } QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const @@ -403,10 +447,13 @@ QPrint::DuplexMode QWindowsPrintDevice::defaultDuplexMode() const void QWindowsPrintDevice::loadColorModes() const { m_colorModes.append(QPrint::GrayScale); - DWORD color = DeviceCapabilities((LPWSTR)m_id.utf16(), NULL, DC_COLORDEVICE, NULL, NULL); + DWORD color = DeviceCapabilities(wcharId(), nullptr, DC_COLORDEVICE, nullptr, nullptr); if (int(color) == 1) m_colorModes.append(QPrint::Color); m_haveColorModes = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveColorModes = true; + info[m_infoIndex].m_colorModes = m_colorModes; } QPrint::ColorMode QWindowsPrintDevice::defaultColorMode() const @@ -457,4 +504,68 @@ QString QWindowsPrintDevice::defaultPrintDeviceId() return QString::fromWCharArray(name.data()); } +void QWindowsPrintDevice::loadCopiesSupport() const +{ + auto printerId = wcharId(); + m_supportsMultipleCopies = (DeviceCapabilities(printerId, NULL, DC_COPIES, NULL, NULL) > 1); + m_supportsCollateCopies = DeviceCapabilities(printerId, NULL, DC_COLLATE, NULL, NULL); + m_haveCopies = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveCopies = true; + info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies; + info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies; +} + +bool QWindowsPrintDevice::supportsCollateCopies() const +{ + if (!m_haveCopies) + loadCopiesSupport(); + return m_supportsCollateCopies; +} + +bool QWindowsPrintDevice::supportsMultipleCopies() const +{ + if (!m_haveCopies) + loadCopiesSupport(); + return m_supportsMultipleCopies; +} + +bool QWindowsPrintDevice::supportsCustomPageSizes() const +{ + if (!m_haveMinMaxPageSizes) + loadMinMaxPageSizes(); + return m_supportsCustomPageSizes; +} + +QSize QWindowsPrintDevice::minimumPhysicalPageSize() const +{ + if (!m_haveMinMaxPageSizes) + loadMinMaxPageSizes(); + return m_minimumPhysicalPageSize; +} + +QSize QWindowsPrintDevice::maximumPhysicalPageSize() const +{ + if (!m_haveMinMaxPageSizes) + loadMinMaxPageSizes(); + return m_maximumPhysicalPageSize; +} + +void QWindowsPrintDevice::loadMinMaxPageSizes() const +{ + // Min/Max custom size is in tenths of a millimeter + const qreal multiplier = qt_pointMultiplier(QPageLayout::Millimeter); + auto printerId = wcharId(); + DWORD min = DeviceCapabilities(printerId, NULL, DC_MINEXTENT, NULL, NULL); + m_minimumPhysicalPageSize = QSize((LOWORD(min) / 10.0) * multiplier, (HIWORD(min) / 10.0) * multiplier); + DWORD max = DeviceCapabilities(printerId, NULL, DC_MAXEXTENT, NULL, NULL); + m_maximumPhysicalPageSize = QSize((LOWORD(max) / 10.0) * multiplier, (HIWORD(max) / 10.0) * multiplier); + m_supportsCustomPageSizes = (m_maximumPhysicalPageSize.width() > 0 && m_maximumPhysicalPageSize.height() > 0); + m_haveMinMaxPageSizes = true; + QWindowsPrinterInfo *info = windowsDeviceLookup()->data(); + info[m_infoIndex].m_haveCopies = true; + info[m_infoIndex].m_supportsMultipleCopies = m_supportsMultipleCopies; + info[m_infoIndex].m_supportsCollateCopies = m_supportsCollateCopies; +} + QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintdevice.h b/src/plugins/printsupport/windows/qwindowsprintdevice.h index 6b51ee8785..166f0f65b2 100644 --- a/src/plugins/printsupport/windows/qwindowsprintdevice.h +++ b/src/plugins/printsupport/windows/qwindowsprintdevice.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2014 John Layt <jlayt@kde.org> +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -57,6 +58,43 @@ QT_BEGIN_NAMESPACE +class QWindowsPrinterInfo +{ +public: + bool operator==(const QWindowsPrinterInfo &other) const + { + // We only need to check if these are the same for matching up + return m_id == other.m_id && m_name == other.m_name && + m_location == other.m_location && + m_makeAndModel == other.m_makeAndModel && + m_isRemote == other.m_isRemote; + } + QString m_id; + QString m_name; + QString m_location; + QString m_makeAndModel; + QList<QPageSize> m_pageSizes; + QList<int> m_resolutions; + QVector<QPrint::InputSlot> m_inputSlots; + QVector<QPrint::OutputBin> m_outputBins; + QVector<QPrint::DuplexMode> m_duplexModes; + QVector<QPrint::ColorMode> m_colorModes; + QSize m_minimumPhysicalPageSize; + QSize m_maximumPhysicalPageSize; + bool m_isRemote = false; + bool m_havePageSizes = false; + bool m_haveResolutions = false; + bool m_haveCopies = false; + bool m_supportsMultipleCopies = false; + bool m_supportsCollateCopies = false; + bool m_haveMinMaxPageSizes = false; + bool m_supportsCustomPageSizes = false; + bool m_haveInputSlots = false; + bool m_haveOutputBins = false; + bool m_haveDuplexModes = false; + bool m_haveColorModes = false; +}; + class QWindowsPrintDevice : public QPlatformPrintDevice { public: @@ -85,6 +123,12 @@ public: static QStringList availablePrintDeviceIds(); static QString defaultPrintDeviceId(); + bool supportsCollateCopies() const override; + bool supportsMultipleCopies() const override; + bool supportsCustomPageSizes() const override; + QSize minimumPhysicalPageSize() const override; + QSize maximumPhysicalPageSize() const override; + protected: void loadPageSizes() const override; void loadResolutions() const override; @@ -92,9 +136,16 @@ protected: void loadOutputBins() const override; void loadDuplexModes() const override; void loadColorModes() const override; + void loadCopiesSupport() const; + void loadMinMaxPageSizes() const; private: + LPCWSTR wcharId() const { return reinterpret_cast<LPCWSTR>(m_id.utf16()); } + HANDLE m_hPrinter; + mutable bool m_haveCopies; + mutable bool m_haveMinMaxPageSizes; + int m_infoIndex; }; QT_END_NAMESPACE diff --git a/src/plugins/printsupport/windows/qwindowsprintersupport.h b/src/plugins/printsupport/windows/qwindowsprintersupport.h index c42e7aa551..4267701145 100644 --- a/src/plugins/printsupport/windows/qwindowsprintersupport.h +++ b/src/plugins/printsupport/windows/qwindowsprintersupport.h @@ -46,9 +46,10 @@ QT_BEGIN_NAMESPACE class QWindowsPrinterSupport : public QPlatformPrinterSupport { + Q_DISABLE_COPY(QWindowsPrinterSupport) public: QWindowsPrinterSupport(); - ~QWindowsPrinterSupport(); + ~QWindowsPrinterSupport() override; QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override; QPaintEngine *createPaintEngine(QPrintEngine *printEngine, QPrinter::PrinterMode) override; |