- change: Merge search and replace to one dialog.

- fix: Search dialog's "Match whole word" option doesn't work with "Use Regular expresion".
  - fix:Search dialog's "Close after search" option doesn't work.
  - change: Fill the search dialog with the current selection if it's available.
This commit is contained in:
Roy Qu 2023-02-28 16:17:56 +08:00
parent 78739e388a
commit d3fde7ab53
17 changed files with 983 additions and 880 deletions

View File

@ -21,6 +21,10 @@ Red Panda C++ Version 2.15
- enhancement: Generate asm with/without SEH directives. - enhancement: Generate asm with/without SEH directives.
- enhancement: Generate asm using intel style/att style. - enhancement: Generate asm using intel style/att style.
- enhancement: make description for jump/cmov/setb instructions more explicit. (used for signed or unsigned) - enhancement: make description for jump/cmov/setb instructions more explicit. (used for signed or unsigned)
- fix: Lead and end spaces in search/replace text is wrongly trimmed.
- change: Merge search and replace to one dialog.
- fix: Search dialog's "Match whole word" option doesn't work with "Use Regular expresion".
- fixSearch dialog's "Close after search" option doesn't work.
Red Panda C++ Version 2.14 Red Panda C++ Version 2.14

View File

@ -1,6 +1,4 @@
QT += core gui printsupport network svg xml QT += core gui printsupport network svg xml widgets
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17 CONFIG += c++17
CONFIG += nokey CONFIG += nokey
@ -213,7 +211,6 @@ SOURCES += \
widgets/projectalreadyopendialog.cpp \ widgets/projectalreadyopendialog.cpp \
widgets/qconsole.cpp \ widgets/qconsole.cpp \
widgets/qpatchedcombobox.cpp \ widgets/qpatchedcombobox.cpp \
widgets/replacedialog.cpp \
widgets/searchdialog.cpp \ widgets/searchdialog.cpp \
widgets/searchinfiledialog.cpp \ widgets/searchinfiledialog.cpp \
widgets/searchresultview.cpp \ widgets/searchresultview.cpp \
@ -349,7 +346,6 @@ HEADERS += \
widgets/projectalreadyopendialog.h \ widgets/projectalreadyopendialog.h \
widgets/qconsole.h \ widgets/qconsole.h \
widgets/qpatchedcombobox.h \ widgets/qpatchedcombobox.h \
widgets/replacedialog.h \
widgets/searchdialog.h \ widgets/searchdialog.h \
widgets/searchinfiledialog.h \ widgets/searchinfiledialog.h \
widgets/searchresultview.h \ widgets/searchresultview.h \
@ -417,7 +413,6 @@ FORMS += \
widgets/newtemplatedialog.ui \ widgets/newtemplatedialog.ui \
widgets/ojproblempropertywidget.ui \ widgets/ojproblempropertywidget.ui \
widgets/projectalreadyopendialog.ui \ widgets/projectalreadyopendialog.ui \
widgets/replacedialog.ui \
widgets/searchdialog.ui \ widgets/searchdialog.ui \
widgets/searchinfiledialog.ui \ widgets/searchinfiledialog.ui \
widgets/signalmessagedialog.ui widgets/signalmessagedialog.ui

View File

@ -1902,10 +1902,10 @@ void Editor::onTooltipTimer()
} }
break; break;
case TipType::Identifier: case TipType::Identifier:
if (pMainWindow->debugger()->executing() && !pMainWindow->debugger()->inferiorRunning()) if (pMainWindow->debugger()->executing() && !pMainWindow->debugger()->inferiorRunning()) {
if (mParentPageControl) if (mParentPageControl)
s = getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpEvaluation); // debugging s = getWordAtPosition(this,p, pBeginPos,pEndPos, WordPurpose::wpEvaluation); // debugging
else if (!mCompletionPopup->isVisible() } else if (!mCompletionPopup->isVisible()
&& !mHeaderCompletionPopup->isVisible()) { && !mHeaderCompletionPopup->isVisible()) {
expression = getExpressionAtPosition(p); expression = getExpressionAtPosition(p);
s = expression.join(""); // information during coding s = expression.join(""); // information during coding

View File

@ -114,7 +114,6 @@ MainWindow::MainWindow(QWidget *parent)
mFullInitialized{false}, mFullInitialized{false},
mSearchInFilesDialog{nullptr}, mSearchInFilesDialog{nullptr},
mSearchDialog{nullptr}, mSearchDialog{nullptr},
mReplaceDialog{nullptr},
mQuitting{false}, mQuitting{false},
mClosingProject{false}, mClosingProject{false},
mCheckSyntaxInBack{false}, mCheckSyntaxInBack{false},
@ -1070,8 +1069,6 @@ int MainWindow::calIconSize(const QString &fontName, int fontPointSize)
void MainWindow::hideAllSearchDialogs() void MainWindow::hideAllSearchDialogs()
{ {
if (mReplaceDialog)
mReplaceDialog->hide();
if (mSearchDialog) if (mSearchDialog)
mSearchDialog->hide(); mSearchDialog->hide();
if (mSearchInFilesDialog) if (mSearchInFilesDialog)
@ -1084,12 +1081,6 @@ void MainWindow::prepareSearchDialog()
mSearchDialog = new SearchDialog(this); mSearchDialog = new SearchDialog(this);
} }
void MainWindow::prepareReplaceDialog()
{
if (!mReplaceDialog)
mReplaceDialog = new ReplaceDialog(this);
}
void MainWindow::prepareSearchInFilesDialog() void MainWindow::prepareSearchInFilesDialog()
{ {
if (mSearchInFilesDialog==nullptr) { if (mSearchInFilesDialog==nullptr) {
@ -6296,10 +6287,12 @@ void MainWindow::on_actionFind_triggered()
Editor *e = mEditorList->getEditor(); Editor *e = mEditorList->getEditor();
if (!e) if (!e)
return; return;
QString s = e->wordAtCursor();
hideAllSearchDialogs(); hideAllSearchDialogs();
prepareSearchDialog(); prepareSearchDialog();
mSearchDialog->find(s); if (e->selAvail())
mSearchDialog->find(e->selText());
else
mSearchDialog->find(e->wordAtCursor());
} }
void MainWindow::on_actionFind_in_files_triggered() void MainWindow::on_actionFind_in_files_triggered()
@ -6308,8 +6301,10 @@ void MainWindow::on_actionFind_in_files_triggered()
prepareSearchInFilesDialog(); prepareSearchInFilesDialog();
Editor *e = mEditorList->getEditor(); Editor *e = mEditorList->getEditor();
if (e) { if (e) {
QString s = e->wordAtCursor(); if (e->selAvail())
mSearchInFilesDialog->findInFiles(s); mSearchInFilesDialog->findInFiles(e->selText());
else
mSearchInFilesDialog->findInFiles(e->wordAtCursor());
} else { } else {
mSearchInFilesDialog->findInFiles(""); mSearchInFilesDialog->findInFiles("");
} }
@ -6321,10 +6316,12 @@ void MainWindow::on_actionReplace_triggered()
if (!e) if (!e)
return; return;
QString s = e->wordAtCursor();
hideAllSearchDialogs(); hideAllSearchDialogs();
prepareReplaceDialog(); prepareSearchDialog();
mReplaceDialog->replace(s); if (e->selAvail())
mSearchDialog->replace(e->selText());
else
mSearchDialog->replace(e->wordAtCursor());
} }
void MainWindow::on_actionFind_Next_triggered() void MainWindow::on_actionFind_Next_triggered()

View File

@ -67,7 +67,6 @@ class CPUDialog;
class QPlainTextEdit; class QPlainTextEdit;
class SearchInFileDialog; class SearchInFileDialog;
class SearchDialog; class SearchDialog;
class ReplaceDialog;
class Project; class Project;
struct ProjectModelNode; struct ProjectModelNode;
class ProjectUnit; class ProjectUnit;
@ -276,7 +275,6 @@ private:
int calIconSize(const QString &fontName, int fontPointSize); int calIconSize(const QString &fontName, int fontPointSize);
void hideAllSearchDialogs(); void hideAllSearchDialogs();
void prepareSearchDialog(); void prepareSearchDialog();
void prepareReplaceDialog();
void prepareSearchInFilesDialog(); void prepareSearchInFilesDialog();
void prepareProjectForCompile(); void prepareProjectForCompile();
void closeProject(bool refreshEditor); void closeProject(bool refreshEditor);
@ -818,7 +816,6 @@ private:
CPUDialog *mCPUDialog; CPUDialog *mCPUDialog;
SearchInFileDialog *mSearchInFilesDialog; SearchInFileDialog *mSearchInFilesDialog;
SearchDialog *mSearchDialog; SearchDialog *mSearchDialog;
ReplaceDialog *mReplaceDialog;
bool mQuitting; bool mQuitting;
bool mClosingProject; bool mClosingProject;
QElapsedTimer mParserTimer; QElapsedTimer mParserTimer;

View File

@ -6754,55 +6754,55 @@
<name>ReplaceDialog</name> <name>ReplaceDialog</name>
<message> <message>
<source>Replace</source> <source>Replace</source>
<translation type="unfinished">Substituir</translation> <translation type="obsolete">Substituir</translation>
</message> </message>
<message> <message>
<source>Text to Find:</source> <source>Text to Find:</source>
<translation type="unfinished">Texto a procurar:</translation> <translation type="obsolete">Texto a procurar:</translation>
</message> </message>
<message> <message>
<source>Replace with:</source> <source>Replace with:</source>
<translation type="unfinished">Substituir por:</translation> <translation type="obsolete">Substituir por:</translation>
</message> </message>
<message> <message>
<source>Scope:</source> <source>Scope:</source>
<translation type="unfinished">Escopo:</translation> <translation type="obsolete">Escopo:</translation>
</message> </message>
<message> <message>
<source>Global</source> <source>Global</source>
<translation type="unfinished">Global</translation> <translation type="obsolete">Global</translation>
</message> </message>
<message> <message>
<source>Selection</source> <source>Selection</source>
<translation type="unfinished">Seleção</translation> <translation type="obsolete">Seleção</translation>
</message> </message>
<message> <message>
<source>Origin:</source> <source>Origin:</source>
<translation type="unfinished">Origem:</translation> <translation type="obsolete">Origem:</translation>
</message> </message>
<message> <message>
<source>From cursor</source> <source>From cursor</source>
<translation type="unfinished">A partir do cursor</translation> <translation type="obsolete">A partir do cursor</translation>
</message> </message>
<message> <message>
<source>Entire scope</source> <source>Entire scope</source>
<translation type="unfinished">Escopo inteiro</translation> <translation type="obsolete">Escopo inteiro</translation>
</message> </message>
<message> <message>
<source>Options:</source> <source>Options:</source>
<translation type="unfinished">Opções:</translation> <translation type="obsolete">Opções:</translation>
</message> </message>
<message> <message>
<source>Whole words only</source> <source>Whole words only</source>
<translation type="unfinished">Apenas palavras inteiras</translation> <translation type="obsolete">Apenas palavras inteiras</translation>
</message> </message>
<message> <message>
<source>Wrap Around</source> <source>Wrap Around</source>
<translation type="unfinished">Wrap Around</translation> <translation type="obsolete">Wrap Around</translation>
</message> </message>
<message> <message>
<source>Regular Expression</source> <source>Regular Expression</source>
<translation type="unfinished">Expressão regular</translation> <translation type="obsolete">Expressão regular</translation>
</message> </message>
<message> <message>
<source>Prompt on replace</source> <source>Prompt on replace</source>
@ -6810,43 +6810,27 @@
</message> </message>
<message> <message>
<source>Case Sensitive</source> <source>Case Sensitive</source>
<translation type="unfinished">Sensibilidade a maiúsculas/minúsculas</translation> <translation type="obsolete">Sensibilidade a maiúsculas/minúsculas</translation>
</message> </message>
<message> <message>
<source>Find Previous</source> <source>Find Previous</source>
<translation type="unfinished">Procurar anterior</translation> <translation type="obsolete">Procurar anterior</translation>
</message> </message>
<message> <message>
<source>Find Next</source> <source>Find Next</source>
<translation type="unfinished">Procurar outro</translation> <translation type="obsolete">Procurar outro</translation>
</message>
<message>
<source>Replace All</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Beginning of file has been reached. </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Do you want to continue from file&apos;s end?</source>
<translation type="unfinished"></translation>
</message> </message>
<message> <message>
<source>End of file has been reached. </source> <source>End of file has been reached. </source>
<translation type="unfinished">Encontrado fim de arquivo.</translation> <translation type="obsolete">Encontrado fim de arquivo.</translation>
</message> </message>
<message> <message>
<source>Do you want to continue from file&apos;s beginning?</source> <source>Do you want to continue from file&apos;s beginning?</source>
<translation type="unfinished">Quer continuar a partir do início do arquivo?</translation> <translation type="obsolete">Quer continuar a partir do início do arquivo?</translation>
</message> </message>
<message> <message>
<source>Continue Search</source> <source>Continue Search</source>
<translation type="unfinished">Continuar a procura</translation> <translation type="obsolete">Continuar a procura</translation>
</message> </message>
</context> </context>
<context> <context>
@ -6861,7 +6845,7 @@
</message> </message>
<message> <message>
<source>Replace with:</source> <source>Replace with:</source>
<translation type="vanished">Substituir por:</translation> <translation>Substituir por:</translation>
</message> </message>
<message> <message>
<source>Options:</source> <source>Options:</source>
@ -6949,7 +6933,7 @@
</message> </message>
<message> <message>
<source>Replace</source> <source>Replace</source>
<translation type="vanished">Substituir</translation> <translation>Substituir</translation>
</message> </message>
<message> <message>
<source>Find in files</source> <source>Find in files</source>
@ -7003,6 +6987,14 @@
<source>Do you want to continue from file&apos;s end?</source> <source>Do you want to continue from file&apos;s end?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Replace All</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search</source>
<translation type="unfinished">Procurar</translation>
</message>
</context> </context>
<context> <context>
<name>SearchInFileDialog</name> <name>SearchInFileDialog</name>

File diff suppressed because it is too large Load Diff

View File

@ -6331,101 +6331,6 @@
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
</context> </context>
<context>
<name>ReplaceDialog</name>
<message>
<source>Replace</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Text to Find:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Replace with:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Scope:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Global</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Selection</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Origin:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>From cursor</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Entire scope</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Options:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Whole words only</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Wrap Around</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Regular Expression</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Case Sensitive</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Find Previous</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Find Next</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Replace All</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Close</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Beginning of file has been reached. </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Do you want to continue from file&apos;s end?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>End of file has been reached. </source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Do you want to continue from file&apos;s beginning?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Continue Search</source>
<translation type="unfinished"></translation>
</message>
</context>
<context> <context>
<name>SearchDialog</name> <name>SearchDialog</name>
<message> <message>
@ -6516,6 +6421,22 @@
<source>Do you want to continue from file&apos;s end?</source> <source>Do you want to continue from file&apos;s end?</source>
<translation type="unfinished"></translation> <translation type="unfinished"></translation>
</message> </message>
<message>
<source>Replace with:</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Replace</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Replace All</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Search</source>
<translation type="unfinished"></translation>
</message>
</context> </context>
<context> <context>
<name>SearchInFileDialog</name> <name>SearchInFileDialog</name>

View File

@ -530,7 +530,7 @@ QString getSizeString(int size)
} }
void saveComboHistory(QComboBox* cb,const QString& text) { void saveComboHistory(QComboBox* cb,const QString& text) {
QString s = text.trimmed(); QString s = text;
if (s.isEmpty()) if (s.isEmpty())
return; return;
int i = cb->findText(s); int i = cb->findText(s);

View File

@ -15,9 +15,20 @@ SearchDialog::SearchDialog(QWidget *parent) :
ui(new Ui::SearchDialog), ui(new Ui::SearchDialog),
mSearchOptions() mSearchOptions()
{ {
setWindowFlag(Qt::WindowContextHelpButtonHint,false);
ui->setupUi(this); ui->setupUi(this);
mBasicSearchEngine= std::make_shared<QSynedit::BasicSearcher>(); mTabBar=new QTabBar(this);
mRegexSearchEngine= std::make_shared<QSynedit::RegexSearcher>(); mTabBar->setExpanding(false);
mSearchTabIdx = mTabBar->addTab(tr("Search"));
mReplaceTabIdx = mTabBar->addTab(tr("Replace"));
ui->dialogLayout->insertWidget(0,mTabBar);
mTabBar->setCurrentIndex(mSearchTabIdx);
connect(mTabBar, &QTabBar::currentChanged, this,
&SearchDialog::onTabBarCurrentChanged);
onTabBarCurrentChanged(mSearchTabIdx);
mBasicSearchEngine = std::make_shared<QSynedit::BasicSearcher>();
mRegexSearchEngine = std::make_shared<QSynedit::RegexSearcher>();
} }
SearchDialog::~SearchDialog() SearchDialog::~SearchDialog()
@ -27,62 +38,39 @@ SearchDialog::~SearchDialog()
void SearchDialog::find(const QString &text) void SearchDialog::find(const QString &text)
{ {
mTabBar->setCurrentIndex(mSearchTabIdx);
ui->cbFind->setCurrentText(text); ui->cbFind->setCurrentText(text);
ui->cbFind->setFocus(); ui->cbFind->setFocus();
show(); show();
} }
void SearchDialog::replace(const QString &text)
{
mTabBar->setCurrentIndex(mReplaceTabIdx);
ui->cbFind->setCurrentText(text);
ui->cbFind->setFocus();
//ui->cbReplace->setCurrentText("");
show();
}
void SearchDialog::findNext() void SearchDialog::findNext()
{ {
doSearch(false); doSearch(false);
if (ui->chkCloseAfterSearch) if (ui->chkCloseAfterSearch->isChecked())
close(); close();
} }
void SearchDialog::findPrevious() void SearchDialog::findPrevious()
{ {
doSearch(true); doSearch(true);
if (ui->chkCloseAfterSearch) if (ui->chkCloseAfterSearch->isChecked())
close(); close();
} }
void SearchDialog::doSearch(bool backward) void SearchDialog::doSearch(bool backward)
{ {
saveComboHistory(ui->cbFind,ui->cbFind->currentText()); saveComboHistory(ui->cbFind,ui->cbFind->currentText());
prepareOptions(backward);
mSearchOptions&=0;
// Apply options
if (backward) {
mSearchOptions.setFlag(QSynedit::ssoBackwards);
}
if (ui->chkRegExp->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoRegExp);
}
if (ui->chkCaseSensetive->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoMatchCase);
}
if (ui->chkWholeWord->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoWholeWord);
}
if (ui->chkWrapAround->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoWrapAround);
}
// Apply scope, when enabled
if (ui->grpScope->isEnabled()) {
if (ui->rbSelection->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoSelectedOnly);
}
}
// Apply origin, when enabled
if (ui->grpOrigin->isEnabled()) {
if (ui->rbEntireScope->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoEntireScope);
}
}
Editor *editor = pMainWindow->editorList()->getEditor(); Editor *editor = pMainWindow->editorList()->getEditor();
if (editor) { if (editor) {
@ -130,10 +118,113 @@ void SearchDialog::doSearch(bool backward)
} }
} }
void SearchDialog::doReplace(bool replaceAll)
{
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
saveComboHistory(ui->cbReplace,ui->cbReplace->currentText());
prepareOptions(false);
Editor *editor = pMainWindow->editorList()->getEditor();
if (editor) {
QSynedit::PSynSearchBase searchEngine;
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
searchEngine = mRegexSearchEngine;
} else {
searchEngine = mBasicSearchEngine;
}
editor->searchReplace(
ui->cbFind->currentText(),
ui->cbReplace->currentText(),
mSearchOptions,
searchEngine,
[&replaceAll](const QString& /*sSearch*/,
const QString& /*sReplace*/, int /*Line*/, int /*ch*/, int /*wordLen*/){
if (replaceAll) {
return QSynedit::SearchAction::ReplaceAll;
} else {
return QSynedit::SearchAction::ReplaceAndExit;
}
},
[this](){
QString msg = tr("End of file has been reached. ")
+tr("Do you want to continue from file's beginning?");
QWidget *p;
if (isVisible()) {
p=this;
} else {
p=pMainWindow;
}
return QMessageBox::question(p,
tr("Continue Search"),
msg,
QMessageBox::Yes|QMessageBox::No,
QMessageBox::Yes) == QMessageBox::Yes;
});
}
}
void SearchDialog::prepareOptions(bool backward)
{
mSearchOptions&=0;
// Apply options
if (backward) {
mSearchOptions.setFlag(QSynedit::ssoBackwards);
}
if (ui->chkRegExp->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoRegExp);
}
if (ui->chkCaseSensetive->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoMatchCase);
}
if (ui->chkWholeWord->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoWholeWord);
}
if (ui->chkWrapAround->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoWrapAround);
}
// Apply scope, when enabled
if (ui->grpScope->isEnabled()) {
if (ui->rbSelection->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoSelectedOnly);
}
}
// Apply origin, when enabled
if (ui->grpOrigin->isEnabled()) {
if (ui->rbEntireScope->isChecked()) {
mSearchOptions.setFlag(QSynedit::ssoEntireScope);
}
}
}
void SearchDialog::onTabBarCurrentChanged(int currentIndex)
{
if(currentIndex==mSearchTabIdx) {
ui->lbReplace->setVisible(false);
ui->cbReplace->setVisible(false);
ui->chkCloseAfterSearch->setVisible(true);
ui->btnReplace->setVisible(false);
ui->btnReplaceAll->setVisible(false);
} else {
ui->lbReplace->setVisible(true);
ui->cbReplace->setVisible(true);
ui->chkCloseAfterSearch->setVisible(false);
ui->btnReplace->setVisible(true);
ui->btnReplaceAll->setVisible(true);
}
}
void SearchDialog::on_cbFind_currentTextChanged(const QString &value) void SearchDialog::on_cbFind_currentTextChanged(const QString &value)
{ {
ui->btnNext->setEnabled(!value.isEmpty()); ui->btnNext->setEnabled(!value.isEmpty());
ui->btnPrevious->setEnabled(!value.isEmpty()); ui->btnPrevious->setEnabled(!value.isEmpty());
ui->btnReplace->setEnabled(!value.isEmpty());
ui->btnReplaceAll->setEnabled(!value.isEmpty());
} }
void SearchDialog::on_btnClose_clicked() void SearchDialog::on_btnClose_clicked()
@ -143,10 +234,23 @@ void SearchDialog::on_btnClose_clicked()
void SearchDialog::on_btnNext_clicked() void SearchDialog::on_btnNext_clicked()
{ {
doSearch(false); findNext();
} }
void SearchDialog::on_btnPrevious_clicked() void SearchDialog::on_btnPrevious_clicked()
{ {
doSearch(true); findPrevious();
}
void SearchDialog::on_btnReplace_clicked()
{
doReplace(false);
}
void SearchDialog::on_btnReplaceAll_clicked()
{
doReplace(true);
close();
} }

View File

@ -2,6 +2,7 @@
#define SEARCHDIALOG_H #define SEARCHDIALOG_H
#include <QDialog> #include <QDialog>
#include <QTabBar>
#include <qsynedit/searcher/baseseacher.h> #include <qsynedit/searcher/baseseacher.h>
namespace Ui { namespace Ui {
@ -16,22 +17,35 @@ public:
explicit SearchDialog(QWidget *parent = nullptr); explicit SearchDialog(QWidget *parent = nullptr);
~SearchDialog(); ~SearchDialog();
void find(const QString& text); void find(const QString& text);
void replace(const QString& text);
void findNext(); void findNext();
void findPrevious(); void findPrevious();
private: private:
void doSearch(bool backward); void doSearch(bool backward);
void doReplace(bool replaceAll);
void prepareOptions(bool backward);
private slots: private slots:
void onTabBarCurrentChanged(int currentIndex);
void on_cbFind_currentTextChanged(const QString &arg1); void on_cbFind_currentTextChanged(const QString &arg1);
void on_btnClose_clicked(); void on_btnClose_clicked();
void on_btnNext_clicked(); void on_btnNext_clicked();
void on_btnPrevious_clicked(); void on_btnPrevious_clicked();
void on_btnReplace_clicked();
void on_btnReplaceAll_clicked();
private: private:
Ui::SearchDialog *ui; Ui::SearchDialog *ui;
QTabBar * mTabBar;
int mSearchTabIdx;
int mReplaceTabIdx;
QSynedit::SearchOptions mSearchOptions; QSynedit::SearchOptions mSearchOptions;
QSynedit::PSynSearchBase mBasicSearchEngine; QSynedit::PSynSearchBase mBasicSearchEngine;
QSynedit::PSynSearchBase mRegexSearchEngine; QSynedit::PSynSearchBase mRegexSearchEngine;

View File

@ -13,7 +13,34 @@
<property name="windowTitle"> <property name="windowTitle">
<string>Find</string> <string>Find</string>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_3"> <layout class="QVBoxLayout" name="dialogLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="widget_5" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item> <item>
<widget class="QWidget" name="widget_4" native="true"> <widget class="QWidget" name="widget_4" native="true">
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QVBoxLayout" name="verticalLayout_2">
@ -34,7 +61,7 @@
</property> </property>
<item> <item>
<widget class="QWidget" name="widget" native="true"> <widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin"> <property name="leftMargin">
<number>0</number> <number>0</number>
</property> </property>
@ -47,14 +74,14 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item> <item row="0" column="0">
<widget class="QLabel" name="lblFind"> <widget class="QLabel" name="lblFind">
<property name="text"> <property name="text">
<string>Text to Find:</string> <string>Text to Find:</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item row="0" column="1">
<widget class="QComboBox" name="cbFind"> <widget class="QComboBox" name="cbFind">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
@ -70,6 +97,26 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QComboBox" name="cbReplace">
<property name="editable">
<bool>true</bool>
</property>
<property name="insertPolicy">
<enum>QComboBox::InsertAtTop</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContentsOnFirstShow</enum>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="lbReplace">
<property name="text">
<string>Replace with:</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -179,12 +226,18 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>7</number> <number>7</number>
</property> </property>
<item row="3" column="0"> <item row="2" column="1">
<widget class="QCheckBox" name="chkWrapAround"> <widget class="QLabel" name="txtRegExpHelp">
<property name="text"> <property name="sizePolicy">
<string>Wrap Around</string> <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property> </property>
<property name="checked"> <property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;(?)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
@ -202,6 +255,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0">
<widget class="QCheckBox" name="chkCloseAfterSearch">
<property name="text">
<string>Close after search</string>
</property>
</widget>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QCheckBox" name="chkWholeWord"> <widget class="QCheckBox" name="chkWholeWord">
<property name="text"> <property name="text">
@ -216,28 +276,28 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="1"> <item row="3" column="0">
<widget class="QLabel" name="txtRegExpHelp"> <widget class="QCheckBox" name="chkWrapAround">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text"> <property name="text">
<string notr="true">&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;(?)&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>Wrap Around</string>
</property> </property>
<property name="openExternalLinks"> <property name="checked">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0"> <item row="5" column="0">
<widget class="QCheckBox" name="chkCloseAfterSearch"> <spacer name="verticalSpacer_4">
<property name="text"> <property name="orientation">
<string>Close after search</string> <enum>Qt::Vertical</enum>
</property> </property>
</widget> <property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item> </item>
</layout> </layout>
</widget> </widget>
@ -293,6 +353,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btnReplace">
<property name="text">
<string>Replace</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnReplaceAll">
<property name="text">
<string>Replace All</string>
</property>
</widget>
</item>
<item> <item>
<spacer name="verticalSpacer_2"> <spacer name="verticalSpacer_2">
<property name="orientation"> <property name="orientation">
@ -334,6 +408,9 @@
</item> </item>
</layout> </layout>
</widget> </widget>
</item>
</layout>
</widget>
<resources/> <resources/>
<connections/> <connections/>
</ui> </ui>

View File

@ -41,4 +41,9 @@ void BaseSearcher::setOptions(const SearchOptions &options)
{ {
mOptions = options; mOptions = options;
} }
bool BaseSearcher::isDelimitChar(const QChar& ch) const
{
return !(ch == '_' || ch.isLetterOrNumber());
}
} }

View File

@ -49,6 +49,8 @@ public:
virtual QString replace(const QString& aOccurrence, const QString& aReplacement) = 0; virtual QString replace(const QString& aOccurrence, const QString& aReplacement) = 0;
SearchOptions options() const; SearchOptions options() const;
virtual void setOptions(const SearchOptions &options); virtual void setOptions(const SearchOptions &options);
protected:
bool isDelimitChar(const QChar& ch) const;
private: private:
QString mPattern; QString mPattern;

View File

@ -79,8 +79,4 @@ QString BasicSearcher::replace(const QString &, const QString &aReplacement)
return aReplacement; return aReplacement;
} }
bool BasicSearcher::isDelimitChar(QChar ch)
{
return !(ch == '_' || ch.isLetterOrNumber());
}
} }

View File

@ -33,8 +33,6 @@ public:
int resultCount() override; int resultCount() override;
int findAll(const QString &text) override; int findAll(const QString &text) override;
QString replace(const QString &aOccurrence, const QString &aReplacement) override; QString replace(const QString &aOccurrence, const QString &aReplacement) override;
private:
bool isDelimitChar(QChar ch);
private: private:
QList<int> mResults; QList<int> mResults;
}; };

View File

@ -53,9 +53,21 @@ int RegexSearcher::findAll(const QString &text)
QRegularExpressionMatchIterator it = mRegex.globalMatch(text); QRegularExpressionMatchIterator it = mRegex.globalMatch(text);
while (it.hasNext()) { while (it.hasNext()) {
QRegularExpressionMatch match = it.next(); QRegularExpressionMatch match = it.next();
if (options().testFlag(ssoWholeWord)) {
int start = match.capturedStart();
int end = match.capturedStart()+match.capturedLength();
if (((start<=0) || isDelimitChar(text[start-1]))
&&
( (end>=text.length()) || isDelimitChar(text[end]) )
) {
mLengths.append(match.capturedLength()); mLengths.append(match.capturedLength());
mResults.append(match.capturedStart()); mResults.append(match.capturedStart());
} }
} else {
mLengths.append(match.capturedLength());
mResults.append(match.capturedStart());
}
}
return mResults.size(); return mResults.size();
} }