diff options
author | John Layt <jlayt@kde.org> | 2013-12-17 15:46:34 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2014-03-17 13:45:39 +0100 |
commit | e33b9152678cd62a7f314dae80898326595c86c0 (patch) | |
tree | 4d028318032c0ce0f0647b2169598f74a9782db3 /src/plugins/platforms | |
parent | 6826912f605f31c8e13bfd84127fd6676602d5f1 (diff) |
QPlatformPrintDevice - Add Mac implementation
Implement the OSX support for QPlatformPrintDevice
Change-Id: I2e3900818d4d9f0682a15ed94b8c824085adb465
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/plugins/platforms')
-rw-r--r-- | src/plugins/platforms/cocoa/cocoa.pro | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaprintdevice.h | 130 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaprintdevice.mm | 498 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaprintersupport.h | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaprintersupport.mm | 35 |
5 files changed, 670 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index d8cd32255c..a60f4adc28 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -81,7 +81,7 @@ HEADERS += qcocoaintegration.h \ RESOURCES += qcocoaresources.qrc -LIBS += -framework Cocoa -framework Carbon -framework IOKit +LIBS += -framework Cocoa -framework Carbon -framework IOKit -lcups QT += core-private gui-private platformsupport-private @@ -90,11 +90,13 @@ qtHaveModule(widgets) { qpaintengine_mac.mm \ qprintengine_mac.mm \ qcocoaprintersupport.mm \ + qcocoaprintdevice.mm \ HEADERS += \ qpaintengine_mac_p.h \ qprintengine_mac_p.h \ qcocoaprintersupport.h \ + qcocoaprintdevice.h \ QT += widgets-private printsupport-private } diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h new file mode 100644 index 0000000000..3f1fa475d5 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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 QCOCOAPRINTDEVICE_H +#define QCOCOAPRINTDEVICE_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 <QtCore/qfeatures.h> // Some feature dependencies might define QT_NO_PRINTER +#ifndef QT_NO_PRINTER + +#include <qpa/qplatformprintdevice.h> + +#include "qt_mac_p.h" + +#include <cups/ppd.h> + +QT_BEGIN_NAMESPACE + +class QCocoaPrintDevice : public QPlatformPrintDevice +{ +public: + QCocoaPrintDevice(); + explicit QCocoaPrintDevice(const QString &id); + QCocoaPrintDevice(const QCocoaPrintDevice &other); + virtual ~QCocoaPrintDevice(); + + QCocoaPrintDevice *clone(); + + bool operator==(const QCocoaPrintDevice &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; + + PMPrinter macPrinter() const; + PMPaper macPaper(const QPageSize &pageSize) const; + +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: + QPageSize createPageSize(const PMPaper &paper) const; + bool openPpdFile(); + + // Mac Core Printing + PMPrinter m_printer; + PMPrintSession m_session; + mutable QHash<QString, PMPaper> m_macPapers; + + // PPD File + ppd_file_t *m_ppd; + + QMarginsF m_customMargins; + mutable QHash<QString, QMarginsF> m_printableMargins; +}; + +QT_END_NAMESPACE + +#endif // QT_NO_PRINTER +#endif // QCOCOAPRINTDEVICE_H diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm new file mode 100644 index 0000000000..d8b01ec07f --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -0,0 +1,498 @@ +/**************************************************************************** +** +** 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 "qcocoaprintdevice.h" + +#include <QtCore/qmimedatabase.h> +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode) +{ + if (mode == kPMDuplexTumble) + return QPrint::DuplexShortSide; + else if (mode == kPMDuplexNoTumble) + return QPrint::DuplexLongSide; + else // kPMDuplexNone or kPMSimplexTumble + return QPrint::DuplexNone; +} + +QCocoaPrintDevice::QCocoaPrintDevice() + : QPlatformPrintDevice(), + m_printer(0), + m_session(0), + m_ppd(0) +{ +} + +QCocoaPrintDevice::QCocoaPrintDevice(const QString &id) + : QPlatformPrintDevice(id), + m_printer(0), + m_session(0), + m_ppd(0) +{ + if (!id.isEmpty()) { + m_printer = PMPrinterCreateFromPrinterID(QCFString::toCFStringRef(id)); + if (m_printer) { + m_name = QCFString::toQString(PMPrinterGetName(m_printer)); + m_location = QCFString::toQString(PMPrinterGetLocation(m_printer)); + CFStringRef cfMakeAndModel; + if (PMPrinterGetMakeAndModelName(m_printer, &cfMakeAndModel) == noErr) + m_makeAndModel = QCFString::toQString(cfMakeAndModel); + Boolean isRemote; + if (PMPrinterIsRemote(m_printer, &isRemote) == noErr) + m_isRemote = isRemote; + if (PMCreateSession(&m_session) == noErr) + PMSessionSetCurrentPMPrinter(m_session, m_printer); + + // No native api to query these options, need to use PPD directly, note is deprecated from 1.6 onwards + if (openPpdFile()) { + // Note this is if the hardware does multiple copies, not if Cups can + m_supportsMultipleCopies = !m_ppd->manual_copies; + // Note this is if the hardware does collation, not if Cups can + ppd_option_t *collate = ppdFindOption(m_ppd, "Collate"); + if (collate) + m_supportsCollateCopies = true; + m_supportsCustomPageSizes = m_ppd->custom_max[0] > 0 && m_ppd->custom_max[1] > 0; + 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]); + } + } + } +} + +QCocoaPrintDevice::QCocoaPrintDevice(const QCocoaPrintDevice &other) + : QPlatformPrintDevice(other), + m_printer(0), + m_session(0), + m_ppd(0) +{ + m_printer = other.m_printer; + PMRetain(m_printer); + m_session = other.m_session; + PMRetain(m_session); + m_macPapers = other.m_macPapers; + foreach (PMPaper paper, m_macPapers.values()) + PMRetain(paper); + openPpdFile(); + m_customMargins = other.m_customMargins; + m_printableMargins = other.m_printableMargins; +} + +QCocoaPrintDevice::~QCocoaPrintDevice() +{ + if (m_ppd) + ppdClose(m_ppd); + foreach (PMPaper paper, m_macPapers.values()) + PMRelease(paper); + // Releasing the session appears to also release the printer + if (m_session) + PMRelease(m_session); + else if (m_printer) + PMRelease(m_printer); +} + +QCocoaPrintDevice *QCocoaPrintDevice::clone() +{ + return new QCocoaPrintDevice(*this); +} + +bool QCocoaPrintDevice::operator==(const QCocoaPrintDevice &other) const +{ + return (m_id == other.m_id); +} + +bool QCocoaPrintDevice::isValid() const +{ + return m_printer ? true : false; +} + +bool QCocoaPrintDevice::isDefault() const +{ + return PMPrinterIsDefault(m_printer); +} + +QPrint::DeviceState QCocoaPrintDevice::state() const +{ + PMPrinterState state; + if (PMPrinterGetState(m_printer, &state) == noErr) { + if (state == kPMPrinterIdle) + return QPrint::Idle; + else if (state == kPMPrinterProcessing) + return QPrint::Active; + else if (state == kPMPrinterStopped) + return QPrint::Error; + } + return QPrint::Error; +} + +QPageSize QCocoaPrintDevice::createPageSize(const PMPaper &paper) const +{ + QCFString key; + double width; + double height; + QCFString localizedName; + if (PMPaperGetPPDPaperName(paper, &key) == noErr + && PMPaperGetWidth(paper, &width) == noErr + && PMPaperGetHeight(paper, &height) == noErr + && PMPaperCreateLocalizedName(paper, m_printer, &localizedName) == noErr) { + return(QPlatformPrintDevice::createPageSize(key, QSize(width, height), localizedName)); + } + return QPageSize(); +} + +void QCocoaPrintDevice::loadPageSizes() const +{ + m_pageSizes.clear(); + foreach (PMPaper paper, m_macPapers.values()) + PMRelease(paper); + m_macPapers.clear(); + m_printableMargins.clear(); + CFArrayRef paperSizes; + if (PMPrinterGetPaperList(m_printer, &paperSizes) == noErr) { + int count = CFArrayGetCount(paperSizes); + for (int i = 0; i < count; ++i) { + PMPaper paper = static_cast<PMPaper>(const_cast<void *>(CFArrayGetValueAtIndex(paperSizes, i))); + QPageSize pageSize = createPageSize(paper); + if (pageSize.isValid()) { + m_pageSizes.append(pageSize); + PMRetain(paper); + m_macPapers.insert(pageSize.key(), paper); + PMPaperMargins printMargins; + PMPaperGetMargins(paper, &printMargins); + m_printableMargins.insert(pageSize.key(), QMarginsF(printMargins.left, printMargins.top, + printMargins.right, printMargins.bottom)); + } + } + } + m_havePageSizes = true; +} + +QPageSize QCocoaPrintDevice::defaultPageSize() const +{ + QPageSize pageSize; + PMPageFormat pageFormat; + PMPaper paper; + if (PMCreatePageFormat(&pageFormat) == noErr + && PMSessionDefaultPageFormat(m_session, pageFormat) == noErr + && PMGetPageFormatPaper(pageFormat, &paper) == noErr) { + pageSize = createPageSize(paper); + PMRelease(pageFormat); + } + return pageSize; +} + +QMarginsF QCocoaPrintDevice::printableMargins(const QPageSize &pageSize, + QPageLayout::Orientation orientation, + int resolution) const +{ + Q_UNUSED(orientation) + Q_UNUSED(resolution) + if (!m_havePageSizes) + loadPageSizes(); + if (m_printableMargins.contains(pageSize.key())) + return m_printableMargins.value(pageSize.key()); + return m_customMargins; +} + +void QCocoaPrintDevice::loadResolutions() const +{ + m_resolutions.clear(); + UInt32 count; + if (PMPrinterGetPrinterResolutionCount(m_printer, &count) == noErr) { + // 1-based index + for (UInt32 i = 1; i <= count; ++i) { + PMResolution resolution; + if (PMPrinterGetIndexedPrinterResolution(m_printer, i, &resolution) == noErr) + m_resolutions.append(int(resolution.hRes)); + } + } + m_haveResolutions = true; +} + +int QCocoaPrintDevice::defaultResolution() const +{ + int defaultResolution = 72; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + PMResolution resolution; + if (PMSessionDefaultPrintSettings(m_session, settings) == noErr + && PMPrinterGetOutputResolution(m_printer, settings, &resolution) == noErr) { + // PMPrinterGetOutputResolution usually fails with -9589 kPMKeyNotFound as not set in PPD + defaultResolution = int(resolution.hRes); + } + PMRelease(settings); + } + // If no value returned (usually means not set in PPD) then use supported resolutions which + // OSX will have populated with at least one default value (but why not returned by call?) + if (defaultResolution <= 0) { + if (!m_haveResolutions) + loadResolutions(); + if (m_resolutions.count() > 0) + return m_resolutions.at(0); // First value or highest? Only likely to be one anyway. + return 72; // TDOD More sensible default value??? + } + return defaultResolution; +} + +void QCocoaPrintDevice::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 QCocoaPrintDevice::defaultInputSlot() const +{ + // No native api to query, use PPD directly + // 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 QCocoaPrintDevice::loadOutputBins() const +{ + // No native api to query, use PPD directly + // 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 QCocoaPrintDevice::defaultOutputBin() const +{ + // No native api to query, use PPD directly + // 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 QCocoaPrintDevice::loadDuplexModes() const +{ + // No native api to query, use PPD directly + // 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 QCocoaPrintDevice::defaultDuplexMode() const +{ + QPrint::DuplexMode defaultMode = QPrint::DuplexNone; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + PMDuplexMode duplexMode; + if (PMSessionDefaultPrintSettings(m_session, settings) == noErr + && PMGetDuplex(settings, &duplexMode) == noErr) { + defaultMode = macToDuplexMode(duplexMode); + } + PMRelease(settings); + } + return defaultMode; +} + +void QCocoaPrintDevice::loadColorModes() const +{ + // No native api to query, use PPD directly + m_colorModes.clear(); + m_colorModes.append(QPrint::GrayScale); + if (!m_ppd || (m_ppd && m_ppd->color_device)) + m_colorModes.append(QPrint::Color); + m_haveColorModes = true; +} + +QPrint::ColorMode QCocoaPrintDevice::defaultColorMode() const +{ + // No native api to query, use PPD directly + // 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 QCocoaPrintDevice::loadMimeTypes() const +{ + // TODO Check how settings affect returned list + m_mimeTypes.clear(); + QMimeDatabase db; + PMPrintSettings settings; + if (PMCreatePrintSettings(&settings) == noErr) { + CFArrayRef mimeTypes; + if (PMPrinterGetMimeTypes(m_printer, settings, &mimeTypes) == noErr) { + int count = CFArrayGetCount(mimeTypes); + for (int i = 0; i < count; ++i) { + CFStringRef mimeName = static_cast<CFStringRef>(const_cast<void *>(CFArrayGetValueAtIndex(mimeTypes, i))); + QMimeType mimeType = db.mimeTypeForName(QCFString::toQString(mimeName)); + if (mimeType.isValid()) + m_mimeTypes.append(mimeType); + } + } + PMRelease(settings); + } + m_haveMimeTypes = true; +} + +bool QCocoaPrintDevice::openPpdFile() +{ + if (m_ppd) + ppdClose(m_ppd); + m_ppd = 0; + CFURLRef ppdURL = NULL; + char ppdPath[MAXPATHLEN]; + if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr + && ppdURL != NULL + && CFURLGetFileSystemRepresentation(ppdURL, true, (UInt8*)ppdPath, sizeof(ppdPath))) { + m_ppd = ppdOpenFile(ppdPath); + } + CFRelease(ppdURL); + return m_ppd ? true : false; +} + +PMPrinter QCocoaPrintDevice::macPrinter() const +{ + return m_printer; +} + +// Returns a cached printer PMPaper, or creates and caches a new custom PMPaper +// Caller should never release a cached PMPaper! +PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const +{ + if (!m_havePageSizes) + loadPageSizes(); + // If keys match, then is a supported size or an existing custom size + if (m_macPapers.contains(pageSize.key())) + return m_macPapers.value(pageSize.key()); + // For any other page size, whether custom or just unsupported, needs to be a custom PMPaper + PMPaper paper = 0; + PMPaperMargins paperMargins; + paperMargins.left = m_customMargins.left(); + paperMargins.right = m_customMargins.right(); + paperMargins.top = m_customMargins.top(); + paperMargins.bottom = m_customMargins.bottom(); + PMPaperCreateCustom(m_printer, QCFString(pageSize.key()), QCFString(pageSize.name()), + pageSize.sizePoints().width(), pageSize.sizePoints().height(), + &paperMargins, &paper); + m_macPapers.insert(pageSize.key(), paper); + return paper; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index a48790ef34..4c6a99ec9d 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -58,6 +58,10 @@ public: QList<QPrinter::PaperSize> supportedPaperSizes(const QPrinterInfo &) const Q_DECL_OVERRIDE; QList<QPair<QString, QSizeF> > supportedSizesWithNames(const QPrinterInfo &) const Q_DECL_OVERRIDE; + QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; + QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; + QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; + QList<QPrinterInfo> availablePrinters() Q_DECL_OVERRIDE; QPrinterInfo printerInfo(const QString &printerName) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm index cb2aa7132b..70c83498e1 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.mm @@ -42,11 +42,13 @@ #include "qcocoaprintersupport.h" #ifndef QT_NO_PRINTER +#include "qcocoaprintdevice.h" #include "qprintengine_mac_p.h" #include <QtPrintSupport/QPrinter> #include <QtPrintSupport/QPrinterInfo> #include <private/qprinterinfo_p.h> +#include <private/qprintdevice_p.h> QCocoaPrinterSupport::QCocoaPrinterSupport() { } @@ -69,6 +71,39 @@ QPaintEngine *QCocoaPrinterSupport::createPaintEngine(QPrintEngine *printEngine, return static_cast<QMacPrintEngine *>(printEngine); } +QPrintDevice QCocoaPrinterSupport::createPrintDevice(const QString &id) +{ + return QPlatformPrinterSupport::createPrintDevice(new QCocoaPrintDevice(id)); +} + +QStringList QCocoaPrinterSupport::availablePrintDeviceIds() const +{ + QStringList list; + QCFType<CFArrayRef> printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i))); + list.append(QCFString::toQString(PMPrinterGetID(printer))); + } + } + return list; +} + +QString QCocoaPrinterSupport::defaultPrintDeviceId() const +{ + QCFType<CFArrayRef> printerList; + if (PMServerCreatePrinterList(kPMServerLocal, &printerList) == noErr) { + CFIndex count = CFArrayGetCount(printerList); + for (CFIndex i = 0; i < count; ++i) { + PMPrinter printer = static_cast<PMPrinter>(const_cast<void *>(CFArrayGetValueAtIndex(printerList, i))); + if (PMPrinterIsDefault(printer)) + return QCFString::toQString(PMPrinterGetID(printer)); + } + } + return QString(); +} + QList<QPrinter::PaperSize> QCocoaPrinterSupport::supportedPaperSizes(const QPrinterInfo &printerInfo) const { QList<QPrinter::PaperSize> returnValue; |