diff --git a/src/utils/vvim.cpp b/src/utils/vvim.cpp index 5a2ccd5b..c0f6c67e 100644 --- a/src/utils/vvim.cpp +++ b/src/utils/vvim.cpp @@ -12,6 +12,7 @@ #include "veditor.h" #include "utils/veditutils.h" #include "vconstants.h" +#include "vmdeditor.h" extern VConfigManager *g_config; @@ -2269,9 +2270,14 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection, int p_position) m_mode = p_mode; resetState(); + VMdEditor *mdEditor = dynamic_cast(m_editor); switch (m_mode) { case VimMode::Insert: m_editor->setCursorBlockModeW(CursorBlock::None); + if (mdEditor) { + mdEditor->setHighlightCursorLineBlockEnabled(false); + } + break; case VimMode::Visual: @@ -2280,6 +2286,18 @@ void VVim::setMode(VimMode p_mode, bool p_clearSelection, int p_position) default: m_editor->setCursorBlockModeW(CursorBlock::RightSide); + if (mdEditor) { + QString color; + if (m_mode == VimMode::Normal) { + color = g_config->getEditorVimNormalBg(); + } else { + color = g_config->getEditorVimVisualBg(); + } + + mdEditor->setCursorLineBlockBg(color); + mdEditor->setHighlightCursorLineBlockEnabled(true); + } + break; } diff --git a/src/vedittab.cpp b/src/vedittab.cpp index 6822112a..9636ef50 100644 --- a/src/vedittab.cpp +++ b/src/vedittab.cpp @@ -81,9 +81,10 @@ void VEditTab::wheelEvent(QWheelEvent *p_event) p_event->ignore(); } -VEditTabInfo VEditTab::fetchTabInfo() const +VEditTabInfo VEditTab::fetchTabInfo(VEditTabInfo::InfoType p_type) const { VEditTabInfo info; + info.m_type = p_type; info.m_editTab = const_cast(this); return info; diff --git a/src/vedittab.h b/src/vedittab.h index e0bd1253..64d23e9f 100644 --- a/src/vedittab.h +++ b/src/vedittab.h @@ -80,7 +80,7 @@ public: } // Create a filled VEditTabInfo. - virtual VEditTabInfo fetchTabInfo() const; + virtual VEditTabInfo fetchTabInfo(VEditTabInfo::InfoType p_type = VEditTabInfo::InfoType::All) const; const VTableOfContent &getOutline() const; diff --git a/src/vedittabinfo.h b/src/vedittabinfo.h index f80fd623..3f4245c8 100644 --- a/src/vedittabinfo.h +++ b/src/vedittabinfo.h @@ -5,8 +5,18 @@ class VEditTab; struct VEditTabInfo { + enum InfoType + { + // Update all information. + All = 0, + + // Update only cursor information. + Cursor + }; + VEditTabInfo() - : m_editTab(NULL), + : m_type(InfoType::All), + m_editTab(NULL), m_cursorBlockNumber(-1), m_cursorPositionInBlock(-1), m_blockCount(-1), @@ -16,6 +26,7 @@ struct VEditTabInfo void clear() { + m_type = InfoType::All; m_editTab = NULL; m_cursorBlockNumber = -1; m_cursorPositionInBlock = -1; @@ -23,6 +34,8 @@ struct VEditTabInfo m_headerIndex = -1; } + InfoType m_type; + VEditTab *m_editTab; // Cursor information. -1 for invalid info. diff --git a/src/veditwindow.cpp b/src/veditwindow.cpp index 9c4feddc..835326ee 100644 --- a/src/veditwindow.cpp +++ b/src/veditwindow.cpp @@ -766,8 +766,10 @@ void VEditWindow::handleTabStatusUpdated(const VEditTabInfo &p_info) { int idx = indexOf(dynamic_cast(sender())); - updateTabInfo(idx); - updateAllTabsSequence(); + if (p_info.m_type == VEditTabInfo::InfoType::All) { + updateTabInfo(idx); + updateAllTabsSequence(); + } if (idx == currentIndex()) { // Current tab. Propogate its status. diff --git a/src/vmainwindow.cpp b/src/vmainwindow.cpp index 9dd473e1..8762f5f6 100644 --- a/src/vmainwindow.cpp +++ b/src/vmainwindow.cpp @@ -1880,32 +1880,35 @@ void VMainWindow::handleAreaTabStatusUpdated(const VEditTabInfo &p_info) m_curFile = NULL; } - updateActionsStateFromTab(m_curTab); + if (p_info.m_type == VEditTabInfo::InfoType::All) { + updateActionsStateFromTab(m_curTab); - m_attachmentList->setFile(dynamic_cast(m_curFile.data())); + m_attachmentList->setFile(dynamic_cast(m_curFile.data())); - QString title; - if (m_curFile) { - m_findReplaceDialog->updateState(m_curFile->getDocType(), - m_curTab->isEditMode()); + QString title; + if (m_curFile) { + m_findReplaceDialog->updateState(m_curFile->getDocType(), + m_curTab->isEditMode()); - if (m_curFile->getType() == FileType::Note) { - const VNoteFile *tmpFile = dynamic_cast((VFile *)m_curFile); - title = QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath()); - } else { - title = QString("%1").arg(m_curFile->fetchPath()); + if (m_curFile->getType() == FileType::Note) { + const VNoteFile *tmpFile = dynamic_cast((VFile *)m_curFile); + title = QString("[%1] %2").arg(tmpFile->getNotebookName()).arg(tmpFile->fetchPath()); + } else { + title = QString("%1").arg(m_curFile->fetchPath()); + } + + if (!m_curFile->isModifiable()) { + title.append('#'); + } + + if (m_curTab->isModified()) { + title.append('*'); + } } - if (!m_curFile->isModifiable()) { - title.append('#'); - } - - if (m_curTab->isModified()) { - title.append('*'); - } + updateWindowTitle(title); } - updateWindowTitle(title); updateStatusInfo(p_info); } @@ -2418,7 +2421,9 @@ void VMainWindow::updateStatusInfo(const VEditTabInfo &p_info) m_tabIndicator->show(); if (m_curTab->isEditMode()) { - m_curTab->requestUpdateVimStatus(); + if (p_info.m_type == VEditTabInfo::InfoType::All) { + m_curTab->requestUpdateVimStatus(); + } } else { m_vimIndicator->hide(); } diff --git a/src/vmdtab.cpp b/src/vmdtab.cpp index 5ab261ee..3d913af9 100644 --- a/src/vmdtab.cpp +++ b/src/vmdtab.cpp @@ -423,7 +423,7 @@ void VMdTab::setupMarkdownEditor() connect(m_editor, &VMdEditor::textChanged, this, &VMdTab::updateStatus); connect(m_editor, &VMdEditor::cursorPositionChanged, - this, &VMdTab::updateStatus); + this, &VMdTab::updateCursorStatus); connect(g_mainWin, &VMainWindow::editorConfigUpdated, m_editor, &VMdEditor::updateConfig); connect(m_editor->object(), &VEditorObject::saveAndRead, @@ -702,9 +702,9 @@ void VMdTab::requestUpdateVimStatus() } } -VEditTabInfo VMdTab::fetchTabInfo() const +VEditTabInfo VMdTab::fetchTabInfo(VEditTabInfo::InfoType p_type) const { - VEditTabInfo info = VEditTab::fetchTabInfo(); + VEditTabInfo info = VEditTab::fetchTabInfo(p_type); if (m_editor) { QTextCursor cursor = m_editor->textCursor(); @@ -972,3 +972,8 @@ bool VMdTab::checkPreviousBackupFile() return true; } + +void VMdTab::updateCursorStatus() +{ + emit statusUpdated(fetchTabInfo(VEditTabInfo::InfoType::Cursor)); +} diff --git a/src/vmdtab.h b/src/vmdtab.h index 7b547fa7..266cd8fe 100644 --- a/src/vmdtab.h +++ b/src/vmdtab.h @@ -69,7 +69,7 @@ public: void decorateText(TextDecoration p_decoration, int p_level = -1) Q_DECL_OVERRIDE; // Create a filled VEditTabInfo. - VEditTabInfo fetchTabInfo() const Q_DECL_OVERRIDE; + VEditTabInfo fetchTabInfo(VEditTabInfo::InfoType p_type = VEditTabInfo::InfoType::All) const Q_DECL_OVERRIDE; // Enable or disable heading sequence. void enableHeadingSequence(bool p_enabled); @@ -179,6 +179,9 @@ private: // Return true if we could continue. bool checkPreviousBackupFile(); + // updateStatus() with only cursor position information. + void updateCursorStatus(); + VMdEditor *m_editor; VWebView *m_webViewer; VDocument *m_document; diff --git a/src/vtextdocumentlayout.cpp b/src/vtextdocumentlayout.cpp index 12d98617..7b47491e 100644 --- a/src/vtextdocumentlayout.cpp +++ b/src/vtextdocumentlayout.cpp @@ -34,7 +34,10 @@ VTextDocumentLayout::VTextDocumentLayout(QTextDocument *p_doc, m_imageLineColor("#9575CD"), m_cursorBlockMode(CursorBlock::None), m_virtualCursorBlockWidth(8), - m_lastCursorBlockWidth(-1) + m_lastCursorBlockWidth(-1), + m_highlightCursorLineBlock(false), + m_cursorLineBlockBg("#C0C0C0"), + m_cursorLineBlockNumber(-1) { } @@ -219,7 +222,11 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex QTextBlockFormat blockFormat = block.blockFormat(); QBrush bg = blockFormat.background(); if (bg != Qt::NoBrush) { - fillBackground(p_painter, rect, bg); + int x = offset.x(); + int y = offset.y(); + fillBackground(p_painter, + rect.adjusted(x, y, x, y), + bg); } auto selections = formatRangeFromSelection(block, p_context.selections); @@ -252,6 +259,16 @@ void VTextDocumentLayout::draw(QPainter *p_painter, const PaintContext &p_contex } } + // Draw cursor line block. + if (m_highlightCursorLineBlock + && m_cursorLineBlockNumber == block.blockNumber()) { + int x = offset.x(); + int y = offset.y(); + fillBackground(p_painter, + rect.adjusted(x, y, x, y), + m_cursorLineBlockBg); + } + layout->draw(p_painter, offset, selections, @@ -1090,3 +1107,15 @@ int VTextDocumentLayout::getTextWidthWithinTextLine(const QTextLayout *p_layout, Q_ASSERT(p_pos + p_length <= line.textStart() + line.textLength()); return line.cursorToX(p_pos + p_length) - line.cursorToX(p_pos); } + +void VTextDocumentLayout::updateBlockByNumber(int p_blockNumber) +{ + if (p_blockNumber == -1) { + return; + } + + QTextBlock block = document()->findBlockByNumber(p_blockNumber); + if (block.isValid()) { + emit updateBlock(block); + } +} diff --git a/src/vtextdocumentlayout.h b/src/vtextdocumentlayout.h index 898443a8..f0de9df7 100644 --- a/src/vtextdocumentlayout.h +++ b/src/vtextdocumentlayout.h @@ -61,6 +61,15 @@ public: void clearLastCursorBlockWidth(); + void setHighlightCursorLineBlockEnabled(bool p_enabled); + + void setCursorLineBlockBg(const QColor &p_bg); + + void setCursorLineBlockNumber(int p_blockNumber); + + // Request update block by block number. + void updateBlockByNumber(int p_blockNumber); + signals: // Emit to update current cursor block width if m_cursorBlockMode is enabled. void cursorBlockWidthUpdated(int p_width); @@ -287,6 +296,15 @@ private: int m_virtualCursorBlockWidth; int m_lastCursorBlockWidth; + + // Whether highlight the block containing the cursor line. + bool m_highlightCursorLineBlock; + + // The cursor line's block background color. + QColor m_cursorLineBlockBg; + + // The block containing the cursor. + int m_cursorLineBlockNumber; }; inline qreal VTextDocumentLayout::getLineLeading() const @@ -320,4 +338,37 @@ inline void VTextDocumentLayout::clearLastCursorBlockWidth() { m_lastCursorBlockWidth = -1; } + +inline void VTextDocumentLayout::setHighlightCursorLineBlockEnabled(bool p_enabled) +{ + if (m_highlightCursorLineBlock != p_enabled) { + m_highlightCursorLineBlock = p_enabled; + if (!m_highlightCursorLineBlock) { + int pre = m_cursorLineBlockNumber; + m_cursorLineBlockNumber = -1; + updateBlockByNumber(pre); + } + } +} + +inline void VTextDocumentLayout::setCursorLineBlockBg(const QColor &p_bg) +{ + if (p_bg != m_cursorLineBlockBg) { + m_cursorLineBlockBg = p_bg; + updateBlockByNumber(m_cursorLineBlockNumber); + } +} + +inline void VTextDocumentLayout::setCursorLineBlockNumber(int p_blockNumber) +{ + if (p_blockNumber != m_cursorLineBlockNumber) { + int pre = m_cursorLineBlockNumber; + m_cursorLineBlockNumber = p_blockNumber; + + if (m_highlightCursorLineBlock) { + updateBlockByNumber(pre); + updateBlockByNumber(m_cursorLineBlockNumber); + } + } +} #endif // VTEXTDOCUMENTLAYOUT_H diff --git a/src/vtextedit.cpp b/src/vtextedit.cpp index 23a311b8..7c8e73a2 100644 --- a/src/vtextedit.cpp +++ b/src/vtextedit.cpp @@ -51,6 +51,8 @@ void VTextEdit::init() m_cursorBlockMode = CursorBlock::None; + m_highlightCursorLineBlock = false; + m_imageMgr = new VImageResourceManager2(); QTextDocument *doc = document(); @@ -80,7 +82,14 @@ void VTextEdit::init() connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &VTextEdit::updateLineNumberArea); connect(this, &QTextEdit::cursorPositionChanged, - this, &VTextEdit::updateLineNumberArea); + this, [this]() { + if (m_highlightCursorLineBlock) { + QTextCursor cursor = textCursor(); + getLayout()->setCursorLineBlockNumber(cursor.block().blockNumber()); + } + + updateLineNumberArea(); + }); } VTextDocumentLayout *VTextEdit::getLayout() const @@ -356,3 +365,21 @@ void VTextEdit::setCursorBlockMode(CursorBlock p_mode) : 1); } } + +void VTextEdit::setHighlightCursorLineBlockEnabled(bool p_enabled) +{ + if (m_highlightCursorLineBlock != p_enabled) { + auto layout = getLayout(); + m_highlightCursorLineBlock = p_enabled; + layout->setHighlightCursorLineBlockEnabled(p_enabled); + if (m_highlightCursorLineBlock) { + QTextCursor cursor = textCursor(); + layout->setCursorLineBlockNumber(cursor.block().blockNumber()); + } + } +} + +void VTextEdit::setCursorLineBlockBg(const QColor &p_bg) +{ + getLayout()->setCursorLineBlockBg(p_bg); +} diff --git a/src/vtextedit.h b/src/vtextedit.h index 19e3818c..03df606b 100644 --- a/src/vtextedit.h +++ b/src/vtextedit.h @@ -59,6 +59,10 @@ public: void setCursorBlockMode(CursorBlock p_mode); + void setHighlightCursorLineBlockEnabled(bool p_enabled); + + void setCursorLineBlockBg(const QColor &p_bg); + protected: void resizeEvent(QResizeEvent *p_event) Q_DECL_OVERRIDE; @@ -83,6 +87,8 @@ private: bool m_blockImageEnabled; CursorBlock m_cursorBlockMode; + + bool m_highlightCursorLineBlock; }; inline void VTextEdit::setLineNumberType(LineNumberType p_type)