Qt 4.8
qprintdialog_mac.mm
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #ifndef QT_NO_PRINTDIALOG
43 
44 #include <private/qt_mac_p.h>
45 
46 #include <qhash.h>
47 #include <qprintdialog.h>
48 #include <private/qapplication_p.h>
49 #include <private/qabstractprintdialog_p.h>
50 #include <private/qprintengine_mac_p.h>
51 
53 
55 {
57 
58 public:
60 #ifndef QT_MAC_USE_COCOA
61  ,upp(0)
62 #endif
63  {}
64 #ifndef QT_MAC_USE_COCOA
66  if (upp) {
67  DisposePMSheetDoneUPP(upp);
68  upp = 0;
69  }
71  while (it != sheetCallbackMap.end()) {
72  if (it.value() == this) {
73  it = sheetCallbackMap.erase(it);
74  } else {
75  ++it;
76  }
77  }
78  }
79 #endif
80 
81 #ifndef QT_MAC_USE_COCOA
83  void closeCarbonPrintPanel();
84  static void printDialogSheetDoneCallback(PMPrintSession printSession, WindowRef /*documentWindow*/, Boolean accepted) {
86  if (!priv) {
87  qWarning("%s:%d: QPrintDialog::exec: Could not retrieve data structure, "
88  "you most likely now have an infinite loop", __FILE__, __LINE__);
89  return;
90  }
91  priv->q_func()->done(accepted ? QDialog::Accepted : QDialog::Rejected);
92  priv->closeCarbonPrintPanel();
93  }
94 #else
95  void openCocoaPrintPanel(Qt::WindowModality modality);
96  void closeCocoaPrintPanel();
97 #endif
98  void initBeforeRun();
99 
100  inline QPrintDialog *printDialog() { return q_func(); }
101 
102  inline void _q_printToFileChanged(int) {}
103  inline void _q_rbPrintRangeToggled(bool) {}
104  inline void _q_printerChanged(int) {}
105 #ifndef QT_NO_MESSAGEBOX
106  inline void _q_checkFields() {}
107 #endif
108  inline void _q_chbPrintLastFirstToggled(bool) {}
109  inline void _q_paperSizeChanged(int) {}
110  inline void _q_btnBrowseClicked() {}
111  inline void _q_btnPropertiesClicked() {}
112 
114  NSPrintPanel *printPanel;
115 #ifndef QT_MAC_USE_COCOA
116  PMSheetDoneUPP upp;
118 #endif
119 };
120 
122 
124 
125 #ifdef QT_MAC_USE_COCOA
126 
127 @class QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate);
128 
129 @interface QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) : NSObject {
130 }
131 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
132  returnCode:(int)returnCode contextInfo:(void *)contextInfo;
133 @end
134 
135 @implementation QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate)
136 - (void)printPanelDidEnd:(NSPrintPanel *)printPanel
137  returnCode:(int)returnCode contextInfo:(void *)contextInfo
138 {
140 
141  QPrintDialogPrivate *d = static_cast<QPrintDialogPrivate *>(contextInfo);
142  QPrintDialog *dialog = d->printDialog();
143 
144  if (returnCode == NSOKButton) {
145  UInt32 frompage, topage;
146  PMGetFirstPage(d->ep->settings, &frompage);
147  PMGetLastPage(d->ep->settings, &topage);
148  topage = qMin(UInt32(INT_MAX), topage);
149  dialog->setFromTo(frompage, topage);
150 
151  // OK, I need to map these values back let's see
152  // If from is 1 and to is INT_MAX, then print it all
153  // (Apologies to the folks with more than INT_MAX pages)
154  if (dialog->fromPage() == 1 && dialog->toPage() == INT_MAX) {
156  dialog->setFromTo(0, 0);
157  } else {
158  dialog->setPrintRange(QPrintDialog::PageRange); // In a way a lie, but it shouldn't hurt.
159  // Carbon hands us back a very large number here even for ALL, set it to max
160  // in that case to follow the behavior of the other print dialogs.
161  if (dialog->maxPage() < dialog->toPage())
162  dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
163  }
164  // Keep us in sync with file output
165  PMDestinationType dest;
166 
167  // If the user selected print to file, the session has been
168  // changed behind our back and our d->ep->session object is a
169  // dangling pointer. Update it based on the "current" session
170  d->ep->session = static_cast<PMPrintSession>([d->ep->printInfo PMPrintSession]);
171 
172  PMSessionGetDestinationType(d->ep->session, d->ep->settings, &dest);
173  if (dest == kPMDestinationFile) {
174  QCFType<CFURLRef> file;
175  PMSessionCopyDestinationLocation(d->ep->session, d->ep->settings, &file);
176  UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
177  CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
178  d->ep->outputFilename
179  = QString::fromUtf8(reinterpret_cast<const char *>(localFile));
180  } else {
181  // Keep output format.
183  format = d->printer->outputFormat();
185  d->printer->setOutputFormat(format);
186  }
187  }
188 
189  dialog->done((returnCode == NSOKButton) ? QDialog::Accepted : QDialog::Rejected);
190 }
191 @end
192 
193 #endif
194 
196 
198 extern void macStopInterceptWindowTitle();
199 
200 
202 {
203  Q_Q(QPrintDialog);
204  // If someone is reusing a QPrinter object, the end released all our old
205  // information. In this case, we must reinitialize.
206  if (ep->session == 0)
207  ep->initialize();
208 
209 
210  // It seems the only way that PM lets you use all is if the minimum
211  // for the page range is 1. This _kind of_ makes sense if you think about
212  // it. However, calling PMSetFirstPage() or PMSetLastPage() always enforces
213  // the range.
214  PMSetPageRange(ep->settings, q->minPage(), q->maxPage());
215  if (q->printRange() == QAbstractPrintDialog::PageRange) {
216  PMSetFirstPage(ep->settings, q->fromPage(), false);
217  PMSetLastPage(ep->settings, q->toPage(), false);
218  }
219 }
220 
221 #ifndef QT_MAC_USE_COCOA
224 {
225  Q_Q(QPrintDialog);
226  initBeforeRun();
228  if (modality == Qt::ApplicationModal) {
229  QWidget modal_widg(0, Qt::Window);
230  modal_widg.setObjectName(QLatin1String(__FILE__ "__modal_dlg"));
231  modal_widg.createWinId();
232  QApplicationPrivate::enterModal(&modal_widg);
234  Boolean acceptStatus;
235  PMSessionPrintDialog(ep->session, ep->settings, ep->format, &acceptStatus);
236  QApplicationPrivate::leaveModal(&modal_widg);
238  printDialogSheetDoneCallback(ep->session, 0, acceptStatus);
239  } else {
240  // Window Modal means that we use a sheet at the moment, there's no other way to do it correctly.
241  if (!upp)
243  PMSessionUseSheets(ep->session, qt_mac_window_for(q->parentWidget()), upp);
245  Boolean unused;
246  PMSessionPrintDialog(ep->session, ep->settings, ep->format, &unused);
247  }
248 }
249 
251 {
252  Q_Q(QPrintDialog);
254  if (q->result() == QDialog::Accepted) {
255  UInt32 frompage, topage;
256  PMGetFirstPage(ep->settings, &frompage);
257  PMGetLastPage(ep->settings, &topage);
258  topage = qMin(UInt32(INT_MAX), topage);
259  q->setFromTo(frompage, topage);
260 
261  // OK, I need to map these values back let's see
262  // If from is 1 and to is INT_MAX, then print it all
263  // (Apologies to the folks with more than INT_MAX pages)
264  // ...that's a joke.
265  if (q->fromPage() == 1 && q->toPage() == INT_MAX) {
266  q->setPrintRange(QAbstractPrintDialog::AllPages);
267  q->setFromTo(0,0);
268  } else {
269  q->setPrintRange(QAbstractPrintDialog::PageRange); // In a way a lie, but it shouldn't hurt.
270  // Carbon hands us back a very large number here even for ALL, set it to max
271  // in that case to follow the behavior of the other print dialogs.
272  if (q->maxPage() < q->toPage())
273  q->setFromTo(q->fromPage(), q->maxPage());
274  }
275  // Keep us in sync with file output
276  PMDestinationType dest;
277  PMSessionGetDestinationType(ep->session, ep->settings, &dest);
278  if (dest == kPMDestinationFile) {
279  QCFType<CFURLRef> file;
280  PMSessionCopyDestinationLocation(ep->session, ep->settings, &file);
281  UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
282  CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
283  ep->outputFilename = QString::fromUtf8(reinterpret_cast<const char *>(localFile));
284  } else {
286  }
287  }
289 }
290 #else
291 void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
292 {
293  Q_Q(QPrintDialog);
294 
295  initBeforeRun();
296 
297  QPrintDialog::PrintDialogOptions qtOptions = q->options();
298  NSPrintPanelOptions macOptions = NSPrintPanelShowsCopies;
299  if (qtOptions & QPrintDialog::PrintPageRange)
300  macOptions |= NSPrintPanelShowsPageRange;
301  if (qtOptions & QPrintDialog::PrintShowPageSize)
302  macOptions |= NSPrintPanelShowsPaperSize | NSPrintPanelShowsPageSetupAccessory
303  | NSPrintPanelShowsOrientation;
304 
306  printPanel = [NSPrintPanel printPanel];
307  QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) *delegate = [[QT_MANGLE_NAMESPACE(QCocoaPrintPanelDelegate) alloc] init];
308 
309  // Call processEvents in case the event dispatcher has been interrupted, and needs to do
310  // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
311  // close down during the cleanup (QTBUG-17913):
313 
314  [printPanel setOptions:macOptions];
315 
316  if (modality == Qt::ApplicationModal || !q->parentWidget()) {
317  if (modality == Qt::NonModal)
318  qWarning("QPrintDialog is required to be modal on OS X");
319  int rval = [printPanel runModalWithPrintInfo:ep->printInfo];
320  [delegate printPanelDidEnd:printPanel returnCode:rval contextInfo:this];
321  } else {
322  Q_ASSERT(q->parentWidget());
323  NSWindow *windowRef = qt_mac_window_for(q->parentWidget());
324  [printPanel beginSheetWithPrintInfo:ep->printInfo
325  modalForWindow:windowRef
326  delegate:delegate
327  didEndSelector:@selector(printPanelDidEnd:returnCode:contextInfo:)
328  contextInfo:this];
329  }
330 
332 }
333 
334 void QPrintDialogPrivate::closeCocoaPrintPanel()
335 {
336  // ###
337 }
338 #endif
339 
341 {
342  if (printer->outputFormat() != QPrinter::NativeFormat) {
343  qWarning("QPrintDialog: Cannot be used on non-native printers");
344  return false;
345  }
346  return true;
347 }
348 
349 
351  : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
352 {
353  Q_D(QPrintDialog);
354  if (!warnIfNotNative(d->printer))
355  return;
356  d->ep = static_cast<QMacPrintEngine *>(d->printer->paintEngine())->d_func();
357 }
358 
360  : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
361 {
362  Q_D(QPrintDialog);
363  if (!warnIfNotNative(d->printer))
364  return;
365  d->ep = static_cast<QMacPrintEngine *>(d->printer->paintEngine())->d_func();
366 }
367 
369 {
370 }
371 
373 {
374  Q_D(QPrintDialog);
375  if (!warnIfNotNative(d->printer))
376  return QDialog::Rejected;
377 
378 #ifndef QT_MAC_USE_COCOA
380 #else
382 
383  d->openCocoaPrintPanel(Qt::ApplicationModal);
384  d->closeCocoaPrintPanel();
385 #endif
386  return result();
387 }
388 
389 #ifdef QT3_SUPPORT
391 {
392  Q_D(const QPrintDialog);
393  return d->printer;
394 }
395 #endif
396 
401 {
402  Q_D(QPrintDialog);
403 
404  bool isCurrentlyVisible = (d->printPanel != 0);
405 
406  if (!visible == !isCurrentlyVisible)
407  return;
408 
410  return;
411 
412  if (visible) {
413 #ifndef QT_MAC_USE_COCOA
416 #else
417  d->openCocoaPrintPanel(parentWidget() ? Qt::WindowModal
418  : Qt::ApplicationModal);
419 #endif
420  return;
421  } else {
422  if (d->printPanel) {
423 #ifndef QT_MAC_USE_COCOA
425 #else
426  d->closeCocoaPrintPanel();
427 #endif
428  return;
429  }
430  }
431 }
432 
434 
435 #include "moc_qprintdialog.cpp"
436 
437 #endif // QT_NO_PRINTDIALOG
double d
Definition: qnumeric_p.h:62
QWidget * parentWidget() const
Returns the parent of this widget, or 0 if it does not have any parent widget.
Definition: qwidget.h:1035
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int remove(const Key &key)
Removes all the items that have the key from the hash.
Definition: qhash.h:784
static QHash< PMPrintSession, QPrintDialogPrivate * > sheetCallbackMap
#define it(className, varName)
QMacPrintEnginePrivate * ep
struct OpaqueWindowPtr * WindowRef
The QWidget class is the base class of all user interface objects.
Definition: qwidget.h:150
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qhash.h:348
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define Q_D(Class)
Definition: qglobal.h:2482
const T value(const Key &key) const
Returns the value associated with the key.
Definition: qhash.h:606
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
OSWindowRef qt_mac_window_for(const QWidget *)
Definition: qwidget_mac.mm:484
void setObjectName(const QString &name)
Definition: qobject.cpp:1112
#define Q_Q(Class)
Definition: qglobal.h:2483
~QPrintDialog()
Destroys the print dialog.
static void printDialogSheetDoneCallback(PMPrintSession printSession, WindowRef, Boolean accepted)
The QPrintDialog class provides a dialog for specifying the printer&#39;s configuration.
Definition: qprintdialog.h:81
NSWindow * window
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
OutputFormat outputFormat() const
Returns the output format for this printer.
Definition: qprinter.cpp:813
bool visible
whether the widget is visible
Definition: qwidget.h:191
void macStartInterceptWindowTitle(QWidget *window)
#define qApp
The QPrinter class is a paint device that paints on a printer.
Definition: qprinter.h:66
int fromPage() const
Returns the first page to be printed By default, this value is set to 0.
OutputFormat
The OutputFormat enum is used to describe the format QPrinter should use for printing.
Definition: qprinter.h:124
void _q_chbPrintLastFirstToggled(bool)
void * unused
Definition: qobject_p.h:208
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
static bool warnIfNotNative(QPrinter *printer)
int toPage() const
Returns the last page to be printed.
Q_CORE_EXPORT void qWarning(const char *,...)
QPrintDialog * printDialog()
void setFromTo(int fromPage, int toPage)
Sets the range in the print dialog to be from from to to.
int exec()
Reimplemented Function
int maxPage() const
Returns the maximum page in the page range.
void done(int result)
Closes the dialog and sets its result code to result.
The QAbstractPrintDialog class provides a base implementation for print dialogs used to configure pri...
#define Q_DECLARE_PUBLIC(Class)
Definition: qglobal.h:2477
QPaintEngine * paintEngine() const
Returns the paint engine used by the printer.
Definition: qprinter.cpp:1882
iterator end()
Returns an STL-style iterator pointing to the imaginary item after the last item in the hash...
Definition: qhash.h:467
#define QT_MANGLE_NAMESPACE(name)
Definition: qglobal.h:106
QObject * parent() const
Returns a pointer to the parent object.
Definition: qobject.h:273
int result() const
In general returns the modal dialog&#39;s result code, Accepted or Rejected.
Definition: qdialog.cpp:458
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
static const QMetaObjectPrivate * priv(const uint *data)
QPrinter * printer()
Returns the printer that this printer dialog operates on.
static bool native_modal_dialog_active
iterator begin()
Returns an STL-style iterator pointing to the first item in the hash.
Definition: qhash.h:464
#define QT_USE_NAMESPACE
This macro expands to using QT_NAMESPACE if QT_NAMESPACE is defined and nothing otherwise.
Definition: qglobal.h:88
QObject * parent
Definition: qobject.h:92
void setVisible(bool visible)
Reimplemented Function
void createWinId()
Definition: qwidget.cpp:2626
void setPrintRange(PrintRange range)
Sets the print range option in to be range.
void openCarbonPrintPanel(Qt::WindowModality modality)
void setOutputFormat(OutputFormat format)
Sets the output format for this printer to format.
Definition: qprinter.cpp:765
static void leaveModal(QWidget *)
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void macStopInterceptWindowTitle()
void _q_rbPrintRangeToggled(bool)
iterator erase(iterator it)
Removes the (key, value) pair associated with the iterator pos from the hash, and returns an iterator...
Definition: qhash.h:827
WindowModality
Definition: qnamespace.h:1683
#define INT_MAX
QPrintDialog(QPrinter *printer, QWidget *parent=0)
Constructs a new modal printer dialog for the given printer with the given parent.
static void enterModal(QWidget *)
NSPrintPanel * printPanel
void setOutputFileName(const QString &)
Sets the name of the output file to fileName.
Definition: qprinter.cpp:976