|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui module of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #ifndef QT_NO_PRINTDIALOG |
|
43 |
|
44 #include "qprintdialog.h" |
|
45 |
|
46 #include <qwidget.h> |
|
47 #include <qapplication.h> |
|
48 #include <qmessagebox.h> |
|
49 #include <private/qapplication_p.h> |
|
50 |
|
51 #include <private/qabstractprintdialog_p.h> |
|
52 #include <private/qprintengine_win_p.h> |
|
53 #include <private/qprinter_p.h> |
|
54 |
|
55 #if defined(Q_CC_MINGW) && !defined(PD_NOCURRENTPAGE) |
|
56 #define PD_NOCURRENTPAGE 0x00800000 |
|
57 #define PD_RESULT_PRINT 1 |
|
58 #define PD_RESULT_APPLY 2 |
|
59 #define START_PAGE_GENERAL 0XFFFFFFFF |
|
60 #endif |
|
61 |
|
62 QT_BEGIN_NAMESPACE |
|
63 |
|
64 extern void qt_win_eatMouseMove(); |
|
65 |
|
66 class QPrintDialogPrivate : public QAbstractPrintDialogPrivate |
|
67 { |
|
68 Q_DECLARE_PUBLIC(QPrintDialog) |
|
69 public: |
|
70 QPrintDialogPrivate() |
|
71 : ep(0) |
|
72 { |
|
73 } |
|
74 |
|
75 inline void _q_printToFileChanged(int) {} |
|
76 inline void _q_rbPrintRangeToggled(bool) {} |
|
77 inline void _q_printerChanged(int) {} |
|
78 inline void _q_chbPrintLastFirstToggled(bool) {} |
|
79 inline void _q_paperSizeChanged(int) {} |
|
80 inline void _q_btnBrowseClicked() {} |
|
81 inline void _q_btnPropertiesClicked() {} |
|
82 int openWindowsPrintDialogModally(); |
|
83 |
|
84 QWin32PrintEnginePrivate *ep; |
|
85 }; |
|
86 |
|
87 static void qt_win_setup_PRINTDLGEX(PRINTDLGEX *pd, QWidget *parent, |
|
88 QPrintDialog *pdlg, |
|
89 QPrintDialogPrivate *d, HGLOBAL *tempDevNames) |
|
90 { |
|
91 DEVMODE *devMode = d->ep->devMode; |
|
92 |
|
93 if (devMode) { |
|
94 int size = sizeof(DEVMODE) + devMode->dmDriverExtra; |
|
95 pd->hDevMode = GlobalAlloc(GHND, size); |
|
96 { |
|
97 void *dest = GlobalLock(pd->hDevMode); |
|
98 memcpy(dest, devMode, size); |
|
99 GlobalUnlock(pd->hDevMode); |
|
100 } |
|
101 } else { |
|
102 pd->hDevMode = NULL; |
|
103 } |
|
104 pd->hDevNames = tempDevNames; |
|
105 |
|
106 pd->Flags = PD_RETURNDC; |
|
107 pd->Flags |= PD_USEDEVMODECOPIESANDCOLLATE; |
|
108 |
|
109 if (!pdlg->isOptionEnabled(QPrintDialog::PrintSelection)) |
|
110 pd->Flags |= PD_NOSELECTION; |
|
111 if (pdlg->isOptionEnabled(QPrintDialog::PrintPageRange)) { |
|
112 pd->nMinPage = pdlg->minPage(); |
|
113 pd->nMaxPage = pdlg->maxPage(); |
|
114 } |
|
115 |
|
116 if(!pdlg->isOptionEnabled(QPrintDialog::PrintToFile)) |
|
117 pd->Flags |= PD_DISABLEPRINTTOFILE; |
|
118 |
|
119 if (pdlg->printRange() == QPrintDialog::Selection) |
|
120 pd->Flags |= PD_SELECTION; |
|
121 else if (pdlg->printRange() == QPrintDialog::PageRange) |
|
122 pd->Flags |= PD_PAGENUMS; |
|
123 else |
|
124 pd->Flags |= PD_ALLPAGES; |
|
125 |
|
126 // As stated by MSDN, to enable collate option when minpage==maxpage==0 |
|
127 // set the PD_NOPAGENUMS flag |
|
128 if (pd->nMinPage==0 && pd->nMaxPage==0) |
|
129 pd->Flags |= PD_NOPAGENUMS; |
|
130 |
|
131 // we don't have a 'current page' notion in the QPrinter API yet. |
|
132 // Neither do we support more than one page range, so limit those |
|
133 // options |
|
134 pd->Flags |= PD_NOCURRENTPAGE; |
|
135 pd->nStartPage = START_PAGE_GENERAL; |
|
136 pd->nPageRanges = 1; |
|
137 pd->nMaxPageRanges = 1; |
|
138 |
|
139 if (d->ep->printToFile) |
|
140 pd->Flags |= PD_PRINTTOFILE; |
|
141 Q_ASSERT(parent != 0 && parent->testAttribute(Qt::WA_WState_Created)); |
|
142 pd->hwndOwner = parent->winId(); |
|
143 pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage()); |
|
144 pd->lpPageRanges[0].nToPage = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1; |
|
145 pd->nCopies = d->ep->num_copies; |
|
146 } |
|
147 |
|
148 static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d) |
|
149 { |
|
150 if (pd->Flags & PD_SELECTION) { |
|
151 pdlg->setPrintRange(QPrintDialog::Selection); |
|
152 pdlg->setFromTo(0, 0); |
|
153 } else if (pd->Flags & PD_PAGENUMS) { |
|
154 pdlg->setPrintRange(QPrintDialog::PageRange); |
|
155 pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage); |
|
156 } else { |
|
157 pdlg->setPrintRange(QPrintDialog::AllPages); |
|
158 pdlg->setFromTo(0, 0); |
|
159 } |
|
160 |
|
161 d->ep->printToFile = (pd->Flags & PD_PRINTTOFILE) != 0; |
|
162 |
|
163 d->ep->readDevnames(pd->hDevNames); |
|
164 d->ep->readDevmode(pd->hDevMode); |
|
165 d->ep->updateCustomPaperSize(); |
|
166 |
|
167 if (d->ep->printToFile && d->ep->fileName.isEmpty()) |
|
168 d->ep->fileName = d->ep->port; |
|
169 else if (!d->ep->printToFile && d->ep->fileName == QLatin1String("FILE:")) |
|
170 d->ep->fileName.clear(); |
|
171 } |
|
172 |
|
173 static bool warnIfNotNative(QPrinter *printer) |
|
174 { |
|
175 if (printer->outputFormat() != QPrinter::NativeFormat) { |
|
176 qWarning("QPrintDialog: Cannot be used on non-native printers"); |
|
177 return false; |
|
178 } |
|
179 return true; |
|
180 } |
|
181 |
|
182 QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent) |
|
183 : QAbstractPrintDialog( *(new QPrintDialogPrivate), printer, parent) |
|
184 { |
|
185 Q_D(QPrintDialog); |
|
186 if (!warnIfNotNative(d->printer)) |
|
187 return; |
|
188 d->ep = static_cast<QWin32PrintEngine *>(d->printer->paintEngine())->d_func(); |
|
189 } |
|
190 |
|
191 QPrintDialog::QPrintDialog(QWidget *parent) |
|
192 : QAbstractPrintDialog( *(new QPrintDialogPrivate), 0, parent) |
|
193 { |
|
194 Q_D(QPrintDialog); |
|
195 if (!warnIfNotNative(d->printer)) |
|
196 return; |
|
197 d->ep = static_cast<QWin32PrintEngine *>(d->printer->paintEngine())->d_func(); |
|
198 } |
|
199 |
|
200 QPrintDialog::~QPrintDialog() |
|
201 { |
|
202 } |
|
203 |
|
204 int QPrintDialog::exec() |
|
205 { |
|
206 if (!warnIfNotNative(printer())) |
|
207 return 0; |
|
208 |
|
209 Q_D(QPrintDialog); |
|
210 return d->openWindowsPrintDialogModally(); |
|
211 } |
|
212 |
|
213 int QPrintDialogPrivate::openWindowsPrintDialogModally() |
|
214 { |
|
215 Q_Q(QPrintDialog); |
|
216 QWidget *parent = q->parentWidget(); |
|
217 if (parent) |
|
218 parent = parent->window(); |
|
219 else |
|
220 parent = QApplication::activeWindow(); |
|
221 |
|
222 // If there is no window, fall back to the print dialog itself |
|
223 if (parent == 0) |
|
224 parent = q; |
|
225 |
|
226 QWidget modal_widget; |
|
227 modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true); |
|
228 modal_widget.setParent(parent, Qt::Window); |
|
229 QApplicationPrivate::enterModal(&modal_widget); |
|
230 |
|
231 HGLOBAL *tempDevNames = ep->createDevNames(); |
|
232 |
|
233 bool done; |
|
234 bool result; |
|
235 bool doPrinting; |
|
236 |
|
237 PRINTPAGERANGE pageRange; |
|
238 PRINTDLGEX pd; |
|
239 memset(&pd, 0, sizeof(PRINTDLGEX)); |
|
240 pd.lStructSize = sizeof(PRINTDLGEX); |
|
241 pd.lpPageRanges = &pageRange; |
|
242 qt_win_setup_PRINTDLGEX(&pd, parent, q, this, tempDevNames); |
|
243 |
|
244 do { |
|
245 done = true; |
|
246 doPrinting = false; |
|
247 result = (PrintDlgEx(&pd) == S_OK); |
|
248 if (result && (pd.dwResultAction == PD_RESULT_PRINT |
|
249 || pd.dwResultAction == PD_RESULT_APPLY)) |
|
250 { |
|
251 doPrinting = (pd.dwResultAction == PD_RESULT_PRINT); |
|
252 if ((pd.Flags & PD_PAGENUMS) |
|
253 && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage)) |
|
254 { |
|
255 pd.lpPageRanges[0].nFromPage = 1; |
|
256 pd.lpPageRanges[0].nToPage = 1; |
|
257 done = false; |
|
258 } |
|
259 if (pd.hDC == 0) |
|
260 result = false; |
|
261 } |
|
262 |
|
263 if (!done) { |
|
264 QMessageBox::warning(0, QPrintDialog::tr("Print"), |
|
265 QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."), |
|
266 QPrintDialog::tr("OK")); |
|
267 } |
|
268 } while (!done); |
|
269 |
|
270 QApplicationPrivate::leaveModal(&modal_widget); |
|
271 |
|
272 qt_win_eatMouseMove(); |
|
273 |
|
274 // write values back... |
|
275 if (result && (pd.dwResultAction == PD_RESULT_PRINT |
|
276 || pd.dwResultAction == PD_RESULT_APPLY)) |
|
277 { |
|
278 qt_win_read_back_PRINTDLGEX(&pd, q, this); |
|
279 // update printer validity |
|
280 printer->d_func()->validPrinter = !ep->name.isEmpty(); |
|
281 } |
|
282 |
|
283 // Cleanup... |
|
284 GlobalFree(tempDevNames); |
|
285 |
|
286 q->done(result && doPrinting); |
|
287 |
|
288 return result && doPrinting; |
|
289 } |
|
290 |
|
291 void QPrintDialog::setVisible(bool visible) |
|
292 { |
|
293 Q_D(QPrintDialog); |
|
294 |
|
295 // its always modal, so we cannot hide a native print dialog |
|
296 if (!visible) |
|
297 return; |
|
298 |
|
299 if (!warnIfNotNative(d->printer)) |
|
300 return; |
|
301 |
|
302 (void)d->openWindowsPrintDialogModally(); |
|
303 return; |
|
304 } |
|
305 |
|
306 QT_END_NAMESPACE |
|
307 |
|
308 #include "moc_qprintdialog.cpp" |
|
309 |
|
310 #endif // QT_NO_PRINTDIALOG |