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>
15#include <qpa/qplatformwindow_p.h>
17#include <QtPrintSupport/private/qprintengine_mac_p.h>
21using namespace Qt::StringLiterals;
27 Q_DECLARE_PUBLIC(QPrintDialog)
47@
class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
49@interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
52@implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) {
53 NSPrintInfo *printInfo;
56- (instancetype)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
58 if ((self = [self init])) {
59 printInfo = nsPrintInfo;
64- (
void)printPanelDidEnd:(NSPrintPanel *)printPanel
65 returnCode:(
int)returnCode contextInfo:(
void *)contextInfo
69 QPrintDialog *dialog =
static_cast<QPrintDialog *>(contextInfo);
70 QPrinter *printer = dialog->printer();
72 if (returnCode == NSModalResponseOK) {
73 PMPrintSession session =
static_cast<PMPrintSession>(printInfo.PMPrintSession);
74 PMPrintSettings settings =
static_cast<PMPrintSettings>(printInfo.PMPrintSettings);
76 UInt32 frompage, topage;
77 PMGetFirstPage(settings, &frompage);
78 PMGetLastPage(settings, &topage);
79 topage = qMin(UInt32(INT_MAX), topage);
80 dialog->setFromTo(frompage, topage);
85 if (dialog->fromPage() == 1 && dialog->toPage() == INT_MAX) {
86 dialog->setPrintRange(QPrintDialog::AllPages);
87 printer->setPageRanges(QPageRanges());
89 dialog->setPrintRange(QPrintDialog::PageRange);
92 if (dialog->maxPage() < dialog->toPage())
93 dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
97 PMDestinationType dest;
98 PMSessionGetDestinationType(session, settings, &dest);
99 if (dest == kPMDestinationFile) {
100 QCFType<CFURLRef> file;
101 PMSessionCopyDestinationLocation(session, settings, &file);
102 UInt8 localFile[2048];
103 CFURLGetFileSystemRepresentation(file,
true, localFile,
sizeof(localFile));
104 auto outputFile = QFileInfo(QString::fromUtf8(
reinterpret_cast<
const char *>(localFile)));
105 if (outputFile.suffix() ==
"pdf"_L1)
106 printer->setOutputFileName(outputFile.absoluteFilePath());
108 qWarning() <<
"Can not print to file type" << outputFile.suffix();
109 }
else if (dest == kPMDestinationPreview) {
110 static QTemporaryDir printPreviews;
111 auto documentName = printer->docName();
112 if (documentName.isEmpty())
113 documentName = QGuiApplication::applicationDisplayName();
114 auto fileName = printPreviews.filePath(QString(
"%1.pdf"_L1).arg(documentName));
115 printer->setOutputFileName(fileName);
121 dispatch_async(dispatch_get_main_queue(), ^{
122 [NSWorkspace.sharedWorkspace openURL:[NSURL fileURLWithPath:fileName.toNSString()]];
124 }
else if (dest == kPMDestinationProcessPDF) {
125 qWarning(
"Printing workflows are not supported");
126 }
else if (dest == kPMDestinationPrinter) {
127 PMPrinter macPrinter;
128 PMSessionGetCurrentPrinter(session, &macPrinter);
129 QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)).trimmed();
130 if (printer->printerName() != printerId)
131 printer->setPrinterName(printerId);
138 PMPageFormat pageFormat =
static_cast<PMPageFormat>([printInfo PMPageFormat]);
140 PMGetPageFormatPaper(pageFormat, &paper);
141 PMOrientation orientation;
142 PMGetOrientation(pageFormat, &orientation);
148 PMPaperGetPPDPaperName(paper, &key);
149 if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
150 QString ppdKey = QString::fromCFString(key);
151 if (ppdKey.isEmpty()) {
158 if (QLocale().measurementSystem() == QLocale::MetricSystem) {
159 QSizeF sizef = QSizeF(width, height) / qt_pointMultiplier(QPageLayout::Millimeter);
161 pageSize = QPageSize(sizef.toSize(), QPageSize::Millimeter);
163 qreal multiplier = qt_pointMultiplier(QPageLayout::Inch);
164 const int w = qRound(width * 100 / multiplier);
165 const int h = qRound(height * 100 / multiplier);
166 pageSize = QPageSize(QSizeF(w / 100.0, h / 100.0), QPageSize::Inch);
169 pageSize = QPlatformPrintDevice::createPageSize(ppdKey, QSize(width, height), QString());
172 if (pageSize.isValid() && !pageSize.isEquivalentTo(printer->pageLayout().pageSize()))
173 printer->setPageSize(pageSize);
174 printer->setPageOrientation(orientation == kPMLandscape ? QPageLayout::Landscape : QPageLayout::Portrait);
176 dialog->done((returnCode == NSModalResponseOK) ? QDialog::Accepted : QDialog::Rejected);
183void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
187 if (printer->outputFormat() == QPrinter::NativeFormat) {
188 printInfo =
static_cast<QMacPrintEngine *>(printer->printEngine())->printInfo();
191 const QPageLayout pageLayout = printer->pageLayout();
193 const auto dictionary = [NSPrintInfo.sharedPrintInfo dictionary];
194 printInfo = [[NSPrintInfo alloc] initWithDictionary:dictionary];
195 printInfo.orientation = pageLayout.orientation() == QPageLayout::Landscape
196 ? NSPaperOrientationLandscape : NSPaperOrientationPortrait;
197 printInfo.paperSize = pageLayout.pageSize().size(QPageSize::Point).toCGSize();
205 PMPrintSettings settings =
static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
206 PMSetPageRange(settings, q->minPage(), q->maxPage());
207 if (q->printRange() == QAbstractPrintDialog::PageRange) {
208 PMSetFirstPage(settings, q->fromPage(),
false);
209 PMSetLastPage(settings, q->toPage(),
false);
211 [printInfo updateFromPMPrintSettings];
213 QPrintDialog::PrintDialogOptions qtOptions = q->options();
214 NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies;
215 if (qtOptions & QPrintDialog::PrintPageRange)
216 macOptions |= NSPrintPanelShowsPageRange;
217 if (qtOptions & QPrintDialog::PrintShowPageSize)
218 macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory
219 | NSPrintPanelShowsOrientation;
221 printPanel = [NSPrintPanel printPanel];
223 [printPanel setOptions:macOptions];
228 qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
230 QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] initWithNSPrintInfo:printInfo];
231 if (modality == Qt::ApplicationModal || !q->parentWidget()) {
232 if (modality == Qt::NonModal)
233 qWarning(
"QPrintDialog is required to be modal on OS X");
236 (
void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
237 "clearCurrentThreadCocoaEventDispatcherInterruptFlag");
239 int rval = [printPanel runModalWithPrintInfo:printInfo];
240 [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
242 Q_ASSERT(q->window());
243 QWindow *parentWindow = q->window()->windowHandle();
244 auto *cocoaWindow = parentWindow->nativeInterface<QNativeInterface::Private::QCocoaWindow>();
245 NSWindow *window = cocoaWindow ? cocoaWindow->view().window : nil;
246 [printPanel beginSheetWithPrintInfo:printInfo
247 modalForWindow:window
249 didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
258 [printPanel release];
262QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
263 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), printer, parent)
265 setAttribute(Qt::WA_DontShowOnScreen);
268QPrintDialog::QPrintDialog(QWidget *parent)
269 : QAbstractPrintDialog(*(
new QPrintDialogPrivate), 0, parent)
271 setAttribute(Qt::WA_DontShowOnScreen);
274QPrintDialog::~QPrintDialog()
279int QPrintDialog::exec()
283 QDialog::setVisible(
true);
285 QMacAutoReleasePool pool;
286 d->openCocoaPrintPanel(Qt::ApplicationModal);
287 d->closeCocoaPrintPanel();
289 QDialog::setVisible(
false);
296
297
298void QPrintDialog::setVisible(
bool visible)
302 bool isCurrentlyVisible = (d->printPanel != 0);
304 if (!visible == !isCurrentlyVisible)
307 if (d->printer->outputFormat() != QPrinter::NativeFormat)
310 QDialog::setVisible(visible);
313 Qt::WindowModality modality = windowModality();
314 if (modality == Qt::NonModal) {
316 modality = parentWidget() ? Qt::WindowModal : Qt::ApplicationModal;
318 d->openCocoaPrintPanel(modality);
322 d->closeCocoaPrintPanel();
330#include "moc_qprintdialog.cpp"
QPrintDialog * printDialog()
void closeCocoaPrintPanel()
NSPrintPanel * printPanel
Combined button and popup list for selecting options.
qreal qt_pointMultiplier(QPageLayout::Unit unit)