mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 22:09:52 +08:00
318 lines
9.3 KiB
C++
318 lines
9.3 KiB
C++
#include "findandreplacewidget.h"
|
|
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QGridLayout>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QToolButton>
|
|
#include <QAction>
|
|
#include <QCheckBox>
|
|
#include <QKeyEvent>
|
|
#include <QTimer>
|
|
|
|
#include "lineedit.h"
|
|
#include "widgetsfactory.h"
|
|
#include <utils/iconutils.h>
|
|
#include <core/thememgr.h>
|
|
#include <core/vnotex.h>
|
|
#include "propertydefs.h"
|
|
#include "configmgr.h"
|
|
#include "widgetconfig.h"
|
|
|
|
using namespace vnotex;
|
|
|
|
FindAndReplaceWidget::FindAndReplaceWidget(QWidget *p_parent)
|
|
: QWidget(p_parent)
|
|
{
|
|
m_findTextTimer = new QTimer(this);
|
|
m_findTextTimer->setSingleShot(true);
|
|
m_findTextTimer->setInterval(500);
|
|
connect(m_findTextTimer, &QTimer::timeout,
|
|
this, [this]() {
|
|
emit findTextChanged(getFindText(), getOptions());
|
|
});
|
|
|
|
setupUI();
|
|
|
|
auto options = ConfigMgr::getInst().getWidgetConfig().getFindAndReplaceOptions();
|
|
setFindOptions(options);
|
|
}
|
|
|
|
void FindAndReplaceWidget::setupUI()
|
|
{
|
|
auto mainLayout = new QVBoxLayout(this);
|
|
|
|
// Title.
|
|
{
|
|
auto titleLayout = new QHBoxLayout();
|
|
titleLayout->setContentsMargins(0, 0, 0, 0);
|
|
mainLayout->addLayout(titleLayout);
|
|
|
|
auto label = new QLabel(tr("Find And Replace"), this);
|
|
titleLayout->addWidget(label);
|
|
|
|
const auto &themeMgr = VNoteX::getInst().getThemeMgr();
|
|
auto iconFile = themeMgr.getIconFile(QStringLiteral("close.svg"));
|
|
auto closeBtn = new QToolButton(this);
|
|
closeBtn->setProperty(PropertyDefs::c_actionToolButton, true);
|
|
titleLayout->addWidget(closeBtn);
|
|
|
|
auto closeAct = new QAction(IconUtils::fetchIcon(iconFile), QString(), closeBtn);
|
|
closeBtn->setDefaultAction(closeAct);
|
|
connect(closeAct, &QAction::triggered,
|
|
this, &FindAndReplaceWidget::close);
|
|
}
|
|
|
|
auto gridLayout = new QGridLayout();
|
|
gridLayout->setContentsMargins(0, 0, 0, 0);
|
|
mainLayout->addLayout(gridLayout);
|
|
|
|
// Find.
|
|
{
|
|
auto label = new QLabel(tr("Find:"), this);
|
|
|
|
m_findLineEdit = WidgetsFactory::createLineEdit(this);
|
|
m_findLineEdit->setPlaceholderText(tr("Search"));
|
|
connect(m_findLineEdit, &QLineEdit::textChanged,
|
|
m_findTextTimer, QOverload<>::of(&QTimer::start));
|
|
|
|
auto findNextBtn = new QPushButton(tr("Find &Next"), this);
|
|
findNextBtn->setDefault(true);
|
|
connect(findNextBtn, &QPushButton::clicked,
|
|
this, &FindAndReplaceWidget::findNext);
|
|
|
|
auto findPrevBtn = new QPushButton(tr("Find &Previous"), this);
|
|
connect(findPrevBtn, &QPushButton::clicked,
|
|
this, &FindAndReplaceWidget::findPrevious);
|
|
|
|
gridLayout->addWidget(label, 0, 0);
|
|
gridLayout->addWidget(m_findLineEdit, 0, 1);
|
|
gridLayout->addWidget(findNextBtn, 0, 2);
|
|
gridLayout->addWidget(findPrevBtn, 0, 3);
|
|
}
|
|
|
|
// Replace.
|
|
{
|
|
auto label = new QLabel(tr("Replace with:"), this);
|
|
|
|
m_replaceLineEdit = WidgetsFactory::createLineEdit(this);
|
|
m_replaceLineEdit->setPlaceholderText(tr("\\1, \\2 for back reference in regular expression"));
|
|
m_replaceRelatedWidgets.push_back(m_replaceLineEdit);
|
|
|
|
auto replaceBtn = new QPushButton(tr("Replace"), this);
|
|
connect(replaceBtn, &QPushButton::clicked,
|
|
this, &FindAndReplaceWidget::replace);
|
|
m_replaceRelatedWidgets.push_back(replaceBtn);
|
|
|
|
auto replaceFindBtn = new QPushButton(tr("Replace And Find"), this);
|
|
connect(replaceFindBtn, &QPushButton::clicked,
|
|
this, &FindAndReplaceWidget::replaceAndFind);
|
|
m_replaceRelatedWidgets.push_back(replaceFindBtn);
|
|
|
|
auto replaceAllBtn = new QPushButton(tr("Replace All"), this);
|
|
connect(replaceAllBtn, &QPushButton::clicked,
|
|
this, &FindAndReplaceWidget::replaceAll);
|
|
m_replaceRelatedWidgets.push_back(replaceAllBtn);
|
|
|
|
gridLayout->addWidget(label, 1, 0);
|
|
gridLayout->addWidget(m_replaceLineEdit, 1, 1);
|
|
gridLayout->addWidget(replaceBtn, 1, 2);
|
|
gridLayout->addWidget(replaceFindBtn, 1, 3);
|
|
gridLayout->addWidget(replaceAllBtn, 1, 4);
|
|
}
|
|
|
|
// Options.
|
|
{
|
|
auto optionLayout = new QHBoxLayout();
|
|
optionLayout->setContentsMargins(0, 0, 0, 0);
|
|
gridLayout->addLayout(optionLayout, 2, 1, 1, 4);
|
|
|
|
m_caseSensitiveCheckBox = WidgetsFactory::createCheckBox(tr("&Case sensitive"), this);
|
|
connect(m_caseSensitiveCheckBox, &QCheckBox::stateChanged,
|
|
this, &FindAndReplaceWidget::updateFindOptions);
|
|
optionLayout->addWidget(m_caseSensitiveCheckBox);
|
|
|
|
m_wholeWordOnlyCheckBox = WidgetsFactory::createCheckBox(tr("&Whole word only"), this);
|
|
connect(m_wholeWordOnlyCheckBox, &QCheckBox::stateChanged,
|
|
this, &FindAndReplaceWidget::updateFindOptions);
|
|
optionLayout->addWidget(m_wholeWordOnlyCheckBox);
|
|
|
|
m_regularExpressionCheckBox = WidgetsFactory::createCheckBox(tr("Re&gular expression"), this);
|
|
connect(m_regularExpressionCheckBox, &QCheckBox::stateChanged,
|
|
this, &FindAndReplaceWidget::updateFindOptions);
|
|
optionLayout->addWidget(m_regularExpressionCheckBox);
|
|
|
|
m_incrementalSearchCheckBox = WidgetsFactory::createCheckBox(tr("&Incremental search"), this);
|
|
connect(m_incrementalSearchCheckBox, &QCheckBox::stateChanged,
|
|
this, &FindAndReplaceWidget::updateFindOptions);
|
|
optionLayout->addWidget(m_incrementalSearchCheckBox);
|
|
|
|
optionLayout->addStretch();
|
|
}
|
|
}
|
|
|
|
void FindAndReplaceWidget::close()
|
|
{
|
|
hide();
|
|
emit closed();
|
|
}
|
|
|
|
void FindAndReplaceWidget::setReplaceEnabled(bool p_enabled)
|
|
{
|
|
for (auto widget : m_replaceRelatedWidgets) {
|
|
widget->setEnabled(p_enabled);
|
|
}
|
|
}
|
|
|
|
void FindAndReplaceWidget::keyPressEvent(QKeyEvent *p_event)
|
|
{
|
|
switch (p_event->key()) {
|
|
case Qt::Key_Escape:
|
|
close();
|
|
return;
|
|
|
|
case Qt::Key_Return:
|
|
{
|
|
const int modifiers = p_event->modifiers();
|
|
if (modifiers != Qt::ShiftModifier && modifiers != Qt::NoModifier) {
|
|
break;
|
|
}
|
|
|
|
if (!m_findLineEdit->hasFocus() && !m_replaceLineEdit->hasFocus()) {
|
|
break;
|
|
}
|
|
|
|
if (modifiers == Qt::ShiftModifier) {
|
|
findPrevious();
|
|
} else {
|
|
findNext();
|
|
}
|
|
return;
|
|
}
|
|
|
|
default:
|
|
break;
|
|
}
|
|
QWidget::keyPressEvent(p_event);
|
|
}
|
|
|
|
void FindAndReplaceWidget::findNext()
|
|
{
|
|
m_findTextTimer->stop();
|
|
auto text = m_findLineEdit->text();
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
emit findNextRequested(text, m_options);
|
|
}
|
|
|
|
void FindAndReplaceWidget::findPrevious()
|
|
{
|
|
m_findTextTimer->stop();
|
|
auto text = m_findLineEdit->text();
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
emit findNextRequested(text, m_options | FindOption::FindBackward);
|
|
}
|
|
|
|
void FindAndReplaceWidget::updateFindOptions()
|
|
{
|
|
if (m_optionCheckBoxMuted) {
|
|
return;
|
|
}
|
|
|
|
FindOptions options = FindOption::FindNone;
|
|
|
|
if (m_caseSensitiveCheckBox->isChecked()) {
|
|
options |= FindOption::CaseSensitive;
|
|
}
|
|
if (m_wholeWordOnlyCheckBox->isChecked()) {
|
|
options |= FindOption::WholeWordOnly;
|
|
}
|
|
if (m_regularExpressionCheckBox->isChecked()) {
|
|
options |= FindOption::RegularExpression;
|
|
}
|
|
if (m_incrementalSearchCheckBox->isChecked()) {
|
|
options |= FindOption::IncrementalSearch;
|
|
}
|
|
|
|
if (options == m_options) {
|
|
return;
|
|
}
|
|
m_options = options;
|
|
ConfigMgr::getInst().getWidgetConfig().setFindAndReplaceOptions(m_options);
|
|
m_findTextTimer->start();
|
|
}
|
|
|
|
void FindAndReplaceWidget::replace()
|
|
{
|
|
m_findTextTimer->stop();
|
|
auto text = m_findLineEdit->text();
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
emit replaceRequested(text, m_options, m_replaceLineEdit->text());
|
|
}
|
|
|
|
void FindAndReplaceWidget::replaceAndFind()
|
|
{
|
|
m_findTextTimer->stop();
|
|
auto text = m_findLineEdit->text();
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
emit replaceRequested(text, m_options, m_replaceLineEdit->text());
|
|
emit findNextRequested(text, m_options);
|
|
}
|
|
|
|
void FindAndReplaceWidget::replaceAll()
|
|
{
|
|
m_findTextTimer->stop();
|
|
auto text = m_findLineEdit->text();
|
|
if (text.isEmpty()) {
|
|
return;
|
|
}
|
|
emit replaceAllRequested(text, m_options, m_replaceLineEdit->text());
|
|
}
|
|
|
|
void FindAndReplaceWidget::setFindOptions(FindOptions p_options)
|
|
{
|
|
if (p_options == m_options) {
|
|
return;
|
|
}
|
|
|
|
m_optionCheckBoxMuted = true;
|
|
m_options = p_options & ~FindOption::FindBackward;
|
|
m_caseSensitiveCheckBox->setChecked(m_options & FindOption::CaseSensitive);
|
|
m_wholeWordOnlyCheckBox->setChecked(m_options & FindOption::WholeWordOnly);
|
|
m_regularExpressionCheckBox->setChecked(m_options & FindOption::RegularExpression);
|
|
m_incrementalSearchCheckBox->setChecked(m_options & FindOption::IncrementalSearch);
|
|
m_optionCheckBoxMuted = false;
|
|
}
|
|
|
|
void FindAndReplaceWidget::open(const QString &p_text)
|
|
{
|
|
show();
|
|
|
|
if (!p_text.isEmpty()) {
|
|
m_findLineEdit->setText(p_text);
|
|
}
|
|
|
|
m_findLineEdit->setFocus();
|
|
m_findLineEdit->selectAll();
|
|
|
|
emit opened();
|
|
}
|
|
|
|
QString FindAndReplaceWidget::getFindText() const
|
|
{
|
|
return m_findLineEdit->text();
|
|
}
|
|
|
|
FindOptions FindAndReplaceWidget::getOptions() const
|
|
{
|
|
return m_options;
|
|
}
|