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 "qprintpreviewwidget.h"
41 #include "private/qwidget_p.h"
42 #include <private/qprinter_p.h>
43 
44 #include <QtCore/qmath.h>
45 #include <QtWidgets/qboxlayout.h>
46 #include <QtWidgets/qgraphicsitem.h>
47 #include <QtWidgets/qgraphicsview.h>
48 #include <QtWidgets/qscrollbar.h>
49 #include <QtWidgets/qstyleoption.h>
50 
51 QT_BEGIN_NAMESPACE
52 
53 namespace {
54 class PageItem : public QGraphicsItem
55 {
56 public:
PageItem(int _pageNum,const QPicture * _pagePicture,QSize _paperSize,QRect _pageRect)57     PageItem(int _pageNum, const QPicture* _pagePicture, QSize _paperSize, QRect _pageRect)
58         : pageNum(_pageNum), pagePicture(_pagePicture),
59           paperSize(_paperSize), pageRect(_pageRect)
60     {
61         qreal border = qMax(paperSize.height(), paperSize.width()) / 25;
62         brect = QRectF(QPointF(-border, -border),
63                        QSizeF(paperSize)+QSizeF(2*border, 2*border));
64         setCacheMode(DeviceCoordinateCache);
65     }
66 
boundingRect() const67     QRectF boundingRect() const override
68     { return brect; }
69 
pageNumber() const70     inline int pageNumber() const
71     { return pageNum; }
72 
73     void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
74 
75 private:
76     int pageNum;
77     const QPicture* pagePicture;
78     QSize paperSize;
79     QRect pageRect;
80     QRectF brect;
81 };
82 
paint(QPainter * painter,const QStyleOptionGraphicsItem * option,QWidget * widget)83 void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
84 {
85     Q_UNUSED(widget);
86 
87 #if 0
88     // Draw item bounding rect, for debugging
89     painter->save();
90     painter->setPen(QPen(Qt::red, 0));
91     painter->setBrush(Qt::NoBrush);
92     painter->drawRect(QRectF(-border()+1.0, -border()+1.0, boundingRect().width()-2, boundingRect().height()-2));
93     painter->restore();
94 #endif
95 
96     QRectF paperRect(0,0, paperSize.width(), paperSize.height());
97 
98     // Draw shadow
99     painter->setClipRect(option->exposedRect);
100     qreal shWidth = paperRect.width()/100;
101     QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth),
102                    paperRect.bottomRight() + QPointF(shWidth, 0));
103     QLinearGradient rgrad(rshadow.topLeft(), rshadow.topRight());
104     rgrad.setColorAt(0.0, QColor(0,0,0,255));
105     rgrad.setColorAt(1.0, QColor(0,0,0,0));
106     painter->fillRect(rshadow, QBrush(rgrad));
107     QRectF bshadow(paperRect.bottomLeft() + QPointF(shWidth, 0),
108                    paperRect.bottomRight() + QPointF(0, shWidth));
109     QLinearGradient bgrad(bshadow.topLeft(), bshadow.bottomLeft());
110     bgrad.setColorAt(0.0, QColor(0,0,0,255));
111     bgrad.setColorAt(1.0, QColor(0,0,0,0));
112     painter->fillRect(bshadow, QBrush(bgrad));
113     QRectF cshadow(paperRect.bottomRight(),
114                    paperRect.bottomRight() + QPointF(shWidth, shWidth));
115     QRadialGradient cgrad(cshadow.topLeft(), shWidth, cshadow.topLeft());
116     cgrad.setColorAt(0.0, QColor(0,0,0,255));
117     cgrad.setColorAt(1.0, QColor(0,0,0,0));
118     painter->fillRect(cshadow, QBrush(cgrad));
119 
120     painter->setClipRect(paperRect & option->exposedRect);
121     painter->fillRect(paperRect, Qt::white);
122     if (!pagePicture)
123         return;
124     painter->drawPicture(pageRect.topLeft(), *pagePicture);
125 
126     // Effect: make anything drawn in the margins look washed out.
127     QPainterPath path;
128     path.addRect(paperRect);
129     path.addRect(pageRect);
130     painter->setPen(QPen(Qt::NoPen));
131     painter->setBrush(QColor(255, 255, 255, 180));
132     painter->drawPath(path);
133 
134 #if 0
135     // Draw frame around paper.
136     painter->setPen(QPen(Qt::black, 0));
137     painter->setBrush(Qt::NoBrush);
138     painter->drawRect(paperRect);
139 #endif
140 
141     // todo: drawtext "Page N" below paper
142 }
143 
144 class GraphicsView : public QGraphicsView
145 {
146     Q_OBJECT
147 public:
GraphicsView(QWidget * parent=nullptr)148     GraphicsView(QWidget* parent = nullptr)
149         : QGraphicsView(parent)
150     {
151 #ifdef Q_OS_MAC
152         setFrameStyle(QFrame::NoFrame);
153 #endif
154     }
155 signals:
156     void resized();
157 
158 protected:
resizeEvent(QResizeEvent * e)159     void resizeEvent(QResizeEvent* e) override
160     {
161         {
162             const QSignalBlocker blocker(verticalScrollBar()); // Don't change page, QTBUG-14517
163             QGraphicsView::resizeEvent(e);
164         }
165         emit resized();
166     }
167 
showEvent(QShowEvent * e)168     void showEvent(QShowEvent* e) override
169     {
170         QGraphicsView::showEvent(e);
171         emit resized();
172     }
173 };
174 
175 } // anonymous namespace
176 
177 class QPrintPreviewWidgetPrivate : public QWidgetPrivate
178 {
179     Q_DECLARE_PUBLIC(QPrintPreviewWidget)
180 public:
QPrintPreviewWidgetPrivate()181     QPrintPreviewWidgetPrivate()
182         : scene(nullptr), curPage(1),
183           viewMode(QPrintPreviewWidget::SinglePageView),
184           zoomMode(QPrintPreviewWidget::FitInView),
185           zoomFactor(1), initialized(false), fitting(true)
186     {}
187 
188     // private slots
189     void _q_fit(bool doFitting = false);
190     void _q_updateCurrentPage();
191 
192     void init();
193     void populateScene();
194     void layoutPages();
195     void generatePreview();
196     void setCurrentPage(int pageNumber);
197     void zoom(qreal zoom);
198     void setZoomFactor(qreal zoomFactor);
199     int calcCurrentPage();
200 
201     GraphicsView *graphicsView;
202     QGraphicsScene *scene;
203 
204     int curPage;
205     QList<const QPicture *> pictures;
206     QList<QGraphicsItem *> pages;
207 
208     QPrintPreviewWidget::ViewMode viewMode;
209     QPrintPreviewWidget::ZoomMode zoomMode;
210     qreal zoomFactor;
211     bool ownPrinter;
212     QPrinter* printer;
213     bool initialized;
214     bool fitting;
215 };
216 
_q_fit(bool doFitting)217 void QPrintPreviewWidgetPrivate::_q_fit(bool doFitting)
218 {
219     Q_Q(QPrintPreviewWidget);
220 
221     if (curPage < 1 || curPage > pages.count())
222         return;
223 
224     if (!doFitting && !fitting)
225         return;
226 
227     if (doFitting && fitting) {
228         QRect viewRect = graphicsView->viewport()->rect();
229         if (zoomMode == QPrintPreviewWidget::FitInView) {
230             const QList<QGraphicsItem*> containedItems = graphicsView->items(viewRect, Qt::ContainsItemBoundingRect);
231             for (QGraphicsItem* item : containedItems) {
232                 PageItem* pg = static_cast<PageItem*>(item);
233                 if (pg->pageNumber() == curPage)
234                     return;
235             }
236         }
237 
238         int newPage = calcCurrentPage();
239         if (newPage != curPage)
240             curPage = newPage;
241     }
242 
243     QRectF target = pages.at(curPage-1)->sceneBoundingRect();
244     if (viewMode == QPrintPreviewWidget::FacingPagesView) {
245         // fit two pages
246         if (curPage % 2)
247             target.setLeft(target.left() - target.width());
248         else
249             target.setRight(target.right() + target.width());
250     } else if (viewMode == QPrintPreviewWidget::AllPagesView) {
251         target = scene->itemsBoundingRect();
252     }
253 
254     if (zoomMode == QPrintPreviewWidget::FitToWidth) {
255         QTransform t;
256         qreal scale = graphicsView->viewport()->width() / target.width();
257         t.scale(scale, scale);
258         graphicsView->setTransform(t);
259         if (doFitting && fitting) {
260             QRectF viewSceneRect = graphicsView->viewportTransform().mapRect(graphicsView->viewport()->rect());
261             viewSceneRect.moveTop(target.top());
262             graphicsView->ensureVisible(viewSceneRect); // Nah...
263         }
264     } else {
265         graphicsView->fitInView(target, Qt::KeepAspectRatio);
266         if (zoomMode == QPrintPreviewWidget::FitInView) {
267             const int step = qRound(graphicsView->transform().mapRect(target).height());
268             graphicsView->verticalScrollBar()->setSingleStep(step);
269             graphicsView->verticalScrollBar()->setPageStep(step);
270         }
271     }
272 
273     zoomFactor = graphicsView->transform().m11() * (float(printer->logicalDpiY()) / q->logicalDpiY());
274     emit q->previewChanged();
275 }
276 
_q_updateCurrentPage()277 void QPrintPreviewWidgetPrivate::_q_updateCurrentPage()
278 {
279     Q_Q(QPrintPreviewWidget);
280 
281     if (viewMode == QPrintPreviewWidget::AllPagesView)
282         return;
283 
284     int newPage = calcCurrentPage();
285     if (newPage != curPage) {
286         curPage = newPage;
287         emit q->previewChanged();
288     }
289 }
290 
calcCurrentPage()291 int QPrintPreviewWidgetPrivate::calcCurrentPage()
292 {
293     int maxArea = 0;
294     int newPage = curPage;
295     QRect viewRect = graphicsView->viewport()->rect();
296     const QList<QGraphicsItem*> items = graphicsView->items(viewRect);
297     for (auto *item : items) {
298         PageItem* pg = static_cast<PageItem*>(item);
299         QRect overlap = graphicsView->mapFromScene(pg->sceneBoundingRect()).boundingRect() & viewRect;
300         int area = overlap.width() * overlap.height();
301         if (area > maxArea) {
302             maxArea = area;
303             newPage = pg->pageNumber();
304         } else if (area == maxArea && pg->pageNumber() < newPage) {
305             newPage = pg->pageNumber();
306         }
307     }
308     return newPage;
309 }
310 
init()311 void QPrintPreviewWidgetPrivate::init()
312 {
313     Q_Q(QPrintPreviewWidget);
314 
315     graphicsView = new GraphicsView;
316     graphicsView->setInteractive(false);
317     graphicsView->setDragMode(QGraphicsView::ScrollHandDrag);
318     graphicsView->setViewportUpdateMode(QGraphicsView::SmartViewportUpdate);
319     QObject::connect(graphicsView->verticalScrollBar(), SIGNAL(valueChanged(int)),
320                      q, SLOT(_q_updateCurrentPage()));
321     QObject::connect(graphicsView, SIGNAL(resized()), q, SLOT(_q_fit()));
322 
323     scene = new QGraphicsScene(graphicsView);
324     scene->setBackgroundBrush(Qt::gray);
325     graphicsView->setScene(scene);
326 
327     QVBoxLayout *layout = new QVBoxLayout(q);
328     layout->setContentsMargins(0, 0, 0, 0);
329     layout->addWidget(graphicsView);
330 }
331 
populateScene()332 void QPrintPreviewWidgetPrivate::populateScene()
333 {
334     // remove old pages
335     for (auto *page : qAsConst(pages))
336         scene->removeItem(page);
337     qDeleteAll(pages);
338     pages.clear();
339 
340     QSize paperSize = printer->pageLayout().fullRectPixels(printer->resolution()).size();
341     QRect pageRect = printer->pageLayout().paintRectPixels(printer->resolution());
342 
343     int page = 1;
344     for (auto *picture : qAsConst(pictures)) {
345         PageItem* item = new PageItem(page++, picture, paperSize, pageRect);
346         scene->addItem(item);
347         pages.append(item);
348     }
349 }
350 
layoutPages()351 void QPrintPreviewWidgetPrivate::layoutPages()
352 {
353     int numPages = pages.count();
354     if (numPages < 1)
355         return;
356 
357     int numPagePlaces = numPages;
358     int cols = 1; // singleMode and default
359     if (viewMode == QPrintPreviewWidget::AllPagesView) {
360         if (printer->pageLayout().orientation() == QPageLayout::Portrait)
361             cols = qCeil(qSqrt((float) numPages));
362         else
363             cols = qFloor(qSqrt((float) numPages));
364         cols += cols % 2;  // Nicer with an even number of cols
365     }
366     else if (viewMode == QPrintPreviewWidget::FacingPagesView) {
367         cols = 2;
368         numPagePlaces += 1;
369     }
370     int rows = qCeil(qreal(numPagePlaces) / cols);
371 
372     qreal itemWidth = pages.at(0)->boundingRect().width();
373     qreal itemHeight = pages.at(0)->boundingRect().height();
374     int pageNum = 1;
375     for (int i = 0; i < rows && pageNum <= numPages; i++) {
376         for (int j = 0; j < cols && pageNum <= numPages; j++) {
377             if (!i && !j && viewMode == QPrintPreviewWidget::FacingPagesView) {
378                 // Front page doesn't have a facing page
379                 continue;
380             } else {
381                 pages.at(pageNum-1)->setPos(QPointF(j*itemWidth, i*itemHeight));
382                 pageNum++;
383             }
384         }
385     }
386     scene->setSceneRect(scene->itemsBoundingRect());
387 }
388 
generatePreview()389 void QPrintPreviewWidgetPrivate::generatePreview()
390 {
391     //### If QPrinter::setPreviewMode() becomes public, handle the
392     //### case that we have been constructed with a printer that
393     //### _already_ has been preview-painted to, so we should
394     //### initially just show the pages it already contains, and not
395     //### emit paintRequested() until the user changes some parameter
396 
397     Q_Q(QPrintPreviewWidget);
398     printer->d_func()->setPreviewMode(true);
399     emit q->paintRequested(printer);
400     printer->d_func()->setPreviewMode(false);
401     pictures = printer->d_func()->previewPages();
402     populateScene(); // i.e. setPreviewPrintedPictures() e.l.
403     layoutPages();
404     curPage = qBound(1, curPage, pages.count());
405     if (fitting)
406         _q_fit();
407     emit q->previewChanged();
408 }
409 
setCurrentPage(int pageNumber)410 void QPrintPreviewWidgetPrivate::setCurrentPage(int pageNumber)
411 {
412     if (pageNumber < 1 || pageNumber > pages.count())
413         return;
414 
415     int lastPage = curPage;
416     curPage = pageNumber;
417 
418     if (lastPage != curPage && lastPage > 0 && lastPage <= pages.count()) {
419         if (zoomMode != QPrintPreviewWidget::FitInView) {
420             QScrollBar *hsc = graphicsView->horizontalScrollBar();
421             QScrollBar *vsc = graphicsView->verticalScrollBar();
422             QPointF pt = graphicsView->transform().map(pages.at(curPage-1)->pos());
423             vsc->setValue(int(pt.y()) - 10);
424             hsc->setValue(int(pt.x()) - 10);
425         } else {
426             graphicsView->centerOn(pages.at(curPage-1));
427         }
428     }
429 }
430 
zoom(qreal zoom)431 void QPrintPreviewWidgetPrivate::zoom(qreal zoom)
432 {
433     zoomFactor *= zoom;
434     graphicsView->scale(zoom, zoom);
435 }
436 
setZoomFactor(qreal _zoomFactor)437 void QPrintPreviewWidgetPrivate::setZoomFactor(qreal _zoomFactor)
438 {
439     Q_Q(QPrintPreviewWidget);
440     zoomFactor = _zoomFactor;
441     graphicsView->resetTransform();
442     int dpi_y = q->logicalDpiY();
443     int printer_dpi_y = printer->logicalDpiY();
444     graphicsView->scale(zoomFactor*(dpi_y/float(printer_dpi_y)),
445                         zoomFactor*(dpi_y/float(printer_dpi_y)));
446 }
447 
448 ///////////////////////////////////////
449 
450 /*!
451     \class QPrintPreviewWidget
452     \since 4.4
453 
454     \brief The QPrintPreviewWidget class provides a widget for
455     previewing page layouts for printer output.
456 
457     \ingroup printing
458     \inmodule QtPrintSupport
459 
460     QPrintPreviewDialog uses a QPrintPreviewWidget internally, and the
461     purpose of QPrintPreviewWidget is to make it possible to embed the
462     preview into other widgets. It also makes it possible to build a different
463     user interface around it than the default one provided with QPrintPreviewDialog.
464 
465     Using QPrintPreviewWidget is straightforward:
466 
467     \list 1
468     \li Create the QPrintPreviewWidget
469 
470     Construct the QPrintPreviewWidget either by passing in an
471     existing QPrinter object, or have QPrintPreviewWidget create a
472     default constructed QPrinter object for you.
473 
474     \li Connect the paintRequested() signal to a slot.
475 
476     When the widget needs to generate a set of preview pages, a
477     paintRequested() signal will be emitted from the widget. Connect a
478     slot to this signal, and draw onto the QPrinter passed in as a
479     signal parameter. Call QPrinter::newPage(), to start a new
480     page in the preview.
481 
482     \endlist
483 
484     \sa QPrinter, QPrintDialog, QPageSetupDialog, QPrintPreviewDialog
485 */
486 
487 
488 /*!
489     \enum QPrintPreviewWidget::ViewMode
490 
491     This enum is used to describe the view mode of the preview widget.
492 
493     \value SinglePageView   A mode where single pages in the preview
494                             is viewed.
495 
496     \value FacingPagesView  A mode where the facing pages in the preview
497                             is viewed.
498 
499     \value AllPagesView     A view mode where all the pages in the preview
500                             is viewed.
501 */
502 
503 /*!
504     \enum QPrintPreviewWidget::ZoomMode
505 
506     This enum is used to describe zoom mode of the preview widget.
507 
508     \value CustomZoom  The zoom is set to a custom zoom value.
509 
510     \value FitToWidth  This mode fits the current page to the width of the view.
511 
512     \value FitInView   This mode fits the current page inside the view.
513 
514 */
515 
516 /*!
517     Constructs a QPrintPreviewWidget based on \a printer and with \a
518     parent as the parent widget. The widget flags \a flags are passed on
519     to the QWidget constructor.
520 
521     \sa QWidget::setWindowFlags()
522 */
QPrintPreviewWidget(QPrinter * printer,QWidget * parent,Qt::WindowFlags flags)523 QPrintPreviewWidget::QPrintPreviewWidget(QPrinter *printer, QWidget *parent, Qt::WindowFlags flags)
524     : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
525 {
526     Q_D(QPrintPreviewWidget);
527     d->printer = printer;
528     d->ownPrinter = false;
529     d->init();
530 }
531 
532 /*!
533     \overload
534 
535     This will cause QPrintPreviewWidget to create an internal, default
536     constructed QPrinter object, which will be used to generate the
537     preview.
538 */
QPrintPreviewWidget(QWidget * parent,Qt::WindowFlags flags)539 QPrintPreviewWidget::QPrintPreviewWidget(QWidget *parent, Qt::WindowFlags flags)
540     : QWidget(*new QPrintPreviewWidgetPrivate, parent, flags)
541 {
542     Q_D(QPrintPreviewWidget);
543     d->printer = new QPrinter;
544     d->ownPrinter = true;
545     d->init();
546 }
547 
548 
549 /*!
550     Destroys the QPrintPreviewWidget.
551 */
~QPrintPreviewWidget()552 QPrintPreviewWidget::~QPrintPreviewWidget()
553 {
554     Q_D(QPrintPreviewWidget);
555     if (d->ownPrinter)
556         delete d->printer;
557 }
558 
559 /*!
560     Returns the current view mode. The default view mode is SinglePageView.
561 */
viewMode() const562 QPrintPreviewWidget::ViewMode QPrintPreviewWidget::viewMode() const
563 {
564     Q_D(const QPrintPreviewWidget);
565     return d->viewMode;
566 }
567 
568 /*!
569     Sets the view mode to \a mode. The default view mode is
570     SinglePageView.
571 */
setViewMode(ViewMode mode)572 void QPrintPreviewWidget::setViewMode(ViewMode mode)
573 {
574     Q_D(QPrintPreviewWidget);
575     d->viewMode = mode;
576     d->layoutPages();
577     if (d->viewMode == AllPagesView) {
578         d->graphicsView->fitInView(d->scene->itemsBoundingRect(), Qt::KeepAspectRatio);
579         d->fitting = false;
580         d->zoomMode = QPrintPreviewWidget::CustomZoom;
581         d->zoomFactor = d->graphicsView->transform().m11() * (float(d->printer->logicalDpiY()) / logicalDpiY());
582         emit previewChanged();
583     } else {
584         d->fitting = true;
585         d->_q_fit();
586     }
587 }
588 
589 /*!
590     Returns the current orientation of the preview. This value is
591     obtained from the QPrinter object associated with the preview.
592 */
orientation() const593 QPrinter::Orientation QPrintPreviewWidget::orientation() const
594 {
595     Q_D(const QPrintPreviewWidget);
596     return d->printer->pageLayout().orientation() == QPageLayout::Portrait
597            ? QPrinter::Portrait : QPrinter::Landscape;
598 }
599 
600 /*!
601     Sets the current orientation to \a orientation. This value will be
602     set on the QPrinter object associated with the preview.
603 */
setOrientation(QPrinter::Orientation orientation)604 void QPrintPreviewWidget::setOrientation(QPrinter::Orientation orientation)
605 {
606     Q_D(QPrintPreviewWidget);
607     d->printer->setPageOrientation(orientation == QPrinter::Portrait
608                                    ? QPageLayout::Portrait : QPageLayout::Landscape);
609     d->generatePreview();
610 }
611 
612 /*!
613     Prints the preview to the printer associated with the preview.
614 */
print()615 void QPrintPreviewWidget::print()
616 {
617     Q_D(QPrintPreviewWidget);
618     // ### make use of the generated pages
619     emit paintRequested(d->printer);
620 }
621 
622 /*!
623     Zooms the current view in by \a factor. The default value for \a
624     factor is 1.1, which means the view will be scaled up by 10%.
625 */
zoomIn(qreal factor)626 void QPrintPreviewWidget::zoomIn(qreal factor)
627 {
628     Q_D(QPrintPreviewWidget);
629     d->fitting = false;
630     d->zoomMode = QPrintPreviewWidget::CustomZoom;
631     d->zoom(factor);
632 }
633 
634 /*!
635     Zooms the current view out by \a factor. The default value for \a
636     factor is 1.1, which means the view will be scaled down by 10%.
637 */
zoomOut(qreal factor)638 void QPrintPreviewWidget::zoomOut(qreal factor)
639 {
640     Q_D(QPrintPreviewWidget);
641     d->fitting = false;
642     d->zoomMode = QPrintPreviewWidget::CustomZoom;
643     d->zoom(1/factor);
644 }
645 
646 /*!
647     Returns the zoom factor of the view.
648 */
zoomFactor() const649 qreal QPrintPreviewWidget::zoomFactor() const
650 {
651     Q_D(const QPrintPreviewWidget);
652     return d->zoomFactor;
653 }
654 
655 /*!
656     Sets the zoom factor of the view to \a factor. For example, a
657     value of 1.0 indicates an unscaled view, which is approximately
658     the size the view will have on paper. A value of 0.5 will halve
659     the size of the view, while a value of 2.0 will double the size of
660     the view.
661 */
setZoomFactor(qreal factor)662 void QPrintPreviewWidget::setZoomFactor(qreal factor)
663 {
664     Q_D(QPrintPreviewWidget);
665     d->fitting = false;
666     d->zoomMode = QPrintPreviewWidget::CustomZoom;
667     d->setZoomFactor(factor);
668 }
669 
670 /*!
671     \since 4.6
672     Returns the number of pages in the preview.
673 */
pageCount() const674 int QPrintPreviewWidget::pageCount() const
675 {
676     Q_D(const QPrintPreviewWidget);
677     return d->pages.size();
678 }
679 
680 /*!
681     Returns the currently viewed page in the preview.
682 */
currentPage() const683 int QPrintPreviewWidget::currentPage() const
684 {
685     Q_D(const QPrintPreviewWidget);
686     return d->curPage;
687 }
688 
689 /*!
690     Sets the current page in the preview. This will cause the view to
691     skip to the beginning of \a page.
692 */
setCurrentPage(int page)693 void QPrintPreviewWidget::setCurrentPage(int page)
694 {
695     Q_D(QPrintPreviewWidget);
696     d->setCurrentPage(page);
697 }
698 
699 /*!
700     This is a convenience function and is the same as calling \c
701     {setZoomMode(QPrintPreviewWidget::FitToWidth)}.
702 */
fitToWidth()703 void QPrintPreviewWidget::fitToWidth()
704 {
705     setZoomMode(FitToWidth);
706 }
707 
708 /*!
709     This is a convenience function and is the same as calling \c
710     {setZoomMode(QPrintPreviewWidget::FitInView)}.
711 */
fitInView()712 void QPrintPreviewWidget::fitInView()
713 {
714     setZoomMode(FitInView);
715 }
716 
717 /*!
718     Sets the zoom mode to \a zoomMode. The default zoom mode is FitInView.
719 
720     \sa zoomMode(), viewMode(), setViewMode()
721 */
setZoomMode(QPrintPreviewWidget::ZoomMode zoomMode)722 void QPrintPreviewWidget::setZoomMode(QPrintPreviewWidget::ZoomMode zoomMode)
723 {
724     Q_D(QPrintPreviewWidget);
725     d->zoomMode = zoomMode;
726     if (d->zoomMode == FitInView || d->zoomMode == FitToWidth) {
727         d->fitting = true;
728         d->_q_fit(true);
729     } else {
730         d->fitting = false;
731     }
732 }
733 
734 /*!
735     Returns the current zoom mode.
736 
737     \sa setZoomMode(), viewMode(), setViewMode()
738 */
zoomMode() const739 QPrintPreviewWidget::ZoomMode QPrintPreviewWidget::zoomMode() const
740 {
741     Q_D(const QPrintPreviewWidget);
742     return d->zoomMode;
743 }
744 
745 /*!
746     This is a convenience function and is the same as calling \c
747     {setOrientation(QPrinter::Landscape)}.
748 */
setLandscapeOrientation()749 void QPrintPreviewWidget::setLandscapeOrientation()
750 {
751     setOrientation(QPrinter::Landscape);
752 }
753 
754 /*!
755     This is a convenience function and is the same as calling \c
756     {setOrientation(QPrinter::Portrait)}.
757 */
setPortraitOrientation()758 void QPrintPreviewWidget::setPortraitOrientation()
759 {
760     setOrientation(QPrinter::Portrait);
761 }
762 
763 /*!
764     This is a convenience function and is the same as calling \c
765     {setViewMode(QPrintPreviewWidget::SinglePageView)}.
766 */
setSinglePageViewMode()767 void QPrintPreviewWidget::setSinglePageViewMode()
768 {
769     setViewMode(SinglePageView);
770 }
771 
772 /*!
773     This is a convenience function and is the same as calling \c
774     {setViewMode(QPrintPreviewWidget::FacingPagesView)}.
775 */
setFacingPagesViewMode()776 void QPrintPreviewWidget::setFacingPagesViewMode()
777 {
778     setViewMode(FacingPagesView);
779 }
780 
781 /*!
782     This is a convenience function and is the same as calling \c
783     {setViewMode(QPrintPreviewWidget::AllPagesView)}.
784 */
setAllPagesViewMode()785 void QPrintPreviewWidget::setAllPagesViewMode()
786 {
787     setViewMode(AllPagesView);
788 }
789 
790 
791 /*!
792     This function updates the preview, which causes the
793     paintRequested() signal to be emitted.
794 */
updatePreview()795 void QPrintPreviewWidget::updatePreview()
796 {
797     Q_D(QPrintPreviewWidget);
798     d->initialized = true;
799     d->generatePreview();
800     d->graphicsView->updateGeometry();
801 }
802 
803 /*! \reimp
804 */
setVisible(bool visible)805 void QPrintPreviewWidget::setVisible(bool visible)
806 {
807     Q_D(QPrintPreviewWidget);
808     if (visible && !d->initialized)
809         updatePreview();
810     QWidget::setVisible(visible);
811 }
812 
813 /*!
814     \fn void QPrintPreviewWidget::paintRequested(QPrinter *printer)
815 
816     This signal is emitted when the preview widget needs to generate a
817     set of preview pages. \a printer is the printer associated with
818     this preview widget.
819 */
820 
821 /*!
822     \fn void QPrintPreviewWidget::previewChanged()
823 
824     This signal is emitted whenever the preview widget has changed
825     some internal state, such as the orientation.
826 */
827 
828 
829 QT_END_NAMESPACE
830 
831 #include "moc_qprintpreviewwidget.cpp"
832 #include "qprintpreviewwidget.moc"
833