QtPrintSupport - Cleanup QPrintDialog header
[profile/ivi/qtbase.git] / src / printsupport / dialogs / qprintdialog_mac.mm
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
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.
16 **
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.
20 **
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.
28 **
29 ** Other Usage
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.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #ifndef QT_NO_PRINTDIALOG
43
44 #include <Cocoa/Cocoa.h>
45
46 #include "qprintdialog.h"
47 #include "qabstractprintdialog_p.h"
48
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>
54
55 QT_BEGIN_NAMESPACE
56
57 class QPrintDialogPrivate : public QAbstractPrintDialogPrivate
58 {
59     Q_DECLARE_PUBLIC(QPrintDialog)
60
61 public:
62     QPrintDialogPrivate() : printInfo(0), printPanel(0)
63        {}
64
65     void openCocoaPrintPanel(Qt::WindowModality modality);
66     void closeCocoaPrintPanel();
67
68     inline QPrintDialog *printDialog() { return q_func(); }
69
70     NSPrintInfo *printInfo;
71     NSPrintPanel *printPanel;
72 };
73
74 QT_END_NAMESPACE
75
76 QT_USE_NAMESPACE
77
78
79 @class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
80
81 @interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject
82 {
83     NSPrintInfo *printInfo;
84 }
85 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo;
86 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
87         returnCode:(int)returnCode contextInfo:(void *)contextInfo;
88 @end
89
90 @implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate)
91 - (id)initWithNSPrintInfo:(NSPrintInfo *)nsPrintInfo
92 {
93     if (self = [super init]) {
94         printInfo = nsPrintInfo;
95     }
96     return self;
97 }
98 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
99         returnCode:(int)returnCode contextInfo:(void *)contextInfo
100 {
101     Q_UNUSED(printPanel);
102
103     QPrintDialog *dialog = static_cast<QPrintDialog *>(contextInfo);
104     QPrinter *printer = dialog->printer();
105
106     if (returnCode == NSOKButton) {
107         PMPrintSession session = static_cast<PMPrintSession>([printInfo PMPrintSession]);
108         PMPrintSettings settings = static_cast<PMPrintSettings>([printInfo PMPrintSettings]);
109
110         UInt32 frompage, topage;
111         PMGetFirstPage(settings, &frompage);
112         PMGetLastPage(settings, &topage);
113         topage = qMin(UInt32(INT_MAX), topage);
114         dialog->setFromTo(frompage, topage);
115
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);
122         } else {
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());
128         }
129         // Keep us in sync with file output
130         PMDestinationType dest;
131
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)));
142         } else {
143             // Keep output format.
144             QPrinter::OutputFormat format;
145             format = printer->outputFormat();
146             printer->setOutputFileName(QString());
147             printer->setOutputFormat(format);
148         }
149     }
150
151     dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
152 }
153 @end
154
155 QT_BEGIN_NAMESPACE
156
157 void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
158 {
159     Q_Q(QPrintDialog);
160
161     // get the NSPrintInfo from the print engine in the platform plugin
162     void *voidp = 0;
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);
168     [printInfo retain];
169
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
173     // the range.
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);
180     }
181     [printInfo updateFromPMPrintSettings];
182
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;
190
191     printPanel = [NSPrintPanel printPanel];
192     [printPanel retain];
193     [printPanel setOptions:macOptions];
194
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];
199     } else {
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
205                                    delegate:delegate
206                              didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
207                                 contextInfo:q];
208     }
209 }
210
211 void QPrintDialogPrivate::closeCocoaPrintPanel()
212 {
213     [printInfo release];
214     printInfo = 0;
215     [printPanel release];
216     printPanel = 0;
217 }
218
219 static bool warnIfNotNative(QPrinter *printer)
220 {
221     if (printer->outputFormat() != QPrinter::NativeFormat) {
222         qWarning("QPrintDialog: Cannot be used on non-native printers");
223         return false;
224     }
225     return true;
226 }
227
228
229 QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
230     : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
231 {
232     Q_D(QPrintDialog);
233     if (!warnIfNotNative(d->printer))
234         return;
235     setAttribute(Qt::WA_DontShowOnScreen);
236 }
237
238 QPrintDialog::QPrintDialog(QWidget *parent)
239     : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
240 {
241     Q_D(QPrintDialog);
242     if (!warnIfNotNative(d->printer))
243         return;
244     setAttribute(Qt::WA_DontShowOnScreen);
245 }
246
247 QPrintDialog::~QPrintDialog()
248 {
249 }
250
251 int QPrintDialog::exec()
252 {
253     Q_D(QPrintDialog);
254     if (!warnIfNotNative(d->printer))
255         return QDialog::Rejected;
256
257     QDialog::setVisible(true);
258
259     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
260     d->openCocoaPrintPanel(Qt::ApplicationModal);
261     d->closeCocoaPrintPanel();
262     [pool release];
263
264     QDialog::setVisible(false);
265
266     return result();
267 }
268
269
270 /*!
271     \reimp
272 */
273 void QPrintDialog::setVisible(bool visible)
274 {
275     Q_D(QPrintDialog);
276
277     bool isCurrentlyVisible = (d->printPanel != 0);
278
279     if (!visible == !isCurrentlyVisible)
280         return;
281
282     if (d->printer->outputFormat() != QPrinter::NativeFormat)
283         return;
284
285     QDialog::setVisible(visible);
286
287     if (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;
292         }
293         d->openCocoaPrintPanel(modality);
294         return;
295     } else {
296         if (d->printPanel) {
297             d->closeCocoaPrintPanel();
298             return;
299         }
300     }
301 }
302
303 QT_END_NAMESPACE
304
305 #include "moc_qprintdialog.cpp"
306
307 #endif // QT_NO_PRINTDIALOG