mirror of
https://gitee.com/vnotex/vnote.git
synced 2025-07-05 05:49:53 +08:00
implement Find/Replace logics
Supports Find/Replace in both edit and preview modes. Signed-off-by: Le Tan <tamlokveer@gmail.com>
This commit is contained in:
parent
768c1632b0
commit
3005d9bf5c
@ -2,7 +2,7 @@
|
||||
#include <QtWidgets>
|
||||
|
||||
VFindReplaceDialog::VFindReplaceDialog(QWidget *p_parent)
|
||||
: QWidget(p_parent)
|
||||
: QWidget(p_parent), m_options(0), m_replaceAvailable(true)
|
||||
{
|
||||
setupUI();
|
||||
}
|
||||
@ -24,25 +24,42 @@ void VFindReplaceDialog::setupUI()
|
||||
// Find
|
||||
QLabel *findLabel = new QLabel(tr("&Find:"));
|
||||
m_findEdit = new QLineEdit();
|
||||
m_findEdit->setPlaceholderText(tr("Enter text to search"));
|
||||
findLabel->setBuddy(m_findEdit);
|
||||
m_findNextBtn = new QPushButton(tr("Find Next"));
|
||||
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 = new QPushButton(tr("Find &Previous"));
|
||||
m_findPrevBtn->setProperty("FlatBtn", true);
|
||||
|
||||
// Replace
|
||||
QLabel *replaceLabel = new QLabel(tr("&Replace with:"));
|
||||
m_replaceEdit = new QLineEdit();
|
||||
m_replaceEdit->setPlaceholderText(tr("Enter text to replace with"));
|
||||
replaceLabel->setBuddy(m_replaceEdit);
|
||||
m_replaceBtn = new QPushButton(tr("Replace"));
|
||||
m_replaceBtn = new QPushButton(tr("R&eplace"));
|
||||
m_replaceBtn->setProperty("FlatBtn", true);
|
||||
m_replaceFindBtn = new QPushButton(tr("Replace && Find"));
|
||||
m_replaceFindBtn = new QPushButton(tr("Replace && Fin&d"));
|
||||
m_replaceFindBtn->setProperty("FlatBtn", true);
|
||||
m_replaceAllBtn = new QPushButton(tr("Replace All"));
|
||||
m_replaceAllBtn = new QPushButton(tr("Replace A&ll"));
|
||||
m_replaceAllBtn->setProperty("FlatBtn", true);
|
||||
m_advancedBtn = new QPushButton(tr("Advanced"));
|
||||
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);
|
||||
@ -55,6 +72,10 @@ void VFindReplaceDialog::setupUI()
|
||||
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);
|
||||
@ -62,6 +83,7 @@ void VFindReplaceDialog::setupUI()
|
||||
gridLayout->setColumnStretch(4, 1);
|
||||
gridLayout->setColumnStretch(5, 1);
|
||||
gridLayout->setColumnStretch(6, 3);
|
||||
|
||||
QMargins margin = gridLayout->contentsMargins();
|
||||
margin.setLeft(3);
|
||||
gridLayout->setContentsMargins(margin);
|
||||
@ -73,31 +95,195 @@ void VFindReplaceDialog::setupUI()
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
m_caseSensitiveCheck->hide();
|
||||
m_wholeWordOnlyCheck->hide();
|
||||
m_regularExpressionCheck->hide();
|
||||
m_incrementalSearchCheck->hide();
|
||||
|
||||
// Signals
|
||||
connect(m_closeBtn, &QPushButton::clicked,
|
||||
this, &VFindReplaceDialog::closeDialog);
|
||||
connect(m_findEdit, &QLineEdit::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()) {
|
||||
this->hide();
|
||||
hide();
|
||||
emit dialogClosed();
|
||||
}
|
||||
}
|
||||
|
||||
void VFindReplaceDialog::showEvent(QShowEvent *event)
|
||||
{
|
||||
m_findEdit->selectAll();
|
||||
QWidget::showEvent(event);
|
||||
}
|
||||
|
||||
void VFindReplaceDialog::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
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("B&asic <<");
|
||||
} else {
|
||||
m_advancedBtn->setText("&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 {
|
||||
m_wholeWordOnlyCheck->setEnabled(false);
|
||||
m_regularExpressionCheck->setEnabled(false);
|
||||
}
|
||||
m_replaceAvailable = p_editMode;
|
||||
}
|
||||
|
@ -2,28 +2,64 @@
|
||||
#define VFINDREPLACEDIALOG_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QString>
|
||||
#include "vconstants.h"
|
||||
|
||||
class QLineEdit;
|
||||
class QPushButton;
|
||||
class QCheckBox;
|
||||
|
||||
enum FindOption
|
||||
{
|
||||
CaseSensitive = 0x1U,
|
||||
WholeWordOnly = 0x2U,
|
||||
RegularExpression = 0x4U,
|
||||
IncrementalSearch = 0x8U
|
||||
};
|
||||
|
||||
class VFindReplaceDialog : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VFindReplaceDialog(QWidget *p_parent = 0);
|
||||
void setOption(FindOption p_opt, bool p_enabled);
|
||||
// Update the options enabled/disabled state according to current
|
||||
// edit tab.
|
||||
void updateState(DocType p_docType, bool p_editMode);
|
||||
|
||||
signals:
|
||||
void dialogClosed();
|
||||
void findTextChanged(const QString &p_text, uint p_options);
|
||||
void findOptionChanged(uint p_options);
|
||||
void findNext(const QString &p_text, uint p_options, bool p_forward);
|
||||
void replace(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext);
|
||||
void replaceAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent *event) Q_DECL_OVERRIDE;
|
||||
void keyPressEvent(QKeyEvent *event) Q_DECL_OVERRIDE;
|
||||
|
||||
public slots:
|
||||
void closeDialog();
|
||||
void openDialog(QString p_text = "");
|
||||
void findNext();
|
||||
void findPrevious();
|
||||
void replace();
|
||||
void replaceFind();
|
||||
void replaceAll();
|
||||
|
||||
private slots:
|
||||
void handleFindTextChanged(const QString &p_text);
|
||||
void advancedBtnToggled(bool p_checked);
|
||||
void optionBoxToggled(int p_state);
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
// Bit OR of FindOption
|
||||
uint m_options;
|
||||
bool m_replaceAvailable;
|
||||
|
||||
QLineEdit *m_findEdit;
|
||||
QLineEdit *m_replaceEdit;
|
||||
QPushButton *m_findNextBtn;
|
||||
@ -33,6 +69,10 @@ private:
|
||||
QPushButton *m_replaceAllBtn;
|
||||
QPushButton *m_advancedBtn;
|
||||
QPushButton *m_closeBtn;
|
||||
QCheckBox *m_caseSensitiveCheck;
|
||||
QCheckBox *m_wholeWordOnlyCheck;
|
||||
QCheckBox *m_regularExpressionCheck;
|
||||
QCheckBox *m_incrementalSearchCheck;
|
||||
};
|
||||
|
||||
#endif // VFINDREPLACEDIALOG_H
|
||||
|
10
src/resources/icons/find_replace.svg
Normal file
10
src/resources/icons/find_replace.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="512px" height="512px" viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<path d="M445,386.7l-84.8-85.9c13.8-24.1,21-50.9,21-77.9c0-87.6-71.2-158.9-158.6-158.9C135.2,64,64,135.3,64,222.9
|
||||
c0,87.6,71.2,158.9,158.6,158.9c27.9,0,55.5-7.7,80.1-22.4l84.4,85.6c1.9,1.9,4.6,3.1,7.3,3.1c2.7,0,5.4-1.1,7.3-3.1l43.3-43.8
|
||||
C449,397.1,449,390.7,445,386.7z M222.6,125.9c53.4,0,96.8,43.5,96.8,97c0,53.5-43.4,97-96.8,97c-53.4,0-96.8-43.5-96.8-97
|
||||
C125.8,169.4,169.2,125.9,222.6,125.9z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 894 B |
@ -68,6 +68,15 @@ void VConfigManager::initialize()
|
||||
m_mainSplitterState = getConfigFromSettings("session", "main_splitter_state").toByteArray();
|
||||
|
||||
updateMarkdownEditStyle();
|
||||
|
||||
m_findCaseSensitive = getConfigFromSettings("global",
|
||||
"find_case_sensitive").toBool();
|
||||
m_findWholeWordOnly = getConfigFromSettings("global",
|
||||
"find_whole_word_only").toBool();
|
||||
m_findRegularExpression = getConfigFromSettings("global",
|
||||
"find_regular_expression").toBool();
|
||||
m_findIncrementalSearch = getConfigFromSettings("global",
|
||||
"find_incremental_search").toBool();
|
||||
}
|
||||
|
||||
void VConfigManager::readPredefinedColorsFromSettings()
|
||||
|
@ -99,6 +99,18 @@ public:
|
||||
inline const QByteArray &getMainSplitterState() const;
|
||||
inline void setMainSplitterState(const QByteArray &p_state);
|
||||
|
||||
inline bool getFindCaseSensitive() const;
|
||||
inline void setFindCaseSensitive(bool p_enabled);
|
||||
|
||||
inline bool getFindWholeWordOnly() const;
|
||||
inline void setFindWholeWordOnly(bool p_enabled);
|
||||
|
||||
inline bool getFindRegularExpression() const;
|
||||
inline void setFindRegularExpression(bool p_enabled);
|
||||
|
||||
inline bool getFindIncrementalSearch() const;
|
||||
inline void setFindIncrementalSearch(bool p_enabled);
|
||||
|
||||
private:
|
||||
void updateMarkdownEditStyle();
|
||||
QVariant getConfigFromSettings(const QString §ion, const QString &key);
|
||||
@ -144,6 +156,12 @@ private:
|
||||
QByteArray m_mainWindowState;
|
||||
QByteArray m_mainSplitterState;
|
||||
|
||||
// Find/Replace dialog options
|
||||
bool m_findCaseSensitive;
|
||||
bool m_findWholeWordOnly;
|
||||
bool m_findRegularExpression;
|
||||
bool m_findIncrementalSearch;
|
||||
|
||||
// The name of the config file in each directory
|
||||
static const QString dirConfigFileName;
|
||||
// The name of the default configuration file
|
||||
@ -373,4 +391,62 @@ inline void VConfigManager::setMainSplitterState(const QByteArray &p_state)
|
||||
setConfigToSettings("session", "main_splitter_state", m_mainSplitterState);
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getFindCaseSensitive() const
|
||||
{
|
||||
return m_findCaseSensitive;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setFindCaseSensitive(bool p_enabled)
|
||||
{
|
||||
if (m_findCaseSensitive == p_enabled) {
|
||||
return;
|
||||
}
|
||||
m_findCaseSensitive = p_enabled;
|
||||
setConfigToSettings("global", "find_case_sensitive", m_findCaseSensitive);
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getFindWholeWordOnly() const
|
||||
{
|
||||
return m_findWholeWordOnly;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setFindWholeWordOnly(bool p_enabled)
|
||||
{
|
||||
if (m_findWholeWordOnly == p_enabled) {
|
||||
return;
|
||||
}
|
||||
m_findWholeWordOnly = p_enabled;
|
||||
setConfigToSettings("global", "find_whole_word_only", m_findWholeWordOnly);
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getFindRegularExpression() const
|
||||
{
|
||||
return m_findRegularExpression;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setFindRegularExpression(bool p_enabled)
|
||||
{
|
||||
if (m_findRegularExpression == p_enabled) {
|
||||
return;
|
||||
}
|
||||
m_findRegularExpression = p_enabled;
|
||||
setConfigToSettings("global", "find_regular_expression",
|
||||
m_findRegularExpression);
|
||||
}
|
||||
|
||||
inline bool VConfigManager::getFindIncrementalSearch() const
|
||||
{
|
||||
return m_findIncrementalSearch;
|
||||
}
|
||||
|
||||
inline void VConfigManager::setFindIncrementalSearch(bool p_enabled)
|
||||
{
|
||||
if (m_findIncrementalSearch == p_enabled) {
|
||||
return;
|
||||
}
|
||||
m_findIncrementalSearch = p_enabled;
|
||||
setConfigToSettings("global", "find_incremental_search",
|
||||
m_findIncrementalSearch);
|
||||
}
|
||||
|
||||
#endif // VCONFIGMANAGER_H
|
||||
|
164
src/vedit.cpp
164
src/vedit.cpp
@ -1,11 +1,13 @@
|
||||
#include <QtWidgets>
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
#include "vedit.h"
|
||||
#include "vnote.h"
|
||||
#include "vconfigmanager.h"
|
||||
#include "vtoc.h"
|
||||
#include "utils/vutils.h"
|
||||
#include "veditoperations.h"
|
||||
#include "dialog/vfindreplacedialog.h"
|
||||
|
||||
extern VConfigManager vconfig;
|
||||
|
||||
@ -82,3 +84,165 @@ void VEdit::insertImage()
|
||||
m_editOps->insertImage();
|
||||
}
|
||||
}
|
||||
|
||||
bool VEdit::findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward)
|
||||
{
|
||||
static int startPos = textCursor().selectionStart();
|
||||
static int lastPos = startPos;
|
||||
bool found = false;
|
||||
|
||||
if (p_text.isEmpty() && p_peek) {
|
||||
// Clear previous selection
|
||||
QTextCursor cursor = textCursor();
|
||||
cursor.clearSelection();
|
||||
cursor.setPosition(startPos);
|
||||
setTextCursor(cursor);
|
||||
} else {
|
||||
QTextCursor cursor = textCursor();
|
||||
if (p_peek) {
|
||||
int curPos = cursor.selectionStart();
|
||||
if (curPos != lastPos) {
|
||||
// Cursor has been moved. Just start at current position.
|
||||
startPos = curPos;
|
||||
lastPos = curPos;
|
||||
} else {
|
||||
// Move cursor to startPos to search.
|
||||
cursor.setPosition(startPos);
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
|
||||
// Options
|
||||
QTextDocument::FindFlags flags;
|
||||
if (p_options & FindOption::CaseSensitive) {
|
||||
flags |= QTextDocument::FindCaseSensitively;
|
||||
}
|
||||
if (p_options & FindOption::WholeWordOnly) {
|
||||
flags |= QTextDocument::FindWholeWords;
|
||||
}
|
||||
if (!p_forward) {
|
||||
flags |= QTextDocument::FindBackward;
|
||||
}
|
||||
// Use regular expression
|
||||
if (p_options & FindOption::RegularExpression) {
|
||||
QRegExp exp(p_text,
|
||||
p_options & FindOption::CaseSensitive ?
|
||||
Qt::CaseSensitive : Qt::CaseInsensitive);
|
||||
found = find(exp, flags);
|
||||
} else {
|
||||
found = find(p_text, flags);
|
||||
}
|
||||
cursor = textCursor();
|
||||
if (!p_peek) {
|
||||
startPos = cursor.selectionStart();
|
||||
}
|
||||
lastPos = cursor.selectionStart();
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void VEdit::replaceText(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext)
|
||||
{
|
||||
// Options
|
||||
QTextDocument::FindFlags flags;
|
||||
if (p_options & FindOption::CaseSensitive) {
|
||||
flags |= QTextDocument::FindCaseSensitively;
|
||||
}
|
||||
if (p_options & FindOption::WholeWordOnly) {
|
||||
flags |= QTextDocument::FindWholeWords;
|
||||
}
|
||||
|
||||
bool useRegExp = false;
|
||||
QRegExp exp;
|
||||
if (p_options & FindOption::RegularExpression) {
|
||||
useRegExp = true;
|
||||
exp = QRegExp(p_text,
|
||||
p_options & FindOption::CaseSensitive ?
|
||||
Qt::CaseSensitive : Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
if (cursor.hasSelection()) {
|
||||
// Replace occurs only if the selected text matches @p_text with @p_options.
|
||||
QTextCursor matchCursor;
|
||||
if (useRegExp) {
|
||||
matchCursor = document()->find(exp, cursor.selectionStart(),
|
||||
flags);
|
||||
} else {
|
||||
matchCursor = document()->find(p_text, cursor.selectionStart(),
|
||||
flags);
|
||||
}
|
||||
bool matched = (cursor.selectionStart() == matchCursor.selectionStart())
|
||||
&& (cursor.selectionEnd() == matchCursor.selectionEnd());
|
||||
if (matched) {
|
||||
cursor.beginEditBlock();
|
||||
cursor.removeSelectedText();
|
||||
cursor.insertText(p_replaceText);
|
||||
cursor.endEditBlock();
|
||||
setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
if (p_findNext) {
|
||||
findText(p_text, p_options, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
void VEdit::replaceTextAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText)
|
||||
{
|
||||
// Options
|
||||
QTextDocument::FindFlags flags;
|
||||
if (p_options & FindOption::CaseSensitive) {
|
||||
flags |= QTextDocument::FindCaseSensitively;
|
||||
}
|
||||
if (p_options & FindOption::WholeWordOnly) {
|
||||
flags |= QTextDocument::FindWholeWords;
|
||||
}
|
||||
|
||||
bool useRegExp = false;
|
||||
QRegExp exp;
|
||||
if (p_options & FindOption::RegularExpression) {
|
||||
useRegExp = true;
|
||||
exp = QRegExp(p_text,
|
||||
p_options & FindOption::CaseSensitive ?
|
||||
Qt::CaseSensitive : Qt::CaseInsensitive);
|
||||
}
|
||||
|
||||
QTextCursor cursor = textCursor();
|
||||
int pos = cursor.position();
|
||||
int nrReplaces = 0;
|
||||
int startPos = 0;
|
||||
int lastMatch = -1;
|
||||
while (true) {
|
||||
QTextCursor matchCursor;
|
||||
if (useRegExp) {
|
||||
matchCursor = document()->find(exp, startPos, flags);
|
||||
} else {
|
||||
matchCursor = document()->find(p_text, startPos, flags);
|
||||
}
|
||||
if (matchCursor.isNull()) {
|
||||
break;
|
||||
} else {
|
||||
if (matchCursor.selectionStart() <= lastMatch) {
|
||||
// Wrap back.
|
||||
break;
|
||||
} else {
|
||||
lastMatch = matchCursor.selectionStart();
|
||||
}
|
||||
nrReplaces++;
|
||||
matchCursor.beginEditBlock();
|
||||
matchCursor.removeSelectedText();
|
||||
matchCursor.insertText(p_replaceText);
|
||||
matchCursor.endEditBlock();
|
||||
setTextCursor(matchCursor);
|
||||
startPos = matchCursor.position();
|
||||
}
|
||||
}
|
||||
// Restore cursor position.
|
||||
cursor.setPosition(pos);
|
||||
setTextCursor(cursor);
|
||||
qDebug() << "replace all" << nrReplaces << "occurencs";
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,12 @@ public:
|
||||
virtual void scrollToLine(int p_lineNumber);
|
||||
// User requests to insert an image.
|
||||
virtual void insertImage();
|
||||
virtual bool findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward);
|
||||
virtual void replaceText(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext);
|
||||
virtual void replaceTextAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText);
|
||||
|
||||
protected:
|
||||
QPointer<VFile> m_file;
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "vfile.h"
|
||||
#include "dialog/vfindreplacedialog.h"
|
||||
|
||||
extern VConfigManager vconfig;
|
||||
|
||||
VEditArea::VEditArea(VNote *vnote, QWidget *parent)
|
||||
: QWidget(parent), vnote(vnote), curWindowIndex(-1)
|
||||
{
|
||||
@ -20,6 +22,14 @@ void VEditArea::setupUI()
|
||||
{
|
||||
splitter = new QSplitter(this);
|
||||
m_findReplace = new VFindReplaceDialog(this);
|
||||
m_findReplace->setOption(FindOption::CaseSensitive,
|
||||
vconfig.getFindCaseSensitive());
|
||||
m_findReplace->setOption(FindOption::WholeWordOnly,
|
||||
vconfig.getFindWholeWordOnly());
|
||||
m_findReplace->setOption(FindOption::RegularExpression,
|
||||
vconfig.getFindRegularExpression());
|
||||
m_findReplace->setOption(FindOption::IncrementalSearch,
|
||||
vconfig.getFindIncrementalSearch());
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout();
|
||||
mainLayout->addWidget(splitter);
|
||||
@ -31,6 +41,22 @@ void VEditArea::setupUI()
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
||||
connect(m_findReplace, &VFindReplaceDialog::findTextChanged,
|
||||
this, &VEditArea::handleFindTextChanged);
|
||||
connect(m_findReplace, &VFindReplaceDialog::findOptionChanged,
|
||||
this, &VEditArea::handleFindOptionChanged);
|
||||
connect(m_findReplace, SIGNAL(findNext(const QString &, uint, bool)),
|
||||
this, SLOT(handleFindNext(const QString &, uint, bool)));
|
||||
connect(m_findReplace,
|
||||
SIGNAL(replace(const QString &, uint, const QString &, bool)),
|
||||
this,
|
||||
SLOT(handleReplace(const QString &, uint, const QString &, bool)));
|
||||
connect(m_findReplace,
|
||||
SIGNAL(replaceAll(const QString &, uint, const QString &)),
|
||||
this,
|
||||
SLOT(handleReplaceAll(const QString &, uint, const QString &)));
|
||||
connect(m_findReplace, &VFindReplaceDialog::dialogClosed,
|
||||
this, &VEditArea::handleFindDialogClosed);
|
||||
m_findReplace->hide();
|
||||
}
|
||||
|
||||
@ -422,3 +448,80 @@ void VEditArea::moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx)
|
||||
delete p_widget;
|
||||
}
|
||||
}
|
||||
|
||||
// Only propogate the search in the IncrementalSearch case.
|
||||
void VEditArea::handleFindTextChanged(const QString &p_text, uint p_options)
|
||||
{
|
||||
VEditTab *tab = currentEditTab();
|
||||
if (tab) {
|
||||
if (p_options & FindOption::IncrementalSearch) {
|
||||
tab->findText(p_text, p_options, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VEditArea::handleFindOptionChanged(uint p_options)
|
||||
{
|
||||
qDebug() << "find option changed" << p_options;
|
||||
vconfig.setFindCaseSensitive(p_options & FindOption::CaseSensitive);
|
||||
vconfig.setFindWholeWordOnly(p_options & FindOption::WholeWordOnly);
|
||||
vconfig.setFindRegularExpression(p_options & FindOption::RegularExpression);
|
||||
vconfig.setFindIncrementalSearch(p_options & FindOption::IncrementalSearch);
|
||||
}
|
||||
|
||||
void VEditArea::handleFindNext(const QString &p_text, uint p_options,
|
||||
bool p_forward)
|
||||
{
|
||||
qDebug() << "find next" << p_text << p_options << p_forward;
|
||||
VEditTab *tab = currentEditTab();
|
||||
if (tab) {
|
||||
tab->findText(p_text, p_options, false, p_forward);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditArea::handleReplace(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext)
|
||||
{
|
||||
qDebug() << "replace" << p_text << p_options << "with" << p_replaceText
|
||||
<< p_findNext;
|
||||
VEditTab *tab = currentEditTab();
|
||||
if (tab) {
|
||||
tab->replaceText(p_text, p_options, p_replaceText, p_findNext);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditArea::handleReplaceAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText)
|
||||
{
|
||||
qDebug() << "replace all" << p_text << p_options << "with" << p_replaceText;
|
||||
VEditTab *tab = currentEditTab();
|
||||
if (tab) {
|
||||
tab->replaceTextAll(p_text, p_options, p_replaceText);
|
||||
}
|
||||
}
|
||||
|
||||
// Let VEditArea get focus after VFindReplaceDialog is closed.
|
||||
void VEditArea::handleFindDialogClosed()
|
||||
{
|
||||
if (curWindowIndex == -1) {
|
||||
setFocus();
|
||||
} else {
|
||||
getWindow(curWindowIndex)->focusWindow();
|
||||
}
|
||||
|
||||
// Clear all the selection in Web view.
|
||||
int nrWin = splitter->count();
|
||||
for (int i = 0; i < nrWin; ++i) {
|
||||
getWindow(i)->clearFindSelectionInWebView();
|
||||
}
|
||||
}
|
||||
|
||||
QString VEditArea::getSelectedText()
|
||||
{
|
||||
VEditTab *tab = currentEditTab();
|
||||
if (tab) {
|
||||
return tab->getSelectedText();
|
||||
} else {
|
||||
return QString();
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,8 @@ public:
|
||||
// If fail, just delete the p_widget.
|
||||
void moveTab(QWidget *p_widget, int p_fromIdx, int p_toIdx);
|
||||
inline VFindReplaceDialog *getFindReplaceDialog() const;
|
||||
// Return selected text of current edit tab.
|
||||
QString getSelectedText();
|
||||
|
||||
signals:
|
||||
void curTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode);
|
||||
@ -66,6 +68,14 @@ private slots:
|
||||
void handleWindowFocused();
|
||||
void handleOutlineChanged(const VToc &toc);
|
||||
void handleCurHeaderChanged(const VAnchor &anchor);
|
||||
void handleFindTextChanged(const QString &p_text, uint p_options);
|
||||
void handleFindOptionChanged(uint p_options);
|
||||
void handleFindNext(const QString &p_text, uint p_options, bool p_forward);
|
||||
void handleReplace(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext);
|
||||
void handleReplaceAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText);
|
||||
void handleFindDialogClosed();
|
||||
|
||||
private:
|
||||
void setupUI();
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "vnotebook.h"
|
||||
#include "vtoc.h"
|
||||
#include "vmdedit.h"
|
||||
#include "dialog/vfindreplacedialog.h"
|
||||
|
||||
extern VConfigManager vconfig;
|
||||
|
||||
@ -107,6 +108,7 @@ void VEditTab::showFileReadMode()
|
||||
previewByConverter();
|
||||
}
|
||||
setCurrentWidget(webPreviewer);
|
||||
clearFindSelectionInWebView();
|
||||
scrollPreviewToHeader(outlineIndex);
|
||||
break;
|
||||
default:
|
||||
@ -276,6 +278,7 @@ void VEditTab::setupMarkdownPreview()
|
||||
void VEditTab::focusTab()
|
||||
{
|
||||
currentWidget()->setFocus();
|
||||
emit getFocused();
|
||||
}
|
||||
|
||||
void VEditTab::handleFocusChanged(QWidget * /* old */, QWidget *now)
|
||||
@ -455,3 +458,60 @@ void VEditTab::insertImage()
|
||||
}
|
||||
m_textEditor->insertImage();
|
||||
}
|
||||
|
||||
void VEditTab::findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward)
|
||||
{
|
||||
if (isEditMode || !webPreviewer) {
|
||||
m_textEditor->findText(p_text, p_options, p_peek, p_forward);
|
||||
} else {
|
||||
findTextInWebView(p_text, p_options, p_peek, p_forward);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditTab::replaceText(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext)
|
||||
{
|
||||
if (isEditMode) {
|
||||
m_textEditor->replaceText(p_text, p_options, p_replaceText, p_findNext);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditTab::replaceTextAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText)
|
||||
{
|
||||
if (isEditMode) {
|
||||
m_textEditor->replaceTextAll(p_text, p_options, p_replaceText);
|
||||
}
|
||||
}
|
||||
|
||||
void VEditTab::findTextInWebView(const QString &p_text, uint p_options,
|
||||
bool p_peek, bool p_forward)
|
||||
{
|
||||
Q_ASSERT(webPreviewer);
|
||||
QWebEnginePage::FindFlags flags;
|
||||
if (p_options & FindOption::CaseSensitive) {
|
||||
flags |= QWebEnginePage::FindCaseSensitively;
|
||||
}
|
||||
if (!p_forward) {
|
||||
flags |= QWebEnginePage::FindBackward;
|
||||
}
|
||||
webPreviewer->findText(p_text, flags);
|
||||
}
|
||||
|
||||
QString VEditTab::getSelectedText() const
|
||||
{
|
||||
if (isEditMode || !webPreviewer) {
|
||||
QTextCursor cursor = m_textEditor->textCursor();
|
||||
return cursor.selectedText();
|
||||
} else {
|
||||
return webPreviewer->selectedText();
|
||||
}
|
||||
}
|
||||
|
||||
void VEditTab::clearFindSelectionInWebView()
|
||||
{
|
||||
if (webPreviewer) {
|
||||
webPreviewer->findText("");
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,16 @@ public:
|
||||
void scrollToAnchor(const VAnchor& anchor);
|
||||
inline VFile *getFile();
|
||||
void insertImage();
|
||||
// Search @p_text in current note.
|
||||
void findText(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward = true);
|
||||
// Replace @p_text with @p_replaceText in current note.
|
||||
void replaceText(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText, bool p_findNext);
|
||||
void replaceTextAll(const QString &p_text, uint p_options,
|
||||
const QString &p_replaceText);
|
||||
QString getSelectedText() const;
|
||||
void clearFindSelectionInWebView();
|
||||
|
||||
signals:
|
||||
void getFocused();
|
||||
@ -65,6 +75,8 @@ private:
|
||||
void parseTocUl(QXmlStreamReader &xml, QVector<VHeader> &headers, int level);
|
||||
void parseTocLi(QXmlStreamReader &xml, QVector<VHeader> &headers, int level);
|
||||
void scrollPreviewToHeader(int p_outlineIndex);
|
||||
void findTextInWebView(const QString &p_text, uint p_options, bool p_peek,
|
||||
bool p_forward);
|
||||
|
||||
QPointer<VFile> m_file;
|
||||
bool isEditMode;
|
||||
|
@ -362,6 +362,7 @@ void VEditWindow::focusWindow()
|
||||
int idx = currentIndex();
|
||||
if (idx == -1) {
|
||||
setFocus();
|
||||
emit getFocused();
|
||||
return;
|
||||
}
|
||||
getTab(idx)->focusTab();
|
||||
@ -375,7 +376,7 @@ void VEditWindow::handleTabbarClicked(int /* index */)
|
||||
|
||||
void VEditWindow::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
emit getFocused();
|
||||
focusWindow();
|
||||
QTabWidget::mousePressEvent(event);
|
||||
}
|
||||
|
||||
@ -705,3 +706,11 @@ void VEditWindow::setCurrentWindow(bool p_current)
|
||||
leftBtn->setIcon(QIcon(":/resources/icons/corner_tablist.svg"));
|
||||
}
|
||||
}
|
||||
|
||||
void VEditWindow::clearFindSelectionInWebView()
|
||||
{
|
||||
int nrTab = count();
|
||||
for (int i = 0; i < nrTab; ++i) {
|
||||
getTab(i)->clearFindSelectionInWebView();
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
bool addEditTab(QWidget *p_widget);
|
||||
// Set whether it is the current window.
|
||||
void setCurrentWindow(bool p_current);
|
||||
void clearFindSelectionInWebView();
|
||||
|
||||
protected:
|
||||
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
|
||||
|
@ -48,6 +48,7 @@ void VMainWindow::setupUI()
|
||||
|
||||
editArea = new VEditArea(vnote);
|
||||
editArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
m_findReplaceDialog = editArea->getFindReplaceDialog();
|
||||
fileList->setEditArea(editArea);
|
||||
directoryTree->setEditArea(editArea);
|
||||
notebookSelector->setEditArea(editArea);
|
||||
@ -79,10 +80,12 @@ void VMainWindow::setupUI()
|
||||
editArea, &VEditArea::handleFileUpdated);
|
||||
connect(editArea, &VEditArea::curTabStatusChanged,
|
||||
this, &VMainWindow::handleCurTabStatusChanged);
|
||||
connect(m_findReplaceDialog, &VFindReplaceDialog::findTextChanged,
|
||||
this, &VMainWindow::handleFindDialogTextChanged);
|
||||
|
||||
setCentralWidget(mainSplitter);
|
||||
// TODO: Create and show the status bar
|
||||
// statusBar();
|
||||
// Create and show the status bar
|
||||
statusBar();
|
||||
}
|
||||
|
||||
QWidget *VMainWindow::setupDirectoryPanel()
|
||||
@ -179,7 +182,7 @@ void VMainWindow::initFileToolBar()
|
||||
newNoteAct = new QAction(QIcon(":/resources/icons/create_note_tb.svg"),
|
||||
tr("New &Note"), this);
|
||||
newNoteAct->setStatusTip(tr("Create a note in current directory"));
|
||||
newNoteAct->setShortcut(QKeySequence("Ctrl+N"));
|
||||
newNoteAct->setShortcut(QKeySequence::New);
|
||||
connect(newNoteAct, &QAction::triggered,
|
||||
fileList, &VFileList::newFile);
|
||||
|
||||
@ -325,13 +328,49 @@ void VMainWindow::initEditMenu()
|
||||
{
|
||||
QMenu *editMenu = menuBar()->addMenu(tr("&Edit"));
|
||||
|
||||
// Inser image.
|
||||
QAction *insertImageAct = new QAction(QIcon(":/resources/icons/insert_image.svg"),
|
||||
tr("Insert &Image"), this);
|
||||
insertImageAct->setStatusTip(tr("Insert an image from file in current note"));
|
||||
connect(insertImageAct, &QAction::triggered,
|
||||
// Insert image.
|
||||
m_insertImageAct = new QAction(QIcon(":/resources/icons/insert_image.svg"),
|
||||
tr("Insert &Image"), this);
|
||||
m_insertImageAct->setStatusTip(tr("Insert an image from file in current note"));
|
||||
connect(m_insertImageAct, &QAction::triggered,
|
||||
this, &VMainWindow::insertImage);
|
||||
|
||||
// Find/Replace.
|
||||
m_findReplaceAct = new QAction(QIcon(":/resources/icons/find_replace.svg"),
|
||||
tr("Find/Replace"), this);
|
||||
m_findReplaceAct->setStatusTip(tr("Open Find/Replace dialog to search in current note"));
|
||||
m_findReplaceAct->setShortcut(QKeySequence::Find);
|
||||
connect(m_findReplaceAct, &QAction::triggered,
|
||||
this, &VMainWindow::openFindDialog);
|
||||
|
||||
m_findNextAct = new QAction(tr("Find Next"), this);
|
||||
m_findNextAct->setStatusTip(tr("Find next occurence"));
|
||||
m_findNextAct->setShortcut(QKeySequence::FindNext);
|
||||
connect(m_findNextAct, SIGNAL(triggered(bool)),
|
||||
m_findReplaceDialog, SLOT(findNext()));
|
||||
|
||||
m_findPreviousAct = new QAction(tr("Find Previous"), this);
|
||||
m_findPreviousAct->setStatusTip(tr("Find previous occurence"));
|
||||
m_findPreviousAct->setShortcut(QKeySequence::FindPrevious);
|
||||
connect(m_findPreviousAct, SIGNAL(triggered(bool)),
|
||||
m_findReplaceDialog, SLOT(findPrevious()));
|
||||
|
||||
m_replaceAct = new QAction(tr("Replace"), this);
|
||||
m_replaceAct->setStatusTip(tr("Replace current occurence"));
|
||||
m_replaceAct->setShortcut(QKeySequence::Replace);
|
||||
connect(m_replaceAct, SIGNAL(triggered(bool)),
|
||||
m_findReplaceDialog, SLOT(replace()));
|
||||
|
||||
m_replaceFindAct = new QAction(tr("Replace && Find"), this);
|
||||
m_replaceFindAct->setStatusTip(tr("Replace current occurence and find the next one"));
|
||||
connect(m_replaceFindAct, SIGNAL(triggered(bool)),
|
||||
m_findReplaceDialog, SLOT(replaceFind()));
|
||||
|
||||
m_replaceAllAct = new QAction(tr("Replace All"), this);
|
||||
m_replaceAllAct->setStatusTip(tr("Replace all occurences in current note"));
|
||||
connect(m_replaceAllAct, SIGNAL(triggered(bool)),
|
||||
m_findReplaceDialog, SLOT(replaceAll()));
|
||||
|
||||
// Expand Tab into spaces.
|
||||
QAction *expandTabAct = new QAction(tr("&Expand Tab"), this);
|
||||
expandTabAct->setStatusTip(tr("Expand entered tab to spaces"));
|
||||
@ -364,8 +403,25 @@ void VMainWindow::initEditMenu()
|
||||
this, &VMainWindow::changeHighlightCursorLine);
|
||||
|
||||
|
||||
editMenu->addAction(insertImageAct);
|
||||
editMenu->addAction(m_insertImageAct);
|
||||
editMenu->addSeparator();
|
||||
m_insertImageAct->setEnabled(false);
|
||||
|
||||
QMenu *findReplaceMenu = editMenu->addMenu(tr("Find/Replace"));
|
||||
findReplaceMenu->addAction(m_findReplaceAct);
|
||||
findReplaceMenu->addAction(m_findNextAct);
|
||||
findReplaceMenu->addAction(m_findPreviousAct);
|
||||
findReplaceMenu->addAction(m_replaceAct);
|
||||
findReplaceMenu->addAction(m_replaceFindAct);
|
||||
findReplaceMenu->addAction(m_replaceAllAct);
|
||||
editMenu->addSeparator();
|
||||
m_findReplaceAct->setEnabled(false);
|
||||
m_findNextAct->setEnabled(false);
|
||||
m_findPreviousAct->setEnabled(false);
|
||||
m_replaceAct->setEnabled(false);
|
||||
m_replaceFindAct->setEnabled(false);
|
||||
m_replaceAllAct->setEnabled(false);
|
||||
|
||||
editMenu->addAction(expandTabAct);
|
||||
if (vconfig.getIsExpandTab()) {
|
||||
expandTabAct->setChecked(true);
|
||||
@ -588,36 +644,56 @@ void VMainWindow::setRenderBackgroundColor(QAction *action)
|
||||
vnote->updateTemplate();
|
||||
}
|
||||
|
||||
void VMainWindow::updateToolbarFromTabChage(const VFile *p_file, bool p_editMode)
|
||||
void VMainWindow::updateActionStateFromTabStatusChange(const VFile *p_file,
|
||||
bool p_editMode)
|
||||
{
|
||||
qDebug() << "update toolbar";
|
||||
if (!p_file) {
|
||||
if (p_file) {
|
||||
if (p_editMode) {
|
||||
editNoteAct->setVisible(false);
|
||||
saveExitAct->setVisible(true);
|
||||
saveNoteAct->setVisible(true);
|
||||
deleteNoteAct->setEnabled(true);
|
||||
|
||||
m_insertImageAct->setEnabled(true);
|
||||
} else {
|
||||
editNoteAct->setVisible(true);
|
||||
saveExitAct->setVisible(false);
|
||||
saveNoteAct->setVisible(false);
|
||||
deleteNoteAct->setEnabled(true);
|
||||
|
||||
m_insertImageAct->setEnabled(false);
|
||||
m_replaceAct->setEnabled(false);
|
||||
m_replaceFindAct->setEnabled(false);
|
||||
m_replaceAllAct->setEnabled(false);
|
||||
}
|
||||
noteInfoAct->setEnabled(true);
|
||||
|
||||
m_findReplaceAct->setEnabled(true);
|
||||
} else {
|
||||
editNoteAct->setVisible(false);
|
||||
saveExitAct->setVisible(false);
|
||||
saveNoteAct->setVisible(false);
|
||||
deleteNoteAct->setEnabled(false);
|
||||
} else if (p_editMode) {
|
||||
editNoteAct->setVisible(false);
|
||||
saveExitAct->setVisible(true);
|
||||
saveNoteAct->setVisible(true);
|
||||
deleteNoteAct->setEnabled(true);
|
||||
} else {
|
||||
editNoteAct->setVisible(true);
|
||||
saveExitAct->setVisible(false);
|
||||
saveNoteAct->setVisible(false);
|
||||
deleteNoteAct->setEnabled(true);
|
||||
}
|
||||
|
||||
if (p_file) {
|
||||
noteInfoAct->setEnabled(true);
|
||||
} else {
|
||||
noteInfoAct->setEnabled(false);
|
||||
|
||||
m_insertImageAct->setEnabled(false);
|
||||
// Find/Replace
|
||||
m_findReplaceAct->setEnabled(false);
|
||||
m_findNextAct->setEnabled(false);
|
||||
m_findPreviousAct->setEnabled(false);
|
||||
m_replaceAct->setEnabled(false);
|
||||
m_replaceFindAct->setEnabled(false);
|
||||
m_replaceAllAct->setEnabled(false);
|
||||
m_findReplaceDialog->closeDialog();
|
||||
}
|
||||
}
|
||||
|
||||
void VMainWindow::handleCurTabStatusChanged(const VFile *p_file, const VEditTab *p_editTab, bool p_editMode)
|
||||
{
|
||||
updateToolbarFromTabChage(p_file, p_editMode);
|
||||
updateActionStateFromTabStatusChange(p_file, p_editMode);
|
||||
if (p_file) {
|
||||
m_findReplaceDialog->updateState(p_file->getDocType(), p_editMode);
|
||||
}
|
||||
|
||||
QString title;
|
||||
if (p_file) {
|
||||
@ -761,7 +837,7 @@ void VMainWindow::resizeEvent(QResizeEvent *event)
|
||||
void VMainWindow::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
editArea->getFindReplaceDialog()->closeDialog();
|
||||
m_findReplaceDialog->closeDialog();
|
||||
event->accept();
|
||||
return;
|
||||
}
|
||||
@ -809,3 +885,21 @@ void VMainWindow::locateFile(VFile *p_file) const
|
||||
}
|
||||
}
|
||||
|
||||
void VMainWindow::handleFindDialogTextChanged(const QString &p_text, uint /* p_options */)
|
||||
{
|
||||
bool enabled = true;
|
||||
if (p_text.isEmpty()) {
|
||||
enabled = false;
|
||||
}
|
||||
m_findNextAct->setEnabled(enabled);
|
||||
m_findPreviousAct->setEnabled(enabled);
|
||||
m_replaceAct->setEnabled(enabled);
|
||||
m_replaceFindAct->setEnabled(enabled);
|
||||
m_replaceAllAct->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void VMainWindow::openFindDialog()
|
||||
{
|
||||
m_findReplaceDialog->openDialog(editArea->getSelectedText());
|
||||
}
|
||||
|
||||
|
@ -27,6 +27,7 @@ class QToolBox;
|
||||
class VOutline;
|
||||
class VNotebookSelector;
|
||||
class VAvatar;
|
||||
class VFindReplaceDialog;
|
||||
|
||||
class VMainWindow : public QMainWindow
|
||||
{
|
||||
@ -55,6 +56,8 @@ private slots:
|
||||
void handleCurrentDirectoryChanged(const VDirectory *p_dir);
|
||||
void handleCurrentNotebookChanged(const VNotebook *p_notebook);
|
||||
void insertImage();
|
||||
void handleFindDialogTextChanged(const QString &p_text, uint p_options);
|
||||
void openFindDialog();
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
|
||||
@ -83,7 +86,8 @@ private:
|
||||
void initEditorBackgroundMenu(QMenu *menu);
|
||||
void changeSplitterView(int nrPanel);
|
||||
void updateWindowTitle(const QString &str);
|
||||
void updateToolbarFromTabChage(const VFile *p_file, bool p_editMode);
|
||||
void updateActionStateFromTabStatusChange(const VFile *p_file,
|
||||
bool p_editMode);
|
||||
void saveStateAndGeometry();
|
||||
void restoreStateAndGeometry();
|
||||
void repositionAvatar();
|
||||
@ -103,6 +107,7 @@ private:
|
||||
QToolBox *toolBox;
|
||||
VOutline *outline;
|
||||
VAvatar *m_avatar;
|
||||
VFindReplaceDialog *m_findReplaceDialog;
|
||||
|
||||
// Actions
|
||||
QAction *newRootDirAct;
|
||||
@ -115,6 +120,14 @@ private:
|
||||
QAction *discardExitAct;
|
||||
QAction *expandViewAct;
|
||||
|
||||
QAction *m_insertImageAct;
|
||||
QAction *m_findReplaceAct;
|
||||
QAction *m_findNextAct;
|
||||
QAction *m_findPreviousAct;
|
||||
QAction *m_replaceAct;
|
||||
QAction *m_replaceFindAct;
|
||||
QAction *m_replaceAllAct;
|
||||
|
||||
// Menus
|
||||
QMenu *viewMenu;
|
||||
|
||||
|
@ -287,6 +287,7 @@ bool VMdEditOperations::handleKeyBracketLeft(QKeyEvent *p_event)
|
||||
// 1. If it is not in Normal state, just go back to Normal state;
|
||||
// 2. If it is already Normal state, try to clear selection;
|
||||
// 3. Anyway, we accept this event.
|
||||
bool accept = false;
|
||||
if (p_event->modifiers() == Qt::ControlModifier) {
|
||||
if (m_keyState != KeyState::Normal) {
|
||||
m_pendingTimer->stop();
|
||||
@ -299,9 +300,12 @@ bool VMdEditOperations::handleKeyBracketLeft(QKeyEvent *p_event)
|
||||
m_editor->setTextCursor(cursor);
|
||||
}
|
||||
}
|
||||
accept = true;
|
||||
}
|
||||
p_event->accept();
|
||||
return true;
|
||||
if (accept) {
|
||||
p_event->accept();
|
||||
}
|
||||
return accept;
|
||||
}
|
||||
|
||||
bool VMdEditOperations::handleKeyTab(QKeyEvent *p_event)
|
||||
|
@ -82,5 +82,6 @@
|
||||
<file>resources/icons/corner_menu_cur.svg</file>
|
||||
<file>resources/icons/corner_tablist_cur.svg</file>
|
||||
<file>resources/icons/close.svg</file>
|
||||
<file>resources/icons/find_replace.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Loading…
x
Reference in New Issue
Block a user