summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/bar/popouts/Network.qml33
-rw-r--r--plan.md137
-rw-r--r--services/Nmcli.qml33
3 files changed, 49 insertions, 154 deletions
diff --git a/modules/bar/popouts/Network.qml b/modules/bar/popouts/Network.qml
index f040b6a..cb012bf 100644
--- a/modules/bar/popouts/Network.qml
+++ b/modules/bar/popouts/Network.qml
@@ -20,27 +20,27 @@ ColumnLayout {
StyledText {
Layout.topMargin: Appearance.padding.normal
Layout.rightMargin: Appearance.padding.small
- text: qsTr("Wifi %1").arg(Network.wifiEnabled ? "enabled" : "disabled")
+ text: qsTr("Wifi %1").arg(Nmcli.wifiEnabled ? "enabled" : "disabled")
font.weight: 500
}
Toggle {
label: qsTr("Enabled")
- checked: Network.wifiEnabled
- toggle.onToggled: Network.enableWifi(checked)
+ checked: Nmcli.wifiEnabled
+ toggle.onToggled: Nmcli.enableWifi(checked)
}
StyledText {
Layout.topMargin: Appearance.spacing.small
Layout.rightMargin: Appearance.padding.small
- text: qsTr("%1 networks available").arg(Network.networks.length)
+ text: qsTr("%1 networks available").arg(Nmcli.networks.length)
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small
}
Repeater {
model: ScriptModel {
- values: [...Network.networks].sort((a, b) => {
+ values: [...Nmcli.networks].sort((a, b) => {
if (a.active !== b.active)
return b.active - a.active;
return b.strength - a.strength;
@@ -50,7 +50,7 @@ ColumnLayout {
RowLayout {
id: networkItem
- required property Network.AccessPoint modelData
+ required property Nmcli.AccessPoint modelData
readonly property bool isConnecting: root.connectingToSsid === modelData.ssid
readonly property bool loading: networkItem.isConnecting
@@ -111,14 +111,14 @@ ColumnLayout {
StateLayer {
color: networkItem.modelData.active ? Colours.palette.m3onPrimary : Colours.palette.m3onSurface
- disabled: networkItem.loading || !Network.wifiEnabled
+ disabled: networkItem.loading || !Nmcli.wifiEnabled
function onClicked(): void {
if (networkItem.modelData.active) {
- Network.disconnectFromNetwork();
+ Nmcli.disconnectFromNetwork();
} else {
root.connectingToSsid = networkItem.modelData.ssid;
- Network.connectToNetwork(networkItem.modelData.ssid, "", networkItem.modelData.bssid, null);
+ Nmcli.connectToNetwork(networkItem.modelData.ssid, "", networkItem.modelData.bssid, null);
}
}
}
@@ -151,10 +151,10 @@ ColumnLayout {
StateLayer {
color: Colours.palette.m3onPrimaryContainer
- disabled: Network.scanning || !Network.wifiEnabled
+ disabled: Nmcli.scanning || !Nmcli.wifiEnabled
function onClicked(): void {
- Network.rescanWifi();
+ Nmcli.rescanWifi();
}
}
@@ -163,7 +163,7 @@ ColumnLayout {
anchors.centerIn: parent
spacing: Appearance.spacing.small
- opacity: Network.scanning ? 0 : 1
+ opacity: Nmcli.scanning ? 0 : 1
MaterialIcon {
id: scanIcon
@@ -188,22 +188,21 @@ ColumnLayout {
strokeWidth: Appearance.padding.small / 2
bgColour: "transparent"
implicitHeight: parent.implicitHeight - Appearance.padding.smaller * 2
- running: Network.scanning
+ running: Nmcli.scanning
}
}
- // Reset connecting state when network changes
Connections {
- target: Network
+ target: Nmcli
function onActiveChanged(): void {
- if (Network.active && root.connectingToSsid === Network.active.ssid) {
+ if (Nmcli.active && root.connectingToSsid === Nmcli.active.ssid) {
root.connectingToSsid = "";
}
}
function onScanningChanged(): void {
- if (!Network.scanning)
+ if (!Nmcli.scanning)
scanIcon.rotation = 0;
}
}
diff --git a/plan.md b/plan.md
deleted file mode 100644
index 4762ef0..0000000
--- a/plan.md
+++ /dev/null
@@ -1,137 +0,0 @@
-# Nmcli.qml Feature Completion Plan
-
-This document outlines the missing features needed in `Nmcli.qml` to replace `Network.qml` or rewrite the wireless panel in the control center.
-
-## Current Status
-
-`Nmcli.qml` currently has:
-- ✅ Device status queries
-- ✅ Wireless/Ethernet interface listing
-- ✅ Interface connection status checking
-- ✅ Basic wireless connection (SSID + password)
-- ✅ Disconnect functionality
-- ✅ Device details (basic)
-- ✅ Interface up/down
-- ✅ WiFi scanning
-- ✅ SSID listing with signal/security (sorted)
-
-## Missing Features
-
-### 1. WiFi Radio Control
-- [x] `enableWifi(enabled: bool)` - Turn WiFi radio on/off
-- [x] `toggleWifi()` - Toggle WiFi radio state
-- [x] `wifiEnabled` property - Current WiFi radio state
-- [x] Monitor WiFi radio state changes
-
-**Implementation Notes:**
-- Use `nmcli radio wifi on/off`
-- Monitor state with `nmcli radio wifi`
-- Update `wifiEnabled` property on state changes
-
-### 2. Network List Management
-- [x] `networks` property - List of AccessPoint objects
-- [x] `active` property - Currently active network
-- [x] Real-time network list updates
-- [x] Network grouping by SSID with signal prioritization
-- [x] AccessPoint component/object with properties:
- - `ssid`, `bssid`, `strength`, `frequency`, `active`, `security`, `isSecure`
-
-**Implementation Notes:**
-- Use `nmcli -g ACTIVE,SIGNAL,FREQ,SSID,BSSID,SECURITY d w`
-- Parse and group networks by SSID
-- Prioritize active/connected networks
-- Update network list on connection changes
-
-### 3. Connection Management - BSSID Support
-- [x] BSSID support in `connectWireless()` function
-- [x] Connection profile creation with BSSID (`createConnectionWithPassword`)
-- [x] Handle BSSID in connection commands
-
-**Implementation Notes:**
-- Use `nmcli connection add` with `802-11-wireless.bssid` for BSSID-based connections
-- Fallback to SSID-only connection if BSSID not available
-- Handle existing connection profiles when BSSID is provided
-
-### 4. Saved Connection Profile Management
-- [x] `savedConnections` property - List of saved connection names
-- [x] `savedConnectionSsids` property - List of saved SSIDs
-- [x] `hasSavedProfile(ssid: string)` function - Check if profile exists
-- [x] `forgetNetwork(ssid: string)` function - Delete connection profile
-- [x] Load saved connections on startup
-- [x] Update saved connections list after connection changes
-
-**Implementation Notes:**
-- Use `nmcli -t -f NAME,TYPE connection show` to list connections
-- Query SSIDs for WiFi connections: `nmcli -t -f 802-11-wireless.ssid connection show <name>`
-- Use `nmcli connection delete <name>` to forget networks
-- Case-insensitive SSID matching
-
-### 5. Pending Connection Tracking
-- [x] `pendingConnection` property - Track connection in progress
-- [x] Connection state tracking with timers
-- [x] Connection success/failure detection
-- [x] Automatic retry or callback on failure
-
-**Implementation Notes:**
-- Track pending connection with SSID/BSSID
-- Use timers to check connection status
-- Monitor network list updates to detect successful connection
-- Handle connection failures and trigger callbacks
-
-### 6. Connection Failure Handling
-- [x] `connectionFailed(ssid: string)` signal
-- [x] Password requirement detection from error messages
-- [x] Connection retry logic
-- [x] Error message parsing and reporting
-
-**Implementation Notes:**
-- Parse stderr output for password requirements
-- Detect specific error patterns (e.g., "Secrets were required")
-- Emit signals for UI to handle password dialogs
-- Provide meaningful error messages
-
-### 7. Password Callback Handling
-- [x] `connectToNetworkWithPasswordCheck()` function
-- [x] Try connection without password first (use saved password)
-- [x] Callback on password requirement
-- [x] Handle both secure and open networks
-
-**Implementation Notes:**
-- Attempt connection without password for secure networks
-- If connection fails with password error, trigger callback
-- For open networks, connect directly
-- Support callback pattern for password dialogs
-
-### 8. Device Details Parsing
-- [x] Full parsing of `device show` output
-- [x] `wirelessDeviceDetails` property with:
- - `ipAddress`, `gateway`, `dns[]`, `subnet`, `macAddress`
-- [x] `ethernetDeviceDetails` property with:
- - `ipAddress`, `gateway`, `dns[]`, `subnet`, `macAddress`, `speed`
-- [x] `cidrToSubnetMask()` helper function
-- [x] Update device details on connection changes
-
-**Implementation Notes:**
-- Parse `nmcli device show <interface>` output
-- Extract IP4.ADDRESS, IP4.GATEWAY, IP4.DNS, etc.
-- Convert CIDR notation to subnet mask
-- Handle both wireless and ethernet device details
-
-### 9. Connection Status Monitoring
-- [x] Automatic network list refresh on connection changes
-- [x] Monitor connection state changes
-- [x] Update active network property
-- [x] Refresh device details on connection
-
-**Implementation Notes:**
-- Use Process stdout SplitParser to monitor changes
-- Trigger network list refresh on connection events
-- Update `active` property when connection changes
-- Refresh device details when connected
-
-### 10. Ethernet Device Management
-- [x] `ethernetDevices` property - List of ethernet devices
-- [x] `activeEthernet` property - Currently active ethernet device
-- [x] `connectEthernet(connectionName, interfaceName)` function
-- [x] `disconnectEthernet(connectionName)` function
-- [x] Ethernet device details parsing
diff --git a/services/Nmcli.qml b/services/Nmcli.qml
index 4e45b41..5fb0c6c 100644
--- a/services/Nmcli.qml
+++ b/services/Nmcli.qml
@@ -14,6 +14,7 @@ Singleton {
property string activeInterface: ""
property string activeConnection: ""
property bool wifiEnabled: true
+ readonly property bool scanning: rescanProc.running
readonly property list<AccessPoint> networks: []
readonly property AccessPoint active: networks.find(n => n.active) ?? null
property list<string> savedConnections: []
@@ -235,6 +236,10 @@ Singleton {
}
}
+ function connectToNetwork(ssid: string, password: string, bssid: string, callback: var): void {
+ connectWireless(ssid, password, bssid, callback);
+ }
+
function connectWireless(ssid: string, password: string, bssid: string, callback: var, retryCount: int): void {
const hasBssid = bssid !== undefined && bssid !== null && bssid.length > 0;
const retries = retryCount !== undefined ? retryCount : 0;
@@ -473,6 +478,22 @@ Singleton {
}
}
+ function disconnectFromNetwork(): void {
+ if (active && active.ssid) {
+ executeCommand(["connection", "down", active.ssid], (result) => {
+ if (result.success) {
+ getNetworks(() => {});
+ }
+ });
+ } else {
+ executeCommand(["device", "disconnect", "wifi"], (result) => {
+ if (result.success) {
+ getNetworks(() => {});
+ }
+ });
+ }
+ }
+
function getDeviceDetails(interfaceName: string, callback: var): void {
executeCommand(["device", "show", interfaceName], (result) => {
if (callback) callback(result.output);
@@ -543,6 +564,10 @@ Singleton {
});
}
+ function rescanWifi(): void {
+ rescanProc.running = true;
+ }
+
function enableWifi(enabled: bool, callback: var): void {
const cmd = enabled ? "on" : "off";
executeCommand(["radio", "wifi", cmd], (result) => {
@@ -1153,6 +1178,14 @@ Singleton {
}
Process {
+ id: rescanProc
+ command: ["nmcli", "dev", "wifi", "list", "--rescan", "yes"]
+ onExited: {
+ getNetworks(() => {});
+ }
+ }
+
+ Process {
id: monitorProc
running: true
command: ["nmcli", "monitor"]