[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
This commit is contained in:
Xianzhong Wang 2018-05-19 09:56:14 +08:00 committed by Le Tan
parent d8cc69955d
commit 5eb8c4d224
4 changed files with 47 additions and 13 deletions

View File

@ -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<const VMdTab *>(p_tab);
m_headingSequenceAct->setChecked(mdTab && mdTab->isHeadingSequenceEnabled());
m_headingSequenceAct->setChecked(mdTab && editMode && file->isModifiable()
&& mdTab->isHeadingSequenceEnabled());
// Find/Replace
m_findReplaceAct->setEnabled(file);

View File

@ -425,7 +425,8 @@ static QString headerSequenceStr(const QVector<int> &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<VElementRegion> &p_headerRegions)
void VMdEditor::updateHeaderSequenceByConfigChange()
{
updateHeadersHelper(m_mdHighlighter->getHeaderRegions(), true);
}
void VMdEditor::updateHeadersHelper(const QVector<VElementRegion> &p_headerRegions, bool p_configChanged)
{
QTextDocument *doc = document();
@ -520,6 +525,14 @@ void VMdEditor::updateHeaders(const QVector<VElementRegion> &p_headerRegions)
QVector<int> 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<VElementRegion> &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<VElementRegion> &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<VElementRegion> &p_headerRegions)
{
updateHeadersHelper(p_headerRegions, false);
}
void VMdEditor::updateCurrentHeader()
{
emit currentHeaderChanged(textCursor().block().blockNumber());

View File

@ -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<VElementRegion> &p_headerRegions, bool p_configChanged);
// Update the config of VTextEdit according to global configurations.
void updateTextEditConfig();

View File

@ -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();
}
}
}