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#include "qprintpreviewdialog.h"
43#include "qprintpreviewwidget.h"
44#include <private/qprinter_p.h>
45#include "private/qdialog_p.h"
46
47#include <QtGui/qaction.h>
48#include <QtGui/qboxlayout.h>
49#include <QtGui/qcombobox.h>
50#include <QtGui/qlabel.h>
51#include <QtGui/qlineedit.h>
52#include <QtGui/qpagesetupdialog.h>
53#include <QtGui/qprinter.h>
54#include <QtGui/qstyle.h>
55#include <QtGui/qtoolbutton.h>
56#include <QtGui/qvalidator.h>
57#include <QtGui/qfiledialog.h>
58#include <QtGui/qmainwindow.h>
59#include <QtGui/qtoolbar.h>
60#include <QtGui/qformlayout.h>
61#include <QtCore/QCoreApplication>
62
63#include <math.h>
64
65#ifndef QT_NO_PRINTPREVIEWDIALOG
66
67QT_BEGIN_NAMESPACE
68
69namespace {
70class QPrintPreviewMainWindow : public QMainWindow
71{
72public:
73 QPrintPreviewMainWindow(QWidget *parent) : QMainWindow(parent) {}
74 QMenu *createPopupMenu() { return 0; }
75};
76
77class ZoomFactorValidator : public QDoubleValidator
78{
79public:
80 ZoomFactorValidator(QObject* parent)
81 : QDoubleValidator(parent) {}
82 ZoomFactorValidator(qreal bottom, qreal top, int decimals, QObject *parent)
83 : QDoubleValidator(bottom, top, decimals, parent) {}
84
85 State validate(QString &input, int &pos) const
86 {
87 bool replacePercent = false;
88 if (input.endsWith(QLatin1Char('%'))) {
89 input = input.left(input.length() - 1);
90 replacePercent = true;
91 }
92 State state = QDoubleValidator::validate(input, pos);
93 if (replacePercent)
94 input += QLatin1Char('%');
95 const int num_size = 4;
96 if (state == Intermediate) {
97 int i = input.indexOf(QLocale::system().decimalPoint());
98 if ((i == -1 && input.size() > num_size)
99 || (i != -1 && i > num_size))
100 return Invalid;
101 }
102 return state;
103 }
104};
105
106class LineEdit : public QLineEdit
107{
108 Q_OBJECT
109public:
110 LineEdit(QWidget* parent = 0)
111 : QLineEdit(parent)
112 {
113 setContextMenuPolicy(Qt::NoContextMenu);
114 connect(this, SIGNAL(returnPressed()), SLOT(handleReturnPressed()));
115 }
116
117protected:
118 void focusInEvent(QFocusEvent *e)
119 {
120 origText = text();
121 QLineEdit::focusInEvent(e);
122 }
123
124 void focusOutEvent(QFocusEvent *e)
125 {
126 if (isModified() && !hasAcceptableInput())
127 setText(origText);
128 QLineEdit::focusOutEvent(e);
129 }
130
131private slots:
132 void handleReturnPressed()
133 {
134 origText = text();
135 }
136
137private:
138 QString origText;
139};
140} // anonymous namespace
141
142class QPrintPreviewDialogPrivate : public QDialogPrivate
143{
144 Q_DECLARE_PUBLIC(QPrintPreviewDialog)
145public:
146 QPrintPreviewDialogPrivate()
147 : printDialog(0), ownPrinter(false),
148 initialized(false) {}
149
150 // private slots
151 void _q_fit(QAction *action);
152 void _q_zoomIn();
153 void _q_zoomOut();
154 void _q_navigate(QAction *action);
155 void _q_setMode(QAction *action);
156 void _q_pageNumEdited();
157 void _q_print();
158 void _q_pageSetup();
159 void _q_previewChanged();
160 void _q_zoomFactorChanged();
161
162 void init(QPrinter *printer = 0);
163 void populateScene();
164 void layoutPages();
165 void setupActions();
166 void updateNavActions();
167 void setFitting(bool on);
168 bool isFitting();
169 void updatePageNumLabel();
170 void updateZoomFactor();
171
172 QPrintDialog *printDialog;
173 QPrintPreviewWidget *preview;
174 QPrinter *printer;
175 bool ownPrinter;
176 bool initialized;
177
178 // widgets:
179 QLineEdit *pageNumEdit;
180 QLabel *pageNumLabel;
181 QComboBox *zoomFactor;
182
183 // actions:
184 QActionGroup* navGroup;
185 QAction *nextPageAction;
186 QAction *prevPageAction;
187 QAction *firstPageAction;
188 QAction *lastPageAction;
189
190 QActionGroup* fitGroup;
191 QAction *fitWidthAction;
192 QAction *fitPageAction;
193
194 QActionGroup* zoomGroup;
195 QAction *zoomInAction;
196 QAction *zoomOutAction;
197
198 QActionGroup* orientationGroup;
199 QAction *portraitAction;
200 QAction *landscapeAction;
201
202 QActionGroup* modeGroup;
203 QAction *singleModeAction;
204 QAction *facingModeAction;
205 QAction *overviewModeAction;
206
207 QActionGroup *printerGroup;
208 QAction *printAction;
209 QAction *pageSetupAction;
210#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
211 QAction *closeAction;
212#endif
213
214 QPointer<QObject> receiverToDisconnectOnClose;
215 QByteArray memberToDisconnectOnClose;
216};
217
218void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
219{
220 Q_Q(QPrintPreviewDialog);
221
222 if (_printer) {
223 preview = new QPrintPreviewWidget(_printer, q);
224 printer = _printer;
225 } else {
226 ownPrinter = true;
227 printer = new QPrinter;
228 preview = new QPrintPreviewWidget(printer, q);
229 }
230 QObject::connect(preview, SIGNAL(paintRequested(QPrinter*)), q, SIGNAL(paintRequested(QPrinter*)));
231 QObject::connect(preview, SIGNAL(previewChanged()), q, SLOT(_q_previewChanged()));
232 setupActions();
233
234 pageNumEdit = new LineEdit;
235 pageNumEdit->setAlignment(Qt::AlignRight);
236 pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
237 pageNumLabel = new QLabel;
238 QObject::connect(pageNumEdit, SIGNAL(editingFinished()), q, SLOT(_q_pageNumEdited()));
239
240 zoomFactor = new QComboBox;
241 zoomFactor->setEditable(true);
242 zoomFactor->setMinimumContentsLength(7);
243 zoomFactor->setInsertPolicy(QComboBox::NoInsert);
244 LineEdit *zoomEditor = new LineEdit;
245 zoomEditor->setValidator(new ZoomFactorValidator(1, 1000, 1, zoomEditor));
246 zoomFactor->setLineEdit(zoomEditor);
247 static const short factorsX2[] = { 25, 50, 100, 200, 250, 300, 400, 800, 1600 };
248 for (int i = 0; i < int(sizeof(factorsX2) / sizeof(factorsX2[0])); ++i)
249 zoomFactor->addItem(QPrintPreviewDialog::tr("%1%").arg(factorsX2[i] / 2.0));
250 QObject::connect(zoomFactor->lineEdit(), SIGNAL(editingFinished()),
251 q, SLOT(_q_zoomFactorChanged()));
252 QObject::connect(zoomFactor, SIGNAL(currentIndexChanged(int)),
253 q, SLOT(_q_zoomFactorChanged()));
254
255 QPrintPreviewMainWindow *mw = new QPrintPreviewMainWindow(q);
256 QToolBar *toolbar = new QToolBar(mw);
257 toolbar->addAction(fitWidthAction);
258 toolbar->addAction(fitPageAction);
259 toolbar->addSeparator();
260 toolbar->addWidget(zoomFactor);
261 toolbar->addAction(zoomOutAction);
262 toolbar->addAction(zoomInAction);
263 toolbar->addSeparator();
264 toolbar->addAction(portraitAction);
265 toolbar->addAction(landscapeAction);
266 toolbar->addSeparator();
267 toolbar->addAction(firstPageAction);
268 toolbar->addAction(prevPageAction);
269
270 // this is to ensure the label text and the editor text are
271 // aligned in all styles - the extra QVBoxLayout is a workaround
272 // for bug in QFormLayout
273 QWidget *pageEdit = new QWidget(toolbar);
274 QVBoxLayout *vboxLayout = new QVBoxLayout;
275 vboxLayout->setContentsMargins(0, 0, 0, 0);
276#ifdef Q_WS_MAC
277 // We query the widgets about their size and then we fix the size.
278 // This should do the trick for the laying out part...
279 QSize pageNumEditSize, pageNumLabelSize;
280 pageNumEditSize = pageNumEdit->minimumSizeHint();
281 pageNumLabelSize = pageNumLabel->minimumSizeHint();
282 pageNumEdit->resize(pageNumEditSize);
283 pageNumLabel->resize(pageNumLabelSize);
284#endif
285 QFormLayout *formLayout = new QFormLayout;
286#ifdef Q_WS_MAC
287 // We have to change the growth policy in Mac.
288 formLayout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
289#endif
290 formLayout->setWidget(0, QFormLayout::LabelRole, pageNumEdit);
291 formLayout->setWidget(0, QFormLayout::FieldRole, pageNumLabel);
292 vboxLayout->addLayout(formLayout);
293 vboxLayout->setAlignment(Qt::AlignVCenter);
294 pageEdit->setLayout(vboxLayout);
295 toolbar->addWidget(pageEdit);
296
297 toolbar->addAction(nextPageAction);
298 toolbar->addAction(lastPageAction);
299 toolbar->addSeparator();
300 toolbar->addAction(singleModeAction);
301 toolbar->addAction(facingModeAction);
302 toolbar->addAction(overviewModeAction);
303 toolbar->addSeparator();
304 toolbar->addAction(pageSetupAction);
305 toolbar->addAction(printAction);
306#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
307 toolbar->addAction(closeAction);
308#endif
309
310 // Cannot use the actions' triggered signal here, since it doesn't autorepeat
311 QToolButton *zoomInButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomInAction));
312 QToolButton *zoomOutButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomOutAction));
313 zoomInButton->setAutoRepeat(true);
314 zoomInButton->setAutoRepeatInterval(200);
315 zoomInButton->setAutoRepeatDelay(200);
316 zoomOutButton->setAutoRepeat(true);
317 zoomOutButton->setAutoRepeatInterval(200);
318 zoomOutButton->setAutoRepeatDelay(200);
319 QObject::connect(zoomInButton, SIGNAL(clicked()), q, SLOT(_q_zoomIn()));
320 QObject::connect(zoomOutButton, SIGNAL(clicked()), q, SLOT(_q_zoomOut()));
321
322 mw->addToolBar(toolbar);
323 mw->setCentralWidget(preview);
324 // QMainWindows are always created as top levels, force it to be a
325 // plain widget
326 mw->setParent(q, Qt::Widget);
327
328 QVBoxLayout *topLayout = new QVBoxLayout;
329 topLayout->addWidget(mw);
330 topLayout->setMargin(0);
331 q->setLayout(topLayout);
332
333 QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview");
334 if (!printer->docName().isEmpty())
335 caption += QString::fromLatin1(": ") + printer->docName();
336 q->setWindowTitle(caption);
337
338 if (!printer->isValid()
339#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
340 || printer->outputFormat() != QPrinter::NativeFormat
341#endif
342 )
343 pageSetupAction->setEnabled(false);
344 preview->setFocus();
345}
346
347static inline void qt_setupActionIcon(QAction *action, const QLatin1String &name)
348{
349 QLatin1String imagePrefix(":/trolltech/dialogs/qprintpreviewdialog/images/");
350 QIcon icon;
351 icon.addFile(imagePrefix + name + QLatin1String("-24.png"), QSize(24, 24));
352 icon.addFile(imagePrefix + name + QLatin1String("-32.png"), QSize(32, 32));
353 action->setIcon(icon);
354}
355
356void QPrintPreviewDialogPrivate::setupActions()
357{
358 Q_Q(QPrintPreviewDialog);
359
360 // Navigation
361 navGroup = new QActionGroup(q);
362 navGroup->setExclusive(false);
363 nextPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Next page"));
364 prevPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Previous page"));
365 firstPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "First page"));
366 lastPageAction = navGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Last page"));
367 qt_setupActionIcon(nextPageAction, QLatin1String("go-next"));
368 qt_setupActionIcon(prevPageAction, QLatin1String("go-previous"));
369 qt_setupActionIcon(firstPageAction, QLatin1String("go-first"));
370 qt_setupActionIcon(lastPageAction, QLatin1String("go-last"));
371 QObject::connect(navGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_navigate(QAction*)));
372
373
374 fitGroup = new QActionGroup(q);
375 fitWidthAction = fitGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Fit width"));
376 fitPageAction = fitGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Fit page"));
377 fitWidthAction->setObjectName(QLatin1String("fitWidthAction"));
378 fitPageAction->setObjectName(QLatin1String("fitPageAction"));
379 fitWidthAction->setCheckable(true);
380 fitPageAction->setCheckable(true);
381 qt_setupActionIcon(fitWidthAction, QLatin1String("fit-width"));
382 qt_setupActionIcon(fitPageAction, QLatin1String("fit-page"));
383 QObject::connect(fitGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_fit(QAction*)));
384
385 // Zoom
386 zoomGroup = new QActionGroup(q);
387 zoomInAction = zoomGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Zoom in"));
388 zoomOutAction = zoomGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Zoom out"));
389 qt_setupActionIcon(zoomInAction, QLatin1String("zoom-in"));
390 qt_setupActionIcon(zoomOutAction, QLatin1String("zoom-out"));
391
392 // Portrait/Landscape
393 orientationGroup = new QActionGroup(q);
394 portraitAction = orientationGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Portrait"));
395 landscapeAction = orientationGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Landscape"));
396 portraitAction->setCheckable(true);
397 landscapeAction->setCheckable(true);
398 qt_setupActionIcon(portraitAction, QLatin1String("layout-portrait"));
399 qt_setupActionIcon(landscapeAction, QLatin1String("layout-landscape"));
400 QObject::connect(portraitAction, SIGNAL(triggered(bool)), preview, SLOT(setPortraitOrientation()));
401 QObject::connect(landscapeAction, SIGNAL(triggered(bool)), preview, SLOT(setLandscapeOrientation()));
402
403 // Display mode
404 modeGroup = new QActionGroup(q);
405 singleModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show single page"));
406 facingModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show facing pages"));
407 overviewModeAction = modeGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Show overview of all pages"));
408 qt_setupActionIcon(singleModeAction, QLatin1String("view-page-one"));
409 qt_setupActionIcon(facingModeAction, QLatin1String("view-page-sided"));
410 qt_setupActionIcon(overviewModeAction, QLatin1String("view-page-multi"));
411 singleModeAction->setObjectName(QLatin1String("singleModeAction"));
412 facingModeAction->setObjectName(QLatin1String("facingModeAction"));
413 overviewModeAction->setObjectName(QLatin1String("overviewModeAction"));
414
415 singleModeAction->setCheckable(true);
416 facingModeAction->setCheckable(true);
417 overviewModeAction->setCheckable(true);
418 QObject::connect(modeGroup, SIGNAL(triggered(QAction*)), q, SLOT(_q_setMode(QAction*)));
419
420 // Print
421 printerGroup = new QActionGroup(q);
422 printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
423 pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
424 qt_setupActionIcon(printAction, QLatin1String("print"));
425 qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
426 QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
427 QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
428#if defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)
429 closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close"));
430 QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject()));
431#endif
432
433 // Initial state:
434 fitPageAction->setChecked(true);
435 singleModeAction->setChecked(true);
436 if (preview->orientation() == QPrinter::Portrait)
437 portraitAction->setChecked(true);
438 else
439 landscapeAction->setChecked(true);
440}
441
442
443bool QPrintPreviewDialogPrivate::isFitting()
444{
445 return (fitGroup->isExclusive()
446 && (fitWidthAction->isChecked() || fitPageAction->isChecked()));
447}
448
449
450void QPrintPreviewDialogPrivate::setFitting(bool on)
451{
452 if (isFitting() == on)
453 return;
454 fitGroup->setExclusive(on);
455 if (on) {
456 QAction* action = fitWidthAction->isChecked() ? fitWidthAction : fitPageAction;
457 action->setChecked(true);
458 if (fitGroup->checkedAction() != action) {
459 // work around exclusitivity problem
460 fitGroup->removeAction(action);
461 fitGroup->addAction(action);
462 }
463 } else {
464 fitWidthAction->setChecked(false);
465 fitPageAction->setChecked(false);
466 }
467}
468
469void QPrintPreviewDialogPrivate::updateNavActions()
470{
471 int curPage = preview->currentPage();
472 int numPages = preview->pageCount();
473 nextPageAction->setEnabled(curPage < numPages);
474 prevPageAction->setEnabled(curPage > 1);
475 firstPageAction->setEnabled(curPage > 1);
476 lastPageAction->setEnabled(curPage < numPages);
477 pageNumEdit->setText(QString::number(curPage));
478}
479
480void QPrintPreviewDialogPrivate::updatePageNumLabel()
481{
482 Q_Q(QPrintPreviewDialog);
483
484 int numPages = preview->pageCount();
485 int maxChars = QString::number(numPages).length();
486 pageNumLabel->setText(QString::fromLatin1("/ %1").arg(numPages));
487 int cyphersWidth = q->fontMetrics().width(QString().fill(QLatin1Char('8'), maxChars));
488 int maxWidth = pageNumEdit->minimumSizeHint().width() + cyphersWidth;
489 pageNumEdit->setMinimumWidth(maxWidth);
490 pageNumEdit->setMaximumWidth(maxWidth);
491 pageNumEdit->setValidator(new QIntValidator(1, numPages, pageNumEdit));
492 // any old one will be deleted later along with its parent pageNumEdit
493}
494
495void QPrintPreviewDialogPrivate::updateZoomFactor()
496{
497 zoomFactor->lineEdit()->setText(QString().sprintf("%.1f%%", preview->zoomFactor()*100));
498}
499
500void QPrintPreviewDialogPrivate::_q_fit(QAction* action)
501{
502 setFitting(true);
503 if (action == fitPageAction)
504 preview->fitInView();
505 else
506 preview->fitToWidth();
507}
508
509void QPrintPreviewDialogPrivate::_q_zoomIn()
510{
511 setFitting(false);
512 preview->zoomIn();
513 updateZoomFactor();
514}
515
516void QPrintPreviewDialogPrivate::_q_zoomOut()
517{
518 setFitting(false);
519 preview->zoomOut();
520 updateZoomFactor();
521}
522
523void QPrintPreviewDialogPrivate::_q_pageNumEdited()
524{
525 bool ok = false;
526 int res = pageNumEdit->text().toInt(&ok);
527 if (ok)
528 preview->setCurrentPage(res);
529}
530
531void QPrintPreviewDialogPrivate::_q_navigate(QAction* action)
532{
533 int curPage = preview->currentPage();
534 if (action == prevPageAction)
535 preview->setCurrentPage(curPage - 1);
536 else if (action == nextPageAction)
537 preview->setCurrentPage(curPage + 1);
538 else if (action == firstPageAction)
539 preview->setCurrentPage(1);
540 else if (action == lastPageAction)
541 preview->setCurrentPage(preview->pageCount());
542 updateNavActions();
543}
544
545void QPrintPreviewDialogPrivate::_q_setMode(QAction* action)
546{
547 if (action == overviewModeAction) {
548 preview->setViewMode(QPrintPreviewWidget::AllPagesView);
549 setFitting(false);
550 fitGroup->setEnabled(false);
551 navGroup->setEnabled(false);
552 pageNumEdit->setEnabled(false);
553 pageNumLabel->setEnabled(false);
554 } else if (action == facingModeAction) {
555 preview->setViewMode(QPrintPreviewWidget::FacingPagesView);
556 } else {
557 preview->setViewMode(QPrintPreviewWidget::SinglePageView);
558 }
559 if (action == facingModeAction || action == singleModeAction) {
560 fitGroup->setEnabled(true);
561 navGroup->setEnabled(true);
562 pageNumEdit->setEnabled(true);
563 pageNumLabel->setEnabled(true);
564 setFitting(true);
565 }
566}
567
568void QPrintPreviewDialogPrivate::_q_print()
569{
570 Q_Q(QPrintPreviewDialog);
571
572#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
573 if (printer->outputFormat() != QPrinter::NativeFormat) {
574 QString title;
575 QString suffix;
576 if (printer->outputFormat() == QPrinter::PdfFormat) {
577 title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PDF");
578 suffix = QLatin1String(".pdf");
579 } else {
580 title = QCoreApplication::translate("QPrintPreviewDialog", "Export to PostScript");
581 suffix = QLatin1String(".ps");
582 }
583 QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
584 QLatin1Char('*') + suffix);
585 if (!fileName.isEmpty()) {
586 if (QFileInfo(fileName).suffix().isEmpty())
587 fileName.append(suffix);
588 printer->setOutputFileName(fileName);
589 }
590 if (!printer->outputFileName().isEmpty())
591 preview->print();
592 q->accept();
593 return;
594 }
595#endif
596
597 if (!printDialog)
598 printDialog = new QPrintDialog(printer, q);
599 if (printDialog->exec() == QDialog::Accepted) {
600 preview->print();
601 q->accept();
602 }
603}
604
605void QPrintPreviewDialogPrivate::_q_pageSetup()
606{
607 Q_Q(QPrintPreviewDialog);
608
609 QPageSetupDialog pageSetup(printer, q);
610 if (pageSetup.exec() == QDialog::Accepted) {
611 // update possible orientation changes
612 if (preview->orientation() == QPrinter::Portrait) {
613 portraitAction->setChecked(true);
614 preview->setPortraitOrientation();
615 }else {
616 landscapeAction->setChecked(true);
617 preview->setLandscapeOrientation();
618 }
619 }
620}
621
622void QPrintPreviewDialogPrivate::_q_previewChanged()
623{
624 updateNavActions();
625 updatePageNumLabel();
626 updateZoomFactor();
627}
628
629void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
630{
631 QString text = zoomFactor->lineEdit()->text();
632 bool ok;
633 qreal factor = text.remove(QLatin1Char('%')).toFloat(&ok);
634 factor = qMax(qreal(1.0), qMin(qreal(1000.0), factor));
635 if (ok) {
636 preview->setZoomFactor(factor/100.0);
637 zoomFactor->setEditText(QString::fromLatin1("%1%").arg(factor));
638 setFitting(false);
639 }
640}
641
642///////////////////////////////////////////////////////////////////////////
643
644/*!
645 \class QPrintPreviewDialog
646 \since 4.4
647
648 \brief The QPrintPreviewDialog class provides a dialog for
649 previewing and configuring page layouts for printer output.
650
651 \ingroup standard-dialogs
652 \ingroup printing
653
654 Using QPrintPreviewDialog in your existing application is
655 straightforward:
656
657 \list 1
658 \o Create the QPrintPreviewDialog.
659
660 You can construct a QPrintPreviewDialog with an existing QPrinter
661 object, or you can have QPrintPreviewDialog create one for you,
662 which will be the system default printer.
663
664 \o Connect the paintRequested() signal to a slot.
665
666 When the dialog needs to generate a set of preview pages, the
667 paintRequested() signal will be emitted. You can use the exact
668 same code for the actual printing as for having the preview
669 generated, including calling QPrinter::newPage() to start a new
670 page in the preview. Connect a slot to the paintRequested()
671 signal, where you draw onto the QPrinter object that is passed
672 into the slot.
673
674 \o Call exec().
675
676 Call QPrintPreviewDialog::exec() to show the preview dialog.
677 \endlist
678
679 In Symbian, there is no support for printing. Hence, this dialog should not
680 be used in Symbian.
681
682 \sa QPrinter, QPrintDialog, QPageSetupDialog, QPrintPreviewWidget
683*/
684
685/*!
686 Constructs a QPrintPreviewDialog based on \a printer and with \a
687 parent as the parent widget. The widget flags \a flags are passed on
688 to the QWidget constructor.
689
690 \sa QWidget::setWindowFlags()
691*/
692QPrintPreviewDialog::QPrintPreviewDialog(QPrinter* printer, QWidget *parent, Qt::WindowFlags flags)
693 : QDialog(*new QPrintPreviewDialogPrivate, parent, flags)
694{
695 Q_D(QPrintPreviewDialog);
696 d->init(printer);
697}
698
699/*!
700 \overload
701 \fn QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags flags)
702
703 This will create an internal QPrinter object, which will use the
704 system default printer.
705*/
706QPrintPreviewDialog::QPrintPreviewDialog(QWidget *parent, Qt::WindowFlags f)
707 : QDialog(*new QPrintPreviewDialogPrivate, parent, f)
708{
709 Q_D(QPrintPreviewDialog);
710 d->init();
711}
712
713/*!
714 Destroys the QPrintPreviewDialog.
715*/
716QPrintPreviewDialog::~QPrintPreviewDialog()
717{
718 Q_D(QPrintPreviewDialog);
719 if (d->ownPrinter)
720 delete d->printer;
721 delete d->printDialog;
722}
723
724/*!
725 \reimp
726*/
727void QPrintPreviewDialog::setVisible(bool visible)
728{
729 Q_D(QPrintPreviewDialog);
730 // this will make the dialog get a decent default size
731 if (visible && !d->initialized) {
732 d->preview->updatePreview();
733 d->initialized = true;
734 }
735 QDialog::setVisible(visible);
736}
737
738/*!
739 \reimp
740*/
741void QPrintPreviewDialog::done(int result)
742{
743 Q_D(QPrintPreviewDialog);
744 QDialog::done(result);
745 if (d->receiverToDisconnectOnClose) {
746 disconnect(this, SIGNAL(finished(int)),
747 d->receiverToDisconnectOnClose, d->memberToDisconnectOnClose);
748 d->receiverToDisconnectOnClose = 0;
749 }
750 d->memberToDisconnectOnClose.clear();
751}
752
753/*!
754 \overload
755 \since 4.5
756
757 Opens the dialog and connects its finished(int) signal to the slot specified
758 by \a receiver and \a member.
759
760 The signal will be disconnected from the slot when the dialog is closed.
761*/
762void QPrintPreviewDialog::open(QObject *receiver, const char *member)
763{
764 Q_D(QPrintPreviewDialog);
765 // the int parameter isn't very useful here; we could just as well connect
766 // to reject(), but this feels less robust somehow
767 connect(this, SIGNAL(finished(int)), receiver, member);
768 d->receiverToDisconnectOnClose = receiver;
769 d->memberToDisconnectOnClose = member;
770 QDialog::open();
771}
772
773/*!
774 Returns a pointer to the QPrinter object this dialog is currently
775 operating on.
776*/
777QPrinter *QPrintPreviewDialog::printer()
778{
779 Q_D(QPrintPreviewDialog);
780 return d->printer;
781}
782
783/*!
784 \fn void QPrintPreviewDialog::paintRequested(QPrinter *printer)
785
786 This signal is emitted when the QPrintPreviewDialog needs to generate
787 a set of preview pages.
788
789 The \a printer instance supplied is the paint device onto which you should
790 paint the contents of each page, using the QPrinter instance in the same way
791 as you would when printing directly.
792*/
793
794
795QT_END_NAMESPACE
796
797#include "moc_qprintpreviewdialog.cpp"
798#include "qprintpreviewdialog.moc"
799
800#endif // QT_NO_PRINTPREVIEWDIALOG
801
802
803