Skip to content

Conversation

@ut003640
Copy link
Contributor

@ut003640 ut003640 commented Feb 2, 2026

when the system proxy hosts changed,must change the button status of dock

Log: fix proxy status
Influence: dock proxy status
PMS: BUG-313855

Summary by Sourcery

Handle system proxy configuration changes consistently across the network service and UI, ensuring proxy status reflects GSettings updates in real time.

Bug Fixes:

  • Update system proxy existence state when proxy hosts or autoconfig URL change, so the dock proxy button correctly reflects current configuration.
  • Emit proxy change signals when proxy host settings change per protocol, allowing consumers to refresh proxy data.

Enhancements:

  • Introduce a centralized helper to recompute and emit system proxy existence changes based on current manual and auto proxy configuration.
  • Track system proxy GSettings directly in the proxy controller to react to mode and autoconfig URL changes without relying solely on D-Bus.
  • Reconnect UI layer to system proxy existence signals so proxy items update their enabled state when system proxy configuration changes.

Build:

  • Link the src target against gsettings-qt6 and include its headers to support QGSettings usage in the proxy controller.

@sourcery-ai
Copy link

sourcery-ai bot commented Feb 2, 2026

Reviewer's Guide

This PR wires system proxy GSettings changes into the network service and UI controller, ensuring that when system proxy hosts or mode change via GSettings, the D-Bus service emits a proxyChanged signal and the dock button state and proxy status stay in sync. It also factors out system proxy existence computation and links in gsettings-qt6 for the src target.

Sequence diagram for system proxy host change updating dock status

sequenceDiagram
    actor User
    participant SettingsApp
    participant GSettingsDaemon
    participant QGSettings_NetworkProxy as QGSettings_NetworkProxy
    participant NetworkProxy
    participant DBus
    participant ProxyController
    participant NetManagerThreadPrivate
    participant DockProxyItem

    User->>SettingsApp: Change system proxy host
    SettingsApp->>GSettingsDaemon: Write org.gnome.system.proxy.* host
    GSettingsDaemon-->>QGSettings_NetworkProxy: Notify changed(host)
    QGSettings_NetworkProxy-->>NetworkProxy: changed(key=host)
    NetworkProxy->>NetworkProxy: onConfigChanged(key)
    NetworkProxy->>NetworkProxy: sender() as QGSettings
    NetworkProxy-->>DBus: emit proxyChanged(type, host)

    DBus-->>ProxyController: proxyChanged(type, value)
    ProxyController->>ProxyController: onProxyChanged(type, value)
    ProxyController->>ProxyController: queryProxyDataByType(type)
    ProxyController->>ProxyController: update m_sysProxyConfig
    ProxyController->>ProxyController: checkSystemProxyExist()
    ProxyController-->>NetManagerThreadPrivate: systemProxyExistChanged(flag)

    NetManagerThreadPrivate->>DockProxyItem: onSystemProxyExistChanged(flag)
    DockProxyItem->>DockProxyItem: updateenabled(flag)
    DockProxyItem->>DockProxyItem: refresh dock button state
Loading

Sequence diagram for system proxy mode change via GSettings

sequenceDiagram
    actor User
    participant SettingsApp
    participant GSettingsDaemon
    participant QGSettings_ProxyController as QGSettings_ProxyController
    participant ProxyController
    participant NetManagerThreadPrivate
    participant DockProxyItem

    User->>SettingsApp: Change system proxy mode
    SettingsApp->>GSettingsDaemon: Write org.gnome.system.proxy mode
    GSettingsDaemon-->>QGSettings_ProxyController: Notify changed(mode)
    QGSettings_ProxyController-->>ProxyController: changed(key=mode)
    ProxyController->>ProxyController: onSystemProxyChanged(key)
    ProxyController->>ProxyController: onProxyMethodChanged(mode)
    ProxyController-->>NetManagerThreadPrivate: proxyMethodChanged(mode)

    NetManagerThreadPrivate->>DockProxyItem: onSystemProxyMethodChanged(mode)
    DockProxyItem->>DockProxyItem: updatemethod(mode)
    DockProxyItem->>DockProxyItem: updateenabled(mode==Auto or mode==Manual)

    Note over ProxyController,ProxyController: ProxyController also calls onSystemProxyChanged("autoconfigUrl") on startup to sync auto proxy URL and systemProxyExist flag
Loading

Class diagram for updated ProxyController and NetworkProxy

classDiagram
    class ProxyController {
        - NetworkInter* m_networkInter
        - ProxyMethod m_proxyMethod
        - QString m_autoProxyURL
        - QList~SysProxyConfig~ m_sysProxyConfig
        - AppProxyConfig m_appProxyConfig
        - bool m_appProxyExist
        - bool m_systemProxyExist
        - QGSettings* m_proxySettings
        + ProxyController(QObject* parent)
        + void setProxyMethod(ProxyMethod pm)
        + void queryAutoProxy()
        + void checkSystemProxyExist()
        + AppProxyType appProxyType(QString v)
        + QString appProxyType(AppProxyType v)
        + bool systemProxyExist() const
        + QString autoProxy() const
        + AppProxyConfig appProxyConfig() const
        + Q_SIGNAL void proxyMethodChanged(QString method)
        + Q_SIGNAL void systemProxyExistChanged(bool exist)
        + Q_SIGNAL void autoProxyChanged(QString url)
        + Q_SIGNAL void proxyChanged()
        + Q_SLOT void onIPChanged(QString value)
        + Q_SLOT void onPasswordChanged(QString value)
        + Q_SLOT void onUserChanged(QString value)
        + Q_SLOT void onPortChanged(uint value)
        + Q_SLOT void onProxyMethodChanged(QString method)
        + Q_SLOT void onSystemProxyChanged(QString key)
        + Q_SLOT void onProxyChanged(QString type, QString value)
    }

    class NetworkProxy {
        - QDBusConnection m_dbusConnection
        - NetworkStateHandler* m_networkStateHandler
        - QGSettings* m_proxySettings
        - QGSettings* m_proxyChildSettingsHttp
        - QGSettings* m_proxyChildSettingsHttps
        - QGSettings* m_proxyChildSettingsFtp
        - QGSettings* m_proxyChildSettingsSocks
        + NetworkProxy(QDBusConnection& dbusConnection, NetworkStateHandler* handler, QObject* parent)
        + void SetProxyAuthentication(QString proxyType, QString user, QString password)
        + QGSettings* getProxyChildSettings(QString proxyType)
        + Q_SIGNAL void ProxyMethodChanged(QString proxyMode)
        + Q_SIGNAL void proxyChanged(QString type, QString value)
        + Q_SLOT void onConfigChanged(QString key)
    }

    class QGSettings {
        + QVariant get(QString key)
        + void set(QString key, QVariant value)
        + void setProperty(QString name, QVariant value)
        + Q_SIGNAL void changed(QString key)
    }

    class NetworkInter
    class NetworkStateHandler
    class SysProxyConfig {
        QString url
    }
    class AppProxyConfig

    ProxyController --> QGSettings : uses
    ProxyController --> NetworkInter : uses
    ProxyController --> SysProxyConfig : manages
    ProxyController --> AppProxyConfig : manages
    NetworkProxy --> QGSettings : owns
    NetworkProxy --> NetworkStateHandler : uses
    NetworkProxy --> QDBusConnection : uses
Loading

File-Level Changes

Change Details Files
ProxyController now listens to GSettings and D-Bus proxy change signals to recompute and emit system proxy existence state.
  • Add QGSettings member to ProxyController initialized with org.gnome.system.proxy schema.
  • Connect Network1 D-Bus proxyChanged signal to new onProxyChanged slot and emit internal proxyChanged to trigger system proxy checks.
  • Connect QGSettings::changed to new onSystemProxyChanged slot to react to mode and autoconfigUrl changes.
  • Refactor system proxy existence computation into checkSystemProxyExist() and call it from mode/auto-proxy updates and queryAutoProxy().
src/proxycontroller.cpp
src/proxycontroller.h
NetworkProxy D-Bus service now emits a proxyChanged signal when per-protocol host values change, tagging each child GSettings with its proxy type.
  • Set a "type" dynamic property on each child QGSettings instance (http, https, ftp, socks).
  • Implement onConfigChanged to detect host key changes, infer the proxy type from sender(), and emit proxyChanged(type, host).
  • Declare the proxyChanged D-Bus signal in the XML and as a Qt signal; change stored QDBusConnection from reference to value.
network-service-plugin/src/session/networkproxy.cpp
network-service-plugin/src/session/networkproxy.h
NetManagerThreadPrivate now properly initializes and reacts to systemProxyExist changes for the dock UI.
  • On initialization, immediately propagate current systemProxyExist to the UI via onSystemProxyExistChanged.
  • Reconnect ProxyController::systemProxyExistChanged to NetManagerThreadPrivate::onSystemProxyExistChanged so future changes update the dock button state.
net-view/operation/private/netmanagerthreadprivate.cpp
The src target is updated to depend on gsettings-qt6 for QGSettings support.
  • Add pkg_check_modules for QGSettings using gsettings-qt6.
  • Include QGSettings include dirs in target_include_directories and link QGSettings libraries in target_link_libraries.
src/CMakeLists.txt

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 DBus introspection XML for proxyChanged, both <arg> elements are named method; consider renaming them to distinct, meaningful names (e.g. type and value) to match the signal signature and avoid confusion or tooling issues.
  • In ProxyController, m_proxySettings is created with new QGSettings(...) without a parent; consider passing this as the QObject parent to avoid leaking it and to match the ownership pattern used elsewhere.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In the DBus introspection XML for `proxyChanged`, both `<arg>` elements are named `method`; consider renaming them to distinct, meaningful names (e.g. `type` and `value`) to match the signal signature and avoid confusion or tooling issues.
- In `ProxyController`, `m_proxySettings` is created with `new QGSettings(...)` without a parent; consider passing `this` as the QObject parent to avoid leaking it and to match the ownership pattern used elsewhere.

## Individual Comments

### Comment 1
<location> `src/proxycontroller.cpp:22` </location>
<code_context>
     , m_networkInter(new NetworkInter(networkService, networkPath, QDBusConnection::sessionBus(), this))
     , m_proxyMethod(ProxyMethod::Init)
     , m_systemProxyExist(false)
+    , m_proxySettings(new QGSettings(QByteArray("org.gnome.system.proxy"), QByteArray()))
 {
     Q_ASSERT(m_networkInter);
</code_context>

<issue_to_address>
**issue (bug_risk):** Consider giving m_proxySettings a QObject parent to avoid lifecycle and leak issues

Since `ProxyController` is a `QObject` and `QGSettings` also derives from `QObject`, you can construct it with `this` as the parent: `new QGSettings(..., this)`. That ensures it’s destroyed with the controller and avoids leaks or lifetime mismatches.
</issue_to_address>

### Comment 2
<location> `network-service-plugin/src/session/networkproxy.h:67-65` </location>
<code_context>
                 "    <signal name='ProxyMethodChanged'>\n"
                 "        <arg name='method' type='s'></arg>\n"
                 "    </signal>\n"
+                "    <signal name='proxyChanged'>\n"
+                "        <arg name='method' type='s'></arg>\n"
+                "        <arg name='method' type='s'></arg>\n"
+                "    </signal>\n"
</code_context>

<issue_to_address>
**nitpick:** Use distinct, descriptive argument names in the D-Bus introspection for proxyChanged

Both `proxyChanged` signal args are named `method` in the introspection XML. Even though D-Bus only uses order and types, duplicated/misleading names hurt readability and maintenance. Please rename them to distinct, descriptive names (e.g., `type` and `value`) in the XML while keeping the signature unchanged.
</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.

, m_networkInter(new NetworkInter(networkService, networkPath, QDBusConnection::sessionBus(), this))
, m_proxyMethod(ProxyMethod::Init)
, m_systemProxyExist(false)
, m_proxySettings(new QGSettings(QByteArray("org.gnome.system.proxy"), QByteArray()))
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): Consider giving m_proxySettings a QObject parent to avoid lifecycle and leak issues

Since ProxyController is a QObject and QGSettings also derives from QObject, you can construct it with this as the parent: new QGSettings(..., this). That ensures it’s destroyed with the controller and avoids leaks or lifetime mismatches.

@@ -64,6 +64,10 @@ class NetworkProxy : public QObject, protected QDBusContext
" <signal name='ProxyMethodChanged'>\n"
" <arg name='method' type='s'></arg>\n"
Copy link

Choose a reason for hiding this comment

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

nitpick: Use distinct, descriptive argument names in the D-Bus introspection for proxyChanged

Both proxyChanged signal args are named method in the introspection XML. Even though D-Bus only uses order and types, duplicated/misleading names hurt readability and maintenance. Please rename them to distinct, descriptive names (e.g., type and value) in the XML while keeping the signature unchanged.

when the system proxy hosts changed,must change the button status of dock

Log: fix proxy status
Influence: dock proxy status
PMS: BUG-313855
@deepin-ci-robot
Copy link

deepin pr auto review

这份代码diff主要涉及网络代理配置的初始化、信号连接以及系统代理存在性检查的逻辑优化。以下是对语法逻辑、代码质量、代码性能和代码安全方面的详细审查和改进意见:

1. 语法逻辑审查

问题点 1:onSystemProxyExistChanged 的调用时机
netmanagerthreadprivate.cpp 中:

onSystemProxyExistChanged(networkController->proxyController()->systemProxyExist());

紧接着:

connect(networkController->proxyController(), &ProxyController::systemProxyExistChanged, this, &NetManagerThreadPrivate::onSystemProxyExistChanged);

分析:代码先手动调用了一次槽函数,然后才连接信号。这是正确的做法,确保初始化时状态同步。逻辑无误。

问题点 2:proxyChanged 信号的参数命名
networkproxy.h 的 D-Bus 接口描述中:

"    <signal name='proxyChanged'>\n"
"        <arg name='method' type='s'></arg>\n"
"        <arg name='method' type='s'></arg>\n"

分析:两个参数都命名为 method,这虽然在 D-Bus 协议中可能允许,但在语义上非常混淆。根据 networkproxy.cpp 中的实现 emit proxyChanged(settings->property("type").toString(), settings->get(key).toString());,第一个参数是代理类型(如 http, socks),第二个参数是值(如 host 或 autoconfigUrl)。
建议:将参数名修改为更具描述性的名称,例如 typevalue

问题点 3:端口范围检查
networkproxy.cpp 中:

if (portInt < 0 || portInt >= 65535) {

分析:将 > 改为了 >=。根据 TCP/UDP 端口定义,有效端口范围是 0-65535。因此,65535 是有效端口,原代码 > 65535 是正确的,新代码 >= 65535 会拒绝合法的 65535 端口。
建议:改回 portInt < 0 || portInt > 65535

2. 代码质量审查

改进点 1:魔法字符串
networkproxy.cpp 中,多处使用字符串字面量:

const QString ProxyTypeAuto = "auto";
...
m_proxySettings->setProperty("type", ProxyTypeAuto);
...
host = childSettings->get("autoconfigUrl").toString();
...
if (key == "host" || key == "autoconfigUrl") {

分析:虽然引入了常量 ProxyTypeAuto 等,但配置键(如 "host", "autoconfigUrl")仍然是魔法字符串。
建议:将所有配置键定义为常量,例如:

const QString GKeyProxyAutoConfigUrl = "autoconfigUrl";
const QString GKeyProxyHost = "host";

改进点 2:代码重复
proxycontroller.cpp 中,checkSystemProxyExist 函数:

void ProxyController::checkSystemProxyExist()
{
    bool isConfExist = false;
    for (auto conf : m_sysProxyConfig) {
        if (!conf.url.isEmpty()) {
            isConfExist = true;
            break;
        }
    }
    bool systemProxyExist = isConfExist || !m_autoProxyURL.isEmpty();
    if (m_systemProxyExist != systemProxyExist) {
        m_systemProxyExist = systemProxyExist;
        Q_EMIT systemProxyExistChanged(m_systemProxyExist);
    }
}

这段代码是从 onProxyMethodChanged 中提取出来的,重构得很好,提高了可维护性。

改进点 3:空实现槽函数
原代码:

void NetworkProxy::onConfigChanged(const QString &key) { }

新代码实现了具体逻辑:

void NetworkProxy::onConfigChanged(const QString &key)
{
    QGSettings *settings = qobject_cast<QGSettings *>(sender());
    if (!settings)
        return;

    if (key == "host" || key == "autoconfigUrl") {
        emit proxyChanged(settings->property("type").toString(), settings->get(key).toString());
    }
}

分析:这是一个很好的改进,使得配置变更能够被正确处理。

3. 代码性能审查

问题点 1:频繁的字符串比较
onConfigChanged 中:

if (key == "host" || key == "autoconfigUrl") {

分析:每次配置变更都会进行字符串比较。虽然性能影响不大,但如果配置项很多,可以考虑使用哈希表或枚举来优化。

问题点 2:不必要的信号连接
proxycontroller.cpp 构造函数中:

connect(this, &ProxyController::proxyChanged, this, [ this ] { checkSystemProxyExist(); });

分析:这个连接会导致每次 proxyChanged 信号发出时都调用 checkSystemProxyExist。如果 proxyChanged 信号频繁触发,可能会影响性能。
建议:评估是否真的需要在每次代理变更时都检查系统代理存在性。如果不是,可以考虑在特定条件下才触发检查。

4. 代码安全审查

问题点 1:类型转换
networkproxy.cpp 中:

int portInt = port.toInt();

分析:如果 port 是一个无效的数字字符串(如 "abc"),toInt() 会返回 0。这可能会被误认为是有效的端口号 0。
建议:添加转换检查:

bool ok;
int portInt = port.toInt(&ok);
if (!ok || portInt < 0 || portInt > 65535) {
    // 错误处理
}

问题点 2:空指针检查
networkproxy.cppGetProxy 方法中:

QGSettings *childSettings = getProxyChildSettings(proxyType);
if (!childSettings) {
    // 错误处理
}
QString host;
int port = 0;
if (proxyType == ProxyTypeAuto) {
    host = childSettings->get("autoconfigUrl").toString();
} else {
   host = childSettings->get(GKeyProxyHost).toString();
   port = childSettings->get(GKeyProxyPort).toInt();
}

分析:虽然有空指针检查,但 toInt() 的返回值没有检查是否有效。

问题点 3:D-Bus 连接
proxycontroller.cpp 中:

QDBusConnection::sessionBus().connect(networkService, networkPath, networkInterface, "proxyChanged", this, SLOT(onProxyChanged(const QString &, const QString &)));

分析:D-Bus 信号连接没有检查返回值。如果连接失败,会导致功能失效。
建议:检查连接返回值:

if (!QDBusConnection::sessionBus().connect(...)) {
    qCWarning(DSM()) << "Failed to connect D-Bus signal proxyChanged";
}

总结建议

  1. 修复端口范围检查:将 portInt >= 65535 改回 portInt > 65535
  2. 改进 D-Bus 信号参数命名:将 proxyChanged 信号的参数名改为 typevalue
  3. 添加类型转换检查:在 port.toInt() 和类似转换处添加有效性检查。
  4. 检查 D-Bus 连接结果:确保所有 D-Bus 信号连接都检查返回值。
  5. 消除魔法字符串:将所有配置键定义为常量。
  6. 优化性能:评估 checkSystemProxyExist 的调用频率,考虑是否需要优化。

这些改进将提高代码的健壮性、可维护性和安全性。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: caixr23, 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

@ut003640
Copy link
Contributor Author

ut003640 commented Feb 3, 2026

/forcemerge

@deepin-bot
Copy link
Contributor

deepin-bot bot commented Feb 3, 2026

This pr force merged! (status: unstable)

@deepin-bot deepin-bot bot merged commit 2097c72 into linuxdeepin:master Feb 3, 2026
16 of 18 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