1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtGui module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #ifndef QT_NO_PRINTDIALOG
44 #include <Cocoa/Cocoa.h>
46 #include "qprintdialog.h"
47 #include "qabstractprintdialog_p.h"
49 #include <QtCore/qhash.h>
50 #include <QtCore/private/qcore_mac_p.h>
51 #include <QtWidgets/private/qapplication_p.h>
52 #include <QtPrintSupport/qprinter.h>
53 #include <QtPrintSupport/qprintengine.h>
57 class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
59 Q_DECLARE_PUBLIC(QPrintDialog)
62 QPrintDialogPrivate() : printInfo(0), printPanel(0)
65 void openCocoaPrintPanel(Qt::WindowModality modality);
66 void closeCocoaPrintPanel();
68 inline QPrintDialog *printDialog() { return q_func(); }
70 NSPrintInfo *printInfo;
71 NSPrintPanel *printPanel;
79 @class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
81 @interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
83 NSPrintInfo *printInfo;
85 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo;
86 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
87 returnCode:(int)returnCode contextInfo:(void *)contextInfo;
90 @implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate)
91 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
93 if (self = [super init]) {
94 printInfo = nsPrintInfo;
98 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
99 returnCode:(int)returnCode contextInfo:(void *)contextInfo
101 Q_UNUSED(printPanel);
103 QPrintDialog *dialog = static_cast<QPrintDialog *>(contextInfo);
104 QPrinter *printer = dialog->printer();
106 if (returnCode == NSOKButton) {
107 PMPrintSession session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
108 PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
110 UInt32 frompage, topage;
111 PMGetFirstPage(settings, &frompage);
112 PMGetLastPage(settings, &topage);
113 topage = qMin(UInt32(INT_MAX), topage);
114 dialog->setFromTo(frompage, topage);
116 // OK, I need to map these values back let's see
117 // If from is 1 and to is INT_MAX, then print it all
118 // (Apologies to the folks with more than INT_MAX pages)
119 if (dialog->fromPage() == 1 && dialog->toPage() == INT_MAX) {
120 dialog->setPrintRange(QPrintDialog::AllPages);
121 dialog->setFromTo(0, 0);
123 dialog->setPrintRange(QPrintDialog::PageRange); // In a way a lie, but it shouldn't hurt.
124 // Carbon hands us back a very large number here even for ALL, set it to max
125 // in that case to follow the behavior of the other print dialogs.
126 if (dialog->maxPage() < dialog->toPage())
127 dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
129 // Keep us in sync with file output
130 PMDestinationType dest;
132 // If the user selected print to file, the session has been
133 // changed behind our back and our d->ep->session object is a
134 // dangling pointer. Update it based on the "current" session
135 PMSessionGetDestinationType(session, settings, &dest);
136 if (dest == kPMDestinationFile) {
137 QCFType<CFURLRef> file;
138 PMSessionCopyDestinationLocation(session, settings, &file);
139 UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
140 CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
141 printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
143 // Keep output format.
144 QPrinter::OutputFormat format;
145 format = printer->outputFormat();
146 printer->setOutputFileName(QString());
147 printer->setOutputFormat(format);
151 dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
157 void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
161 // get the NSPrintInfo from the print engine in the platform plugin
163 (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
164 "NSPrintInfoForPrintEngine",
165 Q_RETURN_ARG(void *, voidp),
166 Q_ARG(QPrintEngine *, printer->printEngine()));
167 printInfo = static_cast<NSPrintInfo *>(voidp);
170 // It seems the only way that PM lets you use all is if the minimum
171 // for the page range is 1. This _kind of_ makes sense if you think about
172 // it. However, calling PMSetFirstPage() or PMSetLastPage() always enforces
174 // get print settings from the platform plugin
175 PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
176 PMSetPageRange(settings, q->minPage(), q->maxPage());
177 if (q->printRange() == QAbstractPrintDialog::PageRange) {
178 PMSetFirstPage(settings, q->fromPage(), false);
179 PMSetLastPage(settings, q->toPage(), false);
181 [printInfo updateFromPMPrintSettings];
183 QPrintDialog::PrintDialogOptions qtOptions = q->options();
184 NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies;
185 if (qtOptions & QPrintDialog::PrintPageRange)
186 macOptions |= NSPrintPanelShowsPageRange;
187 if (qtOptions & QPrintDialog::PrintShowPageSize)
188 macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory
189 | NSPrintPanelShowsOrientation;
191 printPanel = [NSPrintPanel printPanel];
193 [printPanel setOptions:macOptions];
195 QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init];
196 if (modality == Qt::ApplicationModal) {
197 int rval = [printPanel runModalWithPrintInfo:printInfo];
198 [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
200 Q_ASSERT(q->parentWidget());
201 QWindow *parentWindow = q->parentWidget()->windowHandle();
202 NSWindow *window = static_cast<NSWindow *>(qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parentWindow));
203 [printPanel beginSheetWithPrintInfo:printInfo
204 modalForWindow:window
206 didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
211 void QPrintDialogPrivate::closeCocoaPrintPanel()
215 [printPanel release];
219 static bool warnIfNotNative(QPrinter *printer)
221 if (printer->outputFormat() != QPrinter::NativeFormat) {
222 qWarning("QPrintDialog: Cannot be used on non-native printers");
229 QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
230 : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
233 if (!warnIfNotNative(d->printer))
235 setAttribute(Qt::WA_DontShowOnScreen);
238 QPrintDialog::QPrintDialog(QWidget *parent)
239 : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
242 if (!warnIfNotNative(d->printer))
244 setAttribute(Qt::WA_DontShowOnScreen);
247 QPrintDialog::~QPrintDialog()
251 int QPrintDialog::exec()
254 if (!warnIfNotNative(d->printer))
255 return QDialog::Rejected;
257 QDialog::setVisible(true);
259 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
260 d->openCocoaPrintPanel(Qt::ApplicationModal);
261 d->closeCocoaPrintPanel();
264 QDialog::setVisible(false);
273 void QPrintDialog::setVisible(bool visible)
277 bool isCurrentlyVisible = (d->printPanel != 0);
279 if (!visible == !isCurrentlyVisible)
282 if (d->printer->outputFormat() != QPrinter::NativeFormat)
285 QDialog::setVisible(visible);
288 Qt::WindowModality modality = windowModality();
289 if (modality == Qt::NonModal) {
290 // NSPrintPanels can only be modal, so we must pick a type
291 modality = parentWidget() ? Qt::WindowModal : Qt::ApplicationModal;
293 d->openCocoaPrintPanel(modality);
297 d->closeCocoaPrintPanel();
305 #include "moc_qprintdialog.cpp"
307 #endif // QT_NO_PRINTDIALOG