From 5eb8c4d22464121385271410c8e6f54a61149e9a Mon Sep 17 00:00:00 2001 From: Xianzhong Wang Date: Sat, 19 May 2018 09:56:14 +0800 Subject: [PATCH] [function] Support to remove header sequence when disable it (#243) * [function] Support to remove header sequence when disable it spec: In edit mode: - when click icon to enable auto sequence, add sequence immediately - when click icon to disable auto sequence, remove already added sequence In preview/read mode: - auto sequence icon should be unchecked and disabled For readonly file, always disable the auto sequence icon. * [bugfix] Do not let auto sequence ruin the undo history All the header sequence auto-update should be treated as one edit action. So that user can undo auto-update by pressing undo twice. (One undo for the auto-update change, and one for the original header change) * Refactor and reformat according to PR feedback --- src/vmainwindow.cpp | 6 ++++-- src/vmdeditor.cpp | 47 ++++++++++++++++++++++++++++++++++----------- src/vmdeditor.h | 4 ++++ src/vmdtab.cpp | 3 +++ 4 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index d7f8b16e..12cea016 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -1903,9 +1903,11 @@ void VMainWindow::updateActionsStateFromTab(const VEditTab *p_tab) setActionsEnabled(m_editToolBar, file && editMode); // Handle heading sequence act independently. - m_headingSequenceAct->setEnabled(isHeadingSequenceApplicable()); + m_headingSequenceAct->setEnabled(editMode && file->isModifiable() + && isHeadingSequenceApplicable()); const VMdTab *mdTab = dynamic_cast(p_tab); - m_headingSequenceAct->setChecked(mdTab && mdTab->isHeadingSequenceEnabled()); + m_headingSequenceAct->setChecked(mdTab && editMode && file->isModifiable() + && mdTab->isHeadingSequenceEnabled()); // Find/Replace m_findReplaceAct->setEnabled(file); diff --git a/src/vmdeditor.cpp b/src/vmdeditor.cpp index e6125002..34a048f4 100644 --- a/src/vmdeditor.cpp +++ b/src/vmdeditor.cpp @@ -425,7 +425,8 @@ static QString headerSequenceStr(const QVector &p_sequence) return res; } -static void insertSequenceToHeader(QTextBlock p_block, +static void insertSequenceToHeader(QTextCursor& p_cursor, + QTextBlock p_block, QRegExp &p_reg, QRegExp &p_preReg, const QString &p_seq) @@ -446,20 +447,24 @@ static void insertSequenceToHeader(QTextBlock p_block, Q_ASSERT(start <= end); - QTextCursor cursor(p_block); - cursor.setPosition(p_block.position() + start); + p_cursor.setPosition(p_block.position() + start); if (start != end) { - cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor); + p_cursor.setPosition(p_block.position() + end, QTextCursor::KeepAnchor); } if (p_seq.isEmpty()) { - cursor.removeSelectedText(); + p_cursor.removeSelectedText(); } else { - cursor.insertText(p_seq + ' '); + p_cursor.insertText(p_seq + ' '); } } -void VMdEditor::updateHeaders(const QVector &p_headerRegions) +void VMdEditor::updateHeaderSequenceByConfigChange() +{ + updateHeadersHelper(m_mdHighlighter->getHeaderRegions(), true); +} + +void VMdEditor::updateHeadersHelper(const QVector &p_headerRegions, bool p_configChanged) { QTextDocument *doc = document(); @@ -520,6 +525,14 @@ void VMdEditor::updateHeaders(const QVector &p_headerRegions) QVector seqs(7, 0); QRegExp preReg(VUtils::c_headerPrefixRegExp); int curLevel = baseLevel - 1; + QTextCursor cursor = textCursorW(); + + int blockNo = cursor.block().blockNumber(); + int posToBlockEnd = cursor.block().length() - cursor.positionInBlock(); + + if(autoSequence || p_configChanged) { + cursor.beginEditBlock(); + } for (int i = 0; i < headers.size(); ++i) { VTableOfContentItem &item = headers[i]; while (item.m_level > curLevel + 1) { @@ -530,7 +543,7 @@ void VMdEditor::updateHeaders(const QVector &p_headerRegions) curLevel, -1, m_headers.size())); - if (autoSequence) { + if (autoSequence || p_configChanged) { addHeaderSequence(seqs, curLevel, headingSequenceBaseLevel); } } @@ -538,25 +551,37 @@ void VMdEditor::updateHeaders(const QVector &p_headerRegions) item.m_index = m_headers.size(); m_headers.append(item); curLevel = item.m_level; - if (autoSequence) { + if (autoSequence || p_configChanged) { addHeaderSequence(seqs, item.m_level, headingSequenceBaseLevel); - QString seqStr = headerSequenceStr(seqs); + QString seqStr = autoSequence ? headerSequenceStr(seqs) : ""; if (headerSequences[i] != seqStr) { // Insert correct sequence. - insertSequenceToHeader(doc->findBlockByNumber(headerBlockNumbers[i]), + insertSequenceToHeader(cursor, + doc->findBlockByNumber(headerBlockNumbers[i]), headerReg, preReg, seqStr); } } } + if (autoSequence || p_configChanged) { + QTextBlock block = doc->findBlockByNumber(blockNo); + cursor.setPosition(block.position() + block.length() - posToBlockEnd); + cursor.endEditBlock(); + setTextCursorW(cursor); + } emit headersChanged(m_headers); updateCurrentHeader(); } +void VMdEditor::updateHeaders(const QVector &p_headerRegions) +{ + updateHeadersHelper(p_headerRegions, false); +} + void VMdEditor::updateCurrentHeader() { emit currentHeaderChanged(textCursor().block().blockNumber()); diff --git a/src/vmdeditor.h b/src/vmdeditor.h index 505f0712..5d7003bf 100644 --- a/src/vmdeditor.h +++ b/src/vmdeditor.h @@ -76,6 +76,8 @@ public: VPreviewManager *getPreviewManager() const; + void updateHeaderSequenceByConfigChange(); + public slots: bool jumpTitle(bool p_forward, int p_relativeLevel, int p_repeat) Q_DECL_OVERRIDE; @@ -228,6 +230,8 @@ private slots: void handleCopyAsAction(QAction *p_act); private: + void updateHeadersHelper(const QVector &p_headerRegions, bool p_configChanged); + // Update the config of VTextEdit according to global configurations. void updateTextEditConfig(); diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index 47ff070d..ceb84e79 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -911,6 +911,9 @@ void VMdTab::enableHeadingSequence(bool p_enabled) if (m_editor) { VEditConfig &config = m_editor->getConfig(); config.m_enableHeadingSequence = m_enableHeadingSequence; + if (isEditMode()) { + m_editor->updateHeaderSequenceByConfigChange(); + } } }