diff --git a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp index 5cbae41..428699e 100644 --- a/PdfForQtLib/sources/pdfdrawspacecontroller.cpp +++ b/PdfForQtLib/sources/pdfdrawspacecontroller.cpp @@ -675,6 +675,13 @@ void PDFDrawWidgetProxy::draw(QPainter* painter, QRect rect) painter->restore(); } + for (IDocumentDrawInterface* drawInterface : m_drawInterfaces) + { + painter->save(); + drawInterface->drawPage(painter, item.pageIndex, compiledPage, layoutGetter, matrix); + painter->restore(); + } + const qint64 drawTimeNS = timer.nsecsElapsed(); // Draw rendering times @@ -1200,4 +1207,17 @@ void PDFDrawWidgetProxy::onOptionalContentGroupStateChanged() emit pageImageChanged(true, { }); } +void IDocumentDrawInterface::drawPage(QPainter* painter, + PDFInteger pageIndex, + const PDFPrecompiledPage* compiledPage, + PDFTextLayoutGetter& layoutGetter, + const QMatrix& pagePointToDevicePointMatrix) const +{ + Q_UNUSED(painter); + Q_UNUSED(pageIndex); + Q_UNUSED(compiledPage); + Q_UNUSED(layoutGetter); + Q_UNUSED(pagePointToDevicePointMatrix); +} + } // namespace pdf diff --git a/PdfForQtLib/sources/pdfdrawspacecontroller.h b/PdfForQtLib/sources/pdfdrawspacecontroller.h index f97618a..c3554cb 100644 --- a/PdfForQtLib/sources/pdfdrawspacecontroller.h +++ b/PdfForQtLib/sources/pdfdrawspacecontroller.h @@ -36,9 +36,30 @@ class PDFProgress; class PDFWidget; class IDrawWidget; class PDFCMSManager; +class PDFTextLayoutGetter; class PDFAsynchronousPageCompiler; class PDFAsynchronousTextLayoutCompiler; +class PDFFORQTLIBSHARED_EXPORT IDocumentDrawInterface +{ +public: + explicit inline IDocumentDrawInterface() = default; + virtual ~IDocumentDrawInterface() = default; + + /// Performs drawing of additional graphics onto the painter using precompiled page, + /// optionally text layout and page point to device point matrix. + /// \param painter Painter + /// \param pageIndex Page index + /// \param compiledPage Compiled page + /// \param layoutGetter Layout getter + /// \param pagePointToDevicePointMatrix Matrix mapping page space to device point space + virtual void drawPage(QPainter* painter, + pdf::PDFInteger pageIndex, + const PDFPrecompiledPage* compiledPage, + PDFTextLayoutGetter& layoutGetter, + const QMatrix& pagePointToDevicePointMatrix) const; +}; + /// This class controls draw space - page layout. Pages are divided into blocks /// each block can contain one or multiple pages. Units are in milimeters. /// Pages are layouted in zoom-independent mode. @@ -286,6 +307,9 @@ public: static constexpr PDFReal getMinZoom() { return MIN_ZOOM; } static constexpr PDFReal getMaxZoom() { return MAX_ZOOM; } + void registerDrawInterface(IDocumentDrawInterface* drawInterface) { m_drawInterfaces.insert(drawInterface); } + void unregisterDrawInterface(IDocumentDrawInterface* drawInterface) { m_drawInterfaces.erase(drawInterface); } + signals: void drawSpaceChanged(); void pageLayoutChanged(); @@ -422,6 +446,9 @@ private: /// Progress PDFProgress* m_progress; + + /// Additional drawing interfaces + std::set m_drawInterfaces; }; } // namespace pdf diff --git a/PdfForQtLib/sources/pdftextlayout.cpp b/PdfForQtLib/sources/pdftextlayout.cpp index fdd4c72..9453110 100644 --- a/PdfForQtLib/sources/pdftextlayout.cpp +++ b/PdfForQtLib/sources/pdftextlayout.cpp @@ -1041,7 +1041,7 @@ void PDFTextSelectionPainter::draw(QPainter* painter, PDFInteger pageIndex, PDFT QMatrix transformMatrix = angleMatrix.inverted() * matrix; path = transformMatrix.map(path); - QColor penColor = item.color; + QColor penColor = item.color.darker(); QColor brushColor = item.color; brushColor.setAlphaF(SELECTION_ALPHA); diff --git a/PdfForQtLib/sources/pdftextlayout.h b/PdfForQtLib/sources/pdftextlayout.h index 3724541..8600afc 100644 --- a/PdfForQtLib/sources/pdftextlayout.h +++ b/PdfForQtLib/sources/pdftextlayout.h @@ -208,7 +208,7 @@ using PDFTextSelectionColoredItems = std::vector; /// Text selection, can be used across multiple pages. Also defines color /// for each text selection. -class PDFTextSelection +class PDFFORQTLIBSHARED_EXPORT PDFTextSelection { public: explicit PDFTextSelection() = default; @@ -376,7 +376,7 @@ private: }; /// Paints text selection on various pages using page to device point matrix -class PDFTextSelectionPainter +class PDFFORQTLIBSHARED_EXPORT PDFTextSelectionPainter { public: explicit inline PDFTextSelectionPainter(const PDFTextSelection* selection) : @@ -394,7 +394,7 @@ public: void draw(QPainter* painter, PDFInteger pageIndex, PDFTextLayoutGetter& textLayoutGetter, const QMatrix& matrix); private: - static constexpr const PDFReal HEIGHT_INCREASE_FACTOR = 0.25; + static constexpr const PDFReal HEIGHT_INCREASE_FACTOR = 0.40; static constexpr const PDFReal SELECTION_ALPHA = 0.25; const PDFTextSelection* m_selection; diff --git a/PdfForQtViewer/pdfadvancedfindwidget.cpp b/PdfForQtViewer/pdfadvancedfindwidget.cpp index d5cf228..db66d0b 100644 --- a/PdfForQtViewer/pdfadvancedfindwidget.cpp +++ b/PdfForQtViewer/pdfadvancedfindwidget.cpp @@ -40,6 +40,7 @@ PDFAdvancedFindWidget::PDFAdvancedFindWidget(pdf::PDFDrawWidgetProxy* proxy, QWi connect(ui->regularExpressionsCheckbox, &QCheckBox::clicked, this, &PDFAdvancedFindWidget::updateUI); connect(m_proxy, &pdf::PDFDrawWidgetProxy::textLayoutChanged, this, &PDFAdvancedFindWidget::performSearch); connect(ui->resultsTableWidget, &QTableWidget::cellDoubleClicked, this, &PDFAdvancedFindWidget::onResultItemDoubleClicked); + connect(ui->resultsTableWidget, &QTableWidget::itemSelectionChanged, this, &PDFAdvancedFindWidget::onSelectionChanged); updateUI(); } @@ -105,6 +106,19 @@ void PDFAdvancedFindWidget::on_searchButton_clicked() } } +void PDFAdvancedFindWidget::on_clearButton_clicked() +{ + m_parameters = SearchParameters(); + m_findResults.clear(); + updateResultsUI(); +} + +void PDFAdvancedFindWidget::onSelectionChanged() +{ + m_textSelection.dirty(); + m_proxy->repaintNeeded(); +} + void PDFAdvancedFindWidget::onResultItemDoubleClicked(int row, int column) { Q_UNUSED(column); @@ -144,6 +158,19 @@ void PDFAdvancedFindWidget::updateResultsUI() } } +void PDFAdvancedFindWidget::drawPage(QPainter* painter, + pdf::PDFInteger pageIndex, + const pdf::PDFPrecompiledPage* compiledPage, + pdf::PDFTextLayoutGetter& layoutGetter, + const QMatrix& pagePointToDevicePointMatrix) const +{ + Q_UNUSED(compiledPage); + + const pdf::PDFTextSelection& textSelection = getTextSelection(); + pdf::PDFTextSelectionPainter textSelectionPainter(&textSelection); + textSelectionPainter.draw(painter, pageIndex, layoutGetter, pagePointToDevicePointMatrix); +} + void PDFAdvancedFindWidget::performSearch() { if (m_parameters.isSearchFinished) @@ -215,7 +242,47 @@ void PDFAdvancedFindWidget::performSearch() m_findResults = textLayoutStorage->find(regularExpression, flowFlags); } + m_textSelection.dirty(); + m_proxy->repaintNeeded(); + updateResultsUI(); } +pdf::PDFTextSelection PDFAdvancedFindWidget::getTextSelectionImpl() const +{ + pdf::PDFTextSelection result; + + std::vector selectedRowIndices; + QModelIndexList selectedRows = ui->resultsTableWidget->selectionModel()->selectedRows(); + std::transform(selectedRows.cbegin(), selectedRows.cend(), std::back_inserter(selectedRowIndices), [] (const QModelIndex& index) { return index.row(); }); + std::sort(selectedRowIndices.begin(), selectedRowIndices.end()); + + for (size_t i = 0; i < m_findResults.size(); ++i) + { + const pdf::PDFFindResult& findResult = m_findResults[i]; + + QColor color(Qt::blue); + if (std::binary_search(selectedRowIndices.cbegin(), selectedRowIndices.cend(), i)) + { + color = QColor(Qt::yellow); + } + + result.addItems(findResult.textSelectionItems, color); + } + + return result; +} + +void PDFAdvancedFindWidget::showEvent(QShowEvent* event) +{ + BaseClass::showEvent(event); + m_proxy->registerDrawInterface(this); +} + +void PDFAdvancedFindWidget::hideEvent(QHideEvent* event) +{ + m_proxy->unregisterDrawInterface(this); + BaseClass::hideEvent(event); +} + } // namespace pdfviewer diff --git a/PdfForQtViewer/pdfadvancedfindwidget.h b/PdfForQtViewer/pdfadvancedfindwidget.h index b27f8ab..f2bdfe7 100644 --- a/PdfForQtViewer/pdfadvancedfindwidget.h +++ b/PdfForQtViewer/pdfadvancedfindwidget.h @@ -19,6 +19,7 @@ #define PDFADVANCEDFINDWIDGET_H #include "pdfglobal.h" +#include "pdfdrawspacecontroller.h" #include "pdftextlayout.h" #include @@ -37,25 +38,44 @@ class PDFDrawWidgetProxy; namespace pdfviewer { -class PDFAdvancedFindWidget : public QWidget +class PDFAdvancedFindWidget : public QWidget, public pdf::IDocumentDrawInterface { Q_OBJECT +private: + using BaseClass = QWidget; + public: explicit PDFAdvancedFindWidget(pdf::PDFDrawWidgetProxy* proxy, QWidget* parent = nullptr); virtual ~PDFAdvancedFindWidget() override; + virtual void drawPage(QPainter* painter, + pdf::PDFInteger pageIndex, + const pdf::PDFPrecompiledPage* compiledPage, + pdf::PDFTextLayoutGetter& layoutGetter, + const QMatrix& pagePointToDevicePointMatrix) const override; + void setDocument(const pdf::PDFDocument* document); +protected: + virtual void showEvent(QShowEvent* event) override; + virtual void hideEvent(QHideEvent* event) override; + private slots: void on_searchButton_clicked(); + void onSelectionChanged(); void onResultItemDoubleClicked(int row, int column); + void on_clearButton_clicked(); + private: void updateUI(); void updateResultsUI(); void performSearch(); + pdf::PDFTextSelection getTextSelection() const { return m_textSelection.get(this, &PDFAdvancedFindWidget::getTextSelectionImpl); } + pdf::PDFTextSelection getTextSelectionImpl() const; + struct SearchParameters { QString phrase; @@ -74,6 +94,7 @@ private: const pdf::PDFDocument* m_document; SearchParameters m_parameters; pdf::PDFFindResults m_findResults; + mutable pdf::PDFCachedItem m_textSelection; }; } // namespace pdfviewer diff --git a/PdfForQtViewer/pdfadvancedfindwidget.ui b/PdfForQtViewer/pdfadvancedfindwidget.ui index 61f0b0a..cbe79cd 100644 --- a/PdfForQtViewer/pdfadvancedfindwidget.ui +++ b/PdfForQtViewer/pdfadvancedfindwidget.ui @@ -29,38 +29,21 @@ Search Settings - - - - - - + + + - Use regular expressions + Search - + Whole words only - - - - Search for: - - - - - - - Case sensitive - - - @@ -68,10 +51,34 @@ - - + + - Search + Search for: + + + + + + + Case sensitive + + + + + + + + + + Use regular expressions + + + + + + + Clear