Skip to content

fix: fix the language of the first connection which create#544

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
ut003640:master
Apr 9, 2026
Merged

fix: fix the language of the first connection which create#544
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
ut003640:master

Conversation

@ut003640
Copy link
Copy Markdown
Contributor

@ut003640 ut003640 commented Apr 9, 2026

fix the language of the first connection which create

PMS: BUG-354915

Summary by Sourcery

Improve initialization and naming of wired network connections to respect the correct user/system language and updated D-Bus services.

Bug Fixes:

  • Ensure the first automatically created wired connection uses the current user or system locale for its name, and updates cached connection names once language becomes available.
  • Fix MAC address matching and connection detection for wired devices, including fallback to runtime MAC when permanent MAC is unavailable.
  • Correct D-Bus service, path, and interface names for lock and accounts services and use the system bus where appropriate.

Enhancements:

  • Refine wired device and connection handling by using NetworkManager’s device list, tracking newly created connection names, and cleaning up unsaved connections on unmanaged/down devices.
  • Add support for updating connection names when user accounts are added or language changes later, including special handling for server systems and connection name suffixes.
  • Simplify and centralize account locale lookup via a helper method and streamline translator installation with a dedicated language loader.
  • Improve signal wiring for device added/changed events and wireless device management, and replace the static initializer with a lifetime-managed NetworkInitialization member in SystemContainer.

fix the language of the first connection which create

PMS: BUG-354915
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Apr 9, 2026

Reviewer's Guide

Refactors network initialization to better integrate with Deepin Accounts and LockService, ensures wired connections are created with the correct user or system language (including delayed translation updates), simplifies device handling, and cleans up connection management for wired and wireless devices.

Sequence diagram for wired connection creation and language update

sequenceDiagram
    actor User
    participant SystemContainer
    participant NetworkInitialization
    participant AccountsService as com.deepin.daemon.Accounts
    participant NetworkManager as org.freedesktop.NetworkManager

    SystemContainer->>NetworkInitialization: constructor(parent)
    activate NetworkInitialization
    NetworkInitialization->>NetworkInitialization: initDeviceInfo()
    NetworkInitialization->>NetworkInitialization: initConnection()
    NetworkInitialization->>AccountsService: checkAccountStatus() via accountInterface(UserList/Locale)
    AccountsService-->>NetworkInitialization: locale or error
    alt locale found
        NetworkInitialization->>NetworkInitialization: installUserTranslator(json)
        NetworkInitialization->>NetworkInitialization: installLaunguage(locale)
        NetworkInitialization->>NetworkInitialization: m_initilized = true
    else no locale
        NetworkInitialization->>NetworkInitialization: m_initilized remains false
    end

    Note over NetworkInitialization,NetworkManager: After 3s QTimer
    NetworkInitialization->>NetworkInitialization: addFirstConnection()
    NetworkInitialization->>NetworkManager: networkInterfaces()
    NetworkManager-->>NetworkInitialization: List<Device>
    loop each Ethernet device
        NetworkInitialization->>NetworkInitialization: hasConnection(device, unSaveConnections)
        alt device unmanaged or down or no carrier
            NetworkInitialization->>NetworkManager: remove unsaved connections
            NetworkManager-->>NetworkInitialization: removed
        else no existing saved connection
            NetworkInitialization->>NetworkInitialization: connectionMatchName(device)
            alt server system
                NetworkInitialization->>NetworkInitialization: use interfaceName
            else desktop system
                NetworkInitialization->>NetworkInitialization: generate tr("Wired Connection"[ N])
            end
            NetworkInitialization->>NetworkManager: addConnection(connMap)
            NetworkManager-->>NetworkInitialization: new connection path and uuid
            alt m_initilized is false and suffix >= 0
                NetworkInitialization->>NetworkInitialization: cache uuid -> suffix in m_untranslactionConnections
            end
            NetworkInitialization->>NetworkInitialization: m_newConnectionNames[path] = name
        end
    end
    deactivate NetworkInitialization

    Note over User,NetworkInitialization: Later when user login or created

    AccountsService-->>NetworkInitialization: UserAdded(userPath) signal
    activate NetworkInitialization
    NetworkInitialization->>NetworkInitialization: onUserAdded(userPath)
    NetworkInitialization->>NetworkInitialization: updateConnectionLaunguage(userPath)
    NetworkInitialization->>AccountsService: accountInterface(userPath, Locale)
    AccountsService-->>NetworkInitialization: locale
    NetworkInitialization->>NetworkInitialization: installLaunguage(locale)
    NetworkInitialization->>NetworkInitialization: m_initilized = true
    NetworkInitialization->>NetworkInitialization: updateConnectionLaunguage()
    loop for each cached uuid in m_untranslactionConnections
        NetworkInitialization->>NetworkManager: findConnectionByUuid(uuid)
        NetworkManager-->>NetworkInitialization: Connection
        NetworkInitialization->>NetworkManager: update or updateUnsaved(new localized id)
        NetworkManager-->>NetworkInitialization: ack
        NetworkInitialization->>NetworkInitialization: m_newConnectionNames[path] = localizedName
    end
    NetworkInitialization->>NetworkInitialization: clear m_untranslactionConnections
    deactivate NetworkInitialization
Loading

Class diagram for updated network initialization and system container

classDiagram
    namespace systemservice {
        class SystemContainer {
            -SystemIPConflict* m_ipConflictHandler
            -ConnectivityProcesser* m_connectivityHelper
            -NetworkInitialization* m_initializator
            +SystemContainer(QObject* parent)
            +~SystemContainer()
        }

        class NetworkInitialization {
            -QMap~QString, QString~ m_newConnectionNames
            -bool m_initilized
            -bool m_accountServiceRegister
            -bool m_hasAddFirstConnection
            -QMap~QString, QDateTime~ m_lastCreateTime
            -QMap~QString, int~ m_untranslactionConnections
            +NetworkInitialization(QObject* parent)
            +~NetworkInitialization()
            +void updateLanguage(QString locale)
            -void initDeviceInfo()
            -void initConnection()
            -void addFirstConnection()
            -void addFirstConnection(NetworkManager::WiredDevice* device)
            -bool hasConnection(NetworkManager::WiredDevice* device, QList~QSharedPointer~NetworkManager::Connection~~ & unSaveDevices)
            -QPair~int, QString~ connectionMatchName(NetworkManager::WiredDevice* device) const
            -QVariant accountInterface(QString path, QString key, bool isUser) const
            -bool installUserTranslator(QString json)
            -void installLaunguage(QString locale)
            -void hideWirelessDevice(QSharedPointer~NetworkManager::Device~ device, bool disableNetwork)
            -void initDeviceConnection(QSharedPointer~NetworkManager::WiredDevice~ device)
            -void checkAccountStatus()
            -void updateConnectionLaunguage(QString account)
            -void updateConnectionLaunguage()
            -bool isServerSystem() const
            <<slots>>
            -void onUserChanged(QString json)
            -void onUserAdded(QString json)
            -void onInitDeviceConnection()
            -void onWiredDevicePropertyChanged()
            -void onDeviceAdded(QString uni)
            -void onAvailableConnectionDisappeared(QString connectionUni)
        }
    }

    SystemContainer --> NetworkInitialization : owns
Loading

File-Level Changes

Change Details Files
Create and update wired connections using current locale with deferred translation support and safer device handling.
  • Replace manual GetDevices DBus calls with NetworkManager::networkInterfaces and direct NetworkManager::WiredDevice pointers to simplify wired device enumeration and lifecycle management.
  • Change addFirstConnection and hasConnection to operate on raw NetworkManager::WiredDevice pointers, use permanent or runtime MAC address for matching, and clear unsaved connections when devices are down or unmanaged.
  • Generate connection names via connectionMatchName returning an index/name pair, track names in a map keyed by connection path, and on non-server systems use localized "Wired Connection" names including numeric suffixes.
  • Attach MAC address to new wired connections via NetworkManager::WiredSetting, initialize the setting, and cache UUIDs and suffix indices for connections created before language initialization to allow later renaming.
  • Introduce updateConnectionLaunguage functions to install the user’s locale and rename cached connections once translations are available, handling both specific accounts and general updates.
network-service-plugin/src/system/networkinitialization.cpp
network-service-plugin/src/system/networkinitialization.h
Revise locale detection and translator installation to use Deepin Accounts DBus APIs and a simplified translation loader.
  • Add accountInterface helper to query Locale, UserList, and other properties from com.deepin.daemon.Accounts and com.deepin.daemon.Accounts.User over the system bus.
  • Rework installUserTranslator to derive locale from user DBus paths, JSON user data (Uid), or Accounts service’s UserList, falling back gracefully when values are missing.
  • Replace installTranslator and installSystemTranslator with installLaunguage, which loads QM files directly by locale and installs a single shared QTranslator instance.
  • Add updateLanguage method on NetworkInitialization as a public entry point to change current locale, mark initialization, and trigger connection language updates.
network-service-plugin/src/system/networkinitialization.cpp
network-service-plugin/src/system/networkinitialization.h
Align DBus service names and connection behaviors with updated Deepin services and improve device signal handling.
  • Update LOCKERVICE and Accounts DBus service, path, and interface constants to com.deepin.dde.LockService and com.deepin.daemon.Accounts.* to match current services.
  • Switch QDBusServiceWatcher for the ConfigManager service to use the system bus instead of the session bus.
  • Refactor wired device signal handling by replacing onAddFirstConnection and onManagedChanged with onWiredDevicePropertyChanged, which logs status and calls addFirstConnection when relevant properties change.
  • Add onDeviceAdded to centralize NetworkManager::Notifier::deviceAdded handling for both Wi-Fi (hideWirelessDevice) and Ethernet (initDeviceConnection and optional addFirstConnection) devices, and track available connection removal via onAvailableConnectionDisappeared.
  • Adjust hideWirelessDevice to reapply Managed state via a lambda slot tied to each device’s managedChanged signal instead of a generic onManagedChanged slot.
network-service-plugin/src/system/networkinitialization.cpp
network-service-plugin/src/system/networkinitialization.h
Integrate NetworkInitialization as a regular SystemContainer member instead of using a static singleton initializer.
  • Remove static NetworkInitialization::doInit helper and make the constructor the primary initializer of network setup logic.
  • Add a NetworkInitialization pointer member to SystemContainer and instantiate it in the SystemContainer constructor, ensuring lifecycle is tied to the container object.
network-service-plugin/src/system/systemcontainer.cpp
network-service-plugin/src/system/systemcontainer.h
Miscellaneous maintenance updates and includes cleanup.
  • Add DSysInfo include and isServerSystem helper to skip localized names on server systems.
  • Reorganize and trim Qt and NetworkManager includes, removing unused DBus message/file helpers and adding Ipv4Setting.
  • Update SPDX copyright years to "2024 - 2026" across touched headers and sources.
network-service-plugin/src/system/networkinitialization.cpp
network-service-plugin/src/system/networkinitialization.h

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

@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 onUserAdded() you now call updateConnectionLaunguage(user) before installUserTranslator(user), but the signal argument may still be a JSON payload rather than a D-Bus path; consider reusing installUserTranslator’s logic (or its parsed path/locale) so that updateConnectionLaunguage() is only invoked with a verified account object path to avoid invalid D-Bus property lookups and loading an empty-locale translator.
  • hideWirelessDevice() now connects a lambda to managedChanged without Qt::UniqueConnection, which can lead to multiple duplicate connections if hideWirelessDevice() is called repeatedly for the same device; it would be safer to add Qt::UniqueConnection or guard against reconnecting.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In onUserAdded() you now call updateConnectionLaunguage(user) before installUserTranslator(user), but the signal argument may still be a JSON payload rather than a D-Bus path; consider reusing installUserTranslator’s logic (or its parsed path/locale) so that updateConnectionLaunguage() is only invoked with a verified account object path to avoid invalid D-Bus property lookups and loading an empty-locale translator.
- hideWirelessDevice() now connects a lambda to managedChanged without Qt::UniqueConnection, which can lead to multiple duplicate connections if hideWirelessDevice() is called repeatedly for the same device; it would be safer to add Qt::UniqueConnection or guard against reconnecting.

## Individual Comments

### Comment 1
<location path="network-service-plugin/src/system/networkinitialization.cpp" line_range="367-374" />
<code_context>
+void NetworkInitialization::installLaunguage(const QString &locale)
</code_context>
<issue_to_address>
**suggestion (bug_risk):** installLaunguage ignores the result of translator.load(), reducing error visibility compared to the previous implementation.

Previously, translator.load(...) was checked and both success and failure (with locale) were logged. Now installLaunguage() always installs the translator and only logs the qm path, even if load() failed (e.g., missing file or wrong locale). Please restore a check on the boolean result of load() and log a warning on failure, as before.

Suggested implementation:

```cpp
void NetworkInitialization::installLaunguage(const QString &locale)
{
    // Build the QM file path for the requested locale using the same logic
    // that was previously used at the call site.
    const QString qmPath = /* existing logic that was previously used to compute the qmPath from locale */;

    const bool loaded = m_translator.load(qmPath);
    if (loaded) {
        qApp->installTranslator(&m_translator);
        qInfo() << "Loaded translation for locale" << locale << "from" << qmPath;
    } else {
        qWarning() << "Failed to load translation for locale" << locale << "from" << qmPath;
    }
}

```

To fully implement the requested behavior without reducing error visibility, you should:

1. Replace the `qmPath` construction comment with the exact logic that was previously inlined at the call site (before the refactor to `installLaunguage`). This ensures the same file path and locale handling as before.
2. Replace `m_translator` with the actual `QTranslator` instance used in this class/file (for example, if it was previously a local `QTranslator translator;`, either:
   - make it a member `QTranslator m_translator;` and reuse it here, or
   - keep it local inside this function and adjust the `qApp->installTranslator(...)` call accordingly).
3. If the original code logged more detailed information (e.g. separate `qInfo` on success and `qWarning` including `locale` and the full path on failure), mirror that exact logging format here.
4. Make sure `qApp` (or `QCoreApplication::instance()`) is available in this translation unit by including the appropriate Qt headers if they were not already included.
</issue_to_address>

### Comment 2
<location path="network-service-plugin/src/system/networkinitialization.cpp" line_range="388-386" />
<code_context>
         dbusInter.setProperty("Managed", managed);
     }
-    connect(device.data(), &NetworkManager::Device::managedChanged, this, &NetworkInitialization::onManagedChanged, Qt::UniqueConnection);
+    NetworkManager::Device *devicePtr = device.data();
+    connect(devicePtr, &NetworkManager::Device::managedChanged, this, [ devicePtr, managed ] {
+        if (devicePtr->managed() == managed)
+            return ;
+
+        qCDebug(DSM) << "device" << devicePtr->interfaceName() << "managed changed" << devicePtr->managed() << ", will set it managed" << managed;
+        QDBusInterface dbusInter("org.freedesktop.NetworkManager", devicePtr->uni(), "org.freedesktop.NetworkManager.Device", QDBusConnection::systemBus());
+        dbusInter.setProperty("Managed", managed);
+    });
 }
</code_context>
<issue_to_address>
**nitpick (bug_risk):** Using a lambda without Qt::UniqueConnection in hideWirelessDevice may attach duplicate slots on repeated calls.

The previous connection used Qt::UniqueConnection to avoid duplicate connections; the new lambda connection does not. If hideWirelessDevice is called repeatedly for the same device, this lambda will be connected multiple times and will run on every managedChanged emission, causing redundant DBus calls and more complex signal/slot state. Please add Qt::UniqueConnection or otherwise ensure the connection is only created once per device.
</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 +367 to +374
void NetworkInitialization::installLaunguage(const QString &locale)
{
QFile file(filePath);
if (!file.open(QFile::ReadOnly | QFile::Text)) {
qCWarning(DSM) << "Failed to open locale file:" << filePath << "-" << file.errorString();
return QString();
}

QMap<QString, QString> localeMap;
QTextStream in(&file);
while (!in.atEnd()) {
QString line = in.readLine();
if (!keywords.isEmpty() && !line.contains(keywords)) {
continue;
}
QStringList pair = line.split(splitKey);
if (pair.size() == 2) {
localeMap.insert(pair.at(0).trimmed(), pair.at(1).trimmed());
}
}
for (const auto &key : keys) {
if (localeMap.contains(key))
return localeMap.value(key).split('.').first();
}
return QString();
}

bool NetworkInitialization::installSystemTranslator()
{
QString locale = getLocaleValue("/etc/locale.conf", { "LANGUAGE", "LANG" }, "=", "LANG");
if (locale.isEmpty()) {
locale = getLocaleValue("/etc/deepin-installer/deepin-installer.conf", { "DI_LOCALE", "LIVE_LOCALES" }, "=", "LOCALE");
}
if (!locale.isEmpty()) {
qCInfo(DSM) << "Install system language:" << locale;
return installTranslator(locale);
}
return false;
static QTranslator translator;
QCoreApplication::removeTranslator(&translator);
const QString qmFile = QString("%1/network-service-plugin_%2.qm").arg(QM_FILES_DIR).arg(locale);
translator.load(qmFile);
QCoreApplication::installTranslator(&translator);
qCDebug(DSM) << "install translation file" << qmFile;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): installLaunguage ignores the result of translator.load(), reducing error visibility compared to the previous implementation.

Previously, translator.load(...) was checked and both success and failure (with locale) were logged. Now installLaunguage() always installs the translator and only logs the qm path, even if load() failed (e.g., missing file or wrong locale). Please restore a check on the boolean result of load() and log a warning on failure, as before.

Suggested implementation:

void NetworkInitialization::installLaunguage(const QString &locale)
{
    // Build the QM file path for the requested locale using the same logic
    // that was previously used at the call site.
    const QString qmPath = /* existing logic that was previously used to compute the qmPath from locale */;

    const bool loaded = m_translator.load(qmPath);
    if (loaded) {
        qApp->installTranslator(&m_translator);
        qInfo() << "Loaded translation for locale" << locale << "from" << qmPath;
    } else {
        qWarning() << "Failed to load translation for locale" << locale << "from" << qmPath;
    }
}

To fully implement the requested behavior without reducing error visibility, you should:

  1. Replace the qmPath construction comment with the exact logic that was previously inlined at the call site (before the refactor to installLaunguage). This ensures the same file path and locale handling as before.
  2. Replace m_translator with the actual QTranslator instance used in this class/file (for example, if it was previously a local QTranslator translator;, either:
    • make it a member QTranslator m_translator; and reuse it here, or
    • keep it local inside this function and adjust the qApp->installTranslator(...) call accordingly).
  3. If the original code logged more detailed information (e.g. separate qInfo on success and qWarning including locale and the full path on failure), mirror that exact logging format here.
  4. Make sure qApp (or QCoreApplication::instance()) is available in this translation unit by including the appropriate Qt headers if they were not already included.

@@ -450,14 +385,25 @@ void NetworkInitialization::hideWirelessDevice(const QSharedPointer<NetworkManag
QDBusInterface dbusInter("org.freedesktop.NetworkManager", device->uni(), "org.freedesktop.NetworkManager.Device", QDBusConnection::systemBus());
dbusInter.setProperty("Managed", managed);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nitpick (bug_risk): Using a lambda without Qt::UniqueConnection in hideWirelessDevice may attach duplicate slots on repeated calls.

The previous connection used Qt::UniqueConnection to avoid duplicate connections; the new lambda connection does not. If hideWirelessDevice is called repeatedly for the same device, this lambda will be connected multiple times and will run on every managedChanged emission, causing redundant DBus calls and more complex signal/slot state. Please add Qt::UniqueConnection or otherwise ensure the connection is only created once per device.

@deepin-ci-robot
Copy link
Copy Markdown

[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
Copy Markdown
Contributor Author

ut003640 commented Apr 9, 2026

/forcemerge

@deepin-bot
Copy link
Copy Markdown
Contributor

deepin-bot bot commented Apr 9, 2026

This pr force merged! (status: unstable)

@deepin-bot deepin-bot bot merged commit 10e995e into linuxdeepin:master Apr 9, 2026
17 of 19 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