5474643de90069d35d5861f04d0ab633009d351a
[profile/ivi/qtbase.git] / src / printsupport / dialogs / qprintdialog_win.cpp
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 "qprintdialog.h"
45
46 #include <qwidget.h>
47 #include <qapplication.h>
48 #include <qmessagebox.h>
49 #include <private/qapplication_p.h>
50
51 #include "qabstractprintdialog_p.h"
52 #include "../kernel/qprintengine_win_p.h"
53 #include "../kernel/qprinter_p.h"
54
55 #if !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     // Disable Current Page option if not required as default is Enabled
132     if (!pdlg->isOptionEnabled(QPrintDialog::PrintCurrentPage))
133         pd->Flags |= PD_NOCURRENTPAGE;
134
135     // Default to showing the General tab first
136     pd->nStartPage = START_PAGE_GENERAL;
137
138     // We don't support more than one page range in the QPrinter API yet.
139     pd->nPageRanges = 1;
140     pd->nMaxPageRanges = 1;
141
142     if (d->ep->printToFile)
143         pd->Flags |= PD_PRINTTOFILE;
144     Q_ASSERT(parent);
145     QWindow *parentWindow = parent->windowHandle();
146     pd->hwndOwner = parentWindow ? (HWND)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", parentWindow) : 0;
147     pd->lpPageRanges[0].nFromPage = qMax(pdlg->fromPage(), pdlg->minPage());
148     pd->lpPageRanges[0].nToPage   = (pdlg->toPage() > 0) ? qMin(pdlg->toPage(), pdlg->maxPage()) : 1;
149     pd->nCopies = d->ep->num_copies;
150 }
151
152 static void qt_win_read_back_PRINTDLGEX(PRINTDLGEX *pd, QPrintDialog *pdlg, QPrintDialogPrivate *d)
153 {
154     if (pd->Flags & PD_SELECTION) {
155         pdlg->setPrintRange(QPrintDialog::Selection);
156         pdlg->setFromTo(0, 0);
157     } else if (pd->Flags & PD_PAGENUMS) {
158         pdlg->setPrintRange(QPrintDialog::PageRange);
159         pdlg->setFromTo(pd->lpPageRanges[0].nFromPage, pd->lpPageRanges[0].nToPage);
160     } else if (pd->Flags & PD_CURRENTPAGE) {
161         pdlg->setPrintRange(QPrintDialog::CurrentPage);
162         pdlg->setFromTo(0, 0);
163     } else { // PD_ALLPAGES
164         pdlg->setPrintRange(QPrintDialog::AllPages);
165         pdlg->setFromTo(0, 0);
166     }
167
168     d->ep->printToFile = (pd->Flags & PD_PRINTTOFILE) != 0;
169
170     d->ep->readDevnames(pd->hDevNames);
171     d->ep->readDevmode(pd->hDevMode);
172     d->ep->updateCustomPaperSize();
173
174     if (d->ep->printToFile && d->ep->fileName.isEmpty())
175         d->ep->fileName = d->ep->port;
176     else if (!d->ep->printToFile && d->ep->fileName == QLatin1String("FILE:"))
177         d->ep->fileName.clear();
178 }
179
180 static bool warnIfNotNative(QPrinter *printer)
181 {
182     if (printer->outputFormat() != QPrinter::NativeFormat) {
183         qWarning("QPrintDialog: Cannot be used on non-native printers");
184         return false;
185     }
186     return true;
187 }
188
189 QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
190     : QAbstractPrintDialog( *(new QPrintDialogPrivate), printer, parent)
191 {
192     Q_D(QPrintDialog);
193     if (!warnIfNotNative(d->printer))
194         return;
195     d->ep = static_cast<QWin32PrintEngine *>(d->printer->paintEngine())->d_func();
196     setAttribute(Qt::WA_DontShowOnScreen);
197 }
198
199 QPrintDialog::QPrintDialog(QWidget *parent)
200     : QAbstractPrintDialog( *(new QPrintDialogPrivate), 0, parent)
201 {
202     Q_D(QPrintDialog);
203     if (!warnIfNotNative(d->printer))
204         return;
205     d->ep = static_cast<QWin32PrintEngine *>(d->printer->paintEngine())->d_func();
206     setAttribute(Qt::WA_DontShowOnScreen);
207 }
208
209 QPrintDialog::~QPrintDialog()
210 {
211 }
212
213 int QPrintDialog::exec()
214 {
215     if (!warnIfNotNative(printer()))
216         return 0;
217
218     Q_D(QPrintDialog);
219     return d->openWindowsPrintDialogModally();
220 }
221
222 int QPrintDialogPrivate::openWindowsPrintDialogModally()
223 {
224     Q_Q(QPrintDialog);
225     QWidget *parent = q->parentWidget();
226     if (parent)
227         parent = parent->window();
228     else
229         parent = QApplication::activeWindow();
230
231     // If there is no window, fall back to the print dialog itself
232     if (parent == 0)
233         parent = q;
234
235     q->QDialog::setVisible(true);
236
237     HGLOBAL *tempDevNames = ep->createDevNames();
238
239     bool done;
240     bool result;
241     bool doPrinting;
242
243     PRINTPAGERANGE pageRange;
244     PRINTDLGEX pd;
245     memset(&pd, 0, sizeof(PRINTDLGEX));
246     pd.lStructSize = sizeof(PRINTDLGEX);
247     pd.lpPageRanges = &pageRange;
248     qt_win_setup_PRINTDLGEX(&pd, parent, q, this, tempDevNames);
249
250     do {
251         done = true;
252         doPrinting = false;
253         result = (PrintDlgEx(&pd) == S_OK);
254         if (result && (pd.dwResultAction == PD_RESULT_PRINT
255                        || pd.dwResultAction == PD_RESULT_APPLY))
256         {
257             doPrinting = (pd.dwResultAction == PD_RESULT_PRINT);
258             if ((pd.Flags & PD_PAGENUMS)
259                 && (pd.lpPageRanges[0].nFromPage > pd.lpPageRanges[0].nToPage))
260             {
261                 pd.lpPageRanges[0].nFromPage = 1;
262                 pd.lpPageRanges[0].nToPage = 1;
263                 done = false;
264             }
265             if (pd.hDC == 0)
266                 result = false;
267         }
268
269         if (!done) {
270             QMessageBox::warning(0, QPrintDialog::tr("Print"),
271                                  QPrintDialog::tr("The 'From' value cannot be greater than the 'To' value."),
272                                  QPrintDialog::tr("OK"));
273         }
274     } while (!done);
275
276     q->QDialog::setVisible(false);
277
278 //    qt_win_eatMouseMove();
279
280     // write values back...
281     if (result && (pd.dwResultAction == PD_RESULT_PRINT
282                    || pd.dwResultAction == PD_RESULT_APPLY))
283     {
284         qt_win_read_back_PRINTDLGEX(&pd, q, this);
285         // update printer validity
286         printer->d_func()->validPrinter = !ep->name.isEmpty();
287     }
288
289     // Cleanup...
290     GlobalFree(tempDevNames);
291
292     q->done(result && doPrinting);
293
294     return result && doPrinting;
295 }
296
297 void QPrintDialog::setVisible(bool visible)
298 {
299     Q_D(QPrintDialog);
300
301     // its always modal, so we cannot hide a native print dialog
302     if (!visible)
303         return;
304
305     if (!warnIfNotNative(d->printer))
306         return;
307
308     (void)d->openWindowsPrintDialogModally();
309     return;
310 }
311
312 QT_END_NAMESPACE
313
314 #include "moc_qprintdialog.cpp"
315
316 #endif // QT_NO_PRINTDIALOG