Skip to content

fix: fix system and app proxy is hide#503

Open
ut003640 wants to merge 1 commit intolinuxdeepin:masterfrom
ut003640:master
Open

fix: fix system and app proxy is hide#503
ut003640 wants to merge 1 commit intolinuxdeepin:masterfrom
ut003640:master

Conversation

@ut003640
Copy link
Contributor

@ut003640 ut003640 commented Feb 10, 2026

the system and app proxy must show on the control center

PMS: BUG-350619

Summary by Sourcery

Ensure system and app proxy controls remain visible and selectable in the network control center.

Bug Fixes:

  • Prevent system and app proxy items from being removed from the model so they stay visible in the UI.
  • Avoid duplicate or hidden proxy entries by filtering to show only the first occurrence of each item type and guarding model comparisons against null items.
  • Allow proxy-related switches in the system proxy page to always be interactive instead of conditionally disabled.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: ut003640

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

Ensures system and app proxy controls are always visible in the control center by preventing their NetItem rows from being removed, filtering duplicate items in the proxy model, and making the System Proxy switches always enabled in QML.

Sequence diagram for NetItem removal with preserved proxy items

sequenceDiagram
    participant View
    participant NetItemModel
    participant ParentItem as NetItem_parent
    participant ChildItem as NetItem_child

    View->>NetItemModel: AboutToRemoveObject(parentItem, pos)
    NetItemModel->>ParentItem: getChild(pos)
    ParentItem-->>NetItemModel: childItem
    NetItemModel->>NetItemModel: needRemoveNodeItem(childItem)
    alt childItem is SystemProxyControlItem or AppProxyControlItem
        NetItemModel-->>View: skip beginRemoveRows
    else other item type
        NetItemModel->>View: beginRemoveRows
    end

    View->>NetItemModel: removeObject(child)
    NetItemModel->>NetItemModel: needRemoveNodeItem(child)
    alt child is SystemProxyControlItem or AppProxyControlItem
        NetItemModel-->>View: skip endRemoveRows
    else other item type
        NetItemModel->>View: endRemoveRows
    end
Loading

Class diagram for updated NetItemModel proxy filtering and row removal

classDiagram
    class NetItemModel {
        +rootChanged(root NetItem)
        +roleNames() QHash~int,QByteArray~
        +lessThan(source_left QModelIndex, source_right QModelIndex) bool
        +filterAcceptsRow(source_row int, source_parent QModelIndex) bool
        -needRemoveNodeItem(childItem NetItem) bool
        -AboutToRemoveObject(parentItem NetItem, pos int) void
        -removeObject(child NetItem) void
        -m_rowMap QMap~NetType_NetItemType,int~
    }

    class NetItem {
        +itemType() NetType_NetItemType
        +getChild(pos int) NetItem
    }

    class NetType_NetItemType {
        <<enumeration>>
        SystemProxyControlItem
        AppProxyControlItem
        otherTypes
    }

    NetItemModel --> NetItem : uses
    NetItemModel --> NetType_NetItemType : uses
    NetItem --> NetType_NetItemType : returns
Loading

File-Level Changes

Change Details Files
Prevent system and app proxy NetItem rows from being removed from the model
  • Introduce needRemoveNodeItem helper to detect system and app proxy items that must remain visible
  • Gate beginRemoveRows in AboutToRemoveObject based on needRemoveNodeItem for the child at the given position
  • Gate endRemoveRows in removeObject so removal notifications are skipped for protected items
dcc-network/operation/netitemmodel.cpp
Ensure unique display of NetItem rows and safer sorting in the proxy model
  • Override filterAcceptsRow to track first row per NetItemType via m_rowMap and filter out subsequent duplicates
  • Add a mutable QMap member m_rowMap to store the first row index per NetItemType
  • Add null checks for left and right items in lessThan before comparing itemType values
  • Move netitem.h include from cpp into header so NetItemType and NetItem are available to the proxy model
dcc-network/operation/netitemmodel.cpp
dcc-network/operation/netitemmodel.h
Make System Proxy toggles always user-interactable in the QML UI
  • Force the main system proxy enable switch to be always enabled instead of relying on netItem.enabledable
  • Force the method selection switch to be always enabled instead of relying on netItem.enabledable
dcc-network/qml/PageSystemProxy.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:

  • The filterAcceptsRow implementation keeps state in m_rowMap across calls but never resets it, which can lead to incorrect filtering as the model changes over time; consider clearing or rebuilding this map when the source model changes or on each filter pass instead of relying on mutable state.
  • Using NetType::NetItemType as the key in m_rowMap ignores the parent index, so only one row per type will ever be shown even if logically distinct items exist under different parents; if that’s not intended, include the parent (or full index path) in the key.
  • In filterAcceptsRow, you don't call the base QSortFilterProxyModel::filterAcceptsRow, so any existing filtering behavior is bypassed; if additional conditions should be combined with the default logic, explicitly delegate to the base implementation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `filterAcceptsRow` implementation keeps state in `m_rowMap` across calls but never resets it, which can lead to incorrect filtering as the model changes over time; consider clearing or rebuilding this map when the source model changes or on each filter pass instead of relying on mutable state.
- Using `NetType::NetItemType` as the key in `m_rowMap` ignores the parent index, so only one row per type will ever be shown even if logically distinct items exist under different parents; if that’s not intended, include the parent (or full index path) in the key.
- In `filterAcceptsRow`, you don't call the base `QSortFilterProxyModel::filterAcceptsRow`, so any existing filtering behavior is bypassed; if additional conditions should be combined with the default logic, explicitly delegate to the base implementation.

## Individual Comments

### Comment 1
<location> `dcc-network/operation/netitemmodel.cpp:233-238` </location>
<code_context>
+
 bool NetItemModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
 {
     NetItem *leftItem = static_cast<NetItem *>(source_left.internalPointer());
+    if (!leftItem)
+        return false;
+
     NetItem *rightItem = static_cast<NetItem *>(source_right.internalPointer());
+    if (!rightItem)
+        return false;
+
</code_context>

<issue_to_address>
**issue (bug_risk):** Handling null pointers in `lessThan` by returning `false` can violate strict weak ordering.

Returning `false` when either pointer is null means that for a null vs non-null pair, both `lessThan(left, right)` and `lessThan(right, left)` can be `false`, which violates strict weak ordering required by `QSortFilterProxyModel` and can cause unstable sorting. Consider defining a consistent ordering for nulls (e.g., always less or always greater than non-null) so comparisons remain deterministic.
</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 233 to +238
NetItem *leftItem = static_cast<NetItem *>(source_left.internalPointer());
if (!leftItem)
return false;

NetItem *rightItem = static_cast<NetItem *>(source_right.internalPointer());
if (!rightItem)
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): Handling null pointers in lessThan by returning false can violate strict weak ordering.

Returning false when either pointer is null means that for a null vs non-null pair, both lessThan(left, right) and lessThan(right, left) can be false, which violates strict weak ordering required by QSortFilterProxyModel and can cause unstable sorting. Consider defining a consistent ordering for nulls (e.g., always less or always greater than non-null) so comparisons remain deterministic.

the system and app proxy must show on the control center

PMS: BUG-350619
@deepin-ci-robot
Copy link

deepin pr auto review

代码审查报告

本次代码审查主要针对 dcc-network 模块中的 netitemmodel.cppnetitemmodel.hPageSystemProxy.qml 的修改。以下是关于语法逻辑、代码质量、代码性能和代码安全的详细分析及改进建议。

1. 文件:dcc-network/operation/netitemmodel.cpp

语法逻辑与代码质量:

  • AboutToRemoveObjectremoveObject 的不对称性

    • 问题AboutToRemoveObject 接收 parentItempos,而 removeObject 接收 child。这导致了逻辑上的不一致。通常,beginRemoveRowsendRemoveRows 应该成对调用,且针对同一个索引范围。如果 needRemoveNodeItemAboutToRemoveObject 中为真但在 removeObject 中为假(反之亦然),或者因为某种状态变化导致判断结果不一致,将会导致模型内部状态错乱,甚至引发崩溃。
    • 改进建议:确保 beginRemoveRowsendRemoveRows 的调用条件完全一致。由于 removeObject 是在 AboutToRemoveObject 之后调用的,建议在 AboutToRemoveObject 中记录是否需要移除的状态,或者确保传入的参数能保证两次判断结果一致。目前的实现依赖于 parentItem->getChild(pos)child 是同一个对象,这通常是安全的,但逻辑上不够严谨。
  • filterAcceptsRow 中的逻辑

    • 问题m_rowMap 用于记录每种 NetItemType 第一次出现的行号,后续相同类型的行被过滤掉。然而,m_rowMapmutable 的,这意味着它可以在 const 函数中被修改。这虽然符合 C++ 语法,但在 filterAcceptsRow 这种会被频繁调用的函数中修改成员变量,会带来副作用。
    • 改进建议filterAcceptsRow 的主要目的是过滤,不应承担记录状态的职责。如果目的是去重(每种类型只显示一个),应该在数据源层面处理,或者在模型初始化/更新时构建一个映射表,而不是在每次过滤时动态构建。如果数据源是动态变化的,这种动态构建的方式在性能上会有问题(见下文性能分析)。
  • 空指针检查

    • 问题:在 lessThan 中增加了对 leftItemrightItem 的空指针检查,这是好的做法。但在 filterAcceptsRow 中,childIndex.internalPointer() 转换后的 curItem 也进行了空指针检查,这是正确的。
    • 改进建议:保持这些空指针检查。

代码性能:

  • filterAcceptsRow 的性能问题
    • 问题filterAcceptsRow 会在视图刷新、数据变化时被频繁调用。每次调用都会查询 m_rowMap,甚至修改它。如果模型中的数据量较大,或者数据更新频繁,这会成为性能瓶颈。此外,m_rowMap 的生命周期和更新时机不明确,它似乎只在当前过滤过程中有效,但作为成员变量,它会一直存在。
    • 改进建议:如果过滤规则是“每种类型只显示第一个”,建议不要在 filterAcceptsRow 中实现。可以考虑:
      1. 在数据源(NetItem)层面确保每种类型只有一个实例。
      2. 如果数据源有多个相同类型的项,但只需要显示一个,可以在模型层面(NetItemModel)维护一个“有效项”列表,在数据变化时更新这个列表,然后在 filterAcceptsRow 中直接检查当前行是否在有效列表中。
      3. 如果必须使用 m_rowMap,确保在数据变化时(比如 rowsInsertedrowsRemoved)清空或更新 m_rowMap,以避免脏数据。

代码安全:

  • m_rowMap 的线程安全
    • 问题m_rowMap 是成员变量,在 filterAcceptsRow 中被修改。如果模型在多线程环境中被访问(虽然 Qt 的模型/视图架构通常在主线程操作,但值得注意),这会导致数据竞争。
    • 改进建议:确保 NetItemModel 的所有操作都在同一线程(通常是主线程)中进行。如果必须在多线程中使用,需要对 m_rowMap 的访问进行加锁。

2. 特定代码段审查

代码段 1:AboutToRemoveObjectremoveObject

void AboutToRemoveObject(const NetItem *parentItem, int pos)
{
    if (!parentItem)
        return;

    if (needRemoveNodeItem(parentItem->getChild(pos)))
        beginRemoveRows(QModelIndex(), pos, pos);
}

void removeObject(const NetItem *filteringChild)
{
    if (needRemoveNodeItem(filteringChild))
        `endRemoveRows`();
}
  • 审查意见
    • 参数命名不一致:AboutToRemoveObject 接收 parentItem,而 removeObject 接收 child。建议统一命名,例如都接收 child,或者都接收 parentpos
    • 逻辑不对称:AboutToRemoveObject 通过 parentItem->getChild(pos) 获取子项,而 removeObject 直接接收子项。这要求调用者必须保证传递的 child 就是 parentItem->getChild(pos),否则 beginRemoveRowsendRemoveRows 将不匹配。
    • 改进建议:将 removeObject 改为接收 parentItempos,与 AboutToRemoveObject 保持一致:
void removeObject(const NetItem *parentItem, int pos)
{
    if (!parentItem)
        return;

    if (needRemoveNodeItem(parentItem->getChild(pos)))
        endRemoveRows();
}

代码段 移除 #include "netitem.h"

  • 审查意见
    • .cpp 文件中移除了 #include "netitem.h",但在 .h 文件中添加了它。
    • 改进建议:这是正确的做法。头文件应该包含它所依赖的类的声明,而源文件应该包含它所依赖的类的定义。这符合良好的 C++ 实践,有助于减少编译依赖。

3. 文件:dcc-network/operation/netitemmodel.h

  • 审查意见
    • 添加了 #include "netitem.h",这是必要的,因为 NetItemModel 使用了 NetItem 类型。
    • 添加了 mutable QMap<NetType::NetItemType, int> m_rowMap;
    • 改进建议:如前所述,m_rowMap 的使用方式可能会导致性能问题。如果可能,考虑使用其他方式实现过滤逻辑。

4. 文件:dcc-network/qml/PageSystemProxy.qml

语法逻辑与代码质量:

  • 硬编码 enabled: true
    • 问题:代码中将 enabled: netItem.enabledable 修改为 enabled: true。这意味着无论 netItem.enabledable 的值是什么,控件始终处于可用状态。
    • 改进建议:这是一个功能性变更。如果 netItem.enabledable 的目的是控制控件是否可用,那么将其硬编码为 true 可能会引入 Bug。建议确认 netItem.enabledable 的含义,以及是否真的需要忽略它的值。如果是为了修复某个特定 Bug,请添加注释说明原因。

代码安全:

  • 没有明显的代码安全问题

总结与建议

  1. 重构 AboutToRemoveObjectremoveObject:确保它们的参数和逻辑一致,避免 beginRemoveRowsendRemoveRows 不匹配。
  2. 优化 filterAcceptsRow:避免在过滤函数中修改成员变量。考虑在数据源层面或模型初始化时处理去重逻辑,以提高性能和代码清晰度。
  3. 审查 QML 中的 enabled: true:确认这是否是预期的行为,并添加必要的注释。
  4. 文档化 m_rowMap:如果必须使用 m_rowMap,请添加注释说明其用途、生命周期和线程安全性假设。

这些改进将有助于提高代码的健壮性、可维护性和性能。

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.

2 participants