Skip to content

Conversation

@JWWTSL
Copy link
Contributor

@JWWTSL JWWTSL commented Feb 10, 2026

Log: The Popup is rendered on the window's Overlay layer and is not part of the content visual tree. As a result, the tooltip does not follow its anchor item during scrolling or window resizing, causing positional drift. To resolve this, AlertToolTip has been changed from a ToolTip (which uses Popup) to a regular Item, making it part of the content visual tree. This ensures it naturally scrolls with its parent, respects container clipping, and maintains correct positioning at all times.

PMS: bug-341973

Summary by Sourcery

Replace the alert tooltip popup with an in-tree item to keep it correctly positioned with its target and respect container scrolling and clipping.

Bug Fixes:

  • Fix alert tooltip drift by making it part of the content visual tree instead of a window overlay popup.

Enhancements:

  • Add explicit sizing, z-ordering, and optional auto-hide timeout behavior to the alert tooltip component in both QtQuick 2 and Qt 6 implementations.

@deepin-ci-robot
Copy link
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: JWWTSL

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
Copy link

sourcery-ai bot commented Feb 10, 2026

Reviewer's Guide

Replaces AlertToolTip’s ToolTip/Popup-based implementation with a regular Item-based layout in both Qt5 and Qt6 QML, so the tooltip remains within the visual tree, scrolls/clips with its target, and gains explicit sizing and timeout behavior.

Sequence diagram for AlertToolTip visibility and timeout behavior

sequenceDiagram
    actor User
    participant TargetItem
    participant AlertToolTip as AlertToolTip_Item
    participant Timer as AlertToolTip_Timer
    participant ContentView

    User->>TargetItem: Hover or focus causes validation error
    TargetItem-->>ContentView: Request to show AlertToolTip_Item
    ContentView->>AlertToolTip: set target, text, timeout
    ContentView->>AlertToolTip: visible = true
    AlertToolTip->>AlertToolTip: compute y = target.height + spacing
    AlertToolTip->>AlertToolTip: compute implicitWidth, implicitHeight
    AlertToolTip->>Timer: interval = timeout
    AlertToolTip->>Timer: running = timeout > 0 && visible

    loop While ContentView scrolls
        ContentView->>TargetItem: update position within visual tree
        ContentView->>AlertToolTip: layout reflow
        AlertToolTip->>AlertToolTip: y remains relative to target
    end

    Timer-->>AlertToolTip: onTriggered()
    AlertToolTip->>AlertToolTip: visible = false
Loading

Class diagram for updated AlertToolTip Item-based structure (Qt5)

classDiagram
    class AlertToolTip_Qt5 {
        <<Item>>
        Item target
        string text
        font font
        int timeout
        real __naturalWidth
        real x
        real y
        int z
        real implicitWidth
        real implicitHeight
        real width
        real height
    }

    class AlertToolTip_Timer_Qt5 {
        <<Timer>>
        int interval
        bool running
        onTriggered()
    }

    class AlertToolTip_Background_Qt5 {
        <<Item>>
        anchors.fill parent
    }

    class AlertToolTip_Text_Qt5 {
        <<Text>>
        D.Palette textColor
        font font
        string text
        color color
        wrapMode wrapMode
        horizontalAlignment horizontalAlignment
        verticalAlignment verticalAlignment
    }

    class AlertToolTip_Connector_Qt5 {
        <<BoxShadow>>
        D.Palette dropShadowColor
        D.Palette backgroundColor
        real y
        real width
        real height
        real shadowBlur
        real radius
        real offsetX
        real offsetY
        real spread
    }

    AlertToolTip_Qt5 "1" o-- "1" AlertToolTip_Timer_Qt5 : contains
    AlertToolTip_Qt5 "1" o-- "1" AlertToolTip_Background_Qt5 : contains
    AlertToolTip_Qt5 "1" o-- "1" AlertToolTip_Text_Qt5 : contains
    AlertToolTip_Qt5 "1" o-- "1" AlertToolTip_Connector_Qt5 : contains
Loading

Class diagram for updated AlertToolTip Item-based structure (Qt6)

classDiagram
    class AlertToolTip_Qt6 {
        <<Item>>
        Item target
        string text
        font font
        int timeout
        real __naturalWidth
        real x
        real y
        int z
        real implicitWidth
        real implicitHeight
        real width
        real height
    }

    class AlertToolTip_Timer_Qt6 {
        <<Timer>>
        int interval
        bool running
        onTriggered()
    }

    class AlertToolTip_FloatingPanel_Qt6 {
        <<FloatingPanel>>
        anchors.fill parent
        real radius
        real implicitWidth
        real implicitHeight
        D.Palette backgroundColor
        D.Palette insideBorderColor
        D.Palette outsideBorderColor
    }

    class AlertToolTip_Text_Qt6 {
        <<Text>>
        D.Palette textColor
        font font
        string text
        color color
        wrapMode wrapMode
        horizontalAlignment horizontalAlignment
        verticalAlignment verticalAlignment
    }

    class AlertToolTip_Connector_Qt6 {
        <<BoxShadow>>
        D.Palette dropShadowColor
        D.Palette backgroundColor
        D.Palette borderColor
        real y
        real width
        real height
        real shadowBlur
        real radius
        real offsetX
        real offsetY
        real spread
    }

    AlertToolTip_Qt6 "1" o-- "1" AlertToolTip_Timer_Qt6 : contains
    AlertToolTip_Qt6 "1" o-- "1" AlertToolTip_FloatingPanel_Qt6 : contains
    AlertToolTip_Qt6 "1" o-- "1" AlertToolTip_Text_Qt6 : contains
    AlertToolTip_Qt6 "1" o-- "1" AlertToolTip_Connector_Qt6 : contains
Loading

File-Level Changes

Change Details Files
Replace ToolTip (Popup) with an Item-based tooltip that stays in the content visual tree and tracks its target correctly.
  • Change AlertToolTip root from ToolTip to Item in both Qt5 and Qt6 variants and position it relative to the target using y = target.height + spacing and a fixed x origin.
  • Introduce explicit sizing logic using a computed natural width based on style width and text implicit size, clamped to the target width when available, and compute implicit height from text height plus vertical padding.
  • Set a fixed z-order (constant in Qt5, D.DTK.TopOrder in Qt6) so the tooltip appears above content while still remaining inside the visual tree.
src/qml/AlertToolTip.qml
qt6/src/qml/AlertToolTip.qml
Inline the tooltip’s background and text layout instead of using ToolTip’s background/contentItem properties.
  • Wrap the visual content in a child Item (Qt5) or FloatingPanel (Qt6) anchored to fill the parent, replacing the previous background property usage.
  • Configure the inner text element with id contentText, full anchoring with padding margins from DS.Style.alertToolTip, and expose its font via a property alias on the control.
  • Recalculate BoxShadow connector positioning to account for removal of ToolTip padding/margins, simplifying the y offset expression.
src/qml/AlertToolTip.qml
qt6/src/qml/AlertToolTip.qml
Add behavior and API for auto-hide timeouts while removing ToolTip-specific transitions and popup behaviors.
  • Add text, font alias, and timeout properties on the root Item to mirror the old API while supporting the new implementation.
  • Add a Timer driven by the timeout property that hides the tooltip by toggling control.visible when the interval elapses.
  • Remove enter/exit Transition animations, closePolicy, margins, and Popup-related padding properties that no longer apply to the Item-based implementation.
src/qml/AlertToolTip.qml
qt6/src/qml/AlertToolTip.qml

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

@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:

  • With the switch from ToolTip(Popup) to Item, the previous enter/exit transitions were dropped; consider reintroducing a simple slide/fade-in/out via Behaviors or explicit animations on y/opacity to preserve the prior interaction feel.
  • The new Item-based tooltip now relies on visible instead of open()/close() semantics from ToolTip; if existing callers expect the old API, consider providing small helper functions or a wrapper to keep the usage pattern consistent.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- With the switch from ToolTip(Popup) to Item, the previous enter/exit transitions were dropped; consider reintroducing a simple slide/fade-in/out via Behaviors or explicit animations on `y`/`opacity` to preserve the prior interaction feel.
- The new `Item`-based tooltip now relies on `visible` instead of `open()/close()` semantics from `ToolTip`; if existing callers expect the old API, consider providing small helper functions or a wrapper to keep the usage pattern consistent.

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.

@mhduiy mhduiy requested a review from 18202781743 February 10, 2026 07:55
@deepin-ci-robot
Copy link
Contributor

deepin pr auto review

这份代码 diff 主要将 AlertToolTip.qml 从继承自 ToolTip (Popup) 改为继承自 Item。这是一个为了解决滚动和裁剪问题的重构。以下是对代码的语法逻辑、代码质量、代码性能和代码安全的详细审查及改进建议:

1. 语法逻辑与代码质量

优点:

  • 架构变更合理:从 ToolTip (Popup) 改为 Item 确实能解决 Popup 在滚动视图中脱离文档流、无法随内容滚动或被正确裁剪的问题。
  • 属性封装:添加了 texttimeout 属性,使得组件接口更清晰,不再依赖 ToolTip 的内部属性。
  • 自动隐藏逻辑:通过 Timer 实现了 timeout 功能,逻辑清晰 (running: control.timeout > 0 && control.visible)。

问题与建议:

  1. Z-Index 层级不一致

    • Qt6 版本:使用了 z: D.DTK.TopOrder
    • Qt5/QtQuick 2.11 版本:使用了硬编码 z: 100
    • 建议:应保持一致。如果 D.DTK.TopOrder 在 Qt5 版本中不可用,应定义一个统一的常量或使用相同的硬编码值,确保不同版本行为一致。
  2. BoxShadow 的位置计算 (Qt5 版本)

    • 在 Qt5 版本的代码中,BoxShadow (用于连接线/箭头) 被放置在一个匿名的 Item 容器内 (Item { anchors.fill: parent ... BoxShadow { ... } })。
    • 在 Qt6 版本中,BoxShadowFloatingPanel 的兄弟元素。
    • 建议:虽然逻辑上都能工作,但建议保持结构一致。Qt5 版本中多了一层无用的 Item 包装(如果该 Item 仅用于包含 BoxShadow),这会增加布局计算开销。
  3. 连接线 (BoxShadow) 的 Y 轴定位

    • 代码修改了 y: - height * (0.75) - control.topMargin - control.topPaddingy: - height * (0.75)
    • 风险:由于 Item 不像 ToolTip 那样有 padding 属性,现在 padding 是通过 anchors.margins 应用在子元素 Text 上的。背景 FloatingPanel (Qt6) 或 Item (Qt5) 是 anchors.fill: parent 的。这意味着背景是填满整个 control (Item) 的。
    • 问题:连接线现在定位在 control 的顶部边界。如果 controly 坐标是基于 target.height + spacing 计算的,那么连接线是位于 control 顶部,指向 target 的底部。由于 TexttopMargin,视觉上连接线应该是指向背景的上边缘。这个修改看起来是正确的,但需要确保视觉上连接线没有和背景重叠或者出现空隙。
  4. 显式宽度设置

    • 代码中设置了 width: implicitWidthheight: implicitHeight
    • 建议:在 QML 中,如果没有父容器强制定义大小,这通常是必要的。但要注意,如果父容器试图拉伸该组件,这行代码可能会阻止拉伸(除非父容器使用的是 implicitWidth/Height 来布局)。

2. 代码性能

问题与建议:

  1. 不必要的绑定计算

    • __naturalWidth 是一个 readonly property,依赖于 contentText.implicitWidth
    • implicitWidth 依赖于 __naturalWidth
    • contentTextanchors.fill: parent 依赖于 control 的宽高。
    • 建议:这是一个典型的循环依赖风险,虽然 readonlyanchors 通常能处理这种情况,但在文本内容变化频繁时,这会导致多次布局传递。
    • 优化:目前的写法在 QML 中是标准的,但需确保 text 属性变化不会导致过于频繁的重排。对于静态提示框,这通常不是问题。
  2. Timer 的开销

    • Timercontrol.visible 为 true 且 timeout > 0 时运行。
    • 建议:这是正确做法。当不可见时停止,节省资源。

3. 代码安全

问题与建议:

  1. Target 为空时的处理

    • y: target ? target.height + DS.Style.control.spacing : 0
    • implicitWidth: target ? Math.min(__naturalWidth, target.width) : __naturalWidth
    • 建议:代码已经做了三元运算符检查,防止了 target 为 null 时的崩溃,这很好。
  2. 组件销毁时的 Timer

    • TimeronTriggered 调用 control.visible = false
    • 建议:如果 control 在 Timer 触发前被销毁(例如父组件卸载),Qt 会自动处理,通常不会有问题。但如果 control 的生命周期非常复杂,建议在 Component.onDestruction 中停止 Timer。

4. 改进意见汇总

针对 Qt6 版本的具体修改建议:

// ... imports

Item {
    id: control
    property Item target
    property string text
    property alias font: contentText.font
    property int timeout: 0

    // 建议:如果 D.DTK.TopOrder 在旧版本不可用,确保有一个回退值或统一的常量
    z: D.DTK.TopOrder 

    // 建议:使用 Binding 来延迟计算或确保逻辑清晰,但当前写法也可接受
    x: 0
    y: target ? target.height + DS.Style.control.spacing : 0

    readonly property real __naturalWidth: Math.max(DS.Style.alertToolTip.width,
                                                    contentText.implicitWidth + DS.Style.alertToolTip.horizontalPadding * 2)
    // 注意:这里隐含了如果 target 存在,宽度不能超过 target.width
    implicitWidth: target ? Math.min(__naturalWidth, target.width) : __naturalWidth
    implicitHeight: Math.max(DS.Style.alertToolTip.height,
                             contentText.implicitHeight + DS.Style.alertToolTip.verticalPadding * 2)
    
    // 显式设置尺寸
    width: implicitWidth
    height: implicitHeight

    // Timer 逻辑良好,无需修改
    Timer {
        interval: control.timeout
        running: control.timeout > 0 && control.visible
        onTriggered: control.visible = false
    }

    // 背景面板
    FloatingPanel {
        id: backgroundPanel
        anchors.fill: parent
        // ... 属性保持不变 ...
    }

    // 文本内容
    Text {
        id: contentText
        // ... 属性保持不变 ...
        // 建议:确保 wrapMode 配合 width 约束能正确换行
    }

    // 连接线
    BoxShadow {
        id: line
        // ...
        // y: - height * (0.75) 
        // 建议:确认视觉位置。由于背景是 anchors.fill parent,且 Text 有 topMargin。
        // 如果背景有圆角,可能需要微调 y 值使其看起来是连接在背景顶部边缘的中间。
        // 例如:y: -height / 2 可能更居中,具体取决于 height * 0.75 的几何含义。
    }
}

针对 Qt5 版本的具体修改建议:

// ... imports

Item {
    id: control
    // ... properties ...

    // 建议:统一 z-index 处理
    z: 100 // 或者引入 DTK 常量

    // ... layout logic ...

    // 建议:移除多余的 Item 包装,直接使用 BoxShadow 作为兄弟元素,类似于 Qt6 版本的结构
    // 除非这个 Item 容器有特殊的裁剪或定位需求。
    
    // 当前代码:
    // Item {
    //     anchors.fill: parent
    //     BoxShadow { ... } // 背景
    //     BoxShadow { ... } // 边框
    // }
    
    // 建议改为直接放置(如果不需要额外容器):
    BoxShadow {
        id: backgroundShadow
        anchors.fill: _background // 确保 _background 是正确定义的 Rectangle 或者 Item
        // ...
    }
    
    // ... Text ...

    // ... Connector BoxShadow ...
}

总结

这次改动整体是积极的,解决了 ToolTip 在滚动视图中的核心痛点。

  1. 安全性:对 target 的空值检查做得很好。
  2. 逻辑:从 Popup 到 Item 的转变逻辑自洽,Timer 实现了自动关闭。
  3. 一致性:主要问题在于 Qt5 和 Qt6 版本实现细节(如背景容器结构、z-index 定义)的不一致,建议在后续迭代中统一。
  4. 性能:布局绑定稍微复杂,但在 UI 组件中可接受范围。

建议开发者重点测试连接线在不同 target 高度和不同文本长度下的视觉对齐情况,以及滚动时的性能表现。

ToolTip {
// Use Item instead of ToolTip(Popup) so it stays in the visual tree,
// scrolls with content and gets clipped properly.
Item {
Copy link
Contributor

Choose a reason for hiding this comment

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

你这是自己写了个ToolTip呀,之后测试要是提了个ToolTip跟随移动的话怎么整,

ToolTip {
// Use Item instead of ToolTip(Popup) so it stays in the visual tree,
// scrolls with content and gets clipped properly.
Item {
Copy link
Contributor

Choose a reason for hiding this comment

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

这个是dtk5的qml,我们目前可以不处理,

Log: The Popup is rendered on the window's Overlay layer and is not part of the content visual tree. As a result, the tooltip does not follow its anchor item during scrolling or window resizing, causing positional drift. To resolve this, AlertToolTip has been changed from a ToolTip (which uses Popup) to a regular Item, making it part of the content visual tree. This ensures it naturally scrolls with its parent, respects container clipping, and maintains correct positioning at all times.

PMS: bug-341973
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