From 31e73bbe1e35fd984ea56b6452a107dbde217bff Mon Sep 17 00:00:00 2001 From: liujinchang Date: Thu, 29 Oct 2026 03:25:03 +0800 Subject: [PATCH] fix: correct column edit mode status after undo operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Root cause: undo_() called refreshUndoRedoColumnStatus() after m_pUndoStack->undo() which decrements index(), so command(index()) returned the just-undone (redo-pending) command instead of the current stack top, keeping m_bIsAltMod=true after undoing the last column edit command 2. Fix: add refreshUndoRedoColumnStatusAfterUndo() that checks command(index()-1) (current applied stack top) instead of command(index()) to correctly determine edit mode after undo 3. Impact: only undo_() path is affected; redo_() still uses original refreshUndoRedoColumnStatus(), no signature changes Log: fix column edit mode status not updating correctly after undo Influence: 1. Test column edit mode input then undo, verify mode exits correctly 2. Test multiple column edits then sequential undo, verify intermediate undo keeps column mode while final undo exits 3. Test redo after undo in column edit mode, verify no regression 4. Test normal edit mode undo/redo, verify no regression fix: 修复列编辑模式下撤销输入不正确的问题 1. 根因:undo_() 在 m_pUndoStack->undo() 之后调用 refreshUndoRedoColumnStatus(),undo() 会递减 index(),导致 command(index()) 返回的是刚被撤销的待重做命令而非当前栈顶, 撤销最后一个列编辑命令后 m_bIsAltMod 错误保持为 true 2. 方案:新增 refreshUndoRedoColumnStatusAfterUndo() 检查 command(index()-1)(当前已应用栈顶)而非 command(index()) 来正确判断撤销后的编辑模式 3. 影响:仅影响 undo_() 路径,redo_() 仍使用原 refreshUndoRedoColumnStatus(),不改变函数签名 Log: 修复列编辑模式下撤销后编辑模式状态不正确的问题 Influence: 1. 测试列编辑模式输入后撤销,验证撤销后正确退出列编辑模式 2. 测试列编辑模式多次输入后逐次撤销,验证中途撤销保持列编辑模式 3. 测试列编辑模式撤销后重做,验证无回归 4. 测试普通编辑模式撤销/重做,验证无回归 Bug: #254289 --- src/editor/dtextedit.cpp | 37 ++++++++++++++++++++++++++++++++++++- src/editor/dtextedit.h | 1 + 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/editor/dtextedit.cpp b/src/editor/dtextedit.cpp index 00bc6d77..cc2a52d3 100644 --- a/src/editor/dtextedit.cpp +++ b/src/editor/dtextedit.cpp @@ -3815,7 +3815,7 @@ void TextEdit::undo_() m_pUndoStack->undo(); qCDebug(appLog) << "Undo operation executed, new stack index:" << m_pUndoStack->index(); - const bool needUpdate = refreshUndoRedoColumnStatus(); + const bool needUpdate = refreshUndoRedoColumnStatusAfterUndo(); if (needUpdate) { renderAllSelections(); update(); @@ -9224,6 +9224,41 @@ bool TextEdit::refreshUndoRedoColumnStatus() return false; } +/** + @brief Call this function after undo, refresh column edit status. + After undo(), index() has decremented, so command(index()) points to the + just-undone (redo-pending) command. To determine the current edit mode, + check command(index()-1) — the current top of the applied stack. + @return True if need update selection status. + */ +bool TextEdit::refreshUndoRedoColumnStatusAfterUndo() +{ + if (const QUndoCommand *cmd = m_pUndoStack->command(m_pUndoStack->index() - 1)) { + const int id = cmd->id(); + const bool columnEdit = (id != Utils::IdDefault) && (Utils::IdColumnEdit & id); + if (columnEdit != m_bIsAltMod) { + // update selection + m_bIsAltMod = columnEdit; + if (!m_bIsAltMod) { + m_altModSelections.clear(); + } + + return true; + } + + // in column editing, update every time. + if (columnEdit) { + return true; + } + } else { + // No commands applied after undo — leave column edit mode state + // unchanged; column mode entry/exit is driven by user actions, + // orthogonal to the undo stack state. + } + + return false; +} + /** * @brief 文档内容变更时触发 * 当前用于记录中键更新前后的动作并压入撤销栈,需要注意鼠标中键不会移除字符仅会插入选中的字符。 diff --git a/src/editor/dtextedit.h b/src/editor/dtextedit.h index b3cce739..7a7bb5d5 100644 --- a/src/editor/dtextedit.h +++ b/src/editor/dtextedit.h @@ -628,6 +628,7 @@ public slots: bool findFoldBlock(int line, QTextBlock &beginBlock, QTextBlock &endBlock, QTextBlock &curBlock); bool refreshUndoRedoColumnStatus(); + bool refreshUndoRedoColumnStatusAfterUndo(); private slots: // 文档内容变更时触发