4#include <AppKit/AppKit.h>
9#include <QtCore/qtemporarydir.h>
10#include <QtCore/private/qcore_mac_p.h>
11#include <QtWidgets/private/qapplication_p.h>
12#include <QtPrintSupport/qprinter.h>
13#include <QtPrintSupport/qprintengine.h>
14#include <qpa/qplatformprintdevice.h>
16#include <QtPrintSupport/private/qprintengine_mac_p.h>
20using namespace Qt::StringLiterals;
26 Q_DECLARE_PUBLIC(QPrintDialog)
46@
class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
48@interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
51@implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) {
52 NSPrintInfo *printInfo;
55- (instancetype)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
57 if ((self = [self init])) {
58 printInfo = nsPrintInfo;
63- (
void)printPanelDidEnd:(NSPrintPanel *)printPanel
64 returnCode:(
int)returnCode contextInfo:(
void *)contextInfo
68 QPrintDialog *dialog =
static_cast<QPrintDialog *>(contextInfo);
69 QPrinter *printer = dialog->printer();
71 if (returnCode == NSModalResponseOK) {
72 PMPrintSession session =
static_cast<PMPrintSession>(printInfo.PMPrintSession);
73 PMPrintSettings settings =
static_cast<PMPrintSettings>(printInfo.PMPrintSettings);
75 UInt32 frompage, topage;
76 PMGetFirstPage(settings, &frompage);
77 PMGetLastPage(settings, &topage);
78 topage = qMin(UInt32(INT_MAX), topage);
79 dialog->setFromTo(frompage, topage);
84 if (dialog->fromPage() == 1 && dialog->toPage() == INT_MAX) {
85 dialog->setPrintRange(QPrintDialog::AllPages);
86 printer->setPageRanges(QPageRanges());
88 dialog->setPrintRange(QPrintDialog::PageRange);
91 if (dialog->maxPage() < dialog->toPage())
92 dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
96 PMDestinationType dest;
97 PMSessionGetDestinationType(session, settings, &dest);
98 if (dest == kPMDestinationFile) {
99 QCFType<CFURLRef> file;
100 PMSessionCopyDestinationLocation(session, settings, &file);
101 UInt8 localFile[2048];
102 CFURLGetFileSystemRepresentation(file,
true, localFile,
sizeof(localFile));
103 auto outputFile = QFileInfo(QString::fromUtf8(
reinterpret_cast<
const char *>(localFile)));
104 if (outputFile.suffix() ==
"pdf"_L1)
105 printer->setOutputFileName(outputFile.absoluteFilePath());
107 qWarning() <<
"Can not print to file type" << outputFile.suffix();
108 }
else if (dest == kPMDestinationPreview) {
109 static QTemporaryDir printPreviews;
110 auto documentName = printer->docName();
111 if (documentName.isEmpty())
112 documentName = QGuiApplication::applicationDisplayName();
113 auto fileName = printPreviews.filePath(QString(
"%1.pdf"_L1).arg(documentName));
114 printer->setOutputFileName(fileName);
120 dispatch_async(dispatch_get_main_queue(), ^{
121 [NSWorkspace.sharedWorkspace openURL:[NSURL fileURLWithPath:fileName.toNSString()]];
123 }
else if (dest == kPMDestinationProcessPDF) {
124 qWarning(
"Printing workflows are not supported");
125 }
else if (dest == kPMDestinationPrinter) {
126 PMPrinter macPrinter;
127 PMSessionGetCurrentPrinter(session, &macPrinter);
128 QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)).trimmed();
129 if (printer->printerName() != printerId)
130 printer->setPrinterName(printerId);
137 PMPageFormat pageFormat =
static_cast<PMPageFormat>([printInfo PMPageFormat]);
139 PMGetPageFormatPaper(pageFormat, &paper);
140 PMOrientation orientation;
141 PMGetOrientation(pageFormat, &orientation);
147 PMPaperGetPPDPaperName(paper, &key);
148 if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
149 QString ppdKey = QString::fromCFString(key);
150 if (ppdKey.isEmpty()) {
157 if (QLocale().measurementSystem() == QLocale::MetricSystem) {
158 QSizeF sizef = QSizeF(width, height) / qt_pointMultiplier(QPageLayout::Millimeter);
160 pageSize = QPageSize(sizef.toSize(), QPageSize::Millimeter);
162 qreal multiplier = qt_pointMultiplier(QPageLayout::Inch);
163 const int w = qRound(width * 100 / multiplier);
164 const int h = qRound(height * 100 / multiplier);
165 pageSize = QPageSize(QSizeF(w / 100.0, h / 100.0), QPageSize::Inch);
168 pageSize = QPlatformPrintDevice::createPageSize(ppdKey, QSize(width, height), QString());
171 if (pageSize.isValid() && !pageSize.isEquivalentTo(printer->pageLayout().pageSize()))
172 printer->setPageSize(pageSize);
173 printer->setPageOrientation(orientation == kPMLandscape ? QPageLayout::Landscape : QPageLayout::Portrait);
175 dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected);
182void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
186 if (printer->outputFormat() == QPrinter::NativeFormat) {
187 printInfo =
static_cast<QMacPrintEngine *>(printer->printEngine())->printInfo();
190 const QPageLayout pageLayout = printer->pageLayout();
192 const auto dictionary = [NSPrintInfo.sharedPrintInfo dictionary];
193 printInfo = [[NSPrintInfo alloc] initWithDictionary:dictionary];
194 printInfo.orientation = pageLayout.orientation() == QPageLayout::Landscape
195 ? NSPaperOrientationLandscape : NSPaperOrientationPortrait;
196 printInfo.paperSize = pageLayout.pageSize().size(QPageSize::Point).toCGSize();
204 PMPrintSettings settings =
static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
205 PMSetPageRange(settings, q->minPage(), q->maxPage());
206 if (q->printRange() == QAbstractPrintDialog::PageRange) {
207 PMSetFirstPage(settings, q->fromPage(),
false);
208 PMSetLastPage(settings, q->toPage(),
false);
210 [printInfo updateFromPMPrintSettings];
212 QPrintDialog::PrintDialogOptions qtOptions = q->options();
213 NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies;
214 if (qtOptions & QPrintDialog::PrintPageRange)
215 macOptions |= NSPrintPanelShowsPageRange;
216 if (qtOptions & QPrintDialog::PrintShowPageSize)
217 macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory
218 | NSPrintPanelShowsOrientation;
220 printPanel = [NSPrintPanel printPanel];
222 [printPanel setOptions:macOptions];
227 qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
229 QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] initWithNSPrintInfo:printInfo];
230 if (modality == Qt::ApplicationModal || !q->parentWidget()) {
231 if (modality == Qt::NonModal)
232 qWarning(
"QPrintDialog is required to be modal on OS X");
235 (
void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
236 "clearCurrentThreadCocoaEventDispatcherInterruptFlag");
238 int rval = [printPanel runModalWithPrintInfo:printInfo];
239 [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
241 Q_ASSERT(q->window());
242 QWindow *parentWindow = q->window()->windowHandle();
243 NSWindow *window =
static_cast<NSWindow *>(qApp->platformNativeInterface()->nativeResourceForWindow(
"nswindow", parentWindow));
244 [printPanel beginSheetWithPrintInfo:printInfo
245 modalForWindow:window
247 didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
256 [printPanel release];
260QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
261 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
263 setAttribute(Qt::WA_DontShowOnScreen);
266QPrintDialog::QPrintDialog(QWidget *parent)
267 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), 0, parent)
269 setAttribute(Qt::WA_DontShowOnScreen);
272QPrintDialog::~QPrintDialog()
277int QPrintDialog::exec()
281 QDialog::setVisible(
true);
283 QMacAutoReleasePool pool;
284 d->openCocoaPrintPanel(Qt::ApplicationModal);
285 d->closeCocoaPrintPanel();
287 QDialog::setVisible(
false);
294
295
296void QPrintDialog::setVisible(
bool visible)
300 bool isCurrentlyVisible = (d->printPanel != 0);
302 if (!visible == !isCurrentlyVisible)
305 if (d->printer->outputFormat() != QPrinter::NativeFormat)
308 QDialog::setVisible(visible);
311 Qt::WindowModality modality = windowModality();
312 if (modality == Qt::NonModal) {
314 modality = parentWidget() ? Qt::WindowModal : Qt::ApplicationModal;
316 d->openCocoaPrintPanel(modality);
320 d->closeCocoaPrintPanel();
328#include "moc_qprintdialog.cpp"
QPrintDialog * printDialog()
void closeCocoaPrintPanel()
NSPrintPanel * printPanel
Combined button and popup list for selecting options.
qreal qt_pointMultiplier(QPageLayout::Unit unit)