diff options
Diffstat (limited to 'src/pdf/quick/qquickpdfsearchmodel.cpp')
-rw-r--r-- | src/pdf/quick/qquickpdfsearchmodel.cpp | 204 |
1 files changed, 158 insertions, 46 deletions
diff --git a/src/pdf/quick/qquickpdfsearchmodel.cpp b/src/pdf/quick/qquickpdfsearchmodel.cpp index 8b0e88673..ec998ef0c 100644 --- a/src/pdf/quick/qquickpdfsearchmodel.cpp +++ b/src/pdf/quick/qquickpdfsearchmodel.cpp @@ -35,13 +35,12 @@ ****************************************************************************/ #include "qquickpdfsearchmodel_p.h" -#include <QQuickItem> -#include <QQmlEngine> -#include <QStandardPaths> -#include <private/qguiapplication_p.h> +#include <QtCore/qloggingcategory.h> QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(qLcS, "qt.pdf.search") + /*! \qmltype PdfSearchModel \instantiates QQuickPdfSearchModel @@ -57,6 +56,8 @@ QT_BEGIN_NAMESPACE QQuickPdfSearchModel::QQuickPdfSearchModel(QObject *parent) : QPdfSearchModel(parent) { + connect(this, &QPdfSearchModel::searchStringChanged, + this, &QQuickPdfSearchModel::onResultsChanged); } QQuickPdfDocument *QQuickPdfSearchModel::document() const @@ -68,16 +69,19 @@ void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document) { if (document == m_quickDocument) return; + m_quickDocument = document; QPdfSearchModel::setDocument(&document->m_doc); } /*! - \qmlproperty list<list<point>> PdfSearchModel::matchGeometry + \qmlproperty list<list<point>> PdfSearchModel::currentResultBoundingPolygons A set of paths in a form that can be bound to the \c paths property of a \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of - rectangles around all the locations where search results are found: + rectangles around the regions comprising the search result \l currentResult + on \l currentPage. This is normally used to highlight one search result + at a time, in a UI that allows stepping through the results: \qml PdfDocument { @@ -86,12 +90,13 @@ void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document) PdfSearchModel { id: searchModel document: doc - page: doc.currentPage + currentPage: view.currentPage + currentResult: ... } Shape { ShapePath { PathMultiline { - paths: searchModel.matchGeometry + paths: searchModel.currentResultBoundingPolygons } } } @@ -99,67 +104,174 @@ void QQuickPdfSearchModel::setDocument(QQuickPdfDocument *document) \sa PathMultiline */ -QVector<QPolygonF> QQuickPdfSearchModel::matchGeometry() const +QVector<QPolygonF> QQuickPdfSearchModel::currentResultBoundingPolygons() const { - return m_matchGeometry; + QVector<QPolygonF> ret; + const auto &results = const_cast<QQuickPdfSearchModel *>(this)->resultsOnPage(m_currentPage); + if (m_currentResult < 0 || m_currentResult >= results.count()) + return ret; + const auto result = results[m_currentResult]; + for (auto rect : result.rectangles()) + ret << QPolygonF(rect); + return ret; } -/*! - \qmlproperty string PdfSearchModel::searchString - - The string to search for. -*/ -QString QQuickPdfSearchModel::searchString() const +void QQuickPdfSearchModel::onResultsChanged() { - return m_searchString; + emit currentPageBoundingPolygonsChanged(); + emit currentResultBoundingPolygonsChanged(); } -void QQuickPdfSearchModel::setSearchString(QString searchString) -{ - if (m_searchString == searchString) - return; +/*! + \qmlproperty list<list<point>> PdfSearchModel::currentPageBoundingPolygons + + A set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around all the regions where search results are found on + \l currentPage: + + \qml + PdfDocument { + id: doc + } + PdfSearchModel { + id: searchModel + document: doc + } + Shape { + ShapePath { + PathMultiline { + paths: searchModel.matchGeometry(view.currentPage) + } + } + } + \endqml - m_searchString = searchString; - emit searchStringChanged(); - updateResults(); + \sa PathMultiline +*/ +QVector<QPolygonF> QQuickPdfSearchModel::currentPageBoundingPolygons() const +{ + return const_cast<QQuickPdfSearchModel *>(this)->boundingPolygonsOnPage(m_currentPage); } /*! - \qmlproperty int PdfSearchModel::page + \qmlfunction list<list<point>> PdfSearchModel::boundingPolygonsOnPage(int page) - The page number on which to search. + Returns a set of paths in a form that can be bound to the \c paths property of a + \l {QtQuick::PathMultiline}{PathMultiline} instance to render a batch of + rectangles around all the locations where search results are found: - \sa QtQuick::Image::currentFrame + \qml + PdfDocument { + id: doc + } + PdfSearchModel { + id: searchModel + document: doc + } + Shape { + ShapePath { + PathMultiline { + paths: searchModel.matchGeometry(view.currentPage) + } + } + } + \endqml + + \sa PathMultiline */ -int QQuickPdfSearchModel::page() const +QVector<QPolygonF> QQuickPdfSearchModel::boundingPolygonsOnPage(int page) { - return m_page; + if (!document() || searchString().isEmpty() || page < 0 || page > document()->pageCount()) + return {}; + + updatePage(page); + + QVector<QPolygonF> ret; + auto m = QPdfSearchModel::resultsOnPage(page); + for (auto result : m) { + for (auto rect : result.rectangles()) + ret << QPolygonF(rect); + } + + return ret; } -void QQuickPdfSearchModel::setPage(int page) +/*! + \qmlproperty int PdfSearchModel::currentPage + + The page on which \l currentMatchGeometry should provide filtered search results. +*/ +void QQuickPdfSearchModel::setCurrentPage(int currentPage) { - if (m_page == page) + if (m_currentPage == currentPage) return; - m_page = page; - emit pageChanged(); - updateResults(); + if (currentPage < 0) + currentPage = document()->pageCount() - 1; + else if (currentPage >= document()->pageCount()) + currentPage = 0; + + m_currentPage = currentPage; + if (!m_suspendSignals) { + emit currentPageChanged(); + onResultsChanged(); + } } -void QQuickPdfSearchModel::updateResults() +/*! + \qmlproperty int PdfSearchModel::currentResult + + The result index on \l currentPage for which \l currentResultBoundingPolygons + should provide the regions to highlight. +*/ +void QQuickPdfSearchModel::setCurrentResult(int currentResult) { - if (!document() || (m_searchString.isEmpty() && !m_matchGeometry.isEmpty()) || m_page < 0 || m_page > document()->pageCount()) { - m_matchGeometry.clear(); - emit matchGeometryChanged(); - } - QVector<QRectF> m = QPdfSearchModel::matches(m_page, m_searchString); - QVector<QPolygonF> matches; - for (QRectF r : m) - matches << QPolygonF(r); - if (matches != m_matchGeometry) { - m_matchGeometry = matches; - emit matchGeometryChanged(); + if (m_currentResult == currentResult) + return; + + int currentResultWas = currentResult; + int currentPageWas = m_currentPage; + if (currentResult < 0) { + setCurrentPage(m_currentPage - 1); + while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { + m_suspendSignals = true; + setCurrentPage(m_currentPage - 1); + } + if (m_suspendSignals) { + emit currentPageChanged(); + m_suspendSignals = false; + } + const auto results = resultsOnPage(m_currentPage); + currentResult = results.count() - 1; + } else { + const auto results = resultsOnPage(m_currentPage); + if (currentResult >= results.count()) { + setCurrentPage(m_currentPage + 1); + while (resultsOnPage(m_currentPage).count() == 0 && m_currentPage != currentPageWas) { + m_suspendSignals = true; + setCurrentPage(m_currentPage + 1); + } + if (m_suspendSignals) { + emit currentPageChanged(); + m_suspendSignals = false; + } + currentResult = 0; + } } + qCDebug(qLcS) << "currentResult was" << m_currentResult + << "requested" << currentResultWas << "on page" << currentPageWas + << "->" << currentResult << "on page" << m_currentPage; + + m_currentResult = currentResult; + emit currentResultChanged(); + emit currentResultBoundingPolygonsChanged(); } +/*! + \qmlproperty string PdfSearchModel::searchString + + The string to search for. +*/ + QT_END_NAMESPACE |