Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qpdfview.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Tobias König <tobias.koenig@kdab.com>
2// Copyright (C) 2022 The Qt Company Ltd.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include "qpdfview.h"
6#include "qpdfview_p.h"
8#include <QtPdf/private/qtpdfglobal_p.h>
9
10#include <QGuiApplication>
11#include <QLoggingCategory>
12#include <QPainter>
13#include <QPaintEvent>
14#include <QPdfDocument>
15#include <QPdfPageNavigator>
16#include <QPdfSearchModel>
17#include <QScreen>
18#include <QScrollBar>
19
21
22Q_PDF_LOGGING_CATEGORY(qLcWLink, "qt.pdf.widgets.links")
23//#define DEBUG_LINKS
24
25static const QColor SearchResultHighlight("#80B0C4DE");
27static const int CurrentSearchResultWidth(2);
28
29QPdfViewPrivate::QPdfViewPrivate(QPdfView *q)
30 : q_ptr(q)
31 , m_document(nullptr)
32 , m_pageNavigator(nullptr)
33 , m_pageRenderer(nullptr)
34 , m_pageMode(QPdfView::PageMode::SinglePage)
35 , m_zoomMode(QPdfView::ZoomMode::Custom)
36 , m_zoomFactor(1.0)
37 , m_pageSpacing(3)
38 , m_documentMargins(6, 6, 6, 6)
41 , m_screenResolution(QGuiApplication::primaryScreen()->logicalDotsPerInch() / 72.0)
42{
43}
44
46{
47 Q_Q(QPdfView);
48
49 m_pageNavigator = new QPdfPageNavigator(q);
50 m_pageRenderer = new QPdfPageRenderer(q);
51 m_pageRenderer->setRenderMode(QPdfPageRenderer::RenderMode::MultiThreaded);
52}
53
59
60void QPdfViewPrivate::currentPageChanged(int currentPage)
61{
62 Q_Q(QPdfView);
63
65 return;
66
67 q->verticalScrollBar()->setValue(yPositionForPage(currentPage));
68
69 if (m_pageMode == QPdfView::PageMode::SinglePage)
71}
72
74{
75 Q_Q(QPdfView);
76
77 const int x = q->horizontalScrollBar()->value();
78 const int y = q->verticalScrollBar()->value();
79 const int width = q->viewport()->width();
80 const int height = q->viewport()->height();
81
82 setViewport(QRect(x, y, width, height));
83}
84
85void QPdfViewPrivate::setViewport(QRect viewport)
86{
87 if (m_viewport == viewport)
88 return;
89
90 const QSize oldSize = m_viewport.size();
91
92 m_viewport = viewport;
93
94 if (oldSize != m_viewport.size()) {
96
97 if (m_zoomMode != QPdfView::ZoomMode::Custom) {
99 }
100 }
101
102 if (m_pageMode == QPdfView::PageMode::MultiPage) {
103 // An imaginary, 2px height line at the upper half of the viewport, which is used to
104 // determine which page is currently located there -> we propagate that as 'current' page
105 // to the QPdfPageNavigator object
106 const QRect currentPageLine(m_viewport.x(), m_viewport.y() + m_viewport.height() * 0.4, m_viewport.width(), 2);
107
108 int currentPage = 0;
109 for (auto it = m_documentLayout.pageGeometryAndScale.cbegin();
110 it != m_documentLayout.pageGeometryAndScale.cend(); ++it) {
111 const QRect pageGeometry = it.value().first;
112 if (pageGeometry.intersects(currentPageLine)) {
113 currentPage = it.key();
114 break;
115 }
116 }
117
118 if (currentPage != m_pageNavigator->currentPage()) {
120 // ΤODO give location on the page
121 m_pageNavigator->jump(currentPage, {}, m_zoomFactor);
122 m_blockPageScrolling = false;
123 }
124 }
125}
126
128{
129 Q_Q(QPdfView);
130
131 const QSize p = q->viewport()->size();
132 const QSize v = m_documentLayout.documentSize;
133
134 q->horizontalScrollBar()->setRange(0, v.width() - p.width());
135 q->horizontalScrollBar()->setPageStep(p.width());
136 q->verticalScrollBar()->setRange(0, v.height() - p.height());
137 q->verticalScrollBar()->setPageStep(p.height());
138}
139
140void QPdfViewPrivate::pageRendered(int pageNumber, QSize imageSize, const QImage &image, quint64 requestId)
141{
142 Q_Q(QPdfView);
143
144 Q_UNUSED(imageSize);
145 Q_UNUSED(requestId);
146
147 if (!m_cachedPagesLRU.contains(pageNumber)) {
148 if (m_cachedPagesLRU.size() > m_pageCacheLimit)
149 m_pageCache.remove(m_cachedPagesLRU.takeFirst());
150
151 m_cachedPagesLRU.append(pageNumber);
152 }
153
154 m_pageCache.insert(pageNumber, image);
155
156 q->viewport()->update();
157}
158
164
166{
167 Q_Q(QPdfView);
168
169 m_pageCache.clear();
170 q->viewport()->update();
171}
172
174{
175 // The DocumentLayout describes a virtual layout where all pages are positioned inside
176 // - For SinglePage mode, this is just an area as large as the current page surrounded
177 // by the m_documentMargins.
178 // - For MultiPage mode, this is the area that is covered by all pages which are placed
179 // below each other, with m_pageSpacing inbetween and surrounded by m_documentMargins
180
181 DocumentLayout documentLayout;
182
183 if (!m_document || m_document->status() != QPdfDocument::Status::Ready)
184 return documentLayout;
185
186 QHash<int, QPair<QRect, qreal>> pageGeometryAndScale;
187
188 const int pageCount = m_document->pageCount();
189
190 int totalWidth = 0;
191
192 const int startPage = (m_pageMode == QPdfView::PageMode::SinglePage ? m_pageNavigator->currentPage() : 0);
193 const int endPage = (m_pageMode == QPdfView::PageMode::SinglePage ? m_pageNavigator->currentPage() + 1 : pageCount);
194
195 // calculate page sizes
196 for (int page = startPage; page < endPage; ++page) {
197 QSize pageSize;
198 qreal pageScale = m_zoomFactor;
199 if (m_zoomMode == QPdfView::ZoomMode::Custom) {
200 pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution * m_zoomFactor).toSize();
201 } else if (m_zoomMode == QPdfView::ZoomMode::FitToWidth) {
202 pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize();
203 pageScale = (qreal(m_viewport.width() - m_documentMargins.left() - m_documentMargins.right()) /
204 qreal(pageSize.width()));
205 pageSize *= pageScale;
206 } else if (m_zoomMode == QPdfView::ZoomMode::FitInView) {
207 const QSize viewportSize(m_viewport.size() +
208 QSize(-m_documentMargins.left() - m_documentMargins.right(), -m_pageSpacing));
209
210 pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize();
211 QSize scaledSize = pageSize.scaled(viewportSize, Qt::KeepAspectRatio);
212 // because of KeepAspectRatio, the ratio of widths should be the same as the ratio of heights
213 pageScale = qreal(scaledSize.width()) / qreal(pageSize.width());
214 pageSize = scaledSize;
215 }
216
217 totalWidth = qMax(totalWidth, pageSize.width());
218
219 pageGeometryAndScale[page] = {QRect(QPoint(0, 0), pageSize), pageScale};
220 }
221
222 totalWidth += m_documentMargins.left() + m_documentMargins.right();
223
224 int pageY = m_documentMargins.top();
225
226 // calculate page positions
227 for (int page = startPage; page < endPage; ++page) {
228 const QSize pageSize = pageGeometryAndScale[page].first.size();
229
230 // center horizontal inside the viewport
231 const int pageX = (qMax(totalWidth, m_viewport.width()) - pageSize.width()) / 2;
232
233 pageGeometryAndScale[page].first.moveTopLeft(QPoint(pageX, pageY));
234
235 pageY += pageSize.height() + m_pageSpacing;
236 }
237
238 pageY += m_documentMargins.bottom();
239
240 documentLayout.pageGeometryAndScale = pageGeometryAndScale;
241
242 // calculate overall document size
243 documentLayout.documentSize = QSize(totalWidth, pageY);
244
245 return documentLayout;
246}
247
249{
250 const auto it = m_documentLayout.pageGeometryAndScale.constFind(pageNumber);
251 if (it == m_documentLayout.pageGeometryAndScale.cend())
252 return 0.0;
253
254 return (*it).first.y();
255}
256
258{
259 qreal scale = m_screenResolution * m_zoomFactor;
260 switch (m_zoomMode) {
261 case QPdfView::ZoomMode::FitToWidth:
262 case QPdfView::ZoomMode::FitInView:
263 scale = m_screenResolution * m_documentLayout.pageGeometryAndScale[page].second;
264 break;
265 default:
266 break;
267 }
268
269 return QTransform::fromScale(scale, scale);
270}
271
273{
274 m_documentLayout = calculateDocumentLayout();
275
277}
278
279/*!
280 \class QPdfView
281 \inmodule QtPdf
282 \brief A PDF viewer widget.
283
284 QPdfView is a PDF viewer widget that offers a user experience similar to
285 many common PDF viewer applications, with two \l {pageMode}{modes}.
286 In the \c MultiPage mode, it supports flicking through the pages in the
287 entire document, with narrow gaps between the page images.
288 In the \c SinglePage mode, it shows one page at a time.
289*/
290
291/*!
292 Constructs a PDF viewer with parent widget \a parent.
293*/
294QPdfView::QPdfView(QWidget *parent)
295 : QAbstractScrollArea(parent)
296 , d_ptr(new QPdfViewPrivate(this))
297{
298 Q_D(QPdfView);
299
300 d->init();
301
302 connect(d->m_pageNavigator, &QPdfPageNavigator::currentPageChanged, this,
303 [d](int page){ d->currentPageChanged(page); });
304
305 connect(d->m_pageRenderer, &QPdfPageRenderer::pageRendered, this,
306 [d](int pageNumber, QSize imageSize, const QImage &image, QPdfDocumentRenderOptions, quint64 requestId) {
307 d->pageRendered(pageNumber, imageSize, image, requestId); });
308
309 verticalScrollBar()->setSingleStep(20);
310 horizontalScrollBar()->setSingleStep(20);
311
312 setMouseTracking(true);
313 d->calculateViewport();
314}
315
316/*!
317 Destroys the PDF viewer.
318*/
319QPdfView::~QPdfView()
320{
321}
322
323/*!
324 \property QPdfView::document
325
326 This property holds the document to be viewed.
327*/
328void QPdfView::setDocument(QPdfDocument *document)
329{
330 Q_D(QPdfView);
331
332 if (d->m_document == document)
333 return;
334
335 if (d->m_document)
336 disconnect(d->m_documentStatusChangedConnection);
337
338 d->m_document = document;
339 emit documentChanged(d->m_document);
340
341 if (d->m_document)
342 d->m_documentStatusChangedConnection =
343 connect(d->m_document.data(), &QPdfDocument::statusChanged, this,
344 [d](){ d->documentStatusChanged(); });
345
346 d->m_pageRenderer->setDocument(d->m_document);
347 d->m_linkModel.setDocument(d->m_document);
348
349 d->documentStatusChanged();
350}
351
352QPdfDocument *QPdfView::document() const
353{
354 Q_D(const QPdfView);
355
356 return d->m_document;
357}
358
359/*!
360 \since 6.6
361 \property QPdfView::searchModel
362
363 If this property is set, QPdfView draws highlight rectangles over the
364 search results provided by \l QPdfSearchModel::resultsOnPage(). By default
365 it is \c nullptr.
366*/
367void QPdfView::setSearchModel(QPdfSearchModel *searchModel)
368{
369 Q_D(QPdfView);
370 if (d->m_searchModel == searchModel)
371 return;
372
373 if (d->m_searchModel)
374 d->m_searchModel->disconnect(this);
375
376 d->m_searchModel = searchModel;
377 emit searchModelChanged(searchModel);
378
379 if (searchModel) {
380 connect(searchModel, &QPdfSearchModel::dataChanged, this,
381 [this](const QModelIndex &, const QModelIndex &, const QList<int> &) { update(); });
382 }
383 setCurrentSearchResultIndex(-1);
384}
385
386QPdfSearchModel *QPdfView::searchModel() const
387{
388 Q_D(const QPdfView);
389 return d->m_searchModel;
390}
391
392/*!
393 \since 6.6
394 \property QPdfView::currentSearchResultIndex
395
396 If this property is set to a positive number, and \l searchModel is set,
397 QPdfView draws a frame around the search result provided by
398 \l QPdfSearchModel at the given index. For example, if QPdfSearchModel is
399 used as the model for a QListView, you can keep this property updated by
400 connecting QItemSelectionModel::currentChanged() from
401 QListView::selectionModel() to a function that will in turn call this function.
402
403 By default it is \c -1, so that no search results are framed.
404*/
405void QPdfView::setCurrentSearchResultIndex(int currentResult)
406{
407 Q_D(QPdfView);
408 if (d->m_currentSearchResultIndex == currentResult)
409 return;
410
411 d->m_currentSearchResultIndex = currentResult;
412 emit currentSearchResultIndexChanged(currentResult);
413 viewport()->update(); //update();
414}
415
416int QPdfView::currentSearchResultIndex() const
417{
418 Q_D(const QPdfView);
419 return d->m_currentSearchResultIndex;
420}
421
422/*!
423 This accessor returns the navigation stack that will handle back/forward navigation.
424*/
425QPdfPageNavigator *QPdfView::pageNavigator() const
426{
427 Q_D(const QPdfView);
428
429 return d->m_pageNavigator;
430}
431
432/*!
433 \enum QPdfView::PageMode
434
435 This enum describes the overall behavior of the PDF viewer:
436
437 \value SinglePage Show one page at a time.
438 \value MultiPage Allow scrolling through all pages in the document.
439*/
440
441/*!
442 \property QPdfView::pageMode
443
444 This property holds whether to show one page at a time, or all pages in the
445 document. The default is \c SinglePage.
446*/
447QPdfView::PageMode QPdfView::pageMode() const
448{
449 Q_D(const QPdfView);
450
451 return d->m_pageMode;
452}
453
454void QPdfView::setPageMode(PageMode mode)
455{
456 Q_D(QPdfView);
457
458 if (d->m_pageMode == mode)
459 return;
460
461 d->m_pageMode = mode;
462 d->invalidateDocumentLayout();
463
464 emit pageModeChanged(d->m_pageMode);
465}
466
467/*!
468 \enum QPdfView::ZoomMode
469
470 This enum describes the magnification behavior of the PDF viewer:
471
472 \value Custom Use \l zoomFactor only.
473 \value FitToWidth Automatically choose a zoom factor so that
474 the width of the page fits in the view.
475 \value FitInView Automatically choose a zoom factor so that
476 the entire page fits in the view.
477*/
478
479/*!
480 \property QPdfView::zoomMode
481
482 This property indicates whether to use a custom size for the page(s),
483 or zoom them to fit to the view. The default is \c CustomZoom.
484*/
485QPdfView::ZoomMode QPdfView::zoomMode() const
486{
487 Q_D(const QPdfView);
488
489 return d->m_zoomMode;
490}
491
492void QPdfView::setZoomMode(ZoomMode mode)
493{
494 Q_D(QPdfView);
495
496 if (d->m_zoomMode == mode)
497 return;
498
499 d->m_zoomMode = mode;
500 d->invalidateDocumentLayout();
501
502 emit zoomModeChanged(d->m_zoomMode);
503}
504
505/*!
506 \property QPdfView::zoomFactor
507
508 This property holds the ratio of pixels to points. The default is \c 1,
509 meaning one point (1/72 of an inch) equals 1 logical pixel.
510*/
511qreal QPdfView::zoomFactor() const
512{
513 Q_D(const QPdfView);
514
515 return d->m_zoomFactor;
516}
517
518void QPdfView::setZoomFactor(qreal factor)
519{
520 Q_D(QPdfView);
521
522 if (d->m_zoomFactor == factor)
523 return;
524
525 d->m_zoomFactor = factor;
526 d->invalidateDocumentLayout();
527
528 emit zoomFactorChanged(d->m_zoomFactor);
529}
530
531/*!
532 \property QPdfView::pageSpacing
533
534 This property holds the size of the padding between pages in the \l MultiPage
535 \l {pageMode}{mode}.
536*/
537int QPdfView::pageSpacing() const
538{
539 Q_D(const QPdfView);
540
541 return d->m_pageSpacing;
542}
543
544void QPdfView::setPageSpacing(int spacing)
545{
546 Q_D(QPdfView);
547
548 if (d->m_pageSpacing == spacing)
549 return;
550
551 d->m_pageSpacing = spacing;
552 d->invalidateDocumentLayout();
553
554 emit pageSpacingChanged(d->m_pageSpacing);
555}
556
557/*!
558 \property QPdfView::documentMargins
559
560 This property holds the margins around the page view.
561*/
562QMargins QPdfView::documentMargins() const
563{
564 Q_D(const QPdfView);
565
566 return d->m_documentMargins;
567}
568
569void QPdfView::setDocumentMargins(QMargins margins)
570{
571 Q_D(QPdfView);
572
573 if (d->m_documentMargins == margins)
574 return;
575
576 d->m_documentMargins = margins;
577 d->invalidateDocumentLayout();
578
579 emit documentMarginsChanged(d->m_documentMargins);
580}
581
582void QPdfView::paintEvent(QPaintEvent *event)
583{
584 Q_D(QPdfView);
585
586 QPainter painter(viewport());
587 painter.fillRect(event->rect(), palette().brush(QPalette::Dark));
588 painter.translate(-d->m_viewport.x(), -d->m_viewport.y());
589
590 for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
591 it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
592 const QRect pageGeometry = it.value().first;
593 if (pageGeometry.intersects(d->m_viewport)) { // page needs to be painted
594 painter.fillRect(pageGeometry, Qt::white);
595
596 const int page = it.key();
597 const auto pageIt = d->m_pageCache.constFind(page);
598 if (pageIt != d->m_pageCache.cend()) {
599 const QImage &img = pageIt.value();
600 painter.drawImage(pageGeometry, img);
601 } else {
602 d->m_pageRenderer->requestPage(page, pageGeometry.size() * devicePixelRatioF());
603 }
604
605 const QTransform scaleTransform = d->screenScaleTransform(page);
606#ifdef DEBUG_LINKS
607 const QString fmt = u"page %1 @ %2, %3"_s;
608 d->m_linkModel.setPage(page);
609 const int linkCount = d->m_linkModel.rowCount({});
610 for (int i = 0; i < linkCount; ++i) {
611 const QRectF linkBounds = scaleTransform.mapRect(
612 d->m_linkModel.data(d->m_linkModel.index(i),
613 int(QPdfLinkModel::Role::Rect)).toRectF())
614 .translated(pageGeometry.topLeft());
615 painter.setPen(Qt::blue);
616 painter.drawRect(linkBounds);
617 painter.setPen(Qt::red);
618 const QPoint loc = d->m_linkModel.data(d->m_linkModel.index(i),
619 int(QPdfLinkModel::Role::Location)).toPoint();
620 // TODO maybe draw destination URL if that's what it is
621 painter.drawText(linkBounds.bottomLeft() + QPoint(2, -2),
622 fmt.arg(d->m_linkModel.data(d->m_linkModel.index(i),
623 int(QPdfLinkModel::Role::Page)).toInt())
624 .arg(loc.x()).arg(loc.y()));
625 }
626#endif
627 if (d->m_searchModel) {
628 for (const QPdfLink &result : d->m_searchModel->resultsOnPage(page)) {
629 for (const QRectF &rect : result.rectangles())
630 painter.fillRect(scaleTransform.mapRect(rect).translated(pageGeometry.topLeft()), SearchResultHighlight);
631 }
632
633 if (d->m_currentSearchResultIndex >= 0 && d->m_currentSearchResultIndex < d->m_searchModel->rowCount({})) {
634 const QPdfLink &cur = d->m_searchModel->resultAtIndex(d->m_currentSearchResultIndex);
635 if (cur.page() == page) {
636 painter.setPen({CurrentSearchResultHighlight, CurrentSearchResultWidth});
637 for (const auto &rect : cur.rectangles())
638 painter.drawRect(scaleTransform.mapRect(rect).translated(pageGeometry.topLeft()));
639 }
640 }
641 }
642 }
643 }
644}
645
646void QPdfView::resizeEvent(QResizeEvent *event)
647{
648 Q_D(QPdfView);
649
650 QAbstractScrollArea::resizeEvent(event);
651
652 d->updateScrollBars();
653 d->calculateViewport();
654}
655
656void QPdfView::scrollContentsBy(int dx, int dy)
657{
658 Q_D(QPdfView);
659
660 QAbstractScrollArea::scrollContentsBy(dx, dy);
661
662 d->calculateViewport();
663}
664
665void QPdfView::mousePressEvent(QMouseEvent *event)
666{
667 Q_ASSERT(event->isAccepted());
668}
669
670void QPdfView::mouseMoveEvent(QMouseEvent *event)
671{
672 Q_D(QPdfView);
673 for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
674 it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
675 const int page = it.key();
676 const QTransform screenInvTransform = d->screenScaleTransform(page).inverted();
677 const QRect pageGeometry = it.value().first;
678 if (pageGeometry.contains(event->position().toPoint())) {
679 QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft()
680 + d->m_viewport.topLeft());
681 d->m_linkModel.setPage(page);
682 auto dest = d->m_linkModel.linkAt(posInPoints);
683 setCursor(dest.isValid() ? Qt::PointingHandCursor : Qt::ArrowCursor);
684 if (dest.isValid())
685 qCDebug(qLcWLink) << event->position() << ":" << posInPoints << "pt ->" << dest;
686 }
687 }
688}
689
690void QPdfView::mouseReleaseEvent(QMouseEvent *event)
691{
692 Q_D(QPdfView);
693 for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
694 it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
695 const int page = it.key();
696 const QTransform screenInvTransform = d->screenScaleTransform(page).inverted();
697 const QRect pageGeometry = it.value().first;
698 if (pageGeometry.contains(event->position().toPoint())) {
699 QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft()
700 + d->m_viewport.topLeft());
701 d->m_linkModel.setPage(page);
702 auto dest = d->m_linkModel.linkAt(posInPoints);
703 if (dest.isValid()) {
704 qCDebug(qLcWLink) << event << ": jumping to" << dest;
705 d->m_pageNavigator->jump(dest.page(), dest.location(), dest.zoom());
706 // TODO scroll and zoom to where the link tells us to
707 }
708 return;
709 }
710 }
711}
712
713QT_END_NAMESPACE
714
715#include "moc_qpdfview.cpp"
QTransform screenScaleTransform(int page) const
Definition qpdfview.cpp:257
void updateScrollBars()
Definition qpdfview.cpp:127
void setViewport(QRect viewport)
Definition qpdfview.cpp:85
QPdfPageRenderer * m_pageRenderer
Definition qpdfview_p.h:64
void updateDocumentLayout()
Definition qpdfview.cpp:272
QPdfPageNavigator * m_pageNavigator
Definition qpdfview_p.h:63
qreal yPositionForPage(int page) const
Definition qpdfview.cpp:248
void invalidatePageCache()
Definition qpdfview.cpp:165
void invalidateDocumentLayout()
Definition qpdfview.cpp:159
void documentStatusChanged()
Definition qpdfview.cpp:54
void currentPageChanged(int currentPage)
Definition qpdfview.cpp:60
bool m_blockPageScrolling
Definition qpdfview_p.h:76
void calculateViewport()
Definition qpdfview.cpp:73
DocumentLayout calculateDocumentLayout() const
Definition qpdfview.cpp:173
void pageRendered(int pageNumber, QSize imageSize, const QImage &image, quint64 requestId)
Definition qpdfview.cpp:140
Combined button and popup list for selecting options.
static const QColor CurrentSearchResultHighlight(Qt::cyan)
static const int CurrentSearchResultWidth(2)