Skip to content

Conversation

@caixr23
Copy link
Contributor

@caixr23 caixr23 commented Jan 30, 2026

  1. Added isIndicatorShown() method to detect "indicator=false" command
  2. Modified doShowPage() to conditionally show indicators based on command
  3. Updated activeItemChanged signal to include indicator visibility state
  4. Enhanced QML components with isIndicatorShown property and conditional rendering
  5. Added timing control in power plugin to prevent indicator flickering during quick page transitions

Log: Added control for indicator display during page navigation

Influence:

  1. Test page navigation with and without "indicator=false" parameter
  2. Verify indicator visibility during quick page transitions
  3. Check power plugin's repeat days and custom time settings
  4. Test that normal page navigation still shows indicators correctly
  5. Verify that indicator hiding doesn't affect other UI functionality

feat: 增加指示器显示控制功能

  1. 添加 isIndicatorShown() 方法检测 "indicator=false" 命令
  2. 修改 doShowPage() 方法根据命令条件性显示指示器
  3. 更新 activeItemChanged 信号包含指示器可见性状态
  4. 增强 QML 组件添加 isIndicatorShown 属性和条件渲染
  5. 在电源插件中添加时序控制防止快速页面切换时的指示器闪烁

Log: 新增页面导航时的指示器显示控制

Influence:

  1. 测试带和不带 "indicator=false" 参数的页面导航
  2. 验证快速页面切换时的指示器可见性
  3. 检查电源插件的重复天数和自定义时间设置
  4. 测试正常页面导航仍正确显示指示器
  5. 验证指示器隐藏不影响其他 UI 功能

PMS: BUG-291067

Summary by Sourcery

Add configurable control over the right-side selection indicator during page navigation and apply it to prevent flicker in power settings pages.

New Features:

  • Allow callers to control whether the selection indicator is shown via an "indicator=false" command parameter.
  • Expose indicator visibility state to QML views through an updated activeItemChanged signal and per-panel isIndicatorShown property.

Bug Fixes:

  • Prevent indicator flickering during rapid page transitions in the power plugin's scheduled shutdown repeat settings.

Enhancements:

  • Centralize indicator visibility logic in DccManager via an isIndicatorShown helper and respect it when deciding whether to show the control center window.

@sourcery-ai
Copy link

sourcery-ai bot commented Jan 30, 2026

Reviewer's Guide

Adds a command-based mechanism to control whether the page highlight indicator is shown during navigation, and wires this through the DccManager, DccApp active item signal, QML right/settings views, and the power plugin’s scheduled-shutdown pages to avoid flicker on quick transitions.

Sequence diagram for page navigation with optional indicator display

sequenceDiagram
    actor User
    participant GeneralPage_repeatDays as GeneralPage_repeatDays
    participant DccApp as DccApp
    participant DccManager as DccManager
    participant DccRightView as DccRightView_panel
    participant DccSettingsView as DccSettingsView_panel
    participant obj as obj

    User->>GeneralPage_repeatDays: Change shutdownRepetition quickly
    activate GeneralPage_repeatDays
    GeneralPage_repeatDays->>GeneralPage_repeatDays: onVisibleChanged visible=true
    GeneralPage_repeatDays->>GeneralPage_repeatDays: showTime = now
    deactivate GeneralPage_repeatDays

    User->>GeneralPage_repeatDays: Open repeatDaysEdit quickly
    activate GeneralPage_repeatDays
    GeneralPage_repeatDays->>DccApp: showPage(dccObj, indicator=false)
    deactivate GeneralPage_repeatDays

    activate DccApp
    DccApp->>DccManager: doShowPage(obj, cmd)
    deactivate DccApp

    activate DccManager
    DccManager->>DccManager: indicatorShown = isIndicatorShown(cmd)
    alt indicatorShown and cmd not empty
        DccManager-->>obj: active(cmd)
        DccManager-->>DccRightView: activeItemChanged(parentItem, true)
        DccManager-->>DccSettingsView: activeItemChanged(parentItem, true)
    else indicatorShown is false or cmd empty
        DccManager-->>DccRightView: activeItemChanged(parentItem, indicatorShown)
        DccManager-->>DccSettingsView: activeItemChanged(parentItem, indicatorShown)
    end
    deactivate DccManager

    activate DccRightView
    DccRightView->>DccRightView: panel.item = item
    DccRightView->>DccRightView: panel.isIndicatorShown = isIndicatorShown
    DccRightView->>DccRightView: Timer onTriggered
    alt panel.isIndicatorShown
        DccRightView->>DccRightView: Update panel geometry
        DccRightView->>DccRightView: panel.visible = cnt & 1
    else indicator hidden
        DccRightView->>DccRightView: Skip geometry and visibility update
        DccRightView->>DccRightView: panel.visible remains false
    end
    deactivate DccRightView

    activate DccSettingsView
    DccSettingsView->>DccSettingsView: Same handling as DccRightView
    deactivate DccSettingsView
Loading

Class diagram for updated DccManager and indicator control

classDiagram
    class DccManager {
        - QSet~QString~ m_hideModule
        + void waitShowPage(QString url, QDBusMessage message)
        + void doShowPage(DccObject *obj, QString cmd)
        + bool eventFilter(QObject *watched, QEvent *event)
        + bool isIndicatorShown(QString cmd) const
        + QVector~DccObject*~ findObjects(QString url, bool onlyRoot, bool one)
        + DccObject * findParent(DccObject *obj)
        + void saveSize()
        + void activeItemChanged(QQuickItem *item, bool isIndicatorShown)
    }

    class DccRightView_Panel {
        + var item
        + int cnt
        + bool isIndicatorShown
        + int x
        + int y
        + int width
        + int height
        + bool visible
        + Timer timer
    }

    class DccSettingsView_Panel {
        + var item
        + int cnt
        + bool isIndicatorShown
        + int x
        + int y
        + int width
        + int height
        + bool visible
        + Timer timer
    }

    class GeneralPage_repeatDays {
        + real showTime
        + bool visible
        + void onVisibleChanged()
    }

    class GeneralPage_repeatDaysEdit {
        + bool forceShow
        + real showTime
        + bool visible
        + void onVisibleChanged()
    }

    DccManager ..> DccRightView_Panel : emits activeItemChanged
    DccManager ..> DccSettingsView_Panel : emits activeItemChanged
    DccRightView_Panel --> DccManager : depends_on_indicator_state
    DccSettingsView_Panel --> DccManager : depends_on_indicator_state
    GeneralPage_repeatDays --> DccManager : uses_showPage_indicator_false
    GeneralPage_repeatDaysEdit --> DccManager : uses_showPage_indicator_false
Loading

File-Level Changes

Change Details Files
Introduce an isIndicatorShown command helper and use it in page showing logic to gate window showing and activation behavior.
  • Add DccManager::isIndicatorShown(const QString &cmd) to interpret the "indicator=false" command flag.
  • Change waitShowPage to only call show() when the indicator is enabled or when there is no command parameter.
  • Update doShowPage to compute an indicatorShown flag once, use it to decide whether to emit the obj->active(cmd) shortcut path, and pass the flag along when emitting activeItemChanged.
src/dde-control-center/dccmanager.cpp
src/dde-control-center/dccmanager.h
Propagate indicator visibility state through the activeItemChanged signal to the right/settings views and conditionally render the highlight panel.
  • Extend the activeItemChanged signal to carry a bool isIndicatorShown parameter and update its usages.
  • Add an isIndicatorShown property on the highlight panel objects in DccRightView.qml and DccSettingsView.qml.
  • Modify the highlight animation timer logic in both views to position and toggle visibility of the panel only when isIndicatorShown is true, and reset the flag when hiding.
src/dde-control-center/dccmanager.h
src/dde-control-center/dccmanager.cpp
src/dde-control-center/plugin/DccRightView.qml
src/dde-control-center/plugin/DccSettingsView.qml
Add timing-based control in the power plugin’s scheduled-shutdown repeat-day pages to suppress indicator display during very fast page switches.
  • Add showTime properties on the repeatDays and repeatDaysEdit DccObjects to record when the item becomes visible.
  • On visible changes, capture the current timestamp so that subsequent initialization code can measure how long the page has been shown.
  • In the ComboBox and edit page Component.onCompleted handlers, if the time since showTime is under 300ms, navigate using DccApp.showPage with the "indicator=false" command to skip indicator display on rapid transitions.
src/plugin-power/qml/GeneralPage.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 2 issues, and left some high level feedback:

  • In the new QML Component.onCompleted handlers (for the repeat combo and repeatDaysEdit), the local time variable is never used and can be removed to simplify the code.
  • The isIndicatorShown(const QString &cmd) check only matches the exact string "indicator=false"; if cmd can contain multiple parameters or different formatting, consider parsing it or using a more robust check (e.g. searching for a key/value pair) so indicator control is consistent.
  • The change in waitShowPage from if (cmd.isEmpty()) show(); to if (!isIndicatorShown(cmd) || cmd.isEmpty()) show(); subtly alters when the window is shown; it may be worth revalidating the intended behavior when commands other than indicator=false are passed to avoid regressions in window visibility.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the new QML `Component.onCompleted` handlers (for the repeat combo and repeatDaysEdit), the local `time` variable is never used and can be removed to simplify the code.
- The `isIndicatorShown(const QString &cmd)` check only matches the exact string "indicator=false"; if `cmd` can contain multiple parameters or different formatting, consider parsing it or using a more robust check (e.g. searching for a key/value pair) so indicator control is consistent.
- The change in `waitShowPage` from `if (cmd.isEmpty()) show();` to `if (!isIndicatorShown(cmd) || cmd.isEmpty()) show();` subtly alters when the window is shown; it may be worth revalidating the intended behavior when commands other than `indicator=false` are passed to avoid regressions in window visibility.

## Individual Comments

### Comment 1
<location> `src/plugin-power/qml/GeneralPage.qml:241-250` </location>
<code_context>
         }

         DccObject {
+            property real showTime: 0
             name: "repeatDays"
             parentName: "power/general/shutdownGroup"
</code_context>

<issue_to_address>
**nitpick:** The timing logic for `showTime` likely wants to use a consistent timestamp variable instead of multiple `new Date().getTime()` calls, and avoid the unused `time` variable.

In `Component.onCompleted`, `var time = new Date().getTime()` is declared but not used, and `new Date().getTime()` is called again in the condition. This is slightly inefficient and can introduce minor timing inconsistencies with `showTime`. Please either reuse `time` in the condition (e.g. `if (dccData.model.shutdownRepetition !== 3 && time - dccObj.showTime < 300)`) or remove the local variable if it’s unnecessary.
</issue_to_address>

### Comment 2
<location> `src/plugin-power/qml/GeneralPage.qml:293-297` </location>
<code_context>
         }
         DccObject {
             id: repeatDaysEditObject
             property bool forceShow: false
+            property real showTime: 0
             name: "repeatDaysEdit"
</code_context>

<issue_to_address>
**issue (bug_risk):** `repeatDaysEditObject.showTime` is never used and the code still references `dccObj.showTime`, which looks inconsistent with the new property.

`repeatDaysEditObject.showTime` is set in `onVisibleChanged`, but the inner `Component.onCompleted` still uses `dccObj.showTime`. That leaves the new property unused and keeps the timing check tied to `dccObj`’s visibility. If the timing is meant to follow `repeatDaysEditObject` becoming visible, update the condition to use `repeatDaysEditObject.showTime`; otherwise remove the new property to avoid dead code.
</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.

Comment on lines 241 to 250
property real showTime: 0
name: "repeatDays"
parentName: "power/general/shutdownGroup"
visible: dccData.model.scheduledShutdownState
displayName: qsTr("Repeat")
weight: 3
pageType: DccObject.Editor
onVisibleChanged: {
if (visible) {
showTime = new Date().getTime()
Copy link

Choose a reason for hiding this comment

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

nitpick: The timing logic for showTime likely wants to use a consistent timestamp variable instead of multiple new Date().getTime() calls, and avoid the unused time variable.

In Component.onCompleted, var time = new Date().getTime() is declared but not used, and new Date().getTime() is called again in the condition. This is slightly inefficient and can introduce minor timing inconsistencies with showTime. Please either reuse time in the condition (e.g. if (dccData.model.shutdownRepetition !== 3 && time - dccObj.showTime < 300)) or remove the local variable if it’s unnecessary.

Comment on lines 293 to 298
property bool forceShow: false
property real showTime: 0
name: "repeatDaysEdit"
parentName: "power/general/shutdownGroup"
visible: (dccData.model.scheduledShutdownState && dccData.model.shutdownRepetition === 3)
Copy link

Choose a reason for hiding this comment

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

issue (bug_risk): repeatDaysEditObject.showTime is never used and the code still references dccObj.showTime, which looks inconsistent with the new property.

repeatDaysEditObject.showTime is set in onVisibleChanged, but the inner Component.onCompleted still uses dccObj.showTime. That leaves the new property unused and keeps the timing check tied to dccObj’s visibility. If the timing is meant to follow repeatDaysEditObject becoming visible, update the condition to use repeatDaysEditObject.showTime; otherwise remove the new property to avoid dead code.

@caixr23 caixr23 force-pushed the BUG-291067 branch 7 times, most recently from 12681de to 9fe09a8 Compare January 31, 2026 08:52
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: caixr23, mhduiy

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. Added isIndicatorShown() method to detect "indicator=false" command
2. Modified doShowPage() to conditionally show indicators based on
command
3. Updated activeItemChanged signal to include indicator visibility
state
4. Enhanced QML components with isIndicatorShown property and
conditional rendering
5. Added timing control in power plugin to prevent indicator flickering
during quick page transitions

Log: Added control for indicator display during page navigation

Influence:
1. Test page navigation with and without "indicator=false" parameter
2. Verify indicator visibility during quick page transitions
3. Check power plugin's repeat days and custom time settings
4. Test that normal page navigation still shows indicators correctly
5. Verify that indicator hiding doesn't affect other UI functionality

feat: 增加指示器显示控制功能

1. 添加 isIndicatorShown() 方法检测 "indicator=false" 命令
2. 修改 doShowPage() 方法根据命令条件性显示指示器
3. 更新 activeItemChanged 信号包含指示器可见性状态
4. 增强 QML 组件添加 isIndicatorShown 属性和条件渲染
5. 在电源插件中添加时序控制防止快速页面切换时的指示器闪烁

Log: 新增页面导航时的指示器显示控制

Influence:
1. 测试带和不带 "indicator=false" 参数的页面导航
2. 验证快速页面切换时的指示器可见性
3. 检查电源插件的重复天数和自定义时间设置
4. 测试正常页面导航仍正确显示指示器
5. 验证指示器隐藏不影响其他 UI 功能

PMS: BUG-291067
@caixr23
Copy link
Contributor Author

caixr23 commented Jan 31, 2026

/forcemerge

@deepin-bot
Copy link

deepin-bot bot commented Jan 31, 2026

This pr force merged! (status: blocked)

@deepin-bot deepin-bot bot merged commit ea23ba4 into linuxdeepin:master Jan 31, 2026
15 of 18 checks passed
@deepin-ci-robot
Copy link

deepin pr auto review

这份代码审查主要针对提供的 git diff,我会从语法逻辑、代码质量、代码性能和代码安全四个方面进行分析。

1. 语法逻辑

优点:

  • 新增函数 isIndicatorShown:将 cmd == "indicator=true" 的判断逻辑封装成独立函数,提高了代码的可读性和复用性。
  • 信号参数扩展activeItemChanged 信号增加了 isIndicatorShown 参数,使得 UI 层(QML)能够根据命令类型决定是否显示指示器(panel),逻辑上是通顺的。
  • QML 属性绑定:在 DccRightView.qmlDccSettingsView.qml 中,通过 Connections 正确监听了 activeItemChanged 信号并更新了 panel.isIndicatorShown 属性。

问题与建议:

  • Magic String(魔术字符串):在 dccmanager.cpp 中,"indicator=true" 是硬编码的字符串。如果未来需要修改这个命令格式,或者支持更多参数,需要修改多处。建议定义一个常量,例如:
    // dccmanager.h 或 dccmanager.cpp
    const QString INDICATOR_CMD_FLAG = "indicator=true";
  • 字符串拼接逻辑:在 searchmodel.cpp 中,return data->sourceUrl() + "?indicator=true"; 直接拼接 URL 和查询参数。如果 sourceUrl() 本身已经包含查询参数(例如 ?a=1),这会导致 URL 格式错误(变成 ...?a=1?indicator=true)。虽然目前可能不存在这种情况,但为了健壮性,建议使用 QUrlQuery 进行处理:
    QUrl url(data->sourceUrl());
    QUrlQuery query(url);
    query.addQueryItem("indicator", "true");
    url.setQuery(query);
    return url.toString();

2. 代码质量

优点:

  • 复用性isIndicatorShown 函数被复用,避免了重复代码。
  • 逻辑分离:将指示器显示的逻辑从单纯的命令判断中分离出来,使得 doShowPage 等函数的逻辑更清晰。

问题与建议:

  • 变量命名一致性:在 dccmanager.cpp 中,局部变量命名为 indicatorShown (驼峰式),而在 QML 中属性命名为 isIndicatorShown (Pascal/布尔问句形式)。虽然 C++ 和 QML 有各自的命名习惯,但作为同一个概念在两边传递,保持一致(例如都用 indicatorShown)或者严格遵循各自语言的规范(C++ 用 isIndicatorShown,QML 用 indicatorShown)会更好。目前的混用可能会造成轻微的认知负担。
  • QML 代码重复DccRightView.qmlDccSettingsView.qml 中关于 panel 的更新逻辑几乎完全相同。建议将这部分逻辑抽取成一个独立的 QML 组件(例如 HighlightPanel.qml),通过属性绑定来控制,以减少重复代码。

3. 代码性能

优点:

  • 字符串比较isIndicatorShown 内部使用 QStringoperator==,对于短字符串来说性能开销极小,可以忽略。

问题与建议:

  • 频繁的坐标计算:在 QML 的 onTriggered 定时器回调中,每次都会调用 panel.item.mapToItem(...) 进行坐标计算。虽然这是动画所必需的,但建议确保 panel.item 在动画过程中是有效的,避免空指针导致的崩溃或性能抖动。
  • URL 构建开销:在 searchmodel.cppdata 函数中,如果使用 QUrlQUrlQuery 重写 URL 拼接逻辑(如上所述),会带来微小的对象构造开销。考虑到这是在 Model 数据获取时调用,通常频率不是极高,为了代码健壮性,这个性能开销是可以接受的。

4. 代码安全

问题与建议:

  • 潜在的空指针解引用:在 dccmanager.cppwaitShowPagedoShowPage 中,虽然有 if (obj) 的检查,但在 isIndicatorShown(cmd) 被调用时,cmd 是作为参数传入的。如果调用方传入了一个非空但格式异常的 cmd,目前的逻辑只是简单地判断是否等于特定字符串,相对安全。
  • URL 注入风险:如果 data->sourceUrl() 的来源不可信(例如来自外部输入),直接拼接字符串可能会导致 URL 注入或 XSS(如果在 Web 环境下渲染)。虽然这是控制中心应用,风险较低,但使用 QUrl 进行标准化处理是一个良好的防御性编程习惯。
  • QML 对象生命周期:在 DccRightView.qmlDccSettingsView.qml 中,panel.item 被赋值。如果 item 被销毁而 panel 仍然持有引用,可能会导致访问野指针。虽然 Connections 通常会处理连接断开,但在复杂的 UI 交互中,建议在 onDestruction 或适当的生命周期钩子中将 panel.item 置为 undefined

总结与改进代码示例

建议修改 searchmodel.cpp 中的 URL 拼接逻辑:

// searchmodel.cpp
#include <QUrl>
#include <QUrlQuery>

// ... 在 data 函数中 ...
case SearchModel::SearchUrlRole: {
    QUrl url(data->sourceUrl());
    if (url.isValid()) {
        QUrlQuery query(url);
        // 只有当不存在该参数时才添加,避免重复
        if (!query.hasQueryItem("indicator")) {
            query.addQueryItem("indicator", "true");
            url.setQuery(query);
        }
    }
    return url.isValid() ? url.toString() : data->sourceUrl();
}

建议定义常量以避免 Magic String:

// dccmanager.h
class DccManager : public QObject {
    // ...
private:
    static const QString INDICATOR_CMD_FLAG;
    // ...
};

// dccmanager.cpp
const QString DccManager::INDICATOR_CMD_FLAG = "indicator=true";

bool DccManager::isIndicatorShown(const QString &cmd) const
{
    return cmd == INDICATOR_CMD_FLAG;
}

关于 QML 的建议:
虽然重构 QML 组件超出了本次 diff 的范围,但建议在后续维护中考虑将 panel 的相关逻辑封装。目前的修改在功能上是正确的,但要注意 panel.item 的生命周期管理,确保在 item 销毁时清理引用。

总体评价:
这份 diff 主要是为了实现通过 URL 参数控制指示器显示的功能。代码逻辑基本正确,能够实现预期功能。主要的改进点在于 URL 拼接的健壮性和消除 Magic String。安全性方面没有明显的严重漏洞,但需注意 QML 对象的生命周期管理。

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