mirror of
https://github.com/JakubMelka/PDF4QT.git
synced 2025-06-05 21:59:17 +02:00
Advanced find (algorithms)
This commit is contained in:
@@ -35,6 +35,7 @@ LIBS += -lPDFForQtLib
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
pdfaboutdialog.cpp \
|
||||
pdfadvancedfindwidget.cpp \
|
||||
pdfdocumentpropertiesdialog.cpp \
|
||||
pdfsendmail.cpp \
|
||||
pdfsidebarwidget.cpp \
|
||||
@@ -45,6 +46,7 @@ SOURCES += \
|
||||
|
||||
HEADERS += \
|
||||
pdfaboutdialog.h \
|
||||
pdfadvancedfindwidget.h \
|
||||
pdfdocumentpropertiesdialog.h \
|
||||
pdfsendmail.h \
|
||||
pdfsidebarwidget.h \
|
||||
@@ -55,6 +57,7 @@ HEADERS += \
|
||||
|
||||
FORMS += \
|
||||
pdfaboutdialog.ui \
|
||||
pdfadvancedfindwidget.ui \
|
||||
pdfdocumentpropertiesdialog.ui \
|
||||
pdfsidebarwidget.ui \
|
||||
pdfviewermainwindow.ui \
|
||||
|
126
PdfForQtViewer/pdfadvancedfindwidget.cpp
Normal file
126
PdfForQtViewer/pdfadvancedfindwidget.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2020 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
// PdfForQt is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// PdfForQt is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pdfadvancedfindwidget.h"
|
||||
#include "ui_pdfadvancedfindwidget.h"
|
||||
|
||||
#include "pdfcompiler.h"
|
||||
#include "pdfdocument.h"
|
||||
#include "pdfdrawspacecontroller.h"
|
||||
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace pdfviewer
|
||||
{
|
||||
|
||||
PDFAdvancedFindWidget::PDFAdvancedFindWidget(pdf::PDFDrawWidgetProxy* proxy, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::PDFAdvancedFindWidget),
|
||||
m_proxy(proxy),
|
||||
m_document(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->regularExpressionsCheckbox, &QCheckBox::clicked, this, &PDFAdvancedFindWidget::updateUI);
|
||||
connect(m_proxy, &pdf::PDFDrawWidgetProxy::textLayoutChanged, this, &PDFAdvancedFindWidget::performSearch);
|
||||
updateUI();
|
||||
}
|
||||
|
||||
PDFAdvancedFindWidget::~PDFAdvancedFindWidget()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void PDFAdvancedFindWidget::setDocument(const pdf::PDFDocument* document)
|
||||
{
|
||||
if (m_document != document)
|
||||
{
|
||||
m_document = document;
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAdvancedFindWidget::on_searchButton_clicked()
|
||||
{
|
||||
m_parameters.phrase = ui->searchPhraseEdit->text();
|
||||
m_parameters.isCaseSensitive = ui->caseSensitiveCheckBox->isChecked();
|
||||
m_parameters.isWholeWordsOnly = ui->wholeWordsOnlyCheckBox->isChecked();
|
||||
m_parameters.isRegularExpression = ui->regularExpressionsCheckbox->isChecked();
|
||||
m_parameters.isDotMatchingEverything = ui->dotMatchesEverythingCheckBox->isChecked();
|
||||
m_parameters.isMultiline = ui->multilineMatchingCheckBox->isChecked();
|
||||
m_parameters.isSearchFinished = m_parameters.phrase.isEmpty();
|
||||
|
||||
if (m_parameters.isSearchFinished)
|
||||
{
|
||||
// We have nothing to search for
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate regular expression
|
||||
if (m_parameters.isRegularExpression)
|
||||
{
|
||||
QRegularExpression expression(m_parameters.phrase);
|
||||
if (!expression.isValid())
|
||||
{
|
||||
m_parameters.isSearchFinished = true;
|
||||
const int patternErrorOffset = expression.patternErrorOffset();
|
||||
QMessageBox::critical(this, tr("Search error"), tr("Search phrase regular expression has error '%1' near symbol %2.").arg(expression.errorString()).arg(patternErrorOffset));
|
||||
ui->searchPhraseEdit->setFocus();
|
||||
ui->searchPhraseEdit->setSelection(patternErrorOffset, 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
pdf::PDFAsynchronousTextLayoutCompiler* compiler = m_proxy->getTextLayoutCompiler();
|
||||
if (compiler->isTextLayoutReady())
|
||||
{
|
||||
performSearch();
|
||||
}
|
||||
else
|
||||
{
|
||||
compiler->makeTextLayout();
|
||||
}
|
||||
}
|
||||
|
||||
void PDFAdvancedFindWidget::updateUI()
|
||||
{
|
||||
const bool enableUI = m_document && m_document->getCatalog()->getPageCount() > 0;
|
||||
const bool enableRegularExpressionUI = enableUI && ui->regularExpressionsCheckbox->isChecked();
|
||||
ui->searchForGroupBox->setEnabled(enableUI);
|
||||
ui->regularExpressionSettingsGroupBox->setEnabled(enableRegularExpressionUI);
|
||||
}
|
||||
|
||||
void PDFAdvancedFindWidget::performSearch()
|
||||
{
|
||||
if (m_parameters.isSearchFinished)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_parameters.isSearchFinished = true;
|
||||
|
||||
pdf::PDFAsynchronousTextLayoutCompiler* compiler = m_proxy->getTextLayoutCompiler();
|
||||
if (!compiler->isTextLayoutReady())
|
||||
{
|
||||
// Text layout is not ready yet
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
} // namespace pdfviewer
|
76
PdfForQtViewer/pdfadvancedfindwidget.h
Normal file
76
PdfForQtViewer/pdfadvancedfindwidget.h
Normal file
@@ -0,0 +1,76 @@
|
||||
// Copyright (C) 2020 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
// PdfForQt is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// PdfForQt is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with PDFForQt. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef PDFADVANCEDFINDWIDGET_H
|
||||
#define PDFADVANCEDFINDWIDGET_H
|
||||
|
||||
#include "pdfglobal.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class PDFAdvancedFindWidget;
|
||||
}
|
||||
|
||||
namespace pdf
|
||||
{
|
||||
class PDFDocument;
|
||||
class PDFDrawWidgetProxy;
|
||||
}
|
||||
|
||||
namespace pdfviewer
|
||||
{
|
||||
|
||||
class PDFAdvancedFindWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PDFAdvancedFindWidget(pdf::PDFDrawWidgetProxy* proxy, QWidget* parent = nullptr);
|
||||
virtual ~PDFAdvancedFindWidget() override;
|
||||
|
||||
void setDocument(const pdf::PDFDocument* document);
|
||||
|
||||
private slots:
|
||||
void on_searchButton_clicked();
|
||||
|
||||
private:
|
||||
void updateUI();
|
||||
void performSearch();
|
||||
|
||||
struct SearchParameters
|
||||
{
|
||||
QString phrase;
|
||||
bool isCaseSensitive = false;
|
||||
bool isWholeWordsOnly = false;
|
||||
bool isRegularExpression = false;
|
||||
bool isDotMatchingEverything = false;
|
||||
bool isMultiline = false;
|
||||
bool isSearchFinished = false;
|
||||
};
|
||||
|
||||
Ui::PDFAdvancedFindWidget* ui;
|
||||
|
||||
pdf::PDFDrawWidgetProxy* m_proxy;
|
||||
const pdf::PDFDocument* m_document;
|
||||
SearchParameters m_parameters;
|
||||
};
|
||||
|
||||
} // namespace pdfviewer
|
||||
|
||||
#endif // PDFADVANCEDFINDWIDGET_H
|
137
PdfForQtViewer/pdfadvancedfindwidget.ui
Normal file
137
PdfForQtViewer/pdfadvancedfindwidget.ui
Normal file
@@ -0,0 +1,137 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PDFAdvancedFindWidget</class>
|
||||
<widget class="QWidget" name="PDFAdvancedFindWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>881</width>
|
||||
<height>457</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="searchTab">
|
||||
<attribute name="title">
|
||||
<string>Search for</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="searchTabLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="searchForGroupBox">
|
||||
<property name="title">
|
||||
<string>Search Settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="searchSettingsGroupBoxLayout" columnstretch="0,1,0">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="searchLabel">
|
||||
<property name="text">
|
||||
<string>Search for:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="2">
|
||||
<widget class="QLineEdit" name="searchPhraseEdit"/>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="searchButton">
|
||||
<property name="text">
|
||||
<string>Search</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="caseSensitiveCheckBox">
|
||||
<property name="text">
|
||||
<string>Case sensitive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="wholeWordsOnlyCheckBox">
|
||||
<property name="text">
|
||||
<string>Whole words only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1" colspan="2">
|
||||
<widget class="QCheckBox" name="regularExpressionsCheckbox">
|
||||
<property name="text">
|
||||
<string>Use regular expressions</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="regularExpressionSettingsGroupBox">
|
||||
<property name="title">
|
||||
<string>Regular Expression Settings</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="regularExpressionSettingsGroupBoxLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="dotMatchesEverythingCheckBox">
|
||||
<property name="text">
|
||||
<string>Dot matches everything (including newline characters)</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="multilineMatchingCheckBox">
|
||||
<property name="text">
|
||||
<string>Multiline matching (enables search using '^' and '$' to mark line beginnings/endings)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="resultsTab">
|
||||
<attribute name="title">
|
||||
<string>Results</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019 Jakub Melka
|
||||
// Copyright (C) 2019-2020 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "pdfaboutdialog.h"
|
||||
#include "pdfsidebarwidget.h"
|
||||
#include "pdfadvancedfindwidget.h"
|
||||
#include "pdfviewersettingsdialog.h"
|
||||
#include "pdfdocumentpropertiesdialog.h"
|
||||
|
||||
@@ -65,7 +66,10 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||
m_CMSManager(new pdf::PDFCMSManager(this)),
|
||||
m_settings(new PDFViewerSettings(this)),
|
||||
m_pdfWidget(nullptr),
|
||||
m_sidebarWidget(nullptr),
|
||||
m_sidebarDockWidget(nullptr),
|
||||
m_advancedFindWidget(nullptr),
|
||||
m_advancedFindDockWidget(nullptr),
|
||||
m_optionalContentActivity(nullptr),
|
||||
m_pageNumberSpinBox(nullptr),
|
||||
m_pageNumberLabel(nullptr),
|
||||
@@ -88,6 +92,7 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||
ui->actionQuit->setShortcut(QKeySequence::Quit);
|
||||
ui->actionZoom_In->setShortcut(QKeySequence::ZoomIn);
|
||||
ui->actionZoom_Out->setShortcut(QKeySequence::ZoomOut);
|
||||
ui->actionFind->setShortcut(QKeySequence::Find);
|
||||
|
||||
connect(ui->actionOpen, &QAction::triggered, this, &PDFViewerMainWindow::onActionOpenTriggered);
|
||||
connect(ui->actionClose, &QAction::triggered, this, &PDFViewerMainWindow::onActionCloseTriggered);
|
||||
@@ -172,6 +177,19 @@ PDFViewerMainWindow::PDFViewerMainWindow(QWidget* parent) :
|
||||
m_sidebarDockWidget->hide();
|
||||
connect(m_sidebarWidget, &PDFSidebarWidget::actionTriggered, this, &PDFViewerMainWindow::onActionTriggered);
|
||||
|
||||
m_advancedFindWidget = new PDFAdvancedFindWidget(m_pdfWidget->getDrawWidgetProxy(), this);
|
||||
m_advancedFindDockWidget = new QDockWidget(tr("Advanced find"), this);
|
||||
m_advancedFindDockWidget->setObjectName("AdvancedFind");
|
||||
m_advancedFindDockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
|
||||
m_advancedFindDockWidget->setWidget(m_advancedFindWidget);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, m_advancedFindDockWidget);
|
||||
m_advancedFindDockWidget->hide();
|
||||
QAction* toggleAdvancedFindAction = m_advancedFindDockWidget->toggleViewAction();
|
||||
toggleAdvancedFindAction->setObjectName("actionAdvancedFind");
|
||||
toggleAdvancedFindAction->setText(tr("Advanced Find"));
|
||||
toggleAdvancedFindAction->setShortcut(QKeySequence("Ctrl+Shift+F"));
|
||||
ui->menuEdit->insertAction(nullptr, toggleAdvancedFindAction);
|
||||
|
||||
ui->actionRenderOptionAntialiasing->setData(pdf::PDFRenderer::Antialiasing);
|
||||
ui->actionRenderOptionTextAntialiasing->setData(pdf::PDFRenderer::TextAntialiasing);
|
||||
ui->actionRenderOptionSmoothPictures->setData(pdf::PDFRenderer::SmoothImages);
|
||||
@@ -858,6 +876,7 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
|
||||
|
||||
m_pdfWidget->setDocument(document, m_optionalContentActivity);
|
||||
m_sidebarWidget->setDocument(document, m_optionalContentActivity);
|
||||
m_advancedFindWidget->setDocument(document);
|
||||
|
||||
if (m_sidebarWidget->isEmpty())
|
||||
{
|
||||
@@ -868,6 +887,11 @@ void PDFViewerMainWindow::setDocument(const pdf::PDFDocument* document)
|
||||
m_sidebarDockWidget->show();
|
||||
}
|
||||
|
||||
if (!document)
|
||||
{
|
||||
m_advancedFindDockWidget->hide();
|
||||
}
|
||||
|
||||
updateTitle();
|
||||
updateUI(true);
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
// Copyright (C) 2019 Jakub Melka
|
||||
// Copyright (C) 2019-2020 Jakub Melka
|
||||
//
|
||||
// This file is part of PdfForQt.
|
||||
//
|
||||
@@ -56,6 +56,7 @@ class PDFOptionalContentTreeItemModel;
|
||||
namespace pdfviewer
|
||||
{
|
||||
class PDFSidebarWidget;
|
||||
class PDFAdvancedFindWidget;
|
||||
|
||||
class PDFViewerMainWindow : public QMainWindow
|
||||
{
|
||||
@@ -145,6 +146,8 @@ private:
|
||||
QString m_currentFile;
|
||||
PDFSidebarWidget* m_sidebarWidget;
|
||||
QDockWidget* m_sidebarDockWidget;
|
||||
PDFAdvancedFindWidget* m_advancedFindWidget;
|
||||
QDockWidget* m_advancedFindDockWidget;
|
||||
pdf::PDFOptionalContentActivity* m_optionalContentActivity;
|
||||
QSpinBox* m_pageNumberSpinBox;
|
||||
QLabel* m_pageNumberLabel;
|
||||
|
@@ -96,7 +96,14 @@
|
||||
<addaction name="actionShow_Text_Blocks"/>
|
||||
<addaction name="actionShow_Text_Lines"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuEdit">
|
||||
<property name="title">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<addaction name="actionFind"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuEdit"/>
|
||||
<addaction name="menuView"/>
|
||||
<addaction name="menuGoTo"/>
|
||||
<addaction name="menuTools"/>
|
||||
@@ -340,6 +347,11 @@
|
||||
<string>Show Text Lines</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFind">
|
||||
<property name="text">
|
||||
<string>Find</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
Reference in New Issue
Block a user