diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2023-03-14 11:52:11 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2023-03-17 12:35:47 +0100 |
commit | 496c4ec76963acdfb09cd5b444e3c3840eb21489 (patch) | |
tree | 3be164f1267dbb1103614ae99deba9d749d066af /examples | |
parent | 288e9be6ba2be40761333036f3397298df5e1018 (diff) | |
download | qtwebengine-496c4ec76963acdfb09cd5b444e3c3840eb21489.tar.gz |
Add search feature to PDF widget example
Task-number: QTBUG-16211
Task-number: QTBUG-77507
Fixes: QTBUG-92973
Change-Id: I650bed9392e5e098e46368c60fb7c5dbebde666f
Reviewed-by: <irfan.omair@qt.io>
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'examples')
-rw-r--r-- | examples/pdfwidgets/pdfviewer/CMakeLists.txt | 3 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/images/go-down-search.svgz | bin | 0 -> 330 bytes | |||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/images/go-up-search.svgz | bin | 0 -> 241 bytes | |||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/mainwindow.cpp | 51 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/mainwindow.h | 7 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/mainwindow.ui | 72 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/pdfviewer.pro | 2 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/resources.qrc | 2 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/searchresultdelegate.cpp | 46 | ||||
-rw-r--r-- | examples/pdfwidgets/pdfviewer/searchresultdelegate.h | 20 |
10 files changed, 203 insertions, 0 deletions
diff --git a/examples/pdfwidgets/pdfviewer/CMakeLists.txt b/examples/pdfwidgets/pdfviewer/CMakeLists.txt index 901509f62..59cf13310 100644 --- a/examples/pdfwidgets/pdfviewer/CMakeLists.txt +++ b/examples/pdfwidgets/pdfviewer/CMakeLists.txt @@ -18,6 +18,7 @@ find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets PdfWidgets) qt_add_executable(pdfviewerwidgets main.cpp mainwindow.cpp mainwindow.h mainwindow.ui + searchresultdelegate.cpp searchresultdelegate.h zoomselector.cpp zoomselector.h ) @@ -46,6 +47,8 @@ set(resources_resource_files "images/zoom-previous.svgz" "images/document-open.svgz" "images/go-next-view.svgz" + "images/go-down-search.svgz" + "images/go-up-search.svgz" ) qt_add_resources(pdfviewerwidgets "resources" diff --git a/examples/pdfwidgets/pdfviewer/images/go-down-search.svgz b/examples/pdfwidgets/pdfviewer/images/go-down-search.svgz Binary files differnew file mode 100644 index 000000000..f845473e7 --- /dev/null +++ b/examples/pdfwidgets/pdfviewer/images/go-down-search.svgz diff --git a/examples/pdfwidgets/pdfviewer/images/go-up-search.svgz b/examples/pdfwidgets/pdfviewer/images/go-up-search.svgz Binary files differnew file mode 100644 index 000000000..6378721fa --- /dev/null +++ b/examples/pdfwidgets/pdfviewer/images/go-up-search.svgz diff --git a/examples/pdfwidgets/pdfviewer/mainwindow.cpp b/examples/pdfwidgets/pdfviewer/mainwindow.cpp index f5dae88e1..277f9cfb3 100644 --- a/examples/pdfwidgets/pdfviewer/mainwindow.cpp +++ b/examples/pdfwidgets/pdfviewer/mainwindow.cpp @@ -4,14 +4,18 @@ #include "mainwindow.h" #include "ui_mainwindow.h" +#include "searchresultdelegate.h" #include "zoomselector.h" #include <QFileDialog> +#include <QLineEdit> #include <QMessageBox> #include <QPdfBookmarkModel> #include <QPdfDocument> #include <QPdfPageNavigator> #include <QPdfPageSelector> +#include <QPdfSearchModel> +#include <QShortcut> #include <QStandardPaths> #include <QtMath> @@ -24,6 +28,8 @@ MainWindow::MainWindow(QWidget *parent) , ui(new Ui::MainWindow) , m_zoomSelector(new ZoomSelector(this)) , m_pageSelector(new QPdfPageSelector(this)) + , m_searchModel(new QPdfSearchModel(this)) + , m_searchField(new QLineEdit(this)) , m_document(new QPdfDocument(this)) { ui->setupUi(this); @@ -51,6 +57,23 @@ MainWindow::MainWindow(QWidget *parent) ui->thumbnailsView->setModel(m_document->pageModel()); + m_searchModel->setDocument(m_document); + ui->pdfView->setSearchModel(m_searchModel); + ui->searchToolBar->insertWidget(ui->actionFindPrevious, m_searchField); + connect(new QShortcut(QKeySequence::Find, this), &QShortcut::activated, this, [this]() { + m_searchField->setFocus(Qt::ShortcutFocusReason); + }); + m_searchField->setPlaceholderText(tr("Find in document")); + m_searchField->setMaximumWidth(400); + connect(m_searchField, &QLineEdit::textEdited, this, [this](const QString &text) { + m_searchModel->setSearchString(text); + ui->tabWidget->setCurrentWidget(ui->searchResultsTab); + }); + ui->searchResultsView->setModel(m_searchModel); + ui->searchResultsView->setItemDelegate(new SearchResultDelegate(this)); + connect(ui->searchResultsView->selectionModel(), &QItemSelectionModel::currentChanged, + this, &MainWindow::searchResultSelected); + ui->pdfView->setDocument(m_document); connect(ui->pdfView, &QPdfView::zoomFactorChanged, @@ -96,6 +119,18 @@ void MainWindow::pageSelected(int page) m_pageSelector->text(), QString::number(page + 1), QString::number(m_document->pageCount()))); } +void MainWindow::searchResultSelected(const QModelIndex ¤t, const QModelIndex &previous) +{ + Q_UNUSED(previous); + if (!current.isValid()) + return; + + const int page = current.data(int(QPdfSearchModel::Role::Page)).toInt(); + const QPointF location = current.data(int(QPdfSearchModel::Role::Location)).toPointF(); + ui->pdfView->pageNavigator()->jump(page, location); + ui->pdfView->setCurrentSearchResult(current.row()); +} + void MainWindow::on_actionOpen_triggered() { if (m_fileDialog == nullptr) { @@ -172,3 +207,19 @@ void MainWindow::on_actionForward_triggered() { ui->pdfView->pageNavigator()->forward(); } + +void MainWindow::on_actionFindNext_triggered() +{ + int next = ui->searchResultsView->currentIndex().row() + 1; + if (next >= m_searchModel->rowCount({})) + next = 0; + ui->searchResultsView->setCurrentIndex(m_searchModel->index(next)); +} + +void MainWindow::on_actionFindPrevious_triggered() +{ + int prev = ui->searchResultsView->currentIndex().row() - 1; + if (prev < 0) + prev = m_searchModel->rowCount({}) - 1; + ui->searchResultsView->setCurrentIndex(m_searchModel->index(prev)); +} diff --git a/examples/pdfwidgets/pdfviewer/mainwindow.h b/examples/pdfwidgets/pdfviewer/mainwindow.h index 84b779be1..7f5a5dbca 100644 --- a/examples/pdfwidgets/pdfviewer/mainwindow.h +++ b/examples/pdfwidgets/pdfviewer/mainwindow.h @@ -15,8 +15,10 @@ class MainWindow; } class QFileDialog; +class QLineEdit; class QPdfDocument; class QPdfPageSelector; +class QPdfSearchModel; class QPdfView; class QSpinBox; QT_END_NAMESPACE @@ -37,6 +39,7 @@ public slots: private slots: void bookmarkSelected(const QModelIndex &index); void pageSelected(int page); + void searchResultSelected(const QModelIndex ¤t, const QModelIndex &previous); // action handlers void on_actionOpen_triggered(); @@ -51,11 +54,15 @@ private slots: void on_actionContinuous_triggered(); void on_actionBack_triggered(); void on_actionForward_triggered(); + void on_actionFindNext_triggered(); + void on_actionFindPrevious_triggered(); private: Ui::MainWindow *ui; ZoomSelector *m_zoomSelector; QPdfPageSelector *m_pageSelector; + QPdfSearchModel *m_searchModel; + QLineEdit *m_searchField; QFileDialog *m_fileDialog = nullptr; QPdfDocument *m_document; diff --git a/examples/pdfwidgets/pdfviewer/mainwindow.ui b/examples/pdfwidgets/pdfviewer/mainwindow.ui index 458c5a8c9..881df2e1b 100644 --- a/examples/pdfwidgets/pdfviewer/mainwindow.ui +++ b/examples/pdfwidgets/pdfviewer/mainwindow.ui @@ -151,6 +151,35 @@ </item> </layout> </widget> + <widget class="QWidget" name="searchResultsTab"> + <attribute name="title"> + <string>Search Results</string> + </attribute> + <layout class="QVBoxLayout" name="verticalLayout_5"> + <property name="spacing"> + <number>0</number> + </property> + <property name="leftMargin"> + <number>2</number> + </property> + <property name="topMargin"> + <number>2</number> + </property> + <property name="rightMargin"> + <number>2</number> + </property> + <property name="bottomMargin"> + <number>2</number> + </property> + <item> + <widget class="QListView" name="searchResultsView"> + <property name="horizontalScrollBarPolicy"> + <enum>Qt::ScrollBarAlwaysOff</enum> + </property> + </widget> + </item> + </layout> + </widget> </widget> <widget class="QPdfView" name="pdfView" native="true"> <property name="sizePolicy"> @@ -227,6 +256,19 @@ <addaction name="actionForward"/> </widget> <widget class="QStatusBar" name="statusBar"/> + <widget class="QToolBar" name="searchToolBar"> + <property name="windowTitle"> + <string>toolBar</string> + </property> + <attribute name="toolBarArea"> + <enum>TopToolBarArea</enum> + </attribute> + <attribute name="toolBarBreak"> + <bool>false</bool> + </attribute> + <addaction name="actionFindPrevious"/> + <addaction name="actionFindNext"/> + </widget> <action name="actionOpen"> <property name="icon"> <iconset theme="document-open" resource="resources.qrc"> @@ -349,6 +391,36 @@ <string>forward to next view</string> </property> </action> + <action name="actionFindNext"> + <property name="icon"> + <iconset theme="go-down" resource=".rcc/resources.qrc"> + <normaloff>:/icons/images/go-down-search.svgz</normaloff>:/icons/images/go-down-search.svgz</iconset> + </property> + <property name="text"> + <string>Find Next</string> + </property> + <property name="toolTip"> + <string>Find the next occurrence of the phrase</string> + </property> + <property name="shortcut"> + <string>F3</string> + </property> + </action> + <action name="actionFindPrevious"> + <property name="icon"> + <iconset theme="go-up" resource=".rcc/resources.qrc"> + <normaloff>:/icons/images/go-up-search.svgz</normaloff>:/icons/images/go-up-search.svgz</iconset> + </property> + <property name="text"> + <string>Find Previous</string> + </property> + <property name="toolTip"> + <string>Find the previous occurrence of the phrase</string> + </property> + <property name="shortcut"> + <string>Shift+F3</string> + </property> + </action> </widget> <layoutdefault spacing="6" margin="11"/> <customwidgets> diff --git a/examples/pdfwidgets/pdfviewer/pdfviewer.pro b/examples/pdfwidgets/pdfviewer/pdfviewer.pro index 08807fa70..5e48edeb9 100644 --- a/examples/pdfwidgets/pdfviewer/pdfviewer.pro +++ b/examples/pdfwidgets/pdfviewer/pdfviewer.pro @@ -5,10 +5,12 @@ QT += core gui widgets pdfwidgets SOURCES += \ main.cpp \ mainwindow.cpp \ + searchresultdelegate.cpp \ zoomselector.cpp HEADERS += \ mainwindow.h \ + searchresultdelegate.h \ zoomselector.h FORMS += \ diff --git a/examples/pdfwidgets/pdfviewer/resources.qrc b/examples/pdfwidgets/pdfviewer/resources.qrc index db77763d2..ea408b825 100644 --- a/examples/pdfwidgets/pdfviewer/resources.qrc +++ b/examples/pdfwidgets/pdfviewer/resources.qrc @@ -1,10 +1,12 @@ <RCC> <qresource prefix="/icons"> <file>images/document-open.svgz</file> + <file>images/go-down-search.svgz</file> <file>images/go-next-view.svgz</file> <file>images/go-previous-view.svgz</file> <file>images/go-next-view-page.svgz</file> <file>images/go-previous-view-page.svgz</file> + <file>images/go-up-search.svgz</file> <file>images/zoom-in.svgz</file> <file>images/zoom-out.svgz</file> </qresource> diff --git a/examples/pdfwidgets/pdfviewer/searchresultdelegate.cpp b/examples/pdfwidgets/pdfviewer/searchresultdelegate.cpp new file mode 100644 index 000000000..87efd916d --- /dev/null +++ b/examples/pdfwidgets/pdfviewer/searchresultdelegate.cpp @@ -0,0 +1,46 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#include <QFontMetrics> +#include <QPainter> +#include <QPdfSearchModel> + +#include "searchresultdelegate.h" + +SearchResultDelegate::SearchResultDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +void SearchResultDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + const QString displayText = index.data().toString(); + const auto boldBegin = displayText.indexOf(u"<b>", 0, Qt::CaseInsensitive) + 3; + const auto boldEnd = displayText.indexOf(u"</b>", boldBegin, Qt::CaseInsensitive); + if (boldBegin >= 3 && boldEnd > boldBegin) { + const QString pageLabel = tr("Page %1: ").arg(index.data(int(QPdfSearchModel::Role::Page)).toInt()); + const QString boldText = displayText.mid(boldBegin, boldEnd - boldBegin); + if (option.state & QStyle::State_Selected) + painter->fillRect(option.rect, option.palette.highlight()); + const QFont defaultFont = painter->font(); + QFontMetrics fm = painter->fontMetrics(); + auto pageLabelWidth = fm.horizontalAdvance(pageLabel); + const int yOffset = (option.rect.height() - fm.height()) / 2 + fm.ascent(); + painter->drawText(0, option.rect.y() + yOffset, pageLabel); + QFont boldFont = defaultFont; + boldFont.setBold(true); + auto boldWidth = QFontMetrics(boldFont).horizontalAdvance(boldText); + auto prefixSuffixWidth = (option.rect.width() - pageLabelWidth - boldWidth) / 2; + painter->setFont(boldFont); + painter->drawText(pageLabelWidth + prefixSuffixWidth, option.rect.y() + yOffset, boldText); + painter->setFont(defaultFont); + const QString suffix = fm.elidedText(displayText.mid(boldEnd + 4), Qt::ElideRight, prefixSuffixWidth); + painter->drawText(pageLabelWidth + prefixSuffixWidth + boldWidth, option.rect.y() + yOffset, suffix); + const QString prefix = fm.elidedText(displayText.left(boldBegin - 3), Qt::ElideLeft, prefixSuffixWidth); + painter->drawText(pageLabelWidth + prefixSuffixWidth - fm.horizontalAdvance(prefix), + option.rect.y() + yOffset, prefix); + } else { + QStyledItemDelegate::paint(painter, option, index); + } +} diff --git a/examples/pdfwidgets/pdfviewer/searchresultdelegate.h b/examples/pdfwidgets/pdfviewer/searchresultdelegate.h new file mode 100644 index 000000000..dcf886111 --- /dev/null +++ b/examples/pdfwidgets/pdfviewer/searchresultdelegate.h @@ -0,0 +1,20 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause + +#ifndef SEARCHRESULTDELEGATE_H +#define SEARCHRESULTDELEGATE_H + +#include <QStyledItemDelegate> + +//! [0] +class SearchResultDelegate : public QStyledItemDelegate +{ + Q_OBJECT +public: + SearchResultDelegate(QObject *parent = nullptr); + + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const override; +}; + +#endif // SEARCHRESULTDELEGATE_H |