[plasma/plasma-nm] /: Refactoring the wifi status

Devin Lin <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 20222fc2c07d7980e6562a4515686bf049f8e9b1 by Devin Lin, on behalf of Tushar Gupta.
Committed on 31/07/2026 at 02:51.
Pushed by devinlin into branch 'master'.

Refactoring the wifi status

This MR focus on the network status tab that will list all the details of the current selected network

M  +1    -0    kcms/kcm_connections_qml/CMakeLists.txt
M  +37   -2    kcms/kcm_connections_qml/kcm.cpp
M  +7    -2    kcms/kcm_connections_qml/kcm.h
M  +4    -1    libs/editorqml/CMakeLists.txt
M  +6    -1    libs/editorqml/qml/components/Wireless.qml
A  +43   -0    libs/editorqml/qml/wifistatus/ConnectionStatusForm.qml     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +158  -0    libs/editorqml/settings/wifistatus/connectionstatus.cpp     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +57   -0    libs/editorqml/settings/wifistatus/connectionstatus.h     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]

https://invent.kde.org/plasma/plasma-nm/-/commit/20222fc2c07d7980e6562a4515686bf049f8e9b1

diff --git a/kcms/kcm_connections_qml/CMakeLists.txt b/kcms/kcm_connections_qml/CMakeLists.txt
index f86b15fe9..8e91c7cd3 100644
--- a/kcms/kcm_connections_qml/CMakeLists.txt
+++ b/kcms/kcm_connections_qml/CMakeLists.txt
@@ -9,6 +9,7 @@ kcmutils_add_qml_kcm(kcm_networkmanagement_qml
 target_sources(kcm_networkmanagement_qml PRIVATE
     kcm.cpp
     kcm.h
+    ${CMAKE_SOURCE_DIR}/libs/enums.cpp
 )
 
 ecm_qt_declare_logging_category(kcm_networkmanagement_qml
diff --git a/kcms/kcm_connections_qml/kcm.cpp b/kcms/kcm_connections_qml/kcm.cpp
index 5ad02f017..ac673d2a4 100644
--- a/kcms/kcm_connections_qml/kcm.cpp
+++ b/kcms/kcm_connections_qml/kcm.cpp
@@ -1,5 +1,6 @@
 /*
       SPDX-FileCopyrightText: 2016 Jan Grulich <[email protected]>
+      SPDX-FileCopyrightText: 2026 Tushar Gupta <[email protected]>
 
       SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
 */
@@ -31,6 +32,7 @@ KCMNetworkManagementQml::KCMNetworkManagementQml(QObject *parent, const KPluginM
     , m_handler(new Handler(this))
     , m_wifiSecurity(new WifiSecuritySetting(this))
     , m_security8021xSetting(new Security8021xSetting(this))
+    , m_connectionStatus(new ConnectionStatus(this))
     , m_timer(new QTimer(this))
 {
     // Check if we can use AP mode to identify security type
@@ -136,6 +138,10 @@ KCMNetworkManagementQml::KCMNetworkManagementQml(QObject *parent, const KPluginM
 
 KCMNetworkManagementQml::~KCMNetworkManagementQml() = default;
 
+ConnectionStatus *KCMNetworkManagementQml::connectionStatus() const
+{
+    return m_connectionStatus;
+}
 WifiSecuritySetting *KCMNetworkManagementQml::wifiSecurity() const
 {
     return m_wifiSecurity;
@@ -160,9 +166,36 @@ void KCMNetworkManagementQml::defaults()
     KQuickConfigModule::defaults();
 }
 
-int KCMNetworkManagementQml::connectionType() const
+Enums::ConnectionType KCMNetworkManagementQml::connectionType() const
 {
-    return m_connectionType;
+    switch (m_connectionType) {
+    case NetworkManager::ConnectionSettings::Wireless:
+        return Enums::Wireless;
+    case NetworkManager::ConnectionSettings::Wired:
+        return Enums::Wired;
+    case NetworkManager::ConnectionSettings::Gsm:
+        return Enums::Gsm;
+    case NetworkManager::ConnectionSettings::Cdma:
+        return Enums::Cdma;
+    case NetworkManager::ConnectionSettings::Bluetooth:
+        return Enums::Bluetooth;
+    case NetworkManager::ConnectionSettings::Infiniband:
+        return Enums::Infiniband;
+    case NetworkManager::ConnectionSettings::Bond:
+        return Enums::Bond;
+    case NetworkManager::ConnectionSettings::Bridge:
+        return Enums::Bridge;
+    case NetworkManager::ConnectionSettings::Vlan:
+        return Enums::Vlan;
+    case NetworkManager::ConnectionSettings::Vpn:
+        return Enums::Vpn;
+    case NetworkManager::ConnectionSettings::Adsl:
+        return Enums::Adsl;
+    case NetworkManager::ConnectionSettings::Pppoe:
+        return Enums::Pppoe;
+    default:
+        return Enums::UnknownConnectionType;
+    }
 }
 void KCMNetworkManagementQml::load()
 {
@@ -261,6 +294,7 @@ void KCMNetworkManagementQml::save()
 void KCMNetworkManagementQml::onSelectedConnectionChanged(const QString &connectionPath)
 {
     if (connectionPath.isEmpty()) {
+        m_connectionStatus->setConnectionUuid(QString());
         resetSelection();
         return;
     }
@@ -270,6 +304,7 @@ void KCMNetworkManagementQml::onSelectedConnectionChanged(const QString &connect
     NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(connectionPath);
     if (connection) {
         loadConnectionSettings(connection->settings());
+        m_connectionStatus->setConnectionUuid(connection->uuid());
     }
 }
 void KCMNetworkManagementQml::loadConnectionSettings(const NetworkManager::ConnectionSettings::Ptr &connectionSettings)
diff --git a/kcms/kcm_connections_qml/kcm.h b/kcms/kcm_connections_qml/kcm.h
index e854d1c75..bc2affbf0 100644
--- a/kcms/kcm_connections_qml/kcm.h
+++ b/kcms/kcm_connections_qml/kcm.h
@@ -7,6 +7,8 @@
 #ifndef PLASMA_NM_KCM_QML_H
 #define PLASMA_NM_KCM_QML_H
 
+#include "connectionstatus.h"
+#include "enums.h"
 #include "handler.h"
 #include "security8021xsetting.h"
 #include "wifisecuritysetting.h"
@@ -24,16 +26,18 @@ class KCMNetworkManagementQml : public KQuickConfigModule
     Q_PROPERTY(Handler *handler READ handler CONSTANT)
     Q_PROPERTY(Security8021xSetting *security8021xSetting READ security8021xSetting CONSTANT)
     Q_PROPERTY(bool useApMode READ useApMode CONSTANT)
-    Q_PROPERTY(int connectionType READ connectionType NOTIFY connectionTypeChanged)
+    Q_PROPERTY(ConnectionStatus *connectionStatus READ connectionStatus CONSTANT)
+    Q_PROPERTY(Enums::ConnectionType connectionType READ connectionType NOTIFY connectionTypeChanged)
 
 public:
     explicit KCMNetworkManagementQml(QObject *parent, const KPluginMetaData &metaData);
     ~KCMNetworkManagementQml() override;
 
-    int connectionType() const;
+    Enums::ConnectionType connectionType() const;
     Handler *handler() const;
     WifiSecuritySetting *wifiSecurity() const;
     Security8021xSetting *security8021xSetting() const;
+    ConnectionStatus *connectionStatus() const;
     bool useApMode() const;
 
     Q_INVOKABLE void onRequestCreateConnection(int connectionType, const QString &vpnType, const QString &specificType, bool shared);
@@ -84,6 +88,7 @@ private:
     Handler *const m_handler;
     WifiSecuritySetting *const m_wifiSecurity;
     Security8021xSetting *const m_security8021xSetting;
+    ConnectionStatus *const m_connectionStatus;
 
     bool m_useApMode = false;
 
diff --git a/libs/editorqml/CMakeLists.txt b/libs/editorqml/CMakeLists.txt
index af2d9ced8..aa93edb06 100644
--- a/libs/editorqml/CMakeLists.txt
+++ b/libs/editorqml/CMakeLists.txt
@@ -5,6 +5,8 @@ set(SETTINGS_SRCS
 	settings/wifisecurities/wifisecuritysetting.h
   settings/stringlistmodel.cpp
   settings/stringlistmodel.h
+	settings/wifistatus/connectionstatus.h
+	settings/wifistatus/connectionstatus.cpp
 )
 
 set(QML_SRCS
@@ -27,7 +29,6 @@ set(QML_SRCS
   qml/wifisecurity/authentication/enterprise/DynamicWep.qml
   qml/wifisecurity/authentication/enterprise/WpaEnterprise.qml
   qml/wifisecurity/authentication/enterprise/Wpa3Enterprise192.qml
-
   qml/wifisecurity/DnsList.qml
   qml/wifisecurity/AlternativeSubjectMatch.qml
 
@@ -36,6 +37,7 @@ set(QML_SRCS
   qml/PasswordPromptDialog.qml
 
   qml/AddConnectionDialog.qml
+  qml/wifistatus/ConnectionStatusForm.qml
 )
 
 add_library(plasmanm_editorqml SHARED ${SETTINGS_SRCS})
@@ -94,6 +96,7 @@ target_include_directories(plasmanm_editorqml
         ${CMAKE_CURRENT_SOURCE_DIR}/settings
         ${CMAKE_CURRENT_BINARY_DIR}
         ${CMAKE_CURRENT_SOURCE_DIR}/settings/wifisecurities
+        ${CMAKE_CURRENT_SOURCE_DIR}/settings/wifistatus
 )
 
 target_compile_definitions(plasmanm_editorqml PRIVATE BROADBANDPROVIDER_DATABASE=\"${BROADBANDPROVIDER_DATABASE}\")
diff --git a/libs/editorqml/qml/components/Wireless.qml b/libs/editorqml/qml/components/Wireless.qml
index 9e749388f..9d5221114 100644
--- a/libs/editorqml/qml/components/Wireless.qml
+++ b/libs/editorqml/qml/components/Wireless.qml
@@ -42,7 +42,12 @@ ColumnLayout {
         Layout.fillHeight: true
         currentIndex: tabBar.currentIndex
 
-        Item {/* TODO: connectionstatus page */}
+        Item {
+            PlasmaNMQ.ConnectionStatusForm {
+                anchors.fill: parent
+                connectionStatus: kcm.connectionStatus
+            }
+        }
 
         Item { /* TODO: general settings page */ }
 
diff --git a/libs/editorqml/qml/wifistatus/ConnectionStatusForm.qml b/libs/editorqml/qml/wifistatus/ConnectionStatusForm.qml
new file mode 100644
index 000000000..34b081e4c
--- /dev/null
+++ b/libs/editorqml/qml/wifistatus/ConnectionStatusForm.qml
@@ -0,0 +1,43 @@
+/*
+    SPDX-FileCopyrightText: 2026 Tushar Gupta <[email protected]>
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+import QtQuick
+import QtQuick.Controls as QQC2
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.networkmanagement.editorqml
+
+Kirigami.FormLayout {
+    id: root
+    required property ConnectionStatus connectionStatus
+    QQC2.Label {
+        visible: !root.connectionStatus.hasDetails
+        text: i18n("Disconnected")
+        horizontalAlignment: Text.AlignHCenter
+    }
+    Repeater {
+        model: root.connectionStatus.detailsModel
+        delegate: Item {
+            required property bool isSection
+            required property string sectionTitle
+            required property string detailLabel
+            required property string detailValue
+            Kirigami.FormData.isSection: isSection
+            Kirigami.FormData.label: isSection ? "" : detailLabel + ":"
+            implicitHeight: isSection ? sectionLabel.implicitHeight : valueLabel.implicitHeight
+            Kirigami.Heading {
+                id: sectionLabel
+                visible: isSection
+                anchors.horizontalCenter: parent.horizontalCenter
+
+                text: sectionTitle
+                level: 2
+            }
+            QQC2.Label {
+                id: valueLabel
+                visible: !isSection
+                text: detailValue
+            }
+        }
+    }
+}
diff --git a/libs/editorqml/settings/wifistatus/connectionstatus.cpp b/libs/editorqml/settings/wifistatus/connectionstatus.cpp
new file mode 100644
index 000000000..85c70e76f
--- /dev/null
+++ b/libs/editorqml/settings/wifistatus/connectionstatus.cpp
@@ -0,0 +1,158 @@
+/*
+    SPDX-FileCopyrightText: 2026 Tushar Gupta <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "connectionstatus.h"
+#include "connectiondetails.h"
+#include "connectiondetailsmodel.h"
+
+#include <NetworkManagerQt/AccessPoint>
+#include <NetworkManagerQt/ActiveConnection>
+#include <NetworkManagerQt/Connection>
+#include <NetworkManagerQt/ConnectionSettings>
+#include <NetworkManagerQt/Device>
+#include <NetworkManagerQt/Manager>
+#include <NetworkManagerQt/Settings>
+#include <NetworkManagerQt/WirelessDevice>
+#include <NetworkManagerQt/WirelessSetting>
+
+ConnectionStatus::ConnectionStatus(QObject *parent)
+    : QObject(parent)
+    , m_detailsModel(new ConnectionDetailsModel(this))
+{
+}
+
+ConnectionStatus::~ConnectionStatus() = default;
+
+void ConnectionStatus::setConnectionAndDevice(const NetworkManager::Connection::Ptr &connection,
+                                              const NetworkManager::Device::Ptr &device,
+                                              const QString &accessPointPath)
+{
+    m_connection = connection;
+    m_device = device;
+    m_accessPointPath = accessPointPath;
+    m_connectionUuid = connection ? connection->uuid() : QString();
+    updateConnectionDetails();
+}
+
+void ConnectionStatus::setConnectionUuid(const QString &uuid)
+{
+    if (m_connectionUuid != uuid) {
+        m_connectionUuid = uuid;
+        updateStatusWidget();
+    }
+}
+
+ConnectionDetailsModel *ConnectionStatus::detailsModel() const
+{
+    return m_detailsModel;
+}
+
+bool ConnectionStatus::hasDetails() const
+{
+    return m_detailsModel->rowCount() > 0;
+}
+
+void ConnectionStatus::updateStatusWidget()
+{
+    m_connection = nullptr;
+    m_device = nullptr;
+    m_accessPointPath.clear();
+
+    if (m_connectionUuid.isEmpty()) {
+        updateConnectionDetails();
+        return;
+    }
+
+    NetworkManager::Connection::Ptr nmConnection = NetworkManager::findConnectionByUuid(m_connectionUuid);
+    if (!nmConnection) {
+        return;
+    }
+    m_connection = nmConnection;
+
+    NetworkManager::ActiveConnection::Ptr activeConnection;
+    for (const NetworkManager::ActiveConnection::Ptr &active : NetworkManager::activeConnections()) {
+        if (active->uuid() == m_connectionUuid) {
+            activeConnection = active;
+            break;
+        }
+    }
+
+    if (activeConnection) {
+        const QStringList devicePaths = activeConnection->devices();
+        if (!devicePaths.isEmpty()) {
+            m_device = NetworkManager::findNetworkInterface(devicePaths.first());
+        }
+    } else {
+        const QString interfaceName = nmConnection->settings()->interfaceName();
+        if (!interfaceName.isEmpty()) {
+            for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) {
+                if (dev->interfaceName() == interfaceName) {
+                    m_device = dev;
+                    break;
+                }
+            }
+        }
+
+        if (!m_device) {
+            NetworkManager::ConnectionSettings::ConnectionType type = nmConnection->settings()->connectionType();
+            for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) {
+                if (type == NetworkManager::ConnectionSettings::Wireless && dev->type() == NetworkManager::Device::Wifi) {
+                    m_device = dev;
+                    break;
+                } else if (type == NetworkManager::ConnectionSettings::Wired && dev->type() == NetworkManager::Device::Ethernet) {
+                    m_device = dev;
+                    break;
+                }
+            }
+        }
+
+        if (m_device && m_device->type() == NetworkManager::Device::Wifi) {
+            NetworkManager::WirelessDevice::Ptr wirelessDevice = m_device.objectCast<NetworkManager::WirelessDevice>();
+            if (wirelessDevice) {
+                NetworkManager::WirelessSetting::Ptr wirelessSetting =
+                    nmConnection->settings()->setting(NetworkManager::Setting::Wireless).dynamicCast<NetworkManager::WirelessSetting>();
+                if (wirelessSetting) {
+                    const QString bssid = wirelessSetting->bssid();
+                    const QString ssid = wirelessSetting->ssid();
+
+                    for (const QString &apPath : wirelessDevice->accessPoints()) {
+                        NetworkManager::AccessPoint::Ptr ap = wirelessDevice->findAccessPoint(apPath);
+                        if (!ap) {
+                            continue;
+                        }
+                        if (!bssid.isEmpty()) {
+                            if (ap->hardwareAddress().toLower() == bssid.toLower()) {
+                                m_accessPointPath = apPath;
+                                break;
+                            }
+                        } else if (ap->ssid() == ssid) {
+                            m_accessPointPath = apPath;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    setConnectionAndDevice(nmConnection, m_device, m_accessPointPath);
+}
+
+QList<ConnectionDetails::ConnectionDetailSection> ConnectionStatus::getConnectionDetails() const
+{
+    if (!m_device) {
+        return {};
+    }
+    return ConnectionDetails::getConnectionDetails(m_connection, m_device, m_accessPointPath);
+}
+
+void ConnectionStatus::updateConnectionDetails()
+{
+    m_detailsModel->setDetailsList(getConnectionDetails());
+    Q_EMIT detailsChanged();
+}
+
+#include "moc_connectionstatus.cpp"
diff --git a/libs/editorqml/settings/wifistatus/connectionstatus.h b/libs/editorqml/settings/wifistatus/connectionstatus.h
new file mode 100644
index 000000000..24742fd2f
--- /dev/null
+++ b/libs/editorqml/settings/wifistatus/connectionstatus.h
@@ -0,0 +1,57 @@
+/*
+    SPDX-FileCopyrightText: 2026 Tushar Gupta <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#ifndef PLASMA_NM_CONNECTION_STATUS_H
+#define PLASMA_NM_CONNECTION_STATUS_H
+
+#include "plasmanm_editorqml_export.h"
+
+#include <NetworkManagerQt/Connection>
+#include <NetworkManagerQt/Device>
+#include <qqmlregistration.h>
+
+class ConnectionDetailsModel;
+namespace ConnectionDetails
+{
+struct ConnectionDetailSection;
+}
+
+class PLASMANM_EDITORQML_EXPORT ConnectionStatus : public QObject
+{
+    Q_OBJECT
+    QML_ELEMENT
+
+    Q_PROPERTY(ConnectionDetailsModel *detailsModel READ detailsModel CONSTANT)
+    Q_PROPERTY(bool hasDetails READ hasDetails NOTIFY detailsChanged)
+
+public:
+    explicit ConnectionStatus(QObject *parent = nullptr);
+    ~ConnectionStatus() override;
+
+    ConnectionDetailsModel *detailsModel() const;
+    bool hasDetails() const;
+
+    void setConnectionAndDevice(const NetworkManager::Connection::Ptr &connection, const NetworkManager::Device::Ptr &device, const QString &accessPointPath);
+
+    Q_INVOKABLE void setConnectionUuid(const QString &uuid);
+Q_SIGNALS:
+    void detailsChanged();
+
+private:
+    void updateStatusWidget();
+    void updateConnectionDetails();
+    QList<ConnectionDetails::ConnectionDetailSection> getConnectionDetails() const;
+
+    QString m_connectionUuid;
+
+    NetworkManager::Connection::Ptr m_connection;
+    NetworkManager::Device::Ptr m_device;
+    QString m_accessPointPath;
+
+    ConnectionDetailsModel *m_detailsModel = nullptr;
+};
+
+#endif // PLASMA_NM_CONNECTION_STATUS_WIDGET_H
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.