Skip to content

fix: Implement full-row hover effect in DataTreeView#399

Merged
deepin-bot[bot] merged 2 commits intolinuxdeepin:masterfrom
dengzhongyuan365-dev:fix-4-30
Apr 28, 2026
Merged

fix: Implement full-row hover effect in DataTreeView#399
deepin-bot[bot] merged 2 commits intolinuxdeepin:masterfrom
dengzhongyuan365-dev:fix-4-30

Conversation

@dengzhongyuan365-dev
Copy link
Copy Markdown
Contributor

  • Added a new ItemViewRowHoverProxyStyle to manage hover effects for rows in the DataTreeView.
  • Enhanced the drawRow method to support full-row highlighting on hover, improving user interaction.
  • Introduced mouse tracking and hover row management to update the visual state based on mouse position.
  • Updated mouseMoveEvent and leaveEvent to handle hover state changes effectively.

This feature enhances the visual feedback for users, making the interface more intuitive and responsive. bug: https://pms.uniontech.com/bug-view-283255.html

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.

Sorry @dengzhongyuan365-dev, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

lzwind
lzwind previously approved these changes Apr 28, 2026
@dengzhongyuan365-dev
Copy link
Copy Markdown
Contributor Author

/forcemerge

- Added a new ItemViewRowHoverProxyStyle to manage hover effects for rows in the DataTreeView.
- Enhanced the drawRow method to support full-row highlighting on hover, improving user interaction.
- Introduced mouse tracking and hover row management to update the visual state based on mouse position.
- Updated mouseMoveEvent and leaveEvent to handle hover state changes effectively.

This feature enhances the visual feedback for users, making the interface more intuitive and responsive.
bug: https://pms.uniontech.com/bug-view-283255.html
@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengzhongyuan365-dev

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

1 similar comment
@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: dengzhongyuan365-dev

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

- Modified the progress update logic to accept sub-percent values while ensuring monotonic progress.
- Introduced a throttling mechanism to limit UI updates, reducing potential performance issues from frequent progress changes.
- Enhanced reset and timer restart functions to invalidate the UI update timer appropriately.

These changes enhance the responsiveness and accuracy of the progress display, improving user experience during long-running tasks.

bug: TASK: https://pms.uniontech.com/task-view-388835.html
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码主要进行了两方面的改进:一是对进度条更新逻辑的优化(progresspage.cpp/h),二是实现了树形视图的整行悬停效果(datatreeview.cpp/h 及相关文件)。以下是对这两部分代码的详细审查意见:

1. 进度条更新逻辑 (progresspage.cpp)

改进点:

  1. 逻辑修复:修复了原先仅当整数百分比变化时才更新速度和剩余时间的问题,现在支持子百分比(如 1.1%)的进度更新,解决了速度计算卡在"计算中"的Bug。
  2. 性能优化(节流):引入了 QElapsedTimer m_uiUpdateTimer,实现了 UI 刷新的节流机制。只有在整数进度变化时,或者距离上次刷新超过 200ms 时,才会触发速度和剩余时间的计算与界面更新。这有效防止了高频进度更新导致的界面卡顿和抖动。
  3. 状态管理:在 resetProgressrestartTimer 中增加了对 m_uiUpdateTimer 的重置逻辑,确保每次重新开始任务时计时器状态正确。

审查意见:

  • 代码质量:代码逻辑清晰,注释详细,变量命名规范(如 percentChanged, timeToUpdate)。
  • 代码安全
    • m_uiUpdateTimer 的使用是安全的,isValid() 检查防止了未启动就 elapsed() 的问题。
    • dPercent 的边界检查(< 0> 100)保留并有效。
  • 代码性能
    • 建议:200ms 的硬编码阈值可以提取为类成员常量或宏定义,例如 static const int kUpdateInterval = 200;,便于后续维护和调整。
    • 逻辑微调qInfo 被改为 qDebug。如果这是为了减少日志输出,建议在发布版本中彻底移除或使用条件编译(#ifdef QT_DEBUG),因为 qDebug 在生产环境中通常会被编译掉,但如果是调试关键问题,保留也无妨。
  • 语法逻辑
    • m_iPerent 变量名存在拼写错误,应为 m_iPercent。虽然不影响编译,但影响代码可读性,建议重构。

2. 树形视图整行悬停效果 (datatreeview.cpp/h, itemviewrowhoverproxystyle.cpp/h)

改进点:

  1. 功能实现:通过自定义 QProxyStyle (ItemViewRowHoverProxyStyle) 和重写 drawRow,实现了整行悬停高亮,而不是默认的单元格悬停。这提升了 UI 的一致性和美观度(与整行选中风格保持一致)。
  2. 交互优化:在 mouseMoveEvent 中增加了 updateHoverRowFromPosition 调用,并重写了 leaveEvent,确保鼠标移入、移出时悬停状态能正确更新。
  3. 绘制逻辑
    • 将背景绘制逻辑拆分为斑马纹(zebraBrush)、悬停(hoverRow)和选中(selected)三层,逻辑分层清晰。
    • 使用 QPainterPath 绘制圆角矩形,并使用 setClipPath 确保悬停效果也被裁剪为圆角,细节处理到位。

审查意见:

  • 代码质量
    • 新增的 ItemViewRowHoverProxyStyle 类职责单一,封装良好。
    • 使用 QPointer<DataTreeView> 保存树视图指针,避免了潜在的悬空指针风险(尽管 setParentQCoreApplication 已经保证了生命周期,但 QPointer 是更安全的防御性编程习惯)。
  • 代码性能
    • 潜在性能问题:在 updateHoverRowFromPosition 中,每次鼠标移动都会调用 indexAtviewport()->update()
      • indexAt 在大数据量下可能会有轻微开销,但对于常规文件列表通常可接受。
      • viewport()->update() 会触发整个视口的 paintEvent。如果列表很长且滚动条未动,这会导致重绘开销较大。
      • 建议:可以考虑只重绘受影响的行(旧的 m_hoverRow 和新的 newRow),而不是整个视口。可以使用 viewport()->update(visualRect(oldIndex) | visualRect(newIndex)) 来优化重绘区域。
  • 代码安全
    • drawRow 开头增加了 Q_ASSERT(m_selectionModel) 和空指针检查,这是一个很好的防御性编程实践。
  • 语法逻辑
    • ItemViewRowHoverProxyStyle 的构造函数中,注释提到生命周期由创建者管理,且 setParent(QCoreApplication::instance())。这确保了 Style 不会因为 TreeView 的销毁而意外销毁(因为 Style 是全局共享的潜在对象),逻辑正确。
    • drawRowselectedhoverRow 的判断逻辑互斥(!selected),确保了选中状态优先于悬停状态,符合常规 UI 逻辑。

总结

整体来看,这是一次高质量的代码提交。

  1. 进度条部分修复了功能性 Bug 并引入了合理的性能优化,建议修正变量名拼写错误并提取时间常量。
  2. 树形视图部分实现了复杂的 UI 效果,代码结构清晰,安全性考虑周全。主要优化点在于 updateHoverRowFromPosition 中的重绘范围,可以进一步优化以提升大数据量下的性能。

具体修改建议示例(针对性能优化):

datatreeview.cpp 中:

void DataTreeView::updateHoverRowFromPosition(const QPoint &pos)
{
    const QModelIndex idx = indexAt(pos);
    const int newRow = idx.isValid() ? idx.row() : -1;
    
    // 只有当行号真正改变时才进行更新
    if (newRow != m_hoverRow) {
        // 优化:只重绘受影响的行,而不是整个视口
        // 注意:需要获取旧行的 QModelIndex,如果 m_hoverRow 是 -1 则忽略
        QModelIndex oldIndex;
        if (m_hoverRow >= 0 && model()) {
            // 假设是单列或者第一列决定行高,实际应根据模型结构调整
            // 这里需要一种方式从 row 获取 QModelIndex,可能需要 root index
            oldIndex = model()->index(m_hoverRow, 0, rootIndex());
        }
        
        m_hoverRow = newRow;
        
        QModelIndex newIndex;
        if (m_hoverRow >= 0 && model()) {
            newIndex = model()->index(m_hoverRow, 0, rootIndex());
        }

        if (oldIndex.isValid() || newIndex.isValid()) {
            QRect updateRect;
            if (oldIndex.isValid()) updateRect |= visualRect(oldIndex);
            if (newIndex.isValid()) updateRect |= visualRect(newIndex);
            
            // 增加一点余量以覆盖圆角或边框等绘制区域
            updateRect = updateRect.adjusted(-1, -1, 1, 1);
            viewport()->update(updateRect);
        }
    }
}

注:上述优化代码假设了模型结构,实际应用中可能需要根据 DataModel 的具体实现调整获取 QModelIndex 的方式。

@dengzhongyuan365-dev
Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot Bot commented Apr 28, 2026

This pr force merged! (status: blocked)

@deepin-bot deepin-bot Bot merged commit 133c855 into linuxdeepin:master Apr 28, 2026
16 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