Skip to content

fix: resolve null pointer crash when TextCalculator exits#1585

Merged
18202781743 merged 1 commit intolinuxdeepin:masterfrom
18202781743:treeland-adapter
Apr 30, 2026
Merged

fix: resolve null pointer crash when TextCalculator exits#1585
18202781743 merged 1 commit intolinuxdeepin:masterfrom
18202781743:treeland-adapter

Conversation

@18202781743
Copy link
Copy Markdown
Contributor

@18202781743 18202781743 commented Apr 30, 2026

  1. Changed m_dataModel and m_calculator member variables from raw
    pointers to QPointer and QPointer to
    automatically track object destruction
  2. Added onDataModelDestroyed() slot to handle model destruction:
    clear m_dataModel pointer, emit dataModelChanged() signal, and reset
    calculated widths to prevent stale pointer access
  3. Extracted width reset logic into resetCalculatedWidths() method to
    avoid code duplication and ensure consistent state cleanup
  4. In scheduleCalculation(), call resetCalculatedWidths() when model is
    null or disabled to properly reset cached values
  5. In setEnabled(false), replaced inline width reset with
    resetCalculatedWidths() call for consistency
  6. In destructor, always call disconnectDataModelSignals() without null
    check, as QPointer ensures safe disconnection even if model is destroyed
  7. In TextCalculatorAttached::setCalculator(), added guard for duplicate
    calculator assignment and proper disconnect of previous calculator
    signals to prevent double connections
  8. Always call updateElidedText() even when calculator is null to ensure
    text is properly cleared
  9. Added QPointer include in header for QPointer usage

Log: Fixed null pointer crash during TextCalculator exit in dock task
panel

Influence:

  1. Test dock task panel close and exit operations to verify no crashes
    occur
  2. Verify task item text display updates correctly when tasks change
  3. Test with rapid task creation/deletion scenarios to check memory
    safety
  4. Verify elided text updates properly when calculator is reassigned
  5. Test disabled state transitions to confirm width values are reset
    correctly

fix: 修复 TextCalculator 退出时的野指针崩溃问题

  1. 将 m_dataModel 和 m_calculator 成员变量从原始指针改为
    QPointer 和 QPointer,自动追踪对象
    销毁
  2. 新增 onDataModelDestroyed() 槽函数处理模型销毁:清除 m_dataModel 指
    针、发射 dataModelChanged() 信号并重置计算宽度,防止野指针访问
  3. 将宽度重置逻辑提取为 resetCalculatedWidths() 方法,避免代码重复并确保
    状态一致清理
  4. 在 scheduleCalculation() 中,当模型为空或禁用时调用
    resetCalculatedWidths() 正确重置缓存值
  5. 在 setEnabled(false) 中,将内联宽度重置替换为 resetCalculatedWidths()
    调用,保持一致性
  6. 在析构函数中,始终调用 disconnectDataModelSignals() 而不进行空检查,
    因为 QPointer 确保即使模型已销毁也能安全断开连接
  7. 在 TextCalculatorAttached::setCalculator() 中,添加重复计算器赋值防
    护,并正确断开前一个计算器的信号连接,防止重复连接
  8. 即使计算器为空也始终调用 updateElidedText(),确保正确清理文本
  9. 在头文件中添加 QPointer 包含以支持 QPointer 使用

Log: 修复 Dock 任务面板 TextCalculator 退出时的野指针崩溃问题

Influence:

  1. 测试 dock 任务面板的关闭和退出操作,验证无崩溃发生
  2. 验证任务项文本显示在任务变更时正确更新
  3. 测试快速创建/删除任务场景,检查内存安全性
  4. 验证当计算器重新赋值时省略文本正确更新
  5. 测试禁用状态切换,确认宽度值正确重置

Summary by Sourcery

Prevent null-pointer-related crashes and stale state in TextCalculator by making model and calculator references safe and resetting cached widths when they become invalid or disabled.

Bug Fixes:

  • Handle destruction of the data model and calculator to avoid null pointer crashes and stale signal connections when TextCalculator or its model are destroyed.
  • Ensure elided text is updated or cleared correctly when the calculator is removed or disabled, preventing inconsistent text display.

Enhancements:

  • Introduce centralized width reset logic to keep cached width state consistent when the calculator is disabled, the model is destroyed, or calculations are skipped.
  • Use QPointer for the data model and attached calculator to automatically track object lifetime and simplify safe signal disconnection.

1. Changed m_dataModel and m_calculator member variables from raw
pointers to QPointer<QAbstractItemModel> and QPointer<TextCalculator> to
automatically track object destruction
2. Added onDataModelDestroyed() slot to handle model destruction:
clear m_dataModel pointer, emit dataModelChanged() signal, and reset
calculated widths to prevent stale pointer access
3. Extracted width reset logic into resetCalculatedWidths() method to
avoid code duplication and ensure consistent state cleanup
4. In scheduleCalculation(), call resetCalculatedWidths() when model is
null or disabled to properly reset cached values
5. In setEnabled(false), replaced inline width reset with
resetCalculatedWidths() call for consistency
6. In destructor, always call disconnectDataModelSignals() without null
check, as QPointer ensures safe disconnection even if model is destroyed
7. In TextCalculatorAttached::setCalculator(), added guard for duplicate
calculator assignment and proper disconnect of previous calculator
signals to prevent double connections
8. Always call updateElidedText() even when calculator is null to ensure
text is properly cleared
9. Added QPointer include in header for QPointer usage

Log: Fixed null pointer crash during TextCalculator exit in dock task
panel

Influence:
1. Test dock task panel close and exit operations to verify no crashes
occur
2. Verify task item text display updates correctly when tasks change
3. Test with rapid task creation/deletion scenarios to check memory
safety
4. Verify elided text updates properly when calculator is reassigned
5. Test disabled state transitions to confirm width values are reset
correctly

fix: 修复 TextCalculator 退出时的野指针崩溃问题

1. 将 m_dataModel 和 m_calculator 成员变量从原始指针改为
QPointer<QAbstractItemModel> 和 QPointer<TextCalculator>,自动追踪对象
销毁
2. 新增 onDataModelDestroyed() 槽函数处理模型销毁:清除 m_dataModel 指
针、发射 dataModelChanged() 信号并重置计算宽度,防止野指针访问
3. 将宽度重置逻辑提取为 resetCalculatedWidths() 方法,避免代码重复并确保
状态一致清理
4. 在 scheduleCalculation() 中,当模型为空或禁用时调用
resetCalculatedWidths() 正确重置缓存值
5. 在 setEnabled(false) 中,将内联宽度重置替换为 resetCalculatedWidths()
调用,保持一致性
6. 在析构函数中,始终调用 disconnectDataModelSignals() 而不进行空检查,
因为 QPointer 确保即使模型已销毁也能安全断开连接
7. 在 TextCalculatorAttached::setCalculator() 中,添加重复计算器赋值防
护,并正确断开前一个计算器的信号连接,防止重复连接
8. 即使计算器为空也始终调用 updateElidedText(),确保正确清理文本
9. 在头文件中添加 QPointer 包含以支持 QPointer 使用

Log: 修复 Dock 任务面板 TextCalculator 退出时的野指针崩溃问题

Influence:
1. 测试 dock 任务面板的关闭和退出操作,验证无崩溃发生
2. 验证任务项文本显示在任务变更时正确更新
3. 测试快速创建/删除任务场景,检查内存安全性
4. 验证当计算器重新赋值时省略文本正确更新
5. 测试禁用状态切换,确认宽度值正确重置
@18202781743
Copy link
Copy Markdown
Contributor Author

#0 0x00007f90d230c344 in QObject::disconnect (sender=0x558845542250, signal=0x0, receiver=0x55884664cce0, method=0x0) at ./src/corelib/kernel/qobject.cpp:3288
#1 0x00007f90c869d0ed in dock::TextCalculator::disconnectDataModelSignals (this=0x55884664cce0) at /home/uod/Desktop/myrepo/dde-shell/panels/dock/taskmanager/textcalculator.cpp:151
#2 0x00007f90c869c7f3 in dock::TextCalculator::~TextCalculator (this=0x55884664cce0, __in_chrg=) at /home/uod/Desktop/myrepo/dde-shell/panels/dock/taskmanager/textcalculator.cpp:34
#3 0x00007f90c868c046 in QQmlPrivate::QQmlElementdock::TextCalculator::~QQmlElement (this=0x55884664cce0, __in_chrg=) at /usr/include/x86_64-linux-gnu/qt6/QtQml/qqmlprivate.h:104
#4 0x00007f90c868c068 in QQmlPrivate::QQmlElementdock::TextCalculator::~QQmlElement (this=0x55884664cce0, __in_chrg=) at /usr/include/x86_64-linux-gnu/qt6/QtQml/qqmlprivate.h:104
#5 0x00007f90d23065eb in QObjectPrivate::deleteChildren (this=this@entry=0x55884663c450) at ./src/corelib/kernel/qobject.cpp:2211
#6 0x00007f90d2308df8 in QObject::~QObject (this=, this=) at ./src/corelib/kernel/qobject.cpp:1138
#7 0x00007f90d4c6ff3c in ds::DAppletItem::~DAppletItem (this=0x55884664b2b0, __in_chrg=) at /home/uod/Desktop/myrepo/dde-shell/frame/appletitem.cpp:28
#8 0x00007f90d4c70378 in ds::DContainmentItem::~DContainmentItem (this=0x55884664b2b0, __in_chrg=) at /home/uod/Desktop/myrepo/dde-shell/frame/containmentitem.cpp:22
#9 0x00007f90b23922de in QQmlPrivate::QQmlElementds::DContainmentItem::~QQmlElement (this=0x55884664b2b0, __in_chrg=) at /usr/include/x86_64-linux-gnu/qt6/QtQml/qqmlprivate.h:104
#10 0x00007f90b2392306 in QQmlPrivate::QQmlElementds::DContainmentItem::~QQmlElement (this=0x55884664b2b0, __in_chrg=) at /usr/include/x86_64-linux-gnu/qt6/QtQml/qqmlprivate.h:104
#11 0x00007f90d2307716 in QObject::event (this=0x55884664b2b0, e=) at ./src/corelib/kernel/qobject.cpp:1404
#12 0x00007f90d30e1025 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib/x86_64-linux-gnu/libQt6Widgets.so.6
#13 0x00007f90d22c4eb8 in QCoreApplication::notifyInternal2 (receiver=0x55884664b2b0, event=0x55884553bb30) at ./src/corelib/kernel/qcoreapplication.cpp:1165
#14 0x00007f90d22ccd77 in QCoreApplicationPrivate::sendPostedEvents (receiver=0x0, event_type=52, data=0x5588453fa750) at ./src/corelib/kernel/qcoreapplication.cpp:1965
#15 0x00007f90d22c7d03 in QCoreApplication::exec () at ./src/corelib/tools/qscopedpointer.h:110
#16 0x0000558826da92f8 in main (argc=6, argv=0x7fff9a5431b8) at /home/uod/Desktop/myrepo/dde-shell/shell/main.cpp:220

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 30, 2026

Reviewer's Guide

Refactors TextCalculator’s model and calculator ownership to use QPointer, adds explicit cleanup on model destruction and disabled states, and improves TextCalculatorAttached’s signal management to prevent null/dangling pointer crashes and inconsistent elided text updates.

Sequence diagram for TextCalculator model destruction and width reset

sequenceDiagram
    participant View
    participant Attached as TextCalculatorAttached
    participant Calc as TextCalculator
    participant Model as QAbstractItemModel

    View->>Calc: setDataModel(Model)
    Calc->>Calc: connectDataModelSignals()
    Calc->>Attached: emit optimalSingleTextWidthChanged
    Attached->>Attached: updateElidedText()

    note over Model,Calc: Later, model is destroyed elsewhere
    Model-->>Calc: destroyed(QObject*)
    Calc->>Calc: onDataModelDestroyed()
    Calc->>Calc: m_dataModel = nullptr
    Calc->>Calc: resetCalculatedWidths()
    Calc->>Attached: emit optimalSingleTextWidthChanged
    Calc->>Attached: emit totalWidthChanged
    Attached->>Attached: updateElidedText() (clears text)

    View->>Calc: setEnabled(false)
    Calc->>Calc: resetCalculatedWidths() (no duplication)
    Calc->>Attached: emit optimalSingleTextWidthChanged
    Attached->>Attached: updateElidedText()
Loading

Sequence diagram for updated TextCalculatorAttached::setCalculator behavior

sequenceDiagram
    actor QML as QMLClient
    participant Attached as TextCalculatorAttached
    participant OldCalc as TextCalculator
    participant NewCalc as TextCalculator

    QML->>Attached: setCalculator(OldCalc)
    Attached->>Attached: m_calculator initially null
    Attached->>Attached: m_calculator = OldCalc
    Attached->>QML: emit calculatorChanged
    Attached->>OldCalc: connect optimalSingleTextWidthChanged -> updateElidedText
    Attached->>Attached: updateElidedText()

    QML->>Attached: setCalculator(OldCalc)
    Attached->>Attached: if m_calculator == calculator return

    QML->>Attached: setCalculator(NewCalc)
    Attached->>Attached: m_calculator != calculator
    Attached->>OldCalc: disconnect all signals to Attached
    Attached->>Attached: m_calculator = NewCalc
    Attached->>QML: emit calculatorChanged
    Attached->>NewCalc: connect optimalSingleTextWidthChanged -> updateElidedText
    Attached->>Attached: updateElidedText()

    QML->>Attached: setCalculator(nullptr)
    Attached->>NewCalc: disconnect all signals to Attached
    Attached->>Attached: m_calculator = nullptr
    Attached->>QML: emit calculatorChanged
    Attached->>Attached: updateElidedText() (clears elided text)
Loading

Updated class diagram for TextCalculator and TextCalculatorAttached

classDiagram
    class TextCalculator {
        +TextCalculator(QObject *parent)
        +~TextCalculator()
        +void setFont(QFont font)
        +void setEnabled(bool enabled)
        +void setDataModel(QAbstractItemModel *model)
        +QAbstractItemModel *dataModel()
        +qreal optimalSingleTextWidth() const
        +qreal totalWidth() const
        +bool isEnabled() const
        +void classBegin()
        +void componentComplete()
        -- signals --
        +void dataModelChanged()
        +void optimalSingleTextWidthChanged()
        +void totalWidthChanged()
        +void enabledChanged()
        -- slots --
        +void onDataModelChanged()
        +void onDataModelDestroyed()
        +void calculateOptimalTextWidth()
        -- private helpers --
        -void connectDataModelSignals()
        -void disconnectDataModelSignals()
        -void scheduleCalculation()
        -void resetCalculatedWidths()
        -qreal calculateBaselineWidth(int charCount) const
        -qreal calculateElidedTextWidth(QString text, qreal maxWidth) const
        -qreal calculateTotalWidth() const
        -- members --
        -QFont m_font
        -qreal m_optimalSingleTextWidth
        -qreal m_totalWidth
        -QHash~int,qreal~ m_baselineWidthCache
        -qreal m_cellSize
        -int m_spacing
        -int m_itemPadding
        -QPointer_QAbstractItemModel_ m_dataModel
        -qreal m_remainingSpace
        -bool m_enabled
        -bool complete
    }

    class TextCalculatorAttached {
        +TextCalculatorAttached(QObject *parent)
        +~TextCalculatorAttached()
        +QString text() const
        +QString elidedText() const
        +qreal ellipsisWidth() const
        +TextCalculator *calculator() const
        +void setText(QString text)
        +void setCalculator(TextCalculator *calculator)
        -- signals --
        +void textChanged()
        +void elidedTextChanged()
        +void ellipsisWidthChanged()
        +void calculatorChanged()
        -- slots --
        +void updateElidedText()
        -- members --
        -QString m_text
        -QString m_elidedText
        -qreal m_ellipsisWidth
        -QPointer_TextCalculator_ m_calculator
        -bool m_initialized
    }

    class QAbstractItemModel
    class QPointer_QAbstractItemModel_ {
    }
    class QPointer_TextCalculator_ {
    }

    TextCalculator --> QPointer_QAbstractItemModel_ : has
    QPointer_QAbstractItemModel_ --> QAbstractItemModel : wraps

    TextCalculatorAttached --> QPointer_TextCalculator_ : has
    QPointer_TextCalculator_ --> TextCalculator : wraps

    TextCalculatorAttached ..> TextCalculator : observes optimalSingleTextWidthChanged
Loading

File-Level Changes

Change Details Files
Harden TextCalculator against model destruction and disabled states using QPointer and centralized width reset logic.
  • Change m_dataModel from raw QAbstractItemModel* to QPointer to auto-null when the model is destroyed.
  • Always call disconnectDataModelSignals() in the TextCalculator destructor, relying on QPointer for safe disconnection even if the model is already destroyed.
  • Connect the model's destroyed() signal to a new onDataModelDestroyed() slot that clears m_dataModel, emits dataModelChanged(), and resets cached widths.
  • Introduce resetCalculatedWidths() to zero m_optimalSingleTextWidth and m_totalWidth and only emit their changed signals when the values were previously non-zero.
  • Use resetCalculatedWidths() in scheduleCalculation() when the calculator is disabled or has no model, and in setEnabled(false) instead of duplicating inline reset logic.
panels/dock/taskmanager/textcalculator.cpp
panels/dock/taskmanager/textcalculator.h
Make TextCalculatorAttached robust to calculator re-assignment and null calculators.
  • Change m_calculator from a raw TextCalculator* to QPointer to avoid dangling references.
  • Update setCalculator() to early-return on duplicate assignment, disconnect signals from any previous calculator, emit calculatorChanged(), and then connect to the new calculator if non-null.
  • Always call updateElidedText() after calculator changes, even when calculator is null, so bound text is cleared correctly.
  • Preserve and slightly clean up updateElidedText() logic for ellipsis width and text updates.
panels/dock/taskmanager/textcalculator.cpp
panels/dock/taskmanager/textcalculator.h
Minor header and formatting adjustments.
  • Add #include in the header to support QPointer usage.
  • Normalize SPDX-FileCopyrightText formatting in both cpp and header files.
  • Apply small whitespace/indentation fix-ups in lambda and elided text handling.
panels/dock/taskmanager/textcalculator.cpp
panels/dock/taskmanager/textcalculator.h

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

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

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

Hey - I've left some high level feedback:

  • In resetCalculatedWidths(), using qFuzzyIsNull() on m_totalWidth and then assigning 0.0 suggests m_totalWidth might be an integral type; consider making m_totalWidth consistently qreal (or avoiding qFuzzyIsNull if it’s an int) to avoid type ambiguity and unintended behavior.
  • Now that updateElidedText() is called even when m_calculator is null and m_calculator is a QPointer, double-check that updateElidedText() safely handles a null calculator without dereferencing it.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In resetCalculatedWidths(), using qFuzzyIsNull() on m_totalWidth and then assigning 0.0 suggests m_totalWidth might be an integral type; consider making m_totalWidth consistently qreal (or avoiding qFuzzyIsNull if it’s an int) to avoid type ambiguity and unintended behavior.
- Now that updateElidedText() is called even when m_calculator is null and m_calculator is a QPointer, double-check that updateElidedText() safely handles a null calculator without dereferencing it.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, BLumia

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

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码的 diff 展示了对 TextCalculator 及其附加类 TextCalculatorAttached 的一系列改进。整体来看,改动主要集中在内存安全代码健壮性代码重构方面。

以下是对这些改动的详细审查和改进意见:

1. 内存安全与生命周期管理

改动点:

  • TextCalculatorAttached 中的成员变量 TextCalculator *m_calculator 修改为 QPointer<TextCalculator> m_calculator
  • TextCalculator 中的成员变量 QAbstractItemModel *m_dataModel 修改为 QPointer<QAbstractItemModel> m_dataModel
  • 新增了槽函数 onDataModelDestroyed,并连接到 &QObject::destroyed 信号。

审查意见:

  • 优点: 这是一个非常显著的改进。使用 QPointer 是 Qt 中处理持有 QObject 派生类指针的标准安全做法。它能够自动在对象被销毁时将指针置为 nullptr,有效防止了悬空指针和野指针的访问。
  • 优点: 新增 onDataModelDestroyed 是必要的。虽然 QPointer 能防止解引用崩溃,但显式地处理 destroyed 信号并在回调中将成员置空、触发 dataModelChanged 和重置计算宽度,使得逻辑更加闭环和清晰,避免了后续逻辑中依赖 m_dataModel 有效性的检查变得复杂。
  • 建议:TextCalculatorAttached::setCalculator 中,使用了 disconnect(m_calculator, nullptr, this, nullptr)。配合 QPointer 使用是安全的,但要注意,如果 m_calculator 已经被销毁(即为 nullptr),disconnect 的行为是安全的,不会报错。代码逻辑正确。

2. 代码逻辑与健壮性

改动点:

  • 析构函数 TextCalculator::~TextCalculator() 中移除了 if (m_dataModel) 判断,直接调用 disconnectDataModelSignals()
  • TextCalculator::setEnabled 中,当禁用时调用新的 resetCalculatedWidths() 函数。
  • TextCalculator::scheduleCalculation 中,当未启用或无模型时,调用 resetCalculatedWidths()
  • 新增 resetCalculatedWidths() 函数,增加了对值是否为 0 的判断 (qFuzzyIsNull),仅在值确实改变时才发送信号。
  • TextCalculatorAttached::setCalculator 增加了重复设置检查 (if (m_calculator == calculator) return;),并优化了连接/断开逻辑。

审查意见:

  • 优点: 析构函数中移除 if 判断是合理的,因为 disconnectDataModelSignals 内部通常应当处理空指针情况,或者 QPointer 的使用保证了安全性。这让析构函数更简洁。
  • 优点: resetCalculatedWidths 的引入提高了代码复用性,减少了重复代码(DRY原则)。
  • 优点: resetCalculatedWidths 中使用 qFuzzyIsNull 检查浮点数是否为 0,并在状态改变时才 emit 信号。这是一个极佳的优化,避免了不必要的信号触发和潜在的 UI 重绘,提高了性能。
  • 优点: TextCalculatorAttached::setCalculator 的改进非常到位。之前的实现如果多次设置同一个 calculator,会导致重复连接信号,甚至导致逻辑错误(虽然 lambda 捕获了 this,但多次连接会导致回调执行多次)。现在的实现确保了连接的唯一性和正确性。

3. 代码规范与风格

改动点:

  • 修改了版权年份格式:2025-2026 -> 2025 - 2026
  • 调整了 connect 中的 lambda 缩进。

审查意见:

  • 优点: 版权年份格式统一化,符合更通用的书写规范。
  • 优点: Lambda 缩进的调整使代码层级更清晰,可读性更好。

4. 潜在的性能与安全建议

尽管改动已经很好,但以下几点可以进一步考虑:

  1. disconnectDataModelSignals 的实现细节

    • 由于引入了 QPointeronDataModelDestroyed,请确保 disconnectDataModelSignals 的实现是安全的。
    • 建议:在该函数内部,如果使用了 disconnect(m_dataModel, ...),请确保不需要显式检查 m_dataModel 是否为空,或者保留检查。因为 QObject::disconnectnullptr 是安全的,但显式检查会让代码意图更明确。
  2. resetCalculatedWidths 中的类型一致性

    • 代码中:m_totalWidth = 0; (旧代码是 int 0,新代码赋值为 0)。
    • 建议确认 m_totalWidth 的类型。如果是 qreal,建议显式写成 0.0 以保持类型一致,尽管 C++ 会自动处理类型转换。在 resetCalculatedWidths 的实现中,diff 显示它被赋值为 0.0,这是正确的。
  3. connect 的上下文

    • connectDataModelSignals 中:
      connect(m_dataModel, &QAbstractItemModel::dataChanged, this, [this](...) { ... });
    • 安全建议:这里的 this 指针作为接收者。如果 TextCalculator 对象先于 m_dataModel 被销毁,Qt 的连接机制会自动断开连接,这是安全的。但如果 m_dataModel 被销毁,QPointer 会置空,且 destroyed 信号会触发 onDataModelDestroyed。逻辑闭环,没有问题。

总结

这段代码的修改质量很高,主要解决了以下核心问题:

  1. 安全性:通过引入 QPointerdestroyed 信号处理,彻底解决了对象生命周期管理中的潜在崩溃风险。
  2. 性能:通过优化信号发送逻辑(仅在值改变时发送),减少了不必要的开销。
  3. 可维护性:提取公共函数 resetCalculatedWidths 并完善 setCalculator 的逻辑,使代码更易于理解和维护。

总体评价:代码逻辑清晰,安全性大幅提升,符合 Qt 最佳实践。无需重大修改,建议合并。

@18202781743 18202781743 merged commit 681895c into linuxdeepin:master Apr 30, 2026
10 of 12 checks passed
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.

3 participants