[plasma/plasma-nm] /: Refactoring general settings tab for all network connections

Devin Lin <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 847b9eef081c184507b84546efc2378dc7d105a1 by Devin Lin, on behalf of Tushar Gupta.
Committed on 06/08/2026 at 02:44.
Pushed by devinlin into branch 'master'.

Refactoring general settings tab for all network connections

This MR focus on the refactoring part for the General settings tab. It includes the QML for both general settings and advance persmission settings. 

Changes - 

1) Backend

`GeneralSetting` - A QML_UNCREATABLE QObject that exposes the general connection options as Q_PROPERTYs, including:

Auto-connect and connection priority
"All users may connect"
Automatic VPN and VPN selection
Firewall zone
Metered mode

`AdvancedPermissionsModel` - Lists system users with allow/disallow toggles, backs the Allowed Users dialog, and changes the per-user permissions with the connection's permissions map.

2) QML
  - `GeneralSettings.qml` - a Kirigami.FormLayout port of the form.
  - `AdvancePermissions.qml` - the "Allowed Users" dialog.

3) KCM wiring
  - Exposes generalSettings on the KCM, loads it in loadConnectionSettings(), and applies it in both save() paths (new and existing connections).

![Screenshot_20260719_215454](/uploads/d56cab1d5a814389621c141728b35b97/Screenshot_20260719_215454.png){width=666 height=600}
![Screenshot_20260718_165736](/uploads/98a44a00a6adbc3db7e4a67f2964d44f/Screenshot_20260718_165736.png){width=900 height=484}

Reused some of the functions such as `GeneralSetting::reloadFirewallZones()` (Previously ConnectionWidget::firewallZones())

M  +13   -0    kcms/kcm_connections_qml/kcm.cpp
M  +4    -0    kcms/kcm_connections_qml/kcm.h
M  +6    -1    kcms/kcm_connections_qml/ui/main.qml
M  +8    -0    libs/editorqml/CMakeLists.txt
M  +6    -1    libs/editorqml/qml/components/Wireless.qml
A  +82   -0    libs/editorqml/qml/generalSettings/AdvancedPermissionsDialog.qml     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +140  -0    libs/editorqml/qml/generalSettings/GeneralSettings.qml     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +101  -0    libs/editorqml/settings/generalSettings/advancedpermissionsmodel.cpp     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +51   -0    libs/editorqml/settings/generalSettings/advancedpermissionsmodel.h     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +263  -0    libs/editorqml/settings/generalSettings/generalsettings.cpp     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
A  +100  -0    libs/editorqml/settings/generalSettings/generalsettings.h     [License: LGPL(3+eV) LGPL(v3.0) LGPL(v2.1)]
M  +12   -0    libs/editorqml/settings/wifisecurities/wifisecuritysetting.cpp
M  +2    -0    libs/editorqml/settings/wifisecurities/wifisecuritysetting.h
M  +1    -0    libs/editorqml/settings/wifistatus/connectionstatus.h

https://invent.kde.org/plasma/plasma-nm/-/commit/847b9eef081c184507b84546efc2378dc7d105a1

diff --git a/kcms/kcm_connections_qml/kcm.cpp b/kcms/kcm_connections_qml/kcm.cpp
index ac673d2a4..9b4b0e40d 100644
--- a/kcms/kcm_connections_qml/kcm.cpp
+++ b/kcms/kcm_connections_qml/kcm.cpp
@@ -33,6 +33,7 @@ KCMNetworkManagementQml::KCMNetworkManagementQml(QObject *parent, const KPluginM
     , m_wifiSecurity(new WifiSecuritySetting(this))
     , m_security8021xSetting(new Security8021xSetting(this))
     , m_connectionStatus(new ConnectionStatus(this))
+    , m_generalSettings(new GeneralSetting(this))
     , m_timer(new QTimer(this))
 {
     // Check if we can use AP mode to identify security type
@@ -121,6 +122,10 @@ KCMNetworkManagementQml::KCMNetworkManagementQml(QObject *parent, const KPluginM
         qCDebug(PLASMA_NM_KCM_QML_LOG) << "Cannot preselect a connection";
     }
 
+    connect(m_generalSettings, &GeneralSetting::validChanged, this, [this]() {
+        kcmChanged(true);
+    });
+
     connect(NetworkManager::settingsNotifier(),
             &NetworkManager::SettingsNotifier::connectionAdded,
             this,
@@ -138,6 +143,10 @@ KCMNetworkManagementQml::KCMNetworkManagementQml(QObject *parent, const KPluginM
 
 KCMNetworkManagementQml::~KCMNetworkManagementQml() = default;
 
+GeneralSetting *KCMNetworkManagementQml::generalSettings() const
+{
+    return m_generalSettings;
+}
 ConnectionStatus *KCMNetworkManagementQml::connectionStatus() const
 {
     return m_connectionStatus;
@@ -252,6 +261,7 @@ void KCMNetworkManagementQml::save()
 {
     // process the pending settings
     if (m_pendingNewSettings) {
+        m_generalSettings->applyTo(m_pendingNewSettings, m_wifiSecurity);
         NMVariantMapMap map = m_pendingNewSettings->toMap();
         map.insert(QStringLiteral("802-11-wireless-security"), m_wifiSecurity->setting());
         if (m_wifiSecurity->enabled8021x()) {
@@ -272,6 +282,8 @@ void KCMNetworkManagementQml::save()
         Q_EMIT saveFailed(QStringLiteral("No connection selected"));
         return;
     }
+    NetworkManager::ConnectionSettings::Ptr settings = connection->settings();
+    m_generalSettings->applyTo(settings, m_wifiSecurity);
 
     NMVariantMapMap map = connection->settings()->toMap();
     if (m_wifiSecurity->securityType() != WifiSecuritySetting::None) {
@@ -314,6 +326,7 @@ void KCMNetworkManagementQml::loadConnectionSettings(const NetworkManager::Conne
 
     m_connectionType = connectionSettings->connectionType();
     Q_EMIT connectionTypeChanged();
+    m_generalSettings->loadConfig(connectionSettings);
     // check wireless only for rn
     if (connectionSettings->connectionType() != NetworkManager::ConnectionSettings::Wireless) {
         kcmChanged(false);
diff --git a/kcms/kcm_connections_qml/kcm.h b/kcms/kcm_connections_qml/kcm.h
index bc2affbf0..2decd8671 100644
--- a/kcms/kcm_connections_qml/kcm.h
+++ b/kcms/kcm_connections_qml/kcm.h
@@ -9,6 +9,7 @@
 
 #include "connectionstatus.h"
 #include "enums.h"
+#include "generalsettings.h"
 #include "handler.h"
 #include "security8021xsetting.h"
 #include "wifisecuritysetting.h"
@@ -28,6 +29,7 @@ class KCMNetworkManagementQml : public KQuickConfigModule
     Q_PROPERTY(bool useApMode READ useApMode CONSTANT)
     Q_PROPERTY(ConnectionStatus *connectionStatus READ connectionStatus CONSTANT)
     Q_PROPERTY(Enums::ConnectionType connectionType READ connectionType NOTIFY connectionTypeChanged)
+    Q_PROPERTY(GeneralSetting *generalSettings READ generalSettings CONSTANT)
 
 public:
     explicit KCMNetworkManagementQml(QObject *parent, const KPluginMetaData &metaData);
@@ -38,6 +40,7 @@ public:
     WifiSecuritySetting *wifiSecurity() const;
     Security8021xSetting *security8021xSetting() const;
     ConnectionStatus *connectionStatus() const;
+    GeneralSetting *generalSettings() const;
     bool useApMode() const;
 
     Q_INVOKABLE void onRequestCreateConnection(int connectionType, const QString &vpnType, const QString &specificType, bool shared);
@@ -89,6 +92,7 @@ private:
     WifiSecuritySetting *const m_wifiSecurity;
     Security8021xSetting *const m_security8021xSetting;
     ConnectionStatus *const m_connectionStatus;
+    GeneralSetting *const m_generalSettings;
 
     bool m_useApMode = false;
 
diff --git a/kcms/kcm_connections_qml/ui/main.qml b/kcms/kcm_connections_qml/ui/main.qml
index 0697f17ed..1fb4fcc27 100644
--- a/kcms/kcm_connections_qml/ui/main.qml
+++ b/kcms/kcm_connections_qml/ui/main.qml
@@ -310,7 +310,7 @@ Kirigami.Page {
             if (connectionPath === connectionView.currentConnectionPath) {
                 root.deselectConnections();
             }
-            handler.removeConnection(connectionPath);
+            kcm.handler.removeConnection(connectionPath);
         }
     }
 
@@ -331,6 +331,11 @@ Kirigami.Page {
         id: configurationDialog
     }
 
+    function deselectConnections() {
+        connectionView.currentConnectionName = "";
+        connectionView.currentConnectionPath = "";
+    }
+
     function showConfigurationDialog() {
         configurationDialog.show();
         configurationDialog.requestActivate();
diff --git a/libs/editorqml/CMakeLists.txt b/libs/editorqml/CMakeLists.txt
index aa93edb06..ff5a8694a 100644
--- a/libs/editorqml/CMakeLists.txt
+++ b/libs/editorqml/CMakeLists.txt
@@ -7,6 +7,10 @@ set(SETTINGS_SRCS
   settings/stringlistmodel.h
 	settings/wifistatus/connectionstatus.h
 	settings/wifistatus/connectionstatus.cpp
+  settings/generalSettings/generalsettings.cpp
+  settings/generalSettings/generalsettings.h
+  settings/generalSettings/advancedpermissionsmodel.h
+  settings/generalSettings/advancedpermissionsmodel.cpp
 )
 
 set(QML_SRCS
@@ -38,6 +42,9 @@ set(QML_SRCS
 
   qml/AddConnectionDialog.qml
   qml/wifistatus/ConnectionStatusForm.qml
+
+  qml/generalSettings/GeneralSettings.qml
+  qml/generalSettings/AdvancedPermissionsDialog.qml
 )
 
 add_library(plasmanm_editorqml SHARED ${SETTINGS_SRCS})
@@ -97,6 +104,7 @@ target_include_directories(plasmanm_editorqml
         ${CMAKE_CURRENT_BINARY_DIR}
         ${CMAKE_CURRENT_SOURCE_DIR}/settings/wifisecurities
         ${CMAKE_CURRENT_SOURCE_DIR}/settings/wifistatus
+        ${CMAKE_CURRENT_SOURCE_DIR}/settings/generalSettings
 )
 
 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 9d5221114..2e79547f6 100644
--- a/libs/editorqml/qml/components/Wireless.qml
+++ b/libs/editorqml/qml/components/Wireless.qml
@@ -49,7 +49,12 @@ ColumnLayout {
             }
         }
 
-        Item { /* TODO: general settings page */ }
+        Item {
+            PlasmaNMQ.GeneralSettings {
+                anchors.fill: parent
+                setting: kcm.generalSettings
+            }
+        }
 
         Item { /* TODO: wifi settings page */ }
 
diff --git a/libs/editorqml/qml/generalSettings/AdvancedPermissionsDialog.qml b/libs/editorqml/qml/generalSettings/AdvancedPermissionsDialog.qml
new file mode 100644
index 000000000..ed57c8fa8
--- /dev/null
+++ b/libs/editorqml/qml/generalSettings/AdvancedPermissionsDialog.qml
@@ -0,0 +1,82 @@
+/*
+    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 QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.networkmanagement.editorqml
+
+QQC2.Dialog {
+    id: dialog
+
+    modal: true
+
+    title: i18n("Allowed Users")
+
+    standardButtons: QQC2.Dialog.Ok | QQC2.Dialog.Cancel
+
+    implicitWidth: Kirigami.Units.gridUnit * 20
+    implicitHeight: Kirigami.Units.gridUnit * 15
+
+    property alias permissions: permissionsModel.permissions
+
+    AdvancedPermissionsModel {
+        id: permissionsModel
+    }
+
+    contentItem: ColumnLayout {
+        spacing: Kirigami.Units.smallSpacing
+
+        QQC2.Frame {
+            Layout.fillWidth: true
+            Layout.fillHeight: true
+            padding: 0
+
+            ListView {
+                anchors.fill: parent
+                clip: true
+
+                model: permissionsModel.users
+
+                delegate: QQC2.ItemDelegate {
+                    width: ListView.view.width
+
+                    contentItem: RowLayout {
+                        spacing: Kirigami.Units.smallSpacing
+
+                        QQC2.CheckBox {
+                            enabled: true
+                            checked: modelData.allowed
+
+                            onToggled: {
+                                if (checked) {
+                                    permissionsModel.allow(modelData.loginName);
+                                } else {
+                                    permissionsModel.disallow(modelData.loginName);
+                                }
+                            }
+                        }
+
+                        QQC2.Label {
+                            text: modelData.fullName
+                            font.bold: modelData.isCurrentUser
+                            Layout.preferredWidth: 160
+                            elide: Text.ElideRight
+                        }
+
+                        QQC2.Label {
+                            text: modelData.loginName
+                            opacity: 0.7
+                            Layout.fillWidth: true
+                            elide: Text.ElideRight
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/libs/editorqml/qml/generalSettings/GeneralSettings.qml b/libs/editorqml/qml/generalSettings/GeneralSettings.qml
new file mode 100644
index 000000000..5866f40ab
--- /dev/null
+++ b/libs/editorqml/qml/generalSettings/GeneralSettings.qml
@@ -0,0 +1,140 @@
+/*
+      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 QtQuick.Layouts
+import org.kde.kirigami as Kirigami
+import org.kde.plasma.networkmanagement.editorqml
+
+Kirigami.FormLayout {
+    id: root
+
+    required property GeneralSetting setting
+
+    RowLayout {
+        Layout.fillWidth: true
+
+        QQC2.CheckBox {
+            id: autoconnect
+
+            text: i18n("Connect automatically with priority")
+            checked: root.setting.autoconnect
+            enabled: !root.setting.isVpnConnection
+
+            onToggled: root.setting.autoconnect = checked
+        }
+
+        QQC2.SpinBox {
+            Layout.fillWidth: true
+
+            from: -100
+            to: 100
+            editable: true
+
+            enabled: autoconnect.checked && autoconnect.enabled
+            value: root.setting.autoconnectPriority
+
+            onValueModified: root.setting.autoconnectPriority = value
+        }
+    }
+
+    Loader {
+        id: permsDialogLoader
+        active: false
+
+        sourceComponent: AdvancedPermissionsDialog {
+            onAccepted: root.setting.permissions = permissions
+        }
+    }
+
+    RowLayout {
+        Layout.fillWidth: true
+
+        QQC2.CheckBox {
+            id: allUsers
+
+            text: i18n("All users may connect to this network")
+            checked: root.setting.allUsers
+
+            onToggled: root.setting.allUsers = checked
+        }
+
+        QQC2.Button {
+            Layout.fillWidth: true
+
+            text: i18n("Advanced…")
+            icon.name: "preferences-desktop-user"
+
+            enabled: !allUsers.checked
+
+            onClicked: {
+                if (!permsDialogLoader.active) {
+                    permsDialogLoader.active = true;
+                }
+
+                permsDialogLoader.item.permissions = root.setting.permissions;
+                permsDialogLoader.item.open();
+            }
+        }
+    }
+
+    RowLayout {
+        Layout.fillWidth: true
+
+        QQC2.CheckBox {
+            id: autoVpn
+
+            text: i18n("Automatically connect to VPN")
+            checked: root.setting.autoconnectVpn
+            enabled: !root.setting.isVpnConnection
+
+            onToggled: root.setting.autoconnectVpn = checked
+        }
+
+        QQC2.ComboBox {
+            Layout.fillWidth: true
+
+            enabled: autoVpn.checked && autoVpn.enabled
+
+            model: root.setting.vpnConnections
+            textRole: "text"
+            valueRole: "uuid"
+
+            currentIndex: indexOfValue(root.setting.vpnUuid)
+
+            onActivated: root.setting.vpnUuid = currentValue
+        }
+    }
+
+    QQC2.ComboBox {
+        Kirigami.FormData.label: i18n("Firewall zone:")
+        Layout.fillWidth: true
+
+        editable: true
+        model: root.setting.firewallZones
+        editText: root.setting.firewallZone
+
+        onEditTextChanged: {
+            if (editText !== root.setting.firewallZone)
+                root.setting.firewallZone = editText;
+        }
+    }
+
+    QQC2.ComboBox {
+        Kirigami.FormData.label: i18n("Metered:")
+        Layout.fillWidth: true
+
+        model: [i18nc("@item metered mode", "Automatic"), i18n("Yes"), i18n("No")]
+
+        currentIndex: root.setting.metered
+        onActivated: root.setting.metered = currentIndex
+    }
+
+    Item {
+        Layout.fillHeight: true
+    }
+}
diff --git a/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.cpp b/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.cpp
new file mode 100644
index 000000000..34aa912db
--- /dev/null
+++ b/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.cpp
@@ -0,0 +1,101 @@
+/*
+      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 "advancedpermissionsmodel.h"
+
+#include <KLocalizedString>
+#include <KUser>
+
+#include <algorithm>
+
+AdvancedPermissionsModel::AdvancedPermissionsModel(QObject *parent)
+    : QObject(parent)
+{
+    const QString currentLogin = KUser().loginName();
+
+    for (const KUser &user : KUser::allUsers()) {
+        if (user.userId().nativeId() < 1000 || user.loginName() == QLatin1String("nobody")) {
+            continue;
+        }
+        Item item;
+        item.loginName = user.loginName();
+        item.fullName = user.property(KUser::FullName).toString();
+        item.isCurrentUser = (item.loginName == currentLogin);
+        item.allowed = item.isCurrentUser;
+        m_users.append(item);
+    }
+}
+
+QVariantList AdvancedPermissionsModel::users() const
+{
+    QList<const Item *> sorted;
+    for (const Item &item : m_users) {
+        sorted.append(&item);
+    }
+
+    std::sort(sorted.begin(), sorted.end(), [](const Item *a, const Item *b) {
+        const QString an = a->fullName.isEmpty() ? a->loginName : a->fullName;
+        const QString bn = b->fullName.isEmpty() ? b->loginName : b->fullName;
+        return QString::localeAwareCompare(an, bn) < 0;
+    });
+
+    QVariantList list;
+    for (const Item *item : std::as_const(sorted)) {
+        list.append(QVariantMap{
+            {QStringLiteral("fullName"), item->fullName.isEmpty() ? i18nc("@item real name not available", "N/A") : item->fullName},
+            {QStringLiteral("loginName"), item->loginName},
+            {QStringLiteral("allowed"), item->allowed},
+            {QStringLiteral("isCurrentUser"), item->isCurrentUser},
+        });
+    }
+
+    return list;
+}
+
+QVariantMap AdvancedPermissionsModel::permissions() const
+{
+    QVariantMap map;
+    for (const Item &item : m_users) {
+        if (item.allowed) {
+            map.insert(item.loginName, item.tags);
+        }
+    }
+    return map;
+}
+
+void AdvancedPermissionsModel::setPermissions(const QVariantMap &permissions)
+{
+    for (Item &item : m_users) {
+        const bool inMap = permissions.contains(item.loginName);
+        item.allowed = inMap;
+        item.tags = inMap ? permissions.value(item.loginName).toString() : QString();
+    }
+    Q_EMIT usersChanged();
+}
+
+void AdvancedPermissionsModel::allow(const QString &loginName)
+{
+    for (Item &item : m_users) {
+        if (item.loginName == loginName && !item.allowed) {
+            item.allowed = true;
+            Q_EMIT usersChanged();
+            return;
+        }
+    }
+}
+
+void AdvancedPermissionsModel::disallow(const QString &loginName)
+{
+    for (Item &item : m_users) {
+        if (item.loginName == loginName && item.allowed && !item.isCurrentUser) {
+            item.allowed = false;
+            Q_EMIT usersChanged();
+            return;
+        }
+    }
+}
+
+#include "moc_advancedpermissionsmodel.cpp"
diff --git a/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.h b/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.h
new file mode 100644
index 000000000..f6b07911e
--- /dev/null
+++ b/libs/editorqml/settings/generalSettings/advancedpermissionsmodel.h
@@ -0,0 +1,51 @@
+/*
+      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_ADVANCED_PERMISSIONS_H
+#define PLASMA_NM_ADVANCED_PERMISSIONS_H
+
+#include "plasmanm_editorqml_export.h"
+
+#include <QObject>
+#include <QVariantList>
+#include <QVariantMap>
+#include <qqmlregistration.h>
+
+class PLASMANM_EDITORQML_EXPORT AdvancedPermissionsModel : public QObject
+{
+    Q_OBJECT
+    QML_ELEMENT
+
+    Q_PROPERTY(QVariantList users READ users NOTIFY usersChanged)
+    Q_PROPERTY(QVariantMap permissions READ permissions WRITE setPermissions NOTIFY usersChanged)
+
+public:
+    explicit AdvancedPermissionsModel(QObject *parent = nullptr);
+
+    QVariantList users() const;
+
+    QVariantMap permissions() const;
+    void setPermissions(const QVariantMap &permissions);
+
+    Q_INVOKABLE void allow(const QString &loginName);
+    Q_INVOKABLE void disallow(const QString &loginName);
+
+Q_SIGNALS:
+    void usersChanged();
+
+private:
+    struct Item {
+        QString fullName;
+        QString loginName;
+        QString tags;
+        bool allowed = false;
+        bool isCurrentUser = false;
+    };
+
+    QList<Item> m_users;
+};
+
+#endif
diff --git a/libs/editorqml/settings/generalSettings/generalsettings.cpp b/libs/editorqml/settings/generalSettings/generalsettings.cpp
new file mode 100644
index 000000000..9d3dafbd0
--- /dev/null
+++ b/libs/editorqml/settings/generalSettings/generalsettings.cpp
@@ -0,0 +1,263 @@
+/*
+      SPDX-FileCopyrightText: 2026 Tushar Gupta <[email protected]>
+      SPDX-FileCopyrightText: 2013 Jan Grulich <[email protected]>
+
+      SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "generalsettings.h"
+#include "wifisecuritysetting.h"
+
+#include <NetworkManagerQt/Connection>
+#include <NetworkManagerQt/Manager>
+#include <NetworkManagerQt/Settings>
+
+#include <KUser>
+
+#include <QDBusConnection>
+#include <QDBusMessage>
+#include <QDBusPendingReply>
+#include <qtmetamacros.h>
+
+GeneralSetting::GeneralSetting(QObject *parent)
+    : QObject(parent)
+{
+}
+
+void GeneralSetting::reloadVpnConnections()
+{
+    m_vpnConnections.clear();
+
+    const NetworkManager::Connection::List list = NetworkManager::listConnections();
+
+    for (const NetworkManager::Connection::Ptr &conn : list) {
+        const NetworkManager::ConnectionSettings::Ptr conSet = conn->settings();
+
+        if (conSet->connectionType() == NetworkManager::ConnectionSettings::Vpn || conSet->connectionType() == NetworkManager::ConnectionSettings::WireGuard) {
+            m_vpnConnections.append(QVariantMap{{QStringLiteral("text"), conSet->id()}, {QStringLiteral("uuid"), conSet->uuid()}});
+        }
+    }
+
+    Q_EMIT vpnConnectionsChanged();
+}
+
+void GeneralSetting::reloadFirewallZones()
+{
+    QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.fedoraproject.FirewallD1"),
+                                                      QStringLiteral("/org/fedoraproject/FirewallD1"),
+                                                      QStringLiteral("org.fedoraproject.FirewallD1.zone"),
+                                                      QStringLiteral("getZones"));
+    QDBusPendingReply<QStringList> reply = QDBusConnection::systemBus().asyncCall(msg);
+    reply.waitForFinished();
+    m_firewallZones = reply.isValid() ? reply.value() : QStringList{};
+    Q_EMIT firewallZonesChanged();
+}
+
+void GeneralSetting::loadConfig(const NetworkManager::ConnectionSettings::Ptr &settings)
+{
+    if (!settings) {
+        return;
+    }
+
+    setIsVpnConnection(settings->connectionType() == NetworkManager::ConnectionSettings::Vpn);
+
+    QVariantMap perms;
+    const QHash<QString, QString> nmPerms = settings->permissions();
+    for (auto it = nmPerms.constBegin(); it != nmPerms.constEnd(); it++) {
+        perms.insert(it.key(), it.value());
+    }
+    setPermissions(perms);
+
+    setFirewallZone(settings->zone());
+
+    reloadVpnConnections();
+
+    const QStringList secondaries = settings->secondaries();
+    QString foundVpn;
+    for (const QVariant &entry : std::as_const(m_vpnConnections)) {
+        const QString uuid = entry.toMap().value(QStringLiteral("uuid")).toString();
+        if (!uuid.isEmpty() && secondaries.contains(uuid)) {
+            foundVpn = uuid;
+            break;
+        }
+    }
+    setAutoconnectVpn(!foundVpn.isEmpty());
+    setVpnUuid(foundVpn);
+
+    setAutoconnect(settings->autoconnect());
+    setAutoconnectPriority(settings->autoconnectPriority());
+    setMetered(static_cast<int>(settings->metered()));
+
+    reloadFirewallZones();
+
+    Q_EMIT validChanged();
+}
+
+void GeneralSetting::applyTo(const NetworkManager::ConnectionSettings::Ptr &settings, WifiSecuritySetting *wifiSecurity) const
+{
+    if (!settings) {
+        return;
+    }
+
+    settings->setAutoconnect(m_autoconnect);
+
+    if (m_allUsers) {
+        settings->setPermissions(QHash<QString, QString>());
+        if (wifiSecurity) {
+            wifiSecurity->setStoreSecretsSystemWide(m_allUsers);
+        }
+    } else if (m_permissions.isEmpty()) {
+        settings->addToPermissions(KUser().loginName(), QString());
+    } else {
+        QHash<QString, QString> nmPerms;
+        for (auto it = m_permissions.constBegin(); it != m_permissions.constEnd(); ++it) {
+            nmPerms.insert(it.key(), it.value().toString());
+        }
+        settings->setPermissions(nmPerms);
+    }
+
+    settings->setSecondaries(m_autoconnectVpn && !m_vpnUuid.isEmpty() ? QStringList{m_vpnUuid} : QStringList{});
+
+    if (!m_firewallZone.isEmpty()) {
+        settings->setZone(m_firewallZone);
+    }
+
+    if (m_autoconnect) {
+        settings->setAutoconnectPriority(m_autoconnectPriority);
+    }
+
+    settings->setMetered(static_cast<NetworkManager::ConnectionSettings::Metered>(m_metered));
+}
+
+bool GeneralSetting::autoconnect() const
+{
+    return m_autoconnect;
+}
+void GeneralSetting::setAutoconnect(bool v)
+{
+    if (m_autoconnect != v) {
+        m_autoconnect = v;
+        Q_EMIT autoconnectChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+int GeneralSetting::autoconnectPriority() const
+{
+    return m_autoconnectPriority;
+}
+void GeneralSetting::setAutoconnectPriority(int v)
+{
+    if (m_autoconnectPriority != v) {
+        m_autoconnectPriority = v;
+        Q_EMIT autoconnectPriorityChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+bool GeneralSetting::allUsers() const
+{
+    return m_allUsers;
+}
+void GeneralSetting::setAllUsers(bool v)
+{
+    if (m_allUsers != v) {
+        m_allUsers = v;
+        Q_EMIT allUsersChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+bool GeneralSetting::autoconnectVpn() const
+{
+    return m_autoconnectVpn;
+}
+void GeneralSetting::setAutoconnectVpn(bool v)
+{
+    if (m_autoconnectVpn != v) {
+        m_autoconnectVpn = v;
+        Q_EMIT autoconnectVpnChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+QString GeneralSetting::vpnUuid() const
+{
+    return m_vpnUuid;
+}
+void GeneralSetting::setVpnUuid(const QString &v)
+{
+    if (m_vpnUuid != v) {
+        m_vpnUuid = v;
+        Q_EMIT vpnUuidChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+QString GeneralSetting::firewallZone() const
+{
+    return m_firewallZone;
+}
+void GeneralSetting::setFirewallZone(const QString &v)
+{
+    if (m_firewallZone != v) {
+        m_firewallZone = v;
+        Q_EMIT firewallZoneChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+int GeneralSetting::metered() const
+{
+    return m_metered;
+}
+void GeneralSetting::setMetered(int v)
+{
+    if (m_metered != v) {
+        m_metered = v;
+        Q_EMIT meteredChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+QVariantMap GeneralSetting::permissions() const
+{
+    return m_permissions;
+}
+void GeneralSetting::setPermissions(const QVariantMap &p)
+{
+    m_permissions = p;
+    setAllUsers(p.isEmpty());
+    Q_EMIT permissionsChanged();
+    Q_EMIT validChanged();
+}
+
+bool GeneralSetting::isVpnConnection() const
+{
+    return m_isVpnConnection;
+}
+void GeneralSetting::setIsVpnConnection(bool v)
+{
+    if (m_isVpnConnection != v) {
+        m_isVpnConnection = v;
+        Q_EMIT isVpnConnectionChanged();
+        Q_EMIT validChanged();
+    }
+}
+
+QVariantList GeneralSetting::vpnConnections() const
+{
+    return m_vpnConnections;
+}
+QStringList GeneralSetting::firewallZones() const
+{
+    return m_firewallZones;
+}
+
+// void GeneralSetting::setWifiSecurity(WifiSecuritySetting *wifiSecurity)
+//{
+//     m_wifisecurity = wifiSecurity;
+//     qDebug() << m_wifisecurity;
+// }
+
+#include "moc_generalsettings.cpp"
diff --git a/libs/editorqml/settings/generalSettings/generalsettings.h b/libs/editorqml/settings/generalSettings/generalsettings.h
new file mode 100644
index 000000000..cbb907d65
--- /dev/null
+++ b/libs/editorqml/settings/generalSettings/generalsettings.h
@@ -0,0 +1,100 @@
+/*
+    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_GENERAL_SETTING_H
+#define PLASMA_NM_GENERAL_SETTING_H
+
+#include "plasmanm_editorqml_export.h"
+#include "wifisecuritysetting.h"
+
+#include <NetworkManagerQt/ConnectionSettings>
+#include <QObject>
+#include <QVariantList>
+#include <QVariantMap>
+#include <qqmlregistration.h>
+
+class PLASMANM_EDITORQML_EXPORT GeneralSetting : public QObject
+{
+    Q_OBJECT
+    QML_ELEMENT
+    QML_UNCREATABLE("")
+
+    Q_PROPERTY(bool autoconnect READ autoconnect WRITE setAutoconnect NOTIFY autoconnectChanged)
+    Q_PROPERTY(int autoconnectPriority READ autoconnectPriority WRITE setAutoconnectPriority NOTIFY autoconnectPriorityChanged)
+    Q_PROPERTY(bool allUsers READ allUsers WRITE setAllUsers NOTIFY allUsersChanged)
+    Q_PROPERTY(bool autoconnectVpn READ autoconnectVpn WRITE setAutoconnectVpn NOTIFY autoconnectVpnChanged)
+    Q_PROPERTY(QString vpnUuid READ vpnUuid WRITE setVpnUuid NOTIFY vpnUuidChanged)
+    Q_PROPERTY(QString firewallZone READ firewallZone WRITE setFirewallZone NOTIFY firewallZoneChanged)
+    Q_PROPERTY(int metered READ metered WRITE setMetered NOTIFY meteredChanged)
+    Q_PROPERTY(QVariantMap permissions READ permissions WRITE setPermissions NOTIFY permissionsChanged)
+
+    Q_PROPERTY(bool isVpnConnection READ isVpnConnection NOTIFY isVpnConnectionChanged)
+    Q_PROPERTY(QVariantList vpnConnections READ vpnConnections NOTIFY vpnConnectionsChanged)
+    Q_PROPERTY(QStringList firewallZones READ firewallZones NOTIFY firewallZonesChanged)
+
+public:
+    explicit GeneralSetting(QObject *parent = nullptr);
+
+    bool autoconnect() const;
+    void setAutoconnect(bool value);
+    int autoconnectPriority() const;
+    void setAutoconnectPriority(int value);
+    bool allUsers() const;
+    void setAllUsers(bool value);
+    bool autoconnectVpn() const;
+    void setAutoconnectVpn(bool value);
+    QString vpnUuid() const;
+    void setVpnUuid(const QString &uuid);
+    QString firewallZone() const;
+    void setFirewallZone(const QString &zone);
+    int metered() const;
+    void setMetered(int value);
+    QVariantMap permissions() const;
+    void setPermissions(const QVariantMap &permissions);
+
+    bool isVpnConnection() const;
+    QVariantList vpnConnections() const;
+    QStringList firewallZones() const;
+
+    void loadConfig(const NetworkManager::ConnectionSettings::Ptr &settings);
+    void applyTo(const NetworkManager::ConnectionSettings::Ptr &settings, WifiSecuritySetting *wifiSecurity) const;
+
+Q_SIGNALS:
+    void autoconnectChanged();
+    void autoconnectPriorityChanged();
+    void allUsersChanged();
+    void autoconnectVpnChanged();
+    void vpnUuidChanged();
+    void firewallZoneChanged();
+    void meteredChanged();
+    void permissionsChanged();
+    void isVpnConnectionChanged();
+    void vpnConnectionsChanged();
+    void firewallZonesChanged();
+    void validChanged();
+
+private:
+    void reloadVpnConnections();
+    void reloadFirewallZones();
+    void setIsVpnConnection(bool value);
+
+    bool m_autoconnect = true;
+    int m_autoconnectPriority = 0;
+    bool m_allUsers = false;
+    bool m_autoconnectVpn = false;
+    QString m_vpnUuid;
+    QString m_firewallZone;
+    int m_metered = 0;
+    QVariantMap m_permissions;
+
+    bool m_isVpnConnection = false;
+    QVariantList m_vpnConnections;
+    QStringList m_firewallZones;
+
+    // WifiSecuritySetting *m_wifisecurity = nullptr;
+};
+
+#endif // PLASMA_NM_GENERAL_SETTING_H
diff --git a/libs/editorqml/settings/wifisecurities/wifisecuritysetting.cpp b/libs/editorqml/settings/wifisecurities/wifisecuritysetting.cpp
index 548e6cbb8..189cd9cf3 100755
--- a/libs/editorqml/settings/wifisecurities/wifisecuritysetting.cpp
+++ b/libs/editorqml/settings/wifisecurities/wifisecuritysetting.cpp
@@ -496,4 +496,16 @@ void WifiSecuritySetting::setLeapPasswordOption(PasswordOption v)
     Q_EMIT validChanged();
 }
 
+void WifiSecuritySetting::setStoreSecretsSystemWide(bool system)
+{
+    const auto passwordOption = system ? StoreForAllUsers : StoreForUser;
+    const auto password8021xOption = system ? Security8021xSetting::StoreForAllUsers : Security8021xSetting::StoreForUser;
+
+    setWepKeyOption(passwordOption);
+    setLeapPasswordOption(passwordOption);
+    setPskOption(passwordOption);
+
+    m_8021xSetting->setPasswordOptions(password8021xOption);
+}
+
 #include "moc_wifisecuritysetting.cpp"
diff --git a/libs/editorqml/settings/wifisecurities/wifisecuritysetting.h b/libs/editorqml/settings/wifisecurities/wifisecuritysetting.h
index a12b6f3cb..f5cd9a7ef 100644
--- a/libs/editorqml/settings/wifisecurities/wifisecuritysetting.h
+++ b/libs/editorqml/settings/wifisecurities/wifisecuritysetting.h
@@ -106,6 +106,8 @@ public:
     [[nodiscard]] PasswordOption leapPasswordOption() const;
     void setLeapPasswordOption(PasswordOption option);
 
+    void setStoreSecretsSystemWide(bool system);
+
     [[nodiscard]] bool showPsk() const;
     [[nodiscard]] bool showWep() const;
     [[nodiscard]] bool showLeap() const;
diff --git a/libs/editorqml/settings/wifistatus/connectionstatus.h b/libs/editorqml/settings/wifistatus/connectionstatus.h
index 24742fd2f..6582d2a96 100644
--- a/libs/editorqml/settings/wifistatus/connectionstatus.h
+++ b/libs/editorqml/settings/wifistatus/connectionstatus.h
@@ -22,6 +22,7 @@ struct ConnectionDetailSection;
 class PLASMANM_EDITORQML_EXPORT ConnectionStatus : public QObject
 {
     Q_OBJECT
+    QML_UNCREATABLE("")
     QML_ELEMENT
 
     Q_PROPERTY(ConnectionDetailsModel *detailsModel READ detailsModel CONSTANT)
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.