5#include <ApplicationServices/ApplicationServices.h>
10#include <QtCore/qmimedatabase.h>
14#include <QtCore/private/qcore_mac_p.h>
23#pragma clang diagnostic push
24#pragma clang diagnostic ignored "-Wdeprecated-declarations"
28 if (mode == kPMDuplexTumble)
29 return QPrint::DuplexShortSide;
30 else if (mode == kPMDuplexNoTumble)
31 return QPrint::DuplexLongSide;
33 return QPrint::DuplexNone;
36QCocoaPrintDevice::QCocoaPrintDevice()
37 : QPlatformPrintDevice(),
44QCocoaPrintDevice::QCocoaPrintDevice(
const QString &id)
45 : QPlatformPrintDevice(id),
51 m_printer = PMPrinterCreateFromPrinterID(id.toCFString());
53 m_name = QString::fromCFString(PMPrinterGetName(m_printer));
54 m_location = QString::fromCFString(PMPrinterGetLocation(m_printer));
55 CFStringRef cfMakeAndModel;
56 if (PMPrinterGetMakeAndModelName(m_printer, &cfMakeAndModel) == noErr)
57 m_makeAndModel = QString::fromCFString(cfMakeAndModel);
59 if (PMPrinterIsRemote(m_printer, &isRemote) == noErr)
60 m_isRemote = isRemote;
61 if (PMCreateSession(&m_session) == noErr)
62 PMSessionSetCurrentPMPrinter(m_session, m_printer);
67 m_supportsMultipleCopies = !m_ppd->manual_copies;
69 ppd_option_t *collate = ppdFindOption(m_ppd,
"Collate");
71 m_supportsCollateCopies =
true;
72 m_supportsCustomPageSizes = m_ppd->custom_max[0] > 0 && m_ppd->custom_max[1] > 0;
73 m_minimumPhysicalPageSize = QSize(m_ppd->custom_min[0], m_ppd->custom_min[1]);
74 m_maximumPhysicalPageSize = QSize(m_ppd->custom_max[0], m_ppd->custom_max[1]);
75 m_customMargins = QMarginsF(m_ppd->custom_margins[0], m_ppd->custom_margins[3],
76 m_ppd->custom_margins[2], m_ppd->custom_margins[1]);
82QCocoaPrintDevice::~QCocoaPrintDevice()
86 for (PMPaper paper : m_macPapers)
95bool QCocoaPrintDevice::isValid()
const
97 return m_printer ?
true :
false;
100bool QCocoaPrintDevice::isDefault()
const
102 return PMPrinterIsDefault(m_printer);
105QPrint::DeviceState QCocoaPrintDevice::state()
const
107 PMPrinterState state;
108 if (PMPrinterGetState(m_printer, &state) == noErr) {
109 if (state == kPMPrinterIdle)
111 else if (state == kPMPrinterProcessing)
112 return QPrint::Active;
113 else if (state == kPMPrinterStopped)
114 return QPrint::Error;
116 return QPrint::Error;
119QPageSize QCocoaPrintDevice::createPageSize(
const PMPaper &paper)
const
124 CFStringRef localizedName;
125 if (PMPaperGetPPDPaperName(paper, &key) == noErr
126 && PMPaperGetWidth(paper, &width) == noErr
127 && PMPaperGetHeight(paper, &height) == noErr
128 && PMPaperCreateLocalizedName(paper, m_printer, &localizedName) == noErr) {
129 QPageSize pageSize = QPlatformPrintDevice::createPageSize(QString::fromCFString(key),QSize(width, height),
130 QString::fromCFString(localizedName));
131 CFRelease(localizedName);
137void QCocoaPrintDevice::loadPageSizes()
const
140 for (PMPaper paper : m_macPapers)
143 m_printableMargins.clear();
144 CFArrayRef paperSizes;
145 if (PMPrinterGetPaperList(m_printer, &paperSizes) == noErr) {
146 int count = CFArrayGetCount(paperSizes);
147 for (
int i = 0; i < count; ++i) {
148 PMPaper paper =
static_cast<PMPaper>(
const_cast<
void *>(CFArrayGetValueAtIndex(paperSizes, i)));
149 QPageSize pageSize = createPageSize(paper);
150 if (pageSize.isValid()) {
151 m_pageSizes.append(pageSize);
153 m_macPapers.insert(pageSize.key(), paper);
154 PMPaperMargins printMargins;
155 PMPaperGetMargins(paper, &printMargins);
156 m_printableMargins.insert(pageSize.key(), QMarginsF(printMargins.left, printMargins.top,
157 printMargins.right, printMargins.bottom));
161 m_havePageSizes =
true;
164QPageSize QCocoaPrintDevice::defaultPageSize()
const
167 PMPageFormat pageFormat;
169 if (PMCreatePageFormat(&pageFormat) == noErr) {
170 if (PMSessionDefaultPageFormat(m_session, pageFormat) == noErr
171 && PMGetPageFormatPaper(pageFormat, &paper) == noErr) {
172 pageSize = createPageSize(paper);
174 PMRelease(pageFormat);
179QMarginsF QCocoaPrintDevice::printableMargins(
const QPageSize &pageSize,
180 QPageLayout::Orientation orientation,
181 int resolution)
const
183 Q_UNUSED(orientation);
184 Q_UNUSED(resolution);
185 if (!m_havePageSizes)
187 if (m_printableMargins.contains(pageSize.key()))
188 return m_printableMargins.value(pageSize.key());
189 return m_customMargins;
192void QCocoaPrintDevice::loadResolutions()
const
194 m_resolutions.clear();
196 if (PMPrinterGetPrinterResolutionCount(m_printer, &count) == noErr) {
198 for (UInt32 i = 1; i <= count; ++i) {
199 PMResolution resolution;
200 if (PMPrinterGetIndexedPrinterResolution(m_printer, i, &resolution) == noErr)
201 m_resolutions.append(
int(resolution.hRes));
204 m_haveResolutions =
true;
207int QCocoaPrintDevice::defaultResolution()
const
209 int defaultResolution = 72;
210 PMPrintSettings settings;
211 if (PMCreatePrintSettings(&settings) == noErr) {
212 PMResolution resolution;
213 if (PMSessionDefaultPrintSettings(m_session, settings) == noErr
214 && PMPrinterGetOutputResolution(m_printer, settings, &resolution) == noErr) {
216 defaultResolution =
int(resolution.hRes);
222 if (defaultResolution <= 0) {
223 if (!m_haveResolutions)
225 if (m_resolutions.count() > 0)
226 return m_resolutions.at(0);
229 return defaultResolution;
232void QCocoaPrintDevice::loadInputSlots()
const
239 m_inputSlots.clear();
241 ppd_option_t *inputSlots = ppdFindOption(m_ppd,
"InputSlot");
243 for (
int i = 0; i < inputSlots->num_choices; ++i)
244 m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[i]));
247 if (m_inputSlots.size() == 0) {
248 inputSlots = ppdFindOption(m_ppd,
"DefaultInputSlot");
250 m_inputSlots.append(QPrintUtils::ppdChoiceToInputSlot(inputSlots->choices[0]));
254 if (m_inputSlots.size() == 0)
255 m_inputSlots.append(QPlatformPrintDevice::defaultInputSlot());
256 m_haveInputSlots =
true;
259QPrint::InputSlot QCocoaPrintDevice::defaultInputSlot()
const
265 ppd_option_t *inputSlot = ppdFindOption(m_ppd,
"DefaultInputSlot");
267 return QPrintUtils::ppdChoiceToInputSlot(inputSlot->choices[0]);
269 ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd,
"InputSlot");
271 return QPrintUtils::ppdChoiceToInputSlot(*defaultChoice);
274 return QPlatformPrintDevice::defaultInputSlot();
277void QCocoaPrintDevice::loadOutputBins()
const
281 m_outputBins.clear();
283 ppd_option_t *outputBins = ppdFindOption(m_ppd,
"OutputBin");
285 for (
int i = 0; i < outputBins->num_choices; ++i)
286 m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[i]));
289 if (m_outputBins.size() == 0) {
290 outputBins = ppdFindOption(m_ppd,
"DefaultOutputBin");
292 m_outputBins.append(QPrintUtils::ppdChoiceToOutputBin(outputBins->choices[0]));
296 if (m_outputBins.size() == 0)
297 m_outputBins.append(QPlatformPrintDevice::defaultOutputBin());
298 m_haveOutputBins =
true;
301QPrint::OutputBin QCocoaPrintDevice::defaultOutputBin()
const
307 ppd_option_t *outputBin = ppdFindOption(m_ppd,
"DefaultOutputBin");
309 return QPrintUtils::ppdChoiceToOutputBin(outputBin->choices[0]);
311 ppd_choice_t *defaultChoice = ppdFindMarkedChoice(m_ppd,
"OutputBin");
313 return QPrintUtils::ppdChoiceToOutputBin(*defaultChoice);
316 return QPlatformPrintDevice::defaultOutputBin();
319void QCocoaPrintDevice::loadDuplexModes()
const
324 m_duplexModes.clear();
326 ppd_option_t *duplexModes = ppdFindOption(m_ppd,
"Duplex");
328 for (
int i = 0; i < duplexModes->num_choices; ++i)
329 m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[i].choice));
332 if (m_duplexModes.size() == 0) {
333 duplexModes = ppdFindOption(m_ppd,
"DefaultDuplex");
335 m_duplexModes.append(QPrintUtils::ppdChoiceToDuplexMode(duplexModes->choices[0].choice));
339 if (m_duplexModes.size() == 0 || !m_duplexModes.contains(QPrint::DuplexNone))
340 m_duplexModes.append(QPrint::DuplexNone);
342 if (m_duplexModes.contains(QPrint::DuplexLongSide) && m_duplexModes.contains(QPrint::DuplexShortSide))
343 m_duplexModes.append(QPrint::DuplexAuto);
344 m_haveDuplexModes =
true;
347QPrint::DuplexMode QCocoaPrintDevice::defaultDuplexMode()
const
349 QPrint::DuplexMode defaultMode = QPrint::DuplexNone;
350 PMPrintSettings settings;
351 if (PMCreatePrintSettings(&settings) == noErr) {
352 PMDuplexMode duplexMode;
353 if (PMSessionDefaultPrintSettings(m_session, settings) == noErr
354 && PMGetDuplex(settings, &duplexMode) == noErr) {
355 defaultMode = macToDuplexMode(duplexMode);
362void QCocoaPrintDevice::loadColorModes()
const
365 m_colorModes.clear();
366 m_colorModes.append(QPrint::GrayScale);
367 if (!m_ppd || (m_ppd && m_ppd->color_device))
368 m_colorModes.append(QPrint::Color);
369 m_haveColorModes =
true;
372QPrint::ColorMode QCocoaPrintDevice::defaultColorMode()
const
378 if (m_ppd && supportedColorModes().contains(QPrint::Color)) {
379 ppd_option_t *colorModel = ppdFindOption(m_ppd,
"DefaultColorModel");
381 colorModel = ppdFindOption(m_ppd,
"ColorModel");
382 if (!colorModel || qstrcmp(colorModel->defchoice,
"Gray") != 0)
383 return QPrint::Color;
385 return QPrint::GrayScale;
388#if QT_CONFIG(mimetype)
389void QCocoaPrintDevice::loadMimeTypes()
const
394 PMPrintSettings settings;
395 if (PMCreatePrintSettings(&settings) == noErr) {
396 CFArrayRef mimeTypes;
397 if (PMPrinterGetMimeTypes(m_printer, settings, &mimeTypes) == noErr) {
398 int count = CFArrayGetCount(mimeTypes);
399 for (
int i = 0; i < count; ++i) {
400 CFStringRef mimeName =
static_cast<CFStringRef>(
const_cast<
void *>(CFArrayGetValueAtIndex(mimeTypes, i)));
401 QMimeType mimeType = db.mimeTypeForName(QString::fromCFString(mimeName));
402 if (mimeType.isValid())
403 m_mimeTypes.append(mimeType);
408 m_haveMimeTypes =
true;
412bool QCocoaPrintDevice::openPpdFile()
417 CFURLRef ppdURL =
nullptr;
418 char ppdPath[MAXPATHLEN];
419 if (PMPrinterCopyDescriptionURL(m_printer, kPMPPDDescriptionType, &ppdURL) == noErr
421 if (CFURLGetFileSystemRepresentation(ppdURL,
true, (UInt8*)ppdPath,
sizeof(ppdPath)))
422 m_ppd = ppdOpenFile(ppdPath);
425 return m_ppd ?
true :
false;
428PMPrinter QCocoaPrintDevice::macPrinter()
const
435PMPaper QCocoaPrintDevice::macPaper(
const QPageSize &pageSize)
const
437 if (!m_havePageSizes)
440 if (m_macPapers.contains(pageSize.key()))
441 return m_macPapers.value(pageSize.key());
443 PMPaper paper =
nullptr;
444 PMPaperMargins paperMargins;
445 paperMargins.left = m_customMargins.left();
446 paperMargins.right = m_customMargins.right();
447 paperMargins.top = m_customMargins.top();
448 paperMargins.bottom = m_customMargins.bottom();
449 PMPaperCreateCustom(m_printer, QCFString(pageSize.key()), QCFString(pageSize.name()),
450 pageSize.sizePoints().width(), pageSize.sizePoints().height(),
451 &paperMargins, &paper);
452 m_macPapers.insert(pageSize.key(), paper);
456#pragma clang diagnostic pop
static QT_BEGIN_NAMESPACE QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode)