find and replace dialog
This commit is contained in:
325
findreplacedialog.cpp
Normal file
325
findreplacedialog.cpp
Normal file
@@ -0,0 +1,325 @@
|
||||
#include "findreplacedialog.h"
|
||||
|
||||
#include "ui_findreplacedialog.h"
|
||||
|
||||
#include <QCheckBox>
|
||||
#include <QCloseEvent>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QTabWidget>
|
||||
|
||||
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<int>(SearchMode::Normal)));
|
||||
ui->modeComboFind->addItem(QStringLiteral("Extended (\\n, \\r, \\t, \\0, \\xNN)"), QVariant::fromValue(static_cast<int>(SearchMode::Extended)));
|
||||
ui->modeComboFind->addItem(QStringLiteral("Regular expression"), QVariant::fromValue(static_cast<int>(SearchMode::Regex)));
|
||||
|
||||
ui->modeComboReplace->addItem(QStringLiteral("Normal"), QVariant::fromValue(static_cast<int>(SearchMode::Normal)));
|
||||
ui->modeComboReplace->addItem(QStringLiteral("Extended (\\n, \\r, \\t, \\0, \\xNN)"), QVariant::fromValue(static_cast<int>(SearchMode::Extended)));
|
||||
ui->modeComboReplace->addItem(QStringLiteral("Regular expression"), QVariant::fromValue(static_cast<int>(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<SearchMode>(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();
|
||||
}
|
||||
Reference in New Issue
Block a user