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 inline void _q_printToFileChanged(int) {}
71 inline void _q_rbPrintRangeToggled(bool) {}
72 inline void _q_printerChanged(int) {}
73 #ifndef QT_NO_MESSAGEBOX
74 inline void _q_checkFields() {}
76 inline void _q_chbPrintLastFirstToggled(bool) {}
77 inline void _q_paperSizeChanged(int) {}
78 inline void _q_btnBrowseClicked() {}
79 inline void _q_btnPropertiesClicked() {}
81 NSPrintInfo *printInfo;
82 NSPrintPanel *printPanel;
90 @class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
92 @interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
94 NSPrintInfo *printInfo;
96 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo;
97 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
98 returnCode:(int)returnCode contextInfo:(void *)contextInfo;
101 @implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate)
102 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
104 if (self = [super init]) {
105 printInfo = nsPrintInfo;
109 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
110 returnCode:(int)returnCode contextInfo:(void *)contextInfo
112 Q_UNUSED(printPanel);
114 QPrintDialog *dialog = static_cast<QPrintDialog *>(contextInfo);
115 QPrinter *printer = dialog->printer();
117 if (returnCode == NSOKButton) {
118 PMPrintSession session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
119 PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
121 UInt32 frompage, topage;
122 PMGetFirstPage(settings, &frompage);
123 PMGetLastPage(settings, &topage);
124 topage = qMin(UInt32(INT_MAX), topage);
125 dialog->setFromTo(frompage, topage);
127 // OK, I need to map these values back let's see
128 // If from is 1 and to is INT_MAX, then print it all
129 // (Apologies to the folks with more than INT_MAX pages)
130 if (dialog->fromPage() == 1 && dialog->toPage() == INT_MAX) {
131 dialog->setPrintRange(QPrintDialog::AllPages);
132 dialog->setFromTo(0, 0);
134 dialog->setPrintRange(QPrintDialog::PageRange); // In a way a lie, but it shouldn't hurt.
135 // Carbon hands us back a very large number here even for ALL, set it to max
136 // in that case to follow the behavior of the other print dialogs.
137 if (dialog->maxPage() < dialog->toPage())
138 dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
140 // Keep us in sync with file output
141 PMDestinationType dest;
143 // If the user selected print to file, the session has been
144 // changed behind our back and our d->ep->session object is a
145 // dangling pointer. Update it based on the "current" session
146 PMSessionGetDestinationType(session, settings, &dest);
147 if (dest == kPMDestinationFile) {
148 QCFType<CFURLRef> file;
149 PMSessionCopyDestinationLocation(session, settings, &file);
150 UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
151 CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
152 printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
154 // Keep output format.
155 QPrinter::OutputFormat format;
156 format = printer->outputFormat();
157 printer->setOutputFileName(QString());
158 printer->setOutputFormat(format);
162 dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
168 void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
172 // get the NSPrintInfo from the print engine in the platform plugin
174 (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
175 "NSPrintInfoForPrintEngine",
176 Q_RETURN_ARG(void *, voidp),
177 Q_ARG(QPrintEngine *, printer->printEngine()));
178 printInfo = static_cast<NSPrintInfo *>(voidp);
181 // It seems the only way that PM lets you use all is if the minimum
182 // for the page range is 1. This _kind of_ makes sense if you think about
183 // it. However, calling PMSetFirstPage() or PMSetLastPage() always enforces
185 // get print settings from the platform plugin
186 PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
187 PMSetPageRange(settings, q->minPage(), q->maxPage());
188 if (q->printRange() == QAbstractPrintDialog::PageRange) {
189 PMSetFirstPage(settings, q->fromPage(), false);
190 PMSetLastPage(settings, q->toPage(), false);
192 [printInfo updateFromPMPrintSettings];
194 QPrintDialog::PrintDialogOptions qtOptions = q->options();
195 NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies;
196 if (qtOptions & QPrintDialog::PrintPageRange)
197 macOptions |= NSPrintPanelShowsPageRange;
198 if (qtOptions & QPrintDialog::PrintShowPageSize)
199 macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory
200 | NSPrintPanelShowsOrientation;
202 printPanel = [NSPrintPanel printPanel];
204 [printPanel setOptions:macOptions];
206 QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init];
207 if (modality == Qt::ApplicationModal) {
208 int rval = [printPanel runModalWithPrintInfo:printInfo];
209 [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:q];
211 Q_ASSERT(q->parentWidget());
212 QWindow *parentWindow = q->parentWidget()->windowHandle();
213 NSWindow *window = static_cast<NSWindow *>(qApp->platformNativeInterface()->nativeResourceForWindow("nswindow", parentWindow));
214 [printPanel beginSheetWithPrintInfo:printInfo
215 modalForWindow:window
217 didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
222 void QPrintDialogPrivate::closeCocoaPrintPanel()
226 [printPanel release];
230 static bool warnIfNotNative(QPrinter *printer)
232 if (printer->outputFormat() != QPrinter::NativeFormat) {
233 qWarning("QPrintDialog: Cannot be used on non-native printers");
240 QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
241 : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
244 if (!warnIfNotNative(d->printer))
246 setAttribute(Qt::WA_DontShowOnScreen);
249 QPrintDialog::QPrintDialog(QWidget *parent)
250 : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
253 if (!warnIfNotNative(d->printer))
255 setAttribute(Qt::WA_DontShowOnScreen);
258 QPrintDialog::~QPrintDialog()
262 int QPrintDialog::exec()
265 if (!warnIfNotNative(d->printer))
266 return QDialog::Rejected;
268 QDialog::setVisible(true);
270 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
271 d->openCocoaPrintPanel(Qt::ApplicationModal);
272 d->closeCocoaPrintPanel();
275 QDialog::setVisible(false);
284 void QPrintDialog::setVisible(bool visible)
288 bool isCurrentlyVisible = (d->printPanel != 0);
290 if (!visible == !isCurrentlyVisible)
293 if (d->printer->outputFormat() != QPrinter::NativeFormat)
296 QDialog::setVisible(visible);
299 Qt::WindowModality modality = windowModality();
300 if (modality == Qt::NonModal) {
301 // NSPrintPanels can only be modal, so we must pick a type
302 modality = parentWidget() ? Qt::WindowModal : Qt::ApplicationModal;
304 d->openCocoaPrintPanel(modality);
308 d->closeCocoaPrintPanel();
316 #include "moc_qprintdialog.cpp"
318 #endif // QT_NO_PRINTDIALOG