Skip to content

Conversation

@deepin-ci-robot
Copy link
Contributor

@deepin-ci-robot deepin-ci-robot commented Dec 26, 2025

Synchronize source files from linuxdeepin/dtkdeclarative.

Source-pull-request: linuxdeepin/dtkdeclarative#554

Summary by Sourcery

Update the progress bar QML implementation to improve the highlight sweep animation and visual masking for both determinate and indeterminate modes.

Enhancements:

  • Replace timer-based light sweep logic with a reusable animation component shared between determinate and indeterminate progress bars.
  • Adjust progress bar masking and layout to preserve rounded corners and avoid visual artifacts at narrow widths.

@deepin-ci-robot
Copy link
Contributor Author

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: deepin-ci-robot

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 Dec 26, 2025

Reviewer's Guide

Refactors the ProgressBar QML implementation to use an opacity-masked, radius-safe filled track and replaces ad‑hoc timer-based highlight animations with a reusable color/position sweep animation component, adjusting both determinate and indeterminate modes and updating the BoxShadow layout.

Sequence diagram for reusable light sweep animation in ProgressBar

sequenceDiagram
    participant ProgressBarImpl
    participant DeterminateRect
    participant IndeterminateRect
    participant LightSweepAnimationComponent
    participant DeterminateLightAnimLoader
    participant IndeterminateLightAnimLoader
    participant LightSweepAnimation

    ProgressBarImpl->>DeterminateLightAnimLoader: create Loader(sourceComponent = lightSweepAnimation)
    DeterminateLightAnimLoader->>LightSweepAnimationComponent: instantiate
    LightSweepAnimationComponent-->>DeterminateLightAnimLoader: instance LightSweepAnimation
    DeterminateLightAnimLoader->>LightSweepAnimation: set targetItem = DeterminateRect
    DeterminateLightAnimLoader->>LightSweepAnimation: running = true

    loop Animation_infinite
        par Color_sweep
            LightSweepAnimation->>DeterminateRect: gradientColor from highlight to handleGradientColor
            LightSweepAnimation->>DeterminateRect: pause
            LightSweepAnimation->>DeterminateRect: gradientColor from handleGradientColor to highlight
        and Position_sweep
            LightSweepAnimation->>DeterminateRect: lightPosition 0 to 1 (InOutSine)
        end
        LightSweepAnimation->>DeterminateRect: pause
    end

    Note over ProgressBarImpl,IndeterminateRect: Indeterminate mode uses same Component with different running condition

    ProgressBarImpl->>IndeterminateLightAnimLoader: create Loader(sourceComponent = lightSweepAnimation)
    IndeterminateLightAnimLoader->>LightSweepAnimationComponent: instantiate
    LightSweepAnimationComponent-->>IndeterminateLightAnimLoader: instance LightSweepAnimation
    IndeterminateLightAnimLoader->>LightSweepAnimation: set targetItem = IndeterminateRect
    ProgressBarImpl->>LightSweepAnimation: running = progressBar.indeterminate && !control.animationStop
Loading

Class diagram for refactored ProgressBar QML structure

classDiagram
    class ProgressBarImpl {
    }

    class BoxShadowFilledTrack {
        +anchors_fill_parent
        +anchors_rightMargin
        +shadowOffsetY
        +shadowBlur
        +cornerRadius
        +shadowColor
        +visible
    }

    class DeterminateItem {
        +x
        +width
        +height
    }

    class DeterminateRect {
        +gradientColor
        +lightPosition
        +width
        +height
        +radius
        +layer_enabled
        +clip
    }

    class DeterminateLightAnimLoader {
        +sourceComponent
        +item
    }

    class DeterminateOuterMaskItem {
        +layer_enabled
    }

    class DeterminateOuterMaskRect {
        +width
        +height
        +radius
    }

    class IndeterminateRect {
        +lightPosition
        +gradientColor
        +radius
    }

    class IndeterminateLightAnimLoader {
        +sourceComponent
        +item
    }

    class LightSweepAnimationComponent {
    }

    class LightSweepAnimation {
        +targetItem
        +loops
        +running
    }

    class LightSweepColorAnimationForward {
        +target
        +property_gradientColor
        +from_highlight
        +to_handleGradientColor
        +duration
    }

    class LightSweepColorAnimationBackward {
        +target
        +property_gradientColor
        +from_handleGradientColor
        +to_highlight
        +duration
    }

    class LightSweepNumberAnimation {
        +target
        +property_lightPosition
        +from
        +to
        +duration
        +easing_InOutSine
    }

    ProgressBarImpl o-- BoxShadowFilledTrack
    ProgressBarImpl o-- DeterminateItem
    DeterminateItem o-- DeterminateRect
    DeterminateRect o-- DeterminateLightAnimLoader
    DeterminateItem o-- DeterminateOuterMaskItem
    DeterminateOuterMaskItem o-- DeterminateOuterMaskRect

    ProgressBarImpl o-- IndeterminateRect
    IndeterminateRect o-- IndeterminateLightAnimLoader

    ProgressBarImpl o-- LightSweepAnimationComponent
    LightSweepAnimationComponent o-- LightSweepAnimation
    LightSweepAnimation o-- LightSweepColorAnimationForward
    LightSweepAnimation o-- LightSweepColorAnimationBackward
    LightSweepAnimation o-- LightSweepNumberAnimation

    DeterminateLightAnimLoader --> LightSweepAnimationComponent : loads
    IndeterminateLightAnimLoader --> LightSweepAnimationComponent : loads

    LightSweepAnimation --> DeterminateRect : animates
    LightSweepAnimation --> IndeterminateRect : animates
Loading

File-Level Changes

Change Details Files
Rework the determinate progress bar fill and shadow layout, and switch its highlight effect from a local timer loop to a shared light sweep animation component.
  • Change BoxShadow to use anchors.fill with rightMargin based on visualPosition and adjust shadow direction by using shadowOffsetY instead of rotation and manual geometry.
  • Introduce an inner Item wrapper that horizontally offsets by its height to avoid rounded-corner glitches when the bar is narrow and extends its width beyond the progress width.
  • Replace the previous Rectangle fill that relied on anchors and a Timer with a fixed-size Rectangle that exposes gradientColor and lightPosition properties and uses a Gradient with Horizontal orientation and an OpacityMask-based rounded-corner clipping.
  • Load the shared light sweep animation via Loader, binding its targetItem to the determinate fill rectangle and enabling the animation when loaded.
qt6/src/qml/private/ProgressBarImpl.qml
Unify the indeterminate progress bar highlight effect with the new shared light sweep animation component instead of a local Timer loop.
  • Refactor the indeterminate Rectangle to use lightPosition and gradientColor properties in its Gradient stops without local count state.
  • Remove the bespoke Timer-based stepping logic and hook up the shared lightSweepAnimation via Loader, starting it only when the progress bar is indeterminate and animations are not stopped.
qt6/src/qml/private/ProgressBarImpl.qml
Introduce a reusable lightSweepAnimation component that animates both gradient color and light position for progress bar highlights.
  • Add a Component wrapping a SequentialAnimation with a targetItem property for generic reuse on any Rectangle with gradientColor and lightPosition properties.
  • Within the animation, combine a SequentialAnimation of ColorAnimations and PauseAnimation to sweep gradientColor between highlight and handleGradientColor, and a parallel NumberAnimation that animates lightPosition from 0 to 1 with InOutSine easing.
  • Configure the animation to loop infinitely with pauses between sweeps to create a repeating but non-constant highlight motion.
qt6/src/qml/private/ProgressBarImpl.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 found 1 issue, and left some high level feedback:

  • Both Loader elements are given the id lightAnimLoader within the same QML component, which will cause an id conflict; give them distinct ids (e.g. determinateLightLoader and indeterminateLightLoader).
  • The lightSweepAnimation component assumes its targetItem defines gradientColor and lightPosition; consider adding a null/hasOwnProperty guard before starting animations in onLoaded to avoid runtime errors if it’s reused elsewhere.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Both `Loader` elements are given the id `lightAnimLoader` within the same QML component, which will cause an id conflict; give them distinct ids (e.g. `determinateLightLoader` and `indeterminateLightLoader`).
- The `lightSweepAnimation` component assumes its `targetItem` defines `gradientColor` and `lightPosition`; consider adding a null/`hasOwnProperty` guard before starting animations in `onLoaded` to avoid runtime errors if it’s reused elsewhere.

## Individual Comments

### Comment 1
<location> `qt6/src/qml/private/ProgressBarImpl.qml:58-59` </location>
<code_context>
-                                moveTimer.interval = 2000
-                                return;
+
+                    Loader {
+                        id: lightAnimLoader
+                        sourceComponent: lightSweepAnimation
+                        onLoaded: {
</code_context>

<issue_to_address>
**suggestion (bug_risk):** Use a binding for `running` instead of setting it imperatively in `onLoaded` so it reacts to state changes.

`lightAnimLoader.item.running` is only set once in `onLoaded`, so changes to `rect.visible` (or other conditions) won’t affect the animation, unlike the previous `Timer { running: rect.visible }` behavior. Move this logic into the animation itself (e.g. bind `running` to `rect.visible && !control.animationStop`), or expose a bindable `running` here instead of assigning it imperatively.
</issue_to_address>

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
Contributor Author

deepin pr auto review

我来对这段代码进行审查:

  1. 代码逻辑和结构改进:
  • 代码重构良好,将原来的Timer动画逻辑抽象成了LightSweepAnimation组件,提高了代码复用性
  • 使用了QML6的component语法,使得组件定义更加清晰
  • 动画控制逻辑更加合理,使用了SequentialAnimation和ParallelAnimation的组合
  1. 性能优化建议:
  • 建议在LightSweepAnimation组件中添加enabled属性,在不使用时完全禁用动画,避免不必要的性能开销
  • 可以考虑将gradientColor属性的动画改为使用PropertyAnimation而不是ColorAnimation,因为PropertyAnimation通常更轻量
  1. 安全性改进:
  • 代码中缺少对targetItem为null的检查,建议在LightSweepAnimation中添加防护:
component LightSweepAnimation: SequentialAnimation{
    property Item targetItem: null
    running: targetItem !== null && targetItem.visible
    
    // ... 其他代码
}
  1. 代码质量建议:
  • LightSweepAnimation组件中的动画持续时间(500ms, 2000ms, 3000ms)应该定义为可配置的属性,而不是硬编码
  • 建议为动画添加缓动函数(easing.type)的配置选项
  • 可以考虑将LightSweepAnimation移到单独的文件中,提高代码的可维护性
  1. 其他改进建议:
  • 在渐变动画中,建议使用Qt.rgba()来定义颜色,这样可以更好地控制透明度
  • 考虑添加动画状态变化的信号,方便外部组件监听
  • 建议为动画添加启动和停止的过渡效果,使动画更加平滑
  1. 具体代码改进建议:
component LightSweepAnimation: SequentialAnimation {
    id: anim
    property Item targetItem: null
    property int transitionDuration: 500
    property int pauseDuration: 2000
    property int sweepDuration: 3000
    property color fromColor: progressBar.palette.highlight
    property color toColor: control.D.ColorSelector.handleGradientColor
    property bool enabled: true
    
    running: enabled && targetItem !== null && targetItem.visible
    
    ParallelAnimation {
        SequentialAnimation {
            PropertyAnimation {
                target: anim.targetItem
                property: "gradientColor"
                from: anim.fromColor
                to: anim.toColor
                duration: anim.transitionDuration
            }
            PauseAnimation { duration: anim.pauseDuration }
            PropertyAnimation {
                target: anim.targetItem
                property: "gradientColor"
                from: anim.toColor
                to: anim.fromColor
                duration: anim.transitionDuration
            }
        }

        NumberAnimation {
            target: anim.targetItem
            property: "lightPosition"
            from: 0
            to: 1
            duration: anim.sweepDuration
            easing.type: Easing.InOutSine
        }
    }

    PauseAnimation { duration: anim.pauseDuration }
}

这些改进将使代码更加健壮、可维护,并提供了更好的性能和灵活性。

Synchronize source files from linuxdeepin/dtkdeclarative.

Source-pull-request: linuxdeepin/dtkdeclarative#554
@mhduiy mhduiy merged commit b589d3c into master Dec 29, 2025
13 of 16 checks passed
@mhduiy mhduiy deleted the sync-pr-554-nosync branch December 29, 2025 09:07
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