#include "findreplacedialog.h" #include "ui_findreplacedialog.h" #include #include #include #include #include #include static QString decodeExtended(const QString &s) { QString out; out.reserve(s.size()); for (int i = 0; i < s.size(); ++i) { const QChar c = s.at(i); if (c != QLatin1Char('\\') || i + 1 >= s.size()) { out.append(c); continue; } const QChar n = s.at(i + 1); if (n == QLatin1Char('n')) { out.append(QLatin1Char('\n')); ++i; } else if (n == QLatin1Char('r')) { out.append(QLatin1Char('\r')); ++i; } else if (n == QLatin1Char('t')) { out.append(QLatin1Char('\t')); ++i; } else if (n == QLatin1Char('\\')) { out.append(QLatin1Char('\\')); ++i; } else if (n == QLatin1Char('0')) { out.append(QChar(0)); ++i; } else if (n == QLatin1Char('x') && i + 3 < s.size()) { bool ok = false; const QString hex = s.mid(i + 2, 2); const int code = hex.toInt(&ok, 16); if (ok) { out.append(QChar(code)); i += 3; } else { out.append(c); } } else { out.append(n); ++i; } } return out; } FindReplaceDialog::FindReplaceDialog(QWidget *parent) : QDialog(parent) , ui(new Ui::FindReplaceDialog) { ui->setupUi(this); setModal(false); setWindowFlags(windowFlags() | Qt::Tool); initCombos(); initModeCombos(); initSync(); connect(ui->tabWidget, &QTabWidget::currentChanged, this, [this](int index) { Q_UNUSED(index) if (ui->tabWidget->currentWidget() == ui->findTab) { syncFromReplaceTab(); } else { syncFromFindTab(); } }); connect(ui->findNextBtnFind, &QPushButton::clicked, this, [this]() { commitHistory(); emit findRequested(true); }); connect(ui->findPrevBtnFind, &QPushButton::clicked, this, [this]() { commitHistory(); emit findRequested(false); }); connect(ui->closeBtnFind, &QPushButton::clicked, this, &QDialog::hide); connect(ui->findNextBtnReplace, &QPushButton::clicked, this, [this]() { commitHistory(); emit findRequested(true); }); connect(ui->replaceBtn, &QPushButton::clicked, this, [this]() { commitHistory(); emit replaceRequested(); }); connect(ui->replaceAllBtn, &QPushButton::clicked, this, [this]() { commitHistory(); emit replaceAllRequested(); }); connect(ui->closeBtnReplace, &QPushButton::clicked, this, &QDialog::hide); resize(520, sizeHint().height()); } FindReplaceDialog::~FindReplaceDialog() { delete ui; } void FindReplaceDialog::initCombos() { ui->findWhatComboFind->setInsertPolicy(QComboBox::NoInsert); ui->findWhatComboReplace->setInsertPolicy(QComboBox::NoInsert); ui->replaceWithComboReplace->setInsertPolicy(QComboBox::NoInsert); } void FindReplaceDialog::initModeCombos() { ui->modeComboFind->addItem(QStringLiteral("Normal"), QVariant::fromValue(static_cast(SearchMode::Normal))); ui->modeComboFind->addItem(QStringLiteral("Extended (\\n, \\r, \\t, \\0, \\xNN)"), QVariant::fromValue(static_cast(SearchMode::Extended))); ui->modeComboFind->addItem(QStringLiteral("Regular expression"), QVariant::fromValue(static_cast(SearchMode::Regex))); ui->modeComboReplace->addItem(QStringLiteral("Normal"), QVariant::fromValue(static_cast(SearchMode::Normal))); ui->modeComboReplace->addItem(QStringLiteral("Extended (\\n, \\r, \\t, \\0, \\xNN)"), QVariant::fromValue(static_cast(SearchMode::Extended))); ui->modeComboReplace->addItem(QStringLiteral("Regular expression"), QVariant::fromValue(static_cast(SearchMode::Regex))); } void FindReplaceDialog::initSync() { if (ui->findWhatComboFind->lineEdit()) { connect(ui->findWhatComboFind->lineEdit(), &QLineEdit::textEdited, this, [this]() { syncFromFindTab(); }); } connect(ui->matchCaseCheckFind, &QCheckBox::toggled, this, [this]() { syncFromFindTab(); }); connect(ui->wholeWordCheckFind, &QCheckBox::toggled, this, [this]() { syncFromFindTab(); }); connect(ui->wrapAroundCheckFind, &QCheckBox::toggled, this, [this]() { syncFromFindTab(); }); connect(ui->inSelectionCheckFind, &QCheckBox::toggled, this, [this]() { syncFromFindTab(); }); connect(ui->modeComboFind, &QComboBox::currentIndexChanged, this, [this](int) { syncFromFindTab(); }); if (ui->findWhatComboReplace->lineEdit()) { connect(ui->findWhatComboReplace->lineEdit(), &QLineEdit::textEdited, this, [this]() { syncFromReplaceTab(); }); } if (ui->replaceWithComboReplace->lineEdit()) { connect(ui->replaceWithComboReplace->lineEdit(), &QLineEdit::textEdited, this, [this]() { syncFromReplaceTab(); }); } connect(ui->matchCaseCheckReplace, &QCheckBox::toggled, this, [this]() { syncFromReplaceTab(); }); connect(ui->wholeWordCheckReplace, &QCheckBox::toggled, this, [this]() { syncFromReplaceTab(); }); connect(ui->wrapAroundCheckReplace, &QCheckBox::toggled, this, [this]() { syncFromReplaceTab(); }); connect(ui->inSelectionCheckReplace, &QCheckBox::toggled, this, [this]() { syncFromReplaceTab(); }); connect(ui->modeComboReplace, &QComboBox::currentIndexChanged, this, [this](int) { syncFromReplaceTab(); }); syncFromFindTab(); } void FindReplaceDialog::syncFromFindTab() { if (m_syncing) { return; } m_syncing = true; ui->findWhatComboReplace->setCurrentText(ui->findWhatComboFind->currentText()); ui->matchCaseCheckReplace->setChecked(ui->matchCaseCheckFind->isChecked()); ui->wholeWordCheckReplace->setChecked(ui->wholeWordCheckFind->isChecked()); ui->wrapAroundCheckReplace->setChecked(ui->wrapAroundCheckFind->isChecked()); ui->inSelectionCheckReplace->setChecked(ui->inSelectionCheckFind->isChecked()); ui->modeComboReplace->setCurrentIndex(ui->modeComboFind->currentIndex()); m_syncing = false; } void FindReplaceDialog::syncFromReplaceTab() { if (m_syncing) { return; } m_syncing = true; ui->findWhatComboFind->setCurrentText(ui->findWhatComboReplace->currentText()); ui->matchCaseCheckFind->setChecked(ui->matchCaseCheckReplace->isChecked()); ui->wholeWordCheckFind->setChecked(ui->wholeWordCheckReplace->isChecked()); ui->wrapAroundCheckFind->setChecked(ui->wrapAroundCheckReplace->isChecked()); ui->inSelectionCheckFind->setChecked(ui->inSelectionCheckReplace->isChecked()); ui->modeComboFind->setCurrentIndex(ui->modeComboReplace->currentIndex()); m_syncing = false; } void FindReplaceDialog::openFind() { ui->tabWidget->setCurrentWidget(ui->findTab); show(); raise(); activateWindow(); ui->findWhatComboFind->setFocus(); if (ui->findWhatComboFind->lineEdit()) { ui->findWhatComboFind->lineEdit()->selectAll(); } } void FindReplaceDialog::openReplace() { ui->tabWidget->setCurrentWidget(ui->replaceTab); show(); raise(); activateWindow(); ui->findWhatComboReplace->setFocus(); if (ui->findWhatComboReplace->lineEdit()) { ui->findWhatComboReplace->lineEdit()->selectAll(); } } QString FindReplaceDialog::findText() const { if (ui->tabWidget->currentWidget() == ui->replaceTab) { return ui->findWhatComboReplace->currentText(); } return ui->findWhatComboFind->currentText(); } QString FindReplaceDialog::replaceText() const { return ui->replaceWithComboReplace->currentText(); } QString FindReplaceDialog::findTextForSearch() const { const QString raw = findText(); if (searchMode() == SearchMode::Extended) { return decodeExtended(raw); } return raw; } QString FindReplaceDialog::replaceTextForReplace() const { const QString raw = replaceText(); if (searchMode() == SearchMode::Extended) { return decodeExtended(raw); } return raw; } bool FindReplaceDialog::matchCase() const { if (ui->tabWidget->currentWidget() == ui->replaceTab) { return ui->matchCaseCheckReplace->isChecked(); } return ui->matchCaseCheckFind->isChecked(); } bool FindReplaceDialog::wholeWord() const { if (ui->tabWidget->currentWidget() == ui->replaceTab) { return ui->wholeWordCheckReplace->isChecked(); } return ui->wholeWordCheckFind->isChecked(); } bool FindReplaceDialog::wrapAround() const { if (ui->tabWidget->currentWidget() == ui->replaceTab) { return ui->wrapAroundCheckReplace->isChecked(); } return ui->wrapAroundCheckFind->isChecked(); } bool FindReplaceDialog::inSelection() const { if (ui->tabWidget->currentWidget() == ui->replaceTab) { return ui->inSelectionCheckReplace->isChecked(); } return ui->inSelectionCheckFind->isChecked(); } SearchMode FindReplaceDialog::searchMode() const { const int v = (ui->tabWidget->currentWidget() == ui->replaceTab) ? ui->modeComboReplace->currentData().toInt() : ui->modeComboFind->currentData().toInt(); return static_cast(v); } void FindReplaceDialog::setFindTextIfNotEmpty(const QString &text) { if (text.isEmpty()) { return; } ui->findWhatComboFind->setCurrentText(text); ui->findWhatComboReplace->setCurrentText(text); if (ui->tabWidget->currentWidget() == ui->replaceTab) { if (ui->findWhatComboReplace->lineEdit()) { ui->findWhatComboReplace->lineEdit()->selectAll(); } } else { if (ui->findWhatComboFind->lineEdit()) { ui->findWhatComboFind->lineEdit()->selectAll(); } } } void FindReplaceDialog::commitHistory() { const auto commit = [](QComboBox *combo) { const QString v = combo->currentText(); if (v.isEmpty()) { return; } const int idx = combo->findText(v); if (idx >= 0) { combo->removeItem(idx); } combo->insertItem(0, v); combo->setCurrentIndex(0); while (combo->count() > 20) { combo->removeItem(combo->count() - 1); } }; commit(ui->findWhatComboFind); commit(ui->findWhatComboReplace); commit(ui->replaceWithComboReplace); } void FindReplaceDialog::closeEvent(QCloseEvent *event) { hide(); event->ignore(); }