2021-08-02 21:58:39 +08:00
|
|
|
#include "searchdialog.h"
|
|
|
|
#include "ui_searchdialog.h"
|
2022-11-11 21:20:57 +08:00
|
|
|
|
2023-03-14 17:49:36 +08:00
|
|
|
#include <QCompleter>
|
2022-11-11 21:20:57 +08:00
|
|
|
#include <QMessageBox>
|
|
|
|
#include <memory>
|
2023-01-11 16:22:26 +08:00
|
|
|
#include <qsynedit/searcher/basicsearcher.h>
|
|
|
|
#include <qsynedit/searcher/regexsearcher.h>
|
2022-11-11 21:20:57 +08:00
|
|
|
#include "../utils.h"
|
|
|
|
#include "../editor.h"
|
|
|
|
#include "../editorlist.h"
|
|
|
|
#include "../mainwindow.h"
|
2021-08-02 21:58:39 +08:00
|
|
|
|
|
|
|
SearchDialog::SearchDialog(QWidget *parent) :
|
|
|
|
QDialog(parent),
|
2021-08-03 23:55:57 +08:00
|
|
|
ui(new Ui::SearchDialog),
|
2022-11-11 21:20:57 +08:00
|
|
|
mSearchOptions()
|
2021-08-02 21:58:39 +08:00
|
|
|
{
|
2023-02-28 16:17:56 +08:00
|
|
|
setWindowFlag(Qt::WindowContextHelpButtonHint,false);
|
2021-08-02 21:58:39 +08:00
|
|
|
ui->setupUi(this);
|
2023-02-28 16:17:56 +08:00
|
|
|
mTabBar=new QTabBar(this);
|
|
|
|
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>();
|
2023-03-14 17:49:36 +08:00
|
|
|
ui->cbFind->completer()->setCaseSensitivity(Qt::CaseSensitive);
|
|
|
|
ui->cbReplace->completer()->setCaseSensitivity(Qt::CaseSensitive);
|
2021-08-02 21:58:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
SearchDialog::~SearchDialog()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
2021-08-02 23:42:10 +08:00
|
|
|
|
|
|
|
void SearchDialog::find(const QString &text)
|
|
|
|
{
|
2023-02-28 16:17:56 +08:00
|
|
|
mTabBar->setCurrentIndex(mSearchTabIdx);
|
|
|
|
ui->cbFind->setCurrentText(text);
|
2024-03-25 18:58:48 +08:00
|
|
|
ui->btnNext->setFocus();
|
2023-02-28 16:17:56 +08:00
|
|
|
show();
|
|
|
|
}
|
|
|
|
|
|
|
|
void SearchDialog::replace(const QString &text)
|
|
|
|
{
|
|
|
|
mTabBar->setCurrentIndex(mReplaceTabIdx);
|
2021-08-02 23:42:10 +08:00
|
|
|
ui->cbFind->setCurrentText(text);
|
2024-03-25 18:58:48 +08:00
|
|
|
ui->btnNext->setFocus();
|
2023-02-28 16:17:56 +08:00
|
|
|
//ui->cbReplace->setCurrentText("");
|
2021-08-02 23:42:10 +08:00
|
|
|
show();
|
|
|
|
}
|
|
|
|
|
2021-08-04 00:17:38 +08:00
|
|
|
void SearchDialog::findNext()
|
|
|
|
{
|
2022-11-11 21:20:57 +08:00
|
|
|
doSearch(false);
|
2023-02-28 16:17:56 +08:00
|
|
|
if (ui->chkCloseAfterSearch->isChecked())
|
2022-11-11 21:20:57 +08:00
|
|
|
close();
|
2021-08-04 00:17:38 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::findPrevious()
|
2021-08-02 23:42:10 +08:00
|
|
|
{
|
2022-11-11 21:20:57 +08:00
|
|
|
doSearch(true);
|
2023-02-28 16:17:56 +08:00
|
|
|
if (ui->chkCloseAfterSearch->isChecked())
|
2022-11-11 21:20:57 +08:00
|
|
|
close();
|
2021-08-02 23:42:10 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::doSearch(bool backward)
|
2021-08-02 23:42:10 +08:00
|
|
|
{
|
2021-11-05 10:44:23 +08:00
|
|
|
saveComboHistory(ui->cbFind,ui->cbFind->currentText());
|
2023-02-28 16:17:56 +08:00
|
|
|
prepareOptions(backward);
|
2021-08-03 23:55:57 +08:00
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
Editor *editor = pMainWindow->editorList()->getEditor();
|
|
|
|
if (editor) {
|
|
|
|
// Modify the caret when using 'from cursor' and when the selection is ignored
|
|
|
|
if (!mSearchOptions.testFlag(QSynedit::ssoEntireScope) && !mSearchOptions.testFlag(QSynedit::ssoSelectedOnly)
|
|
|
|
&& editor->selAvail()) {
|
|
|
|
// start at end of selection
|
|
|
|
if (mSearchOptions.testFlag(QSynedit::ssoBackwards)) {
|
|
|
|
editor->setCaretXY(editor->blockBegin());
|
|
|
|
} else {
|
|
|
|
editor->setCaretXY(editor->blockEnd());
|
2021-09-29 20:45:03 +08:00
|
|
|
}
|
2021-08-05 12:31:53 +08:00
|
|
|
}
|
2022-11-11 21:20:57 +08:00
|
|
|
QSynedit::PSynSearchBase searchEngine;
|
|
|
|
if (mSearchOptions.testFlag(QSynedit::ssoRegExp)) {
|
|
|
|
searchEngine = mRegexSearchEngine;
|
2021-08-03 23:55:57 +08:00
|
|
|
} else {
|
2022-11-11 21:20:57 +08:00
|
|
|
searchEngine = mBasicSearchEngine;
|
2021-08-03 23:55:57 +08:00
|
|
|
}
|
2022-11-11 21:20:57 +08:00
|
|
|
editor->searchReplace(
|
|
|
|
ui->cbFind->currentText(),
|
|
|
|
"",
|
|
|
|
mSearchOptions,
|
|
|
|
searchEngine, nullptr, [this,backward](){
|
|
|
|
QString msg;
|
|
|
|
if (backward) {
|
|
|
|
msg = tr("Beginning of file has been reached. ")
|
|
|
|
+tr("Do you want to continue from file's end?");
|
|
|
|
} else {
|
|
|
|
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;
|
|
|
|
});
|
2021-08-03 23:55:57 +08:00
|
|
|
}
|
2021-08-05 12:31:53 +08:00
|
|
|
}
|
2021-08-03 23:55:57 +08:00
|
|
|
|
2023-02-28 16:17:56 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::on_cbFind_currentTextChanged(const QString &value)
|
2021-08-05 12:31:53 +08:00
|
|
|
{
|
2022-11-11 21:20:57 +08:00
|
|
|
ui->btnNext->setEnabled(!value.isEmpty());
|
|
|
|
ui->btnPrevious->setEnabled(!value.isEmpty());
|
2023-02-28 16:17:56 +08:00
|
|
|
ui->btnReplace->setEnabled(!value.isEmpty());
|
|
|
|
ui->btnReplaceAll->setEnabled(!value.isEmpty());
|
2021-08-03 23:55:57 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::on_btnClose_clicked()
|
2022-04-11 09:39:44 +08:00
|
|
|
{
|
2022-11-11 21:20:57 +08:00
|
|
|
close();
|
2022-04-11 09:39:44 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::on_btnNext_clicked()
|
2021-08-04 00:17:38 +08:00
|
|
|
{
|
2023-02-28 16:17:56 +08:00
|
|
|
findNext();
|
2021-08-04 00:17:38 +08:00
|
|
|
}
|
|
|
|
|
2022-11-11 21:20:57 +08:00
|
|
|
void SearchDialog::on_btnPrevious_clicked()
|
2021-08-03 23:55:57 +08:00
|
|
|
{
|
2023-02-28 16:17:56 +08:00
|
|
|
findPrevious();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SearchDialog::on_btnReplace_clicked()
|
|
|
|
{
|
|
|
|
doReplace(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void SearchDialog::on_btnReplaceAll_clicked()
|
|
|
|
{
|
|
|
|
doReplace(true);
|
|
|
|
close();
|
2021-08-04 00:17:38 +08:00
|
|
|
}
|