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