@@ -109,10 +109,16 @@ TextEdit::TextEdit(QWidget *parent)
109109 // Init widgets.
110110 // 左边栏控件 滑动条滚动跟新行号 折叠标记
111111 connect (this ->verticalScrollBar (), &QScrollBar::valueChanged, this , &TextEdit::slotValueChanged);
112- connect (this , &QPlainTextEdit::textChanged, this , &TextEdit::updateLeftAreaWidget);
113112 connect (this , &QPlainTextEdit::textChanged, this , [this ]() {
114- if (this ->m_wrapper )
115- this ->m_wrapper ->UpdateBottomBarWordCnt (this ->characterCount ());
113+ if (m_wrapper) {
114+ m_wrapper->UpdateBottomBarWordCnt (characterCount ());
115+ }
116+ // 仅行数变化时全量刷新左侧栏;同行编辑由 cursorPositionChanged 局部 update 负责
117+ const int blockCountNow = blockCount ();
118+ if (blockCountNow != m_lastLeftAreaBlockCount) {
119+ m_lastLeftAreaBlockCount = blockCountNow;
120+ updateLeftAreaWidget ();
121+ }
116122 });
117123
118124 connect (this , &QPlainTextEdit::cursorPositionChanged, this , &TextEdit::cursorPositionChanged);
@@ -164,6 +170,11 @@ TextEdit::TextEdit(QWidget *parent)
164170 m_scrollAnimation->setEasingCurve (QEasingCurve::InOutExpo);
165171 m_scrollAnimation->setDuration (300 );
166172
173+ m_typingBurstFlushTimer = new QTimer (this );
174+ m_typingBurstFlushTimer->setSingleShot (true );
175+ m_typingBurstFlushTimer->setInterval (120 );
176+ connect (m_typingBurstFlushTimer, &QTimer::timeout, this , &TextEdit::flushDeferredCursorUpdate);
177+
167178 m_cursorMode = Insert;
168179
169180 connect (m_scrollAnimation, &QPropertyAnimation::finished, this , &TextEdit::handleScrollFinish, Qt::QueuedConnection);
@@ -298,6 +309,7 @@ void TextEdit::deleteSelectTextEx(QTextCursor cursor, QString text, bool currLin
298309void TextEdit::deleteTextEx (QTextCursor cursor)
299310{
300311 qDebug () << " Deleting text at position:" << cursor.position ();
312+ flushDeferredCursorUpdate ();
301313 QUndoCommand *pDeleteStack = new DeleteTextUndoCommand (cursor, this );
302314 m_pUndoStack->push (pDeleteStack);
303315 qDebug () << " Text deleted successfully" ;
@@ -328,15 +340,32 @@ void TextEdit::deleteMultiTextEx(const QList<QTextCursor> &multiText)
328340void TextEdit::insertSelectTextEx (QTextCursor cursor, QString text)
329341{
330342 qDebug () << " Inserting selected text at position:" << cursor.position () << " Length:" << text.length ();
343+
344+ const bool deferHeavyUpdate = shouldDeferCursorHeavyUpdate (cursor, text);
345+ if (!deferHeavyUpdate) {
346+ flushDeferredCursorUpdate ();
347+ } else {
348+ const int line = cursor.blockNumber ();
349+ if (m_deferCursorHeavyUpdate && line != m_deferCursorLastLine) {
350+ flushDeferredCursorUpdate ();
351+ }
352+ m_deferCursorHeavyUpdate = true ;
353+ m_deferCursorLastLine = line;
354+ }
355+
331356 QUndoCommand *pInsertStack = new InsertTextUndoCommand (cursor, text, this );
332357 m_pUndoStack->push (pInsertStack);
333358 ensureCursorVisible ();
359+ if (deferHeavyUpdate) {
360+ scheduleDeferredCursorUpdateBurst ();
361+ }
334362 qDebug () << " Selected text inserted successfully" ;
335363}
336364
337365void TextEdit::insertColumnEditTextEx (QString text)
338366{
339367 qDebug () << " Inserting column text" ;
368+ flushDeferredCursorUpdate ();
340369 if (m_isSelectAll) {
341370 QPlainTextEdit::selectAll ();
342371 }
@@ -2987,7 +3016,63 @@ bool TextEdit::setCursorKeywordSeletoin(int position, bool findNext)
29873016 return false ;
29883017}
29893018
2990- void TextEdit::cursorPositionChanged ()
3019+ bool TextEdit::shouldDeferCursorHeavyUpdate (const QTextCursor &cursor, const QString &text) const
3020+ {
3021+ if (m_cursorMode != Insert
3022+ || m_bIsAltMod
3023+ || m_readOnlyMode
3024+ || m_bReadOnlyPermission
3025+ || m_bIsFileOpen
3026+ || m_isPreeditBefore
3027+ || m_bIsInputMethod) {
3028+ return false ;
3029+ }
3030+
3031+ if (cursor.anchor () != cursor.position ()) {
3032+ return false ;
3033+ }
3034+
3035+ for (const QChar ch : text) {
3036+ if (ch == QLatin1Char (' \n ' ) || ch == QLatin1Char (' \t ' ) || ch == QChar::ParagraphSeparator) {
3037+ return false ;
3038+ }
3039+ }
3040+
3041+ return true ;
3042+ }
3043+
3044+ void TextEdit::scheduleDeferredCursorUpdateBurst ()
3045+ {
3046+ m_deferCursorHeavyUpdate = true ;
3047+ m_deferCursorLastLine = textCursor ().blockNumber ();
3048+ m_typingBurstFlushTimer->start ();
3049+ }
3050+
3051+ void TextEdit::flushDeferredCursorUpdate ()
3052+ {
3053+ if (m_typingBurstFlushTimer != nullptr ) {
3054+ m_typingBurstFlushTimer->stop ();
3055+ }
3056+
3057+ if (!m_deferCursorHeavyUpdate) {
3058+ return ;
3059+ }
3060+
3061+ m_deferCursorHeavyUpdate = false ;
3062+ m_deferCursorLastLine = -1 ;
3063+ applyCursorHeavyUpdate ();
3064+ }
3065+
3066+ void TextEdit::updateCursorPositionStatusLightweight ()
3067+ {
3068+ QTextCursor cursor = textCursor ();
3069+ if (m_wrapper) {
3070+ m_wrapper->bottomBar ()->updatePosition (cursor.blockNumber () + 1 ,
3071+ cursor.positionInBlock () + 1 );
3072+ }
3073+ }
3074+
3075+ void TextEdit::applyCursorHeavyUpdate ()
29913076{
29923077 qDebug () << " Cursor position changed" ;
29933078 // 以赋值形式,清空 Bracket 括号的selection
@@ -3001,19 +3086,30 @@ void TextEdit::cursorPositionChanged()
30013086 updateHighlightBrackets (' [' , ' ]' );
30023087 renderAllSelections ();
30033088
3004- QTextCursor cursor = textCursor ();
3005- if (m_wrapper) {
3006- qDebug () << " Cursor position changed with wrapper" ;
3007- m_wrapper->bottomBar ()->updatePosition (cursor.blockNumber () + 1 ,
3008- cursor.positionInBlock () + 1 );
3009- }
3089+ updateCursorPositionStatusLightweight ();
30103090
30113091 m_pLeftAreaWidget->m_pLineNumberArea ->update ();
30123092 m_pLeftAreaWidget->m_pBookMarkArea ->update ();
30133093 m_pLeftAreaWidget->m_pFlodArea ->update ();
30143094 qDebug () << " Cursor position changed completed" ;
30153095}
30163096
3097+ void TextEdit::cursorPositionChanged ()
3098+ {
3099+ if (m_deferCursorHeavyUpdate) {
3100+ const int line = textCursor ().blockNumber ();
3101+ if (line != m_deferCursorLastLine) {
3102+ flushDeferredCursorUpdate ();
3103+ return ;
3104+ }
3105+
3106+ updateCursorPositionStatusLightweight ();
3107+ return ;
3108+ }
3109+
3110+ applyCursorHeavyUpdate ();
3111+ }
3112+
30173113/* *
30183114 * @brief 剪切光标选中的文本
30193115 * @param ignoreCheck 是否忽略权限判断(外部已进行),默认false
@@ -3539,6 +3635,7 @@ void TextEdit::slotRedoAvailable(bool redoIsAvailable)
35393635void TextEdit::redo_ ()
35403636{
35413637 qDebug () << " Starting redo operation" ;
3638+ flushDeferredCursorUpdate ();
35423639 if (!m_pUndoStack->canRedo ()) {
35433640 qDebug () << " Redo operation skipped - nothing to redo" ;
35443641 return ;
@@ -3570,6 +3667,7 @@ void TextEdit::undo_()
35703667{
35713668 qDebug () << " Starting undo operation" ;
35723669 qDebug () << " Starting undo operation" ;
3670+ flushDeferredCursorUpdate ();
35733671 if (!m_pUndoStack->canUndo ()) {
35743672 qDebug () << " Undo operation skipped - nothing to undo" ;
35753673 return ;
@@ -5495,6 +5593,7 @@ void TextEdit::setTextFinished()
54955593 qDebug () << " Set text finished" ;
54965594 m_bIsFileOpen = false ;
54975595 m_nLines = blockCount ();
5596+ m_lastLeftAreaBlockCount = m_nLines;
54985597
54995598 if (!m_listBookmark.isEmpty ()) {
55005599 qDebug () << " Set text finished, m_listBookmark is not empty" ;
@@ -6563,6 +6662,13 @@ void TextEdit::updateMark(int from, int charsRemoved, int charsAdded)
65636662 return ;
65646663 }
65656664
6665+ // 无任何颜色/关键字标记时无需处理;渲染由 cursorPositionChanged 统一负责
6666+ if (m_wordMarkSelections.isEmpty ()
6667+ && m_mapKeywordMarkSelections.isEmpty ()
6668+ && m_mapWordMarkSelections.isEmpty ()) {
6669+ return ;
6670+ }
6671+
65666672 qDebug () << " updateMark, charsRemoved" << charsRemoved << " charsAdded" << charsAdded;
65676673 // 更新标记
65686674 int nStartPos = 0 ,// /< 标记的起始位置
@@ -7604,6 +7710,7 @@ void TextEdit::dropEvent(QDropEvent *event)
76047710
76057711void TextEdit::inputMethodEvent (QInputMethodEvent *e)
76067712{
7713+ flushDeferredCursorUpdate ();
76077714 m_bIsInputMethod = true ;
76087715
76097716 if (m_isSelectAll)
@@ -7674,6 +7781,7 @@ void TextEdit::inputMethodEvent(QInputMethodEvent *e)
76747781
76757782void TextEdit::mousePressEvent (QMouseEvent *e)
76767783{
7784+ flushDeferredCursorUpdate ();
76777785 if (m_bIsFindClose)
76787786 {
76797787 m_bIsFindClose = false ;
@@ -8193,6 +8301,7 @@ void TextEdit::keyPressEvent(QKeyEvent *e)
81938301
81948302 // 列编辑 删除撤销重做
81958303 if (modifiers == Qt::NoModifier && (e->key () == Qt::Key_Backspace)) {
8304+ flushDeferredCursorUpdate ();
81968305 if (m_isSelectAll)
81978306 QPlainTextEdit::selectAll ();
81988307
@@ -8216,6 +8325,7 @@ void TextEdit::keyPressEvent(QKeyEvent *e)
82168325
82178326 // 列编辑 向后删除撤销重做
82188327 if (modifiers == Qt::NoModifier && (e->key () == Qt::Key_Delete)) {
8328+ flushDeferredCursorUpdate ();
82198329 if (m_isSelectAll)
82208330 QPlainTextEdit::selectAll ();
82218331
0 commit comments