refine edit mode

1. Support "Ctrl+Alt+<N>" to insert title in Markdown;
2. Support Auto Indent;
3. Support Auto List;
This commit is contained in:
Le Tan 2017-04-01 19:58:12 +08:00
parent acec514418
commit b0d3e42647
7 changed files with 234 additions and 17 deletions

View File

@ -7,6 +7,8 @@ is_expand_tab=true
highlight_cursor_line=true highlight_cursor_line=true
highlight_selected_word=true highlight_selected_word=true
highlight_searched_word=true highlight_searched_word=true
auto_indent=true
auto_list=true
current_background_color=System current_background_color=System
current_render_background_color=System current_render_background_color=System
language=System language=System

View File

@ -57,6 +57,8 @@ void VConfigManager::initialize()
m_highlightCursorLine = getConfigFromSettings("global", "highlight_cursor_line").toBool(); m_highlightCursorLine = getConfigFromSettings("global", "highlight_cursor_line").toBool();
m_highlightSelectedWord = getConfigFromSettings("global", "highlight_selected_word").toBool(); m_highlightSelectedWord = getConfigFromSettings("global", "highlight_selected_word").toBool();
m_highlightSearchedWord = getConfigFromSettings("global", "highlight_searched_word").toBool(); m_highlightSearchedWord = getConfigFromSettings("global", "highlight_searched_word").toBool();
m_autoIndent = getConfigFromSettings("global", "auto_indent").toBool();
m_autoList = getConfigFromSettings("global", "auto_list").toBool();
readPredefinedColorsFromSettings(); readPredefinedColorsFromSettings();
curBackgroundColor = getConfigFromSettings("global", "current_background_color").toString(); curBackgroundColor = getConfigFromSettings("global", "current_background_color").toString();

View File

@ -81,6 +81,12 @@ public:
inline bool getHighlightSearchedWord() const; inline bool getHighlightSearchedWord() const;
inline void setHighlightSearchedWord(bool p_searchedWord); inline void setHighlightSearchedWord(bool p_searchedWord);
inline bool getAutoIndent() const;
inline void setAutoIndent(bool p_autoIndent);
inline bool getAutoList() const;
inline void setAutoList(bool p_autoList);
inline const QVector<VColor> &getPredefinedColors() const; inline const QVector<VColor> &getPredefinedColors() const;
inline const QString &getCurBackgroundColor() const; inline const QString &getCurBackgroundColor() const;
@ -167,6 +173,12 @@ private:
// Highlight searched word. // Highlight searched word.
bool m_highlightSearchedWord; bool m_highlightSearchedWord;
// Auto Indent.
bool m_autoIndent;
// Auto List.
bool m_autoList;
// App defined color // App defined color
QVector<VColor> predefinedColors; QVector<VColor> predefinedColors;
QString curBackgroundColor; QString curBackgroundColor;
@ -362,6 +374,36 @@ inline void VConfigManager::setHighlightSearchedWord(bool p_searchedWord)
m_highlightSearchedWord); m_highlightSearchedWord);
} }
inline bool VConfigManager::getAutoIndent() const
{
return m_autoIndent;
}
inline void VConfigManager::setAutoIndent(bool p_autoIndent)
{
if (m_autoIndent == p_autoIndent) {
return;
}
m_autoIndent = p_autoIndent;
setConfigToSettings("global", "auto_indent",
m_autoIndent);
}
inline bool VConfigManager::getAutoList() const
{
return m_autoList;
}
inline void VConfigManager::setAutoList(bool p_autoList)
{
if (m_autoList == p_autoList) {
return;
}
m_autoList = p_autoList;
setConfigToSettings("global", "auto_list",
m_autoList);
}
inline const QVector<VColor>& VConfigManager::getPredefinedColors() const inline const QVector<VColor>& VConfigManager::getPredefinedColors() const
{ {
return predefinedColors; return predefinedColors;

View File

@ -467,6 +467,20 @@ void VMainWindow::initEditMenu()
connect(tabStopWidthAct, &QActionGroup::triggered, connect(tabStopWidthAct, &QActionGroup::triggered,
this, &VMainWindow::setTabStopWidth); this, &VMainWindow::setTabStopWidth);
// Auto Indent.
m_autoIndentAct = new QAction(tr("Auto Indent"), this);
m_autoIndentAct->setStatusTip(tr("Indent automatically when inserting a new line"));
m_autoIndentAct->setCheckable(true);
connect(m_autoIndentAct, &QAction::triggered,
this, &VMainWindow::changeAutoIndent);
// Auto List.
QAction *autoListAct = new QAction(tr("Auto List"), this);
autoListAct->setStatusTip(tr("Continue the list automatically when inserting a new line"));
autoListAct->setCheckable(true);
connect(autoListAct, &QAction::triggered,
this, &VMainWindow::changeAutoList);
// Highlight current cursor line. // Highlight current cursor line.
QAction *cursorLineAct = new QAction(tr("Highlight Cursor Line"), this); QAction *cursorLineAct = new QAction(tr("Highlight Cursor Line"), this);
cursorLineAct->setStatusTip(tr("Highlight current cursor line")); cursorLineAct->setStatusTip(tr("Highlight current cursor line"));
@ -494,11 +508,7 @@ void VMainWindow::initEditMenu()
findReplaceMenu->addAction(m_replaceAllAct); findReplaceMenu->addAction(m_replaceAllAct);
findReplaceMenu->addSeparator(); findReplaceMenu->addSeparator();
findReplaceMenu->addAction(searchedWordAct); findReplaceMenu->addAction(searchedWordAct);
if (vconfig.getHighlightSearchedWord()) { searchedWordAct->setChecked(vconfig.getHighlightSearchedWord());
searchedWordAct->setChecked(true);
} else {
searchedWordAct->setChecked(false);
}
editMenu->addSeparator(); editMenu->addSeparator();
m_findReplaceAct->setEnabled(false); m_findReplaceAct->setEnabled(false);
@ -532,21 +542,26 @@ void VMainWindow::initEditMenu()
default: default:
qWarning() << "unsupported tab stop width" << tabStopWidth << "in config"; qWarning() << "unsupported tab stop width" << tabStopWidth << "in config";
} }
initEditorBackgroundMenu(editMenu);
editMenu->addSeparator(); editMenu->addAction(m_autoIndentAct);
editMenu->addAction(cursorLineAct); m_autoIndentAct->setChecked(vconfig.getAutoIndent());
if (vconfig.getHighlightCursorLine()) {
cursorLineAct->setChecked(true); editMenu->addAction(autoListAct);
} else { if (vconfig.getAutoList()) {
cursorLineAct->setChecked(false); // Let the trigger handler to trigger m_autoIndentAct, too.
autoListAct->trigger();
} }
Q_ASSERT(!(autoListAct->isChecked() && !m_autoIndentAct->isChecked()));
editMenu->addSeparator();
initEditorBackgroundMenu(editMenu);
editMenu->addAction(cursorLineAct);
cursorLineAct->setChecked(vconfig.getHighlightCursorLine());
editMenu->addAction(selectedWordAct); editMenu->addAction(selectedWordAct);
if (vconfig.getHighlightSelectedWord()) { selectedWordAct->setChecked(vconfig.getHighlightSelectedWord());
selectedWordAct->setChecked(true);
} else {
selectedWordAct->setChecked(false);
}
} }
void VMainWindow::initDockWindows() void VMainWindow::initDockWindows()
@ -1075,3 +1090,21 @@ void VMainWindow::closeCurrentFile()
} }
} }
void VMainWindow::changeAutoIndent(bool p_checked)
{
vconfig.setAutoIndent(p_checked);
}
void VMainWindow::changeAutoList(bool p_checked)
{
vconfig.setAutoList(p_checked);
if (p_checked) {
if (!m_autoIndentAct->isChecked()) {
m_autoIndentAct->trigger();
}
m_autoIndentAct->setEnabled(false);
} else {
m_autoIndentAct->setEnabled(true);
}
}

View File

@ -68,6 +68,8 @@ private slots:
void enableMermaid(bool p_checked); void enableMermaid(bool p_checked);
void enableMathjax(bool p_checked); void enableMathjax(bool p_checked);
void handleCaptainModeChanged(bool p_enabled); void handleCaptainModeChanged(bool p_enabled);
void changeAutoIndent(bool p_checked);
void changeAutoList(bool p_checked);
protected: protected:
void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE;
@ -148,6 +150,8 @@ private:
QAction *m_replaceFindAct; QAction *m_replaceFindAct;
QAction *m_replaceAllAct; QAction *m_replaceAllAct;
QAction *m_autoIndentAct;
// Menus // Menus
QMenu *viewMenu; QMenu *viewMenu;

View File

@ -20,6 +20,9 @@
#include "vdownloader.h" #include "vdownloader.h"
#include "vfile.h" #include "vfile.h"
#include "vmdedit.h" #include "vmdedit.h"
#include "vconfigmanager.h"
extern VConfigManager vconfig;
const QString VMdEditOperations::c_defaultImageTitle = "image"; const QString VMdEditOperations::c_defaultImageTitle = "image";
@ -178,7 +181,25 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event)
return true; return true;
} }
} else { } else {
int modifiers = p_event->modifiers();
switch (p_event->key()) { switch (p_event->key()) {
case Qt::Key_1:
case Qt::Key_2:
case Qt::Key_3:
case Qt::Key_4:
case Qt::Key_5:
case Qt::Key_6:
{
if (modifiers == (Qt::ControlModifier | Qt::AltModifier)) {
// Ctrl + Alt + <N>: insert title at level <N>.
if (insertTitle(p_event->key() - Qt::Key_0)) {
p_event->accept();
return true;
}
}
break;
}
case Qt::Key_Tab: case Qt::Key_Tab:
{ {
if (handleKeyTab(p_event)) { if (handleKeyTab(p_event)) {
@ -267,6 +288,14 @@ bool VMdEditOperations::handleKeyPressEvent(QKeyEvent *p_event)
break; break;
} }
case Qt::Key_Return:
{
if (handleKeyReturn(p_event)) {
return true;
}
break;
}
default: default:
break; break;
} }
@ -612,6 +641,73 @@ bool VMdEditOperations::handleKeyEsc(QKeyEvent *p_event)
return accept; return accept;
} }
bool VMdEditOperations::handleKeyReturn(QKeyEvent *p_event)
{
if (p_event->modifiers() & Qt::ControlModifier) {
return false;
}
bool ret = false;
if (vconfig.getAutoIndent()) {
ret = true;
// Indent the new line as previous line.
insertNewBlockWithIndent();
// Continue the list from previous line.
if (vconfig.getAutoList()) {
insertListMarkAsPreviousLine();
}
}
return ret;
}
void VMdEditOperations::insertNewBlockWithIndent()
{
QTextCursor cursor = m_editor->textCursor();
cursor.beginEditBlock();
cursor.removeSelectedText();
QTextBlock block = cursor.block();
QString text = block.text();
QRegExp regExp("(^\\s*)");
regExp.indexIn(text);
Q_ASSERT(regExp.captureCount() == 1);
QString leadingSpaces = regExp.capturedTexts()[1];
cursor.insertBlock();
cursor.insertText(leadingSpaces);
cursor.endEditBlock();
m_editor->setTextCursor(cursor);
}
void VMdEditOperations::insertListMarkAsPreviousLine()
{
QTextCursor cursor = m_editor->textCursor();
QTextBlock block = cursor.block();
QTextBlock preBlock = block.previous();
QString text = preBlock.text();
QRegExp regExp("^\\s*(-|\\d+\\.)\\s");
int regIdx = regExp.indexIn(text);
if (regIdx != -1) {
Q_ASSERT(regExp.captureCount() == 1);
cursor.beginEditBlock();
QString markText = regExp.capturedTexts()[1];
if (markText == "-") {
// Insert - in front.
cursor.insertText("- ");
} else {
// markText is like "123.".
Q_ASSERT(markText.endsWith('.'));
bool ok = false;
int num = markText.left(markText.size() - 1).toInt(&ok, 10);
Q_ASSERT(ok);
num++;
cursor.insertText(QString::number(num, 10) + ". ");
}
cursor.endEditBlock();
m_editor->setTextCursor(cursor);
}
}
bool VMdEditOperations::handleKeyPressVim(QKeyEvent *p_event) bool VMdEditOperations::handleKeyPressVim(QKeyEvent *p_event)
{ {
int modifiers = p_event->modifiers(); int modifiers = p_event->modifiers();
@ -1004,3 +1100,37 @@ void VMdEditOperations::setKeyState(KeyState p_state)
m_keyState = p_state; m_keyState = p_state;
emit keyStateChanged(m_keyState); emit keyStateChanged(m_keyState);
} }
bool VMdEditOperations::insertTitle(int p_level)
{
Q_ASSERT(p_level > 0 && p_level < 7);
QTextDocument *doc = m_editor->document();
QString titleMark(p_level, '#');
QTextCursor cursor = m_editor->textCursor();
if (cursor.hasSelection()) {
// Insert title # in front of the selected lines.
int start = cursor.selectionStart();
int end = cursor.selectionEnd();
int startBlock = doc->findBlock(start).blockNumber();
int endBlock = doc->findBlock(end).blockNumber();
cursor.beginEditBlock();
cursor.clearSelection();
for (int i = startBlock; i <= endBlock; ++i) {
QTextBlock block = doc->findBlockByNumber(i);
cursor.setPosition(block.position(), QTextCursor::MoveAnchor);
cursor.insertText(titleMark + " ");
}
cursor.movePosition(QTextCursor::EndOfBlock);
cursor.endEditBlock();
} else {
// Insert title # in front of current block.
cursor.beginEditBlock();
cursor.movePosition(QTextCursor::StartOfBlock);
cursor.insertText(titleMark + " ");
cursor.movePosition(QTextCursor::EndOfBlock);
cursor.endEditBlock();
}
m_editor->setTextCursor(cursor);
return true;
}

View File

@ -39,11 +39,15 @@ private:
bool handleKeyU(QKeyEvent *p_event); bool handleKeyU(QKeyEvent *p_event);
bool handleKeyW(QKeyEvent *p_event); bool handleKeyW(QKeyEvent *p_event);
bool handleKeyEsc(QKeyEvent *p_event); bool handleKeyEsc(QKeyEvent *p_event);
bool handleKeyReturn(QKeyEvent *p_event);
bool handleKeyPressVim(QKeyEvent *p_event); bool handleKeyPressVim(QKeyEvent *p_event);
bool handleKeyBracketLeft(QKeyEvent *p_event); bool handleKeyBracketLeft(QKeyEvent *p_event);
bool shouldTriggerVimMode(QKeyEvent *p_event); bool shouldTriggerVimMode(QKeyEvent *p_event);
int keySeqToNumber(const QList<QString> &p_seq); int keySeqToNumber(const QList<QString> &p_seq);
bool suffixNumAllowed(const QList<QString> &p_seq); bool suffixNumAllowed(const QList<QString> &p_seq);
bool insertTitle(int p_level);
void insertNewBlockWithIndent();
void insertListMarkAsPreviousLine();
QTimer *m_pendingTimer; QTimer *m_pendingTimer;