Skip to content

fix: sync column-edit selections on undo to restore highlight - #689

Open
pppanghu77 wants to merge 1 commit into
linuxdeepin:release/eaglefrom
pppanghu77:agent/agent/dc4426b1dd2e
Open

pppanghu77 wants to merge 1 commit into
linuxdeepin:release/eaglefrom
pppanghu77:agent/agent/dc4426b1dd2e

Conversation

@pppanghu77

@pppanghu77 pppanghu77 commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Root Cause Analysis

DeleteTextUndoCommand::undo() and InsertTextUndoCommand::undo() column-edit branches restore text and internal cursor selections but only call setTextCursor(last().cursor) — they never sync m_ColumnEditSelections back to TextEdit::m_altModSelections nor call renderAllSelections(). Since renderAllSelections() (dtextedit.cpp:2222) renders visual highlights from m_altModSelections, and that list holds stale (post-cut) cursors after undo, the highlight only appears on the last line. Key evidence: deletetextundocommand.cpp:96 sets only the last cursor; dtextedit.cpp:3047-3066 (undo_()) does not update m_altModSelections.

Fix

Added TextEdit::syncColumnEditSelections(const QList<QTextEdit::ExtraSelection> &) which sets m_altModSelections and calls renderAllSelections(). Both DeleteTextUndoCommand::undo() and InsertTextUndoCommand::undo() column-edit branches now call it via qobject_cast<TextEdit*>(m_edit) after setTextCursor. The cast ensures non-TextEdit editors are unaffected. PMS 254289 (same pattern in InsertTextUndoCommand) is fixed together.

Change Safety Assessment

Code Safety

  • Risk Level: Medium
  • Target lines are original implementation omissions, not products of previous bug fixes — this change does not revert any historical fix.
  • references = 0 in change-safety analysis; no external callers of the modified undo() functions. qobject_cast guards ensure non-TextEdit editors skip the new code path with no behavioral change.

Business Impact Scope

  • Column-edit mode (Alt+drag multi-line selection): cut then undo, insert then undo — selection highlight now restores on all originally selected lines.
  • Normal (non-column-edit) cut/insert/undo: no change (qobject_cast returns null, original path executes).
  • PMS 254289 (insert-undo column-edit): same fix applies.

Verification Suggestion

  • Column-edit multi-line select → cut → undo: verify all lines show selection highlight.
  • Normal mode cut/insert → undo: verify no regression.
  • Column-edit undo → redo → undo cycle: verify selection state consistency.

根因分析

DeleteTextUndoCommand::undo() 和 InsertTextUndoCommand::undo() 列编辑分支恢复文本和内部光标后仅调用 setTextCursor(last().cursor),未将 m_ColumnEditSelections 同步回 TextEdit::m_altModSelections,也未调用 renderAllSelections()。由于 renderAllSelections()(dtextedit.cpp:2222)依赖 m_altModSelections 渲染高亮,而该列表在剪切后持有陈旧光标,撤销后仅最后一行显示选中。关键证据:deletetextundocommand.cpp:96 仅设最后一个光标;dtextedit.cpp:3047-3066(undo_())不更新 m_altModSelections。

修复方案

新增 TextEdit::syncColumnEditSelections(const QList<QTextEdit::ExtraSelection> &) 方法,设置 m_altModSelections 并调用 renderAllSelections()。DeleteTextUndoCommand::undo() 和 InsertTextUndoCommand::undo() 列编辑分支在 setTextCursor 后通过 qobject_cast<TextEdit*>(m_edit) 安全调用该方法。非 TextEdit 类型编辑器不受影响。PMS 254289(InsertTextUndoCommand 同一缺陷)一并修复。

改动安全评估

代码安全评估

  • 风险等级: 中风险
  • 目标行为为原始实现遗漏,非历史修复产物,本次改动不撤销任何已有修复。
  • change-safety 引用列表为 0 条,无外部调用者直接调用被修改的 undo() 函数;qobject_cast 保护确保非 TextEdit 类型编辑器走原路径无行为变化。

业务影响范围

  • 列编辑模式(Alt+鼠标拖拽多行选中):剪切后撤销、插入后撤销——选中高亮现在恢复为所有原始选中行。
  • 普通模式(非列编辑)剪切/插入/撤销:无变化(qobject_cast 返回 null,走原路径)。
  • PMS 254289(插入撤销列编辑):同一修复适用。

验证建议

  • 列编辑多行选中 → 剪切 → 撤销:验证所有行选中高亮恢复。
  • 普通模式剪切/插入 → 撤销:验证无回归。
  • 列编辑撤销 → 重做 → 撤销循环:验证选中状态一致性。

Summary by Sourcery

Restore column-edit selection state and highlighting consistently after undo operations.

Bug Fixes:

  • Restore all column-edit selection highlights when undoing text deletion or insertion.

Enhancements:

  • Centralize synchronization of column-edit selections with rendered editor highlights while preserving existing behavior for other editor types.

1. Root cause: DeleteTextUndoCommand::undo() and
   InsertTextUndoCommand::undo() column-edit branches restore text
   and cursors internally but only call setTextCursor(last cursor),
   without syncing m_ColumnEditSelections back to
   TextEdit::m_altModSelections or calling renderAllSelections()
2. Fix: add TextEdit::syncColumnEditSelections() that sets
   m_altModSelections and calls renderAllSelections(); call it via
   qobject_cast<TextEdit*> in both undo() column-edit branches
3. Impact: column-edit cut/insert undo now restores full multi-line
   selection highlight; non-column-edit paths unaffected; PMS 254289
   (same pattern in InsertTextUndoCommand) fixed together

Log: fix column-edit undo only showing selection on last line

Influence:
1. Test column-edit multi-line select then cut then undo
2. Test column-edit multi-line insert then undo
3. Test normal (non-column) cut/insert undo for no regression
4. Test repeated undo/redo cycle in column-edit mode

fix: 修复列编辑撤销后选中状态仅显示最后一行的问题

1. 根因:DeleteTextUndoCommand::undo() 和 InsertTextUndoCommand::undo()
   列编辑分支恢复文本和光标后仅调用 setTextCursor(最后一个cursor),
   未将 m_ColumnEditSelections 同步回 TextEdit::m_altModSelections,
   也未调用 renderAllSelections()
2. 方案:新增 TextEdit::syncColumnEditSelections() 方法设置
   m_altModSelections 并调用 renderAllSelections(),在两个 undo()
   列编辑分支中通过 qobject_cast<TextEdit*> 安全调用
3. 影响:列编辑剪切/插入撤销后恢复完整多行选中高亮;非列编辑路径
   不受影响;PMS 254289(InsertTextUndoCommand 同一缺陷)一并修复

Log: 修复列编辑撤销后选中状态仅显示最后一行的问题

Influence:
1. 测试列编辑多行选中后剪切再撤销
2. 测试列编辑多行插入后撤销
3. 测试普通模式剪切/插入撤销无回归
4. 测试列编辑模式下多次撤销/重做循环

PMS: BUG-241613
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: pppanghu77

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai

sourcery-ai Bot commented Oct 23, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Fixes column-edit undo highlighting by synchronizing the restored selection list with TextEdit’s alternate selections and re-rendering all highlights, while preserving existing behavior for other editor types and normal editing.

Sequence diagram for column-edit undo highlight restoration

sequenceDiagram
    participant Undo as UndoCommand
    participant Edit as TextEdit
    participant Render as SelectionRenderer

    Undo->>Edit: setTextCursor(last selection cursor)
    Undo->>Edit: syncColumnEditSelections(m_ColumnEditSelections)
    Edit->>Edit: m_altModSelections = selections
    Edit->>Render: renderAllSelections()
    Render-->>Edit: restore highlights on all selected lines
Loading

File-Level Changes

Change Details Files
Synchronize column-edit selections and repaint highlights during undo.
  • Added a TextEdit helper that updates alternate-mode selections and invokes selection rendering.
  • Updated delete-text undo to restore all column selections for TextEdit instances.
  • Updated insert-text undo with the same guarded synchronization path.
src/editor/dtextedit.h
src/editor/dtextedit.cpp
src/editor/deletetextundocommand.cpp
src/editor/inserttextundocommand.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 98 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次变更修复了撤销操作时列编辑选区高亮未同步恢复的问题,新增 syncColumnEditSelections 方法并在 DeleteTextUndoCommand/InsertTextUndoCommand 的 undo 中调用。语法逻辑正确,性能无影响,无安全漏洞。仅存在轻微的代码重复(两个 undo 方法中相同的 qobject_cast+sync 模式),不影响功能正确性。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无语法逻辑问题']


2. 代码质量 ✅

评价: 代码结构清晰,可读性好 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['可考虑在基类或公共工具类中提取一个辅助方法(如 syncColumnEditSelectionsIfTextEdit(QPlainTextEdit*, const QListQTextEdit::ExtraSelection&)),供两个 undo 命令复用,减少代码重复']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无性能问题']


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: ['无安全问题']


💡 改进建议代码示例

// 可选的改进:提取公共辅助方法以减少重复
// 在公共工具类或基类中:
static void syncColumnEditSelectionsIfTextEdit(QPlainTextEdit *edit,
                                                const QList<QTextEdit::ExtraSelection> &selections)
{
    if (edit && !selections.isEmpty()) {
        edit->setTextCursor(selections.last().cursor);
        if (TextEdit *textEdit = qobject_cast<TextEdit*>(edit)) {
            textEdit->syncColumnEditSelections(selections);
        }
    }
}

// 在 DeleteTextUndoCommand::undo() 和 InsertTextUndoCommand::undo() 中替换为:
// syncColumnEditSelectionsIfTextEdit(m_edit, m_ColumnEditSelections);
// syncColumnEditSelectionsIfTextEdit(m_pEdit, m_ColumnEditSelections);

本报告由 AI 代码审查工具自动生成

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants