vnote/src/dialog/vfindreplacedialog.cpp
2018-09-10 20:26:39 +08:00

315 lines
10 KiB
C++

#include "vfindreplacedialog.h"
#include <QtWidgets>
#include "utils/viconutils.h"
#include "vlineedit.h"
VFindReplaceDialog::VFindReplaceDialog(QWidget *p_parent)
: QWidget(p_parent), m_options(0), m_replaceAvailable(true)
{
setupUI();
}
void VFindReplaceDialog::setupUI()
{
QLabel *titleLabel = new QLabel(tr("Find/Replace"));
titleLabel->setProperty("TitleLabel", true);
m_closeBtn = new QPushButton(VIconUtils::titleIcon(":/resources/icons/close.svg"), "");
m_closeBtn->setProperty("TitleBtn", true);
QHBoxLayout *titleLayout = new QHBoxLayout();
titleLayout->addWidget(titleLabel);
titleLayout->addWidget(m_closeBtn);
titleLayout->setStretch(0, 1);
titleLayout->setStretch(1, 0);
titleLayout->setContentsMargins(0, 0, 0, 0);
titleLayout->setSpacing(0);
QWidget *titleWidget = new QWidget();
titleWidget->setObjectName("FindReplaceTitleWidget");
titleWidget->setLayout(titleLayout);
// Find
QLabel *findLabel = new QLabel(tr("Find:"));
m_findEdit = new VLineEdit();
m_findEdit->setPlaceholderText(tr("Enter text to search"));
findLabel->setBuddy(m_findEdit);
m_findNextBtn = new QPushButton(tr("Find &Next"));
m_findNextBtn->setProperty("FlatBtn", true);
m_findNextBtn->setDefault(true);
m_findPrevBtn = new QPushButton(tr("Find &Previous"));
m_findPrevBtn->setProperty("FlatBtn", true);
// Replace
QLabel *replaceLabel = new QLabel(tr("&Replace with:"));
m_replaceEdit = new VLineEdit();
m_replaceEdit->setPlaceholderText(tr("\\1, \\2 for back reference in regular expression"));
replaceLabel->setBuddy(m_replaceEdit);
m_replaceBtn = new QPushButton(tr("Replace"));
m_replaceBtn->setProperty("FlatBtn", true);
m_replaceFindBtn = new QPushButton(tr("Replace && Fin&d"));
m_replaceFindBtn->setProperty("FlatBtn", true);
m_replaceAllBtn = new QPushButton(tr("Replace A&ll"));
m_replaceAllBtn->setProperty("FlatBtn", true);
m_advancedBtn = new QPushButton(tr("&Advanced >>>"));
m_advancedBtn->setProperty("FlatBtn", true);
m_advancedBtn->setCheckable(true);
// Options
m_caseSensitiveCheck = new QCheckBox(tr("&Case sensitive"), this);
connect(m_caseSensitiveCheck, &QCheckBox::stateChanged,
this, &VFindReplaceDialog::optionBoxToggled);
m_wholeWordOnlyCheck = new QCheckBox(tr("&Whole word only"), this);
connect(m_wholeWordOnlyCheck, &QCheckBox::stateChanged,
this, &VFindReplaceDialog::optionBoxToggled);
m_regularExpressionCheck = new QCheckBox(tr("Re&gular expression"), this);
connect(m_regularExpressionCheck, &QCheckBox::stateChanged,
this, &VFindReplaceDialog::optionBoxToggled);
m_incrementalSearchCheck = new QCheckBox(tr("&Incremental search"), this);
connect(m_incrementalSearchCheck, &QCheckBox::stateChanged,
this, &VFindReplaceDialog::optionBoxToggled);
QGridLayout *gridLayout = new QGridLayout();
gridLayout->addWidget(findLabel, 0, 0);
gridLayout->addWidget(m_findEdit, 0, 1);
gridLayout->addWidget(m_findNextBtn, 0, 2);
gridLayout->addWidget(m_findPrevBtn, 0, 3);
gridLayout->addWidget(replaceLabel, 1, 0);
gridLayout->addWidget(m_replaceEdit, 1, 1);
gridLayout->addWidget(m_replaceBtn, 1, 2);
gridLayout->addWidget(m_replaceFindBtn, 1, 3);
gridLayout->addWidget(m_replaceAllBtn, 1, 4);
gridLayout->addWidget(m_advancedBtn, 1, 5);
gridLayout->addWidget(m_caseSensitiveCheck, 2, 1);
gridLayout->addWidget(m_wholeWordOnlyCheck, 2, 2);
gridLayout->addWidget(m_regularExpressionCheck, 3, 1);
gridLayout->addWidget(m_incrementalSearchCheck, 3, 2);
gridLayout->setColumnStretch(0, 0);
gridLayout->setColumnStretch(1, 4);
gridLayout->setColumnStretch(2, 1);
gridLayout->setColumnStretch(3, 1);
gridLayout->setColumnStretch(4, 1);
gridLayout->setColumnStretch(5, 1);
gridLayout->setColumnStretch(6, 3);
QMargins margin = gridLayout->contentsMargins();
margin.setLeft(3);
gridLayout->setContentsMargins(margin);
QVBoxLayout *mainLayout = new QVBoxLayout();
mainLayout->addWidget(titleWidget);
mainLayout->addLayout(gridLayout);
mainLayout->setContentsMargins(0, 0, 0, 0);
setLayout(mainLayout);
setTabOrder(m_findEdit, m_findNextBtn);
setTabOrder(m_findNextBtn, m_findPrevBtn);
setTabOrder(m_findPrevBtn, m_replaceEdit);
setTabOrder(m_replaceEdit, m_replaceBtn);
setTabOrder(m_replaceBtn, m_replaceFindBtn);
setTabOrder(m_replaceFindBtn, m_replaceAllBtn);
setTabOrder(m_replaceAllBtn, m_advancedBtn);
setTabOrder(m_advancedBtn, m_caseSensitiveCheck);
setTabOrder(m_caseSensitiveCheck, m_wholeWordOnlyCheck);
setTabOrder(m_wholeWordOnlyCheck, m_regularExpressionCheck);
setTabOrder(m_regularExpressionCheck, m_incrementalSearchCheck);
setTabOrder(m_incrementalSearchCheck, m_closeBtn);
m_caseSensitiveCheck->hide();
m_wholeWordOnlyCheck->hide();
m_regularExpressionCheck->hide();
m_incrementalSearchCheck->hide();
// Signals
connect(m_closeBtn, &QPushButton::clicked,
this, &VFindReplaceDialog::closeDialog);
connect(m_findEdit, &VLineEdit::textChanged,
this, &VFindReplaceDialog::handleFindTextChanged);
connect(m_advancedBtn, &QPushButton::toggled,
this, &VFindReplaceDialog::advancedBtnToggled);
connect(m_findNextBtn, SIGNAL(clicked(bool)),
this, SLOT(findNext()));
connect(m_findPrevBtn, SIGNAL(clicked(bool)),
this, SLOT(findPrevious()));
connect(m_replaceBtn, SIGNAL(clicked(bool)),
this, SLOT(replace()));
connect(m_replaceFindBtn, SIGNAL(clicked(bool)),
this, SLOT(replaceFind()));
connect(m_replaceAllBtn, SIGNAL(clicked(bool)),
this, SLOT(replaceAll()));
}
void VFindReplaceDialog::closeDialog()
{
if (this->isVisible()) {
hide();
emit dialogClosed();
}
}
void VFindReplaceDialog::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Escape:
event->accept();
closeDialog();
return;
case Qt::Key_Return:
{
int modifiers = event->modifiers();
bool shift = false;
if (modifiers == Qt::ShiftModifier) {
shift = true;
} else if (modifiers != Qt::NoModifier) {
break;
}
if (!m_findEdit->hasFocus() && !m_replaceEdit->hasFocus()) {
break;
}
event->accept();
if (shift) {
findPrevious();
} else {
findNext();
}
return;
}
default:
break;
}
QWidget::keyPressEvent(event);
}
void VFindReplaceDialog::openDialog(QString p_text)
{
show();
if (!p_text.isEmpty()) {
m_findEdit->setText(p_text);
}
m_findEdit->setFocus();
m_findEdit->selectAll();
}
void VFindReplaceDialog::handleFindTextChanged(const QString &p_text)
{
emit findTextChanged(p_text, m_options);
}
void VFindReplaceDialog::advancedBtnToggled(bool p_checked)
{
if (p_checked) {
m_advancedBtn->setText(tr("B&asic <<<"));
} else {
m_advancedBtn->setText(tr("&Advanced >>>"));
}
m_caseSensitiveCheck->setVisible(p_checked);
m_wholeWordOnlyCheck->setVisible(p_checked);
m_regularExpressionCheck->setVisible(p_checked);
m_incrementalSearchCheck->setVisible(p_checked);
}
void VFindReplaceDialog::optionBoxToggled(int p_state)
{
QObject *obj = sender();
FindOption opt = FindOption::CaseSensitive;
if (obj == m_caseSensitiveCheck) {
opt = FindOption::CaseSensitive;
} else if (obj == m_wholeWordOnlyCheck) {
opt = FindOption::WholeWordOnly;
} else if (obj == m_regularExpressionCheck) {
opt = FindOption::RegularExpression;
} else {
opt = FindOption::IncrementalSearch;
}
if (p_state) {
m_options |= opt;
} else {
m_options &= ~opt;
}
emit findOptionChanged(m_options);
}
void VFindReplaceDialog::setOption(FindOption p_opt, bool p_enabled)
{
if (p_opt == FindOption::CaseSensitive) {
m_caseSensitiveCheck->setChecked(p_enabled);
} else if (p_opt == FindOption::WholeWordOnly) {
m_wholeWordOnlyCheck->setChecked(p_enabled);
} else if (p_opt == FindOption::RegularExpression) {
m_regularExpressionCheck->setChecked(p_enabled);
} else if (p_opt == FindOption::IncrementalSearch) {
m_incrementalSearchCheck->setChecked(p_enabled);
} else {
Q_ASSERT(false);
}
}
void VFindReplaceDialog::findNext()
{
QString text = m_findEdit->text();
if (text.isEmpty()) {
return;
}
emit findNext(text, m_options, true);
}
void VFindReplaceDialog::findPrevious()
{
QString text = m_findEdit->text();
if (text.isEmpty()) {
return;
}
emit findNext(text, m_options, false);
}
void VFindReplaceDialog::replace()
{
QString text = m_findEdit->text();
if (text.isEmpty() || !m_replaceAvailable) {
return;
}
QString replaceText = m_replaceEdit->text();
emit replace(text, m_options, replaceText, false);
}
void VFindReplaceDialog::replaceFind()
{
QString text = m_findEdit->text();
if (text.isEmpty() || !m_replaceAvailable) {
return;
}
QString replaceText = m_replaceEdit->text();
emit replace(text, m_options, replaceText, true);
}
void VFindReplaceDialog::replaceAll()
{
QString text = m_findEdit->text();
if (text.isEmpty() || !m_replaceAvailable) {
return;
}
QString replaceText = m_replaceEdit->text();
emit replaceAll(text, m_options, replaceText);
}
void VFindReplaceDialog::updateState(DocType p_docType, bool p_editMode)
{
if (p_editMode || p_docType == DocType::Html) {
m_wholeWordOnlyCheck->setEnabled(true);
m_regularExpressionCheck->setEnabled(true);
} else if (p_docType == DocType::Markdown) {
m_wholeWordOnlyCheck->setEnabled(false);
m_regularExpressionCheck->setEnabled(false);
}
m_replaceAvailable = p_editMode;
}
QString VFindReplaceDialog::textToFind() const
{
return m_findEdit->text();
}