summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/Nmcli.qml624
1 files changed, 333 insertions, 291 deletions
diff --git a/services/Nmcli.qml b/services/Nmcli.qml
index a9f9e8e..24a93da 100644
--- a/services/Nmcli.qml
+++ b/services/Nmcli.qml
@@ -1,4 +1,5 @@
pragma Singleton
+pragma ComponentBehavior: Bound
import Quickshell
import Quickshell.Io
@@ -19,7 +20,7 @@ Singleton {
readonly property AccessPoint active: networks.find(n => n.active) ?? null
property list<string> savedConnections: []
property list<string> savedConnectionSsids: []
-
+
property var wifiConnectionQueue: []
property int currentSsidQueryIndex: 0
property var pendingConnection: null
@@ -28,9 +29,8 @@ Singleton {
property var ethernetDeviceDetails: null
property list<var> ethernetDevices: []
readonly property var activeEthernet: ethernetDevices.find(d => d.connected) ?? null
-
+
property list<var> activeProcesses: []
- property var debugLogger: null
// Constants
readonly property string deviceTypeWifi: "wifi"
@@ -55,63 +55,35 @@ Singleton {
readonly property string connectionParamPassword: "password"
readonly property string connectionParamBssid: "802-11-wireless.bssid"
- function setDebugLogger(logger: var): void {
- root.debugLogger = logger;
- }
-
- function log(message: string): void {
- if (root.debugLogger) {
- root.debugLogger(message);
- } else {
- console.log("[Nmcli]", message);
- }
- }
-
- function appendLog(message: string): void {
- log(message);
- }
-
function detectPasswordRequired(error: string): bool {
if (!error || error.length === 0) {
return false;
}
-
- return (error.includes("Secrets were required") ||
- error.includes("Secrets were required, but not provided") ||
- error.includes("No secrets provided") ||
- error.includes("802-11-wireless-security.psk") ||
- error.includes("password for") ||
- (error.includes("password") && !error.includes("Connection activated") && !error.includes("successfully")) ||
- (error.includes("Secrets") && !error.includes("Connection activated") && !error.includes("successfully")) ||
- (error.includes("802.11") && !error.includes("Connection activated") && !error.includes("successfully"))) &&
- !error.includes("Connection activated") &&
- !error.includes("successfully");
+
+ return (error.includes("Secrets were required") || error.includes("Secrets were required, but not provided") || error.includes("No secrets provided") || error.includes("802-11-wireless-security.psk") || error.includes("password for") || (error.includes("password") && !error.includes("Connection activated") && !error.includes("successfully")) || (error.includes("Secrets") && !error.includes("Connection activated") && !error.includes("successfully")) || (error.includes("802.11") && !error.includes("Connection activated") && !error.includes("successfully"))) && !error.includes("Connection activated") && !error.includes("successfully");
}
function parseNetworkOutput(output: string): list<var> {
if (!output || output.length === 0) {
return [];
}
-
+
const PLACEHOLDER = "STRINGWHICHHOPEFULLYWONTBEUSED";
const rep = new RegExp("\\\\:", "g");
const rep2 = new RegExp(PLACEHOLDER, "g");
-
- const allNetworks = output.trim().split("\n")
- .filter(line => line && line.length > 0)
- .map(n => {
- const net = n.replace(rep, PLACEHOLDER).split(":");
- return {
- active: net[0] === "yes",
- strength: parseInt(net[1] || "0", 10) || 0,
- frequency: parseInt(net[2] || "0", 10) || 0,
- ssid: (net[3]?.replace(rep2, ":") ?? "").trim(),
- bssid: (net[4]?.replace(rep2, ":") ?? "").trim(),
- security: (net[5] ?? "").trim()
- };
- })
- .filter(n => n.ssid && n.ssid.length > 0);
-
+
+ const allNetworks = output.trim().split("\n").filter(line => line && line.length > 0).map(n => {
+ const net = n.replace(rep, PLACEHOLDER).split(":");
+ return {
+ active: net[0] === "yes",
+ strength: parseInt(net[1] || "0", 10) || 0,
+ frequency: parseInt(net[2] || "0", 10) || 0,
+ ssid: (net[3]?.replace(rep2, ":") ?? "").trim(),
+ bssid: (net[4]?.replace(rep2, ":") ?? "").trim(),
+ security: (net[5] ?? "").trim()
+ };
+ }).filter(n => n.ssid && n.ssid.length > 0);
+
return allNetworks;
}
@@ -119,7 +91,7 @@ Singleton {
if (!networks || networks.length === 0) {
return [];
}
-
+
const networkMap = new Map();
for (const network of networks) {
const existing = networkMap.get(network.ssid);
@@ -135,7 +107,7 @@ Singleton {
}
}
}
-
+
return Array.from(networkMap.values());
}
@@ -143,7 +115,7 @@ Singleton {
if (!command || command.length === 0) {
return false;
}
-
+
return command.includes(root.nmcliCommandWifi) || command.includes(root.nmcliCommandConnection);
}
@@ -151,16 +123,16 @@ Singleton {
if (!output || output.length === 0) {
return [];
}
-
+
const interfaces = [];
const lines = output.trim().split("\n");
-
+
for (const line of lines) {
const parts = line.split(":");
if (parts.length >= 2) {
const deviceType = parts[1];
let shouldInclude = false;
-
+
if (filterType === root.deviceTypeWifi && deviceType === root.deviceTypeWifi) {
shouldInclude = true;
} else if (filterType === root.deviceTypeEthernet && deviceType === root.deviceTypeEthernet) {
@@ -168,7 +140,7 @@ Singleton {
} else if (filterType === "both" && (deviceType === root.deviceTypeWifi || deviceType === root.deviceTypeEthernet)) {
shouldInclude = true;
}
-
+
if (shouldInclude) {
interfaces.push({
device: parts[0] || "",
@@ -179,7 +151,7 @@ Singleton {
}
}
}
-
+
return interfaces;
}
@@ -187,53 +159,53 @@ Singleton {
if (!state || state.length === 0) {
return false;
}
-
- return state === "100 (connected)" ||
- state === "connected" ||
- state.startsWith("connected");
+
+ return state === "100 (connected)" || state === "connected" || state.startsWith("connected");
}
function executeCommand(args: list<string>, callback: var): void {
const proc = commandProc.createObject(root);
proc.command = ["nmcli", ...args];
proc.callback = callback;
-
+
activeProcesses.push(proc);
-
+
proc.processFinished.connect(() => {
const index = activeProcesses.indexOf(proc);
if (index >= 0) {
activeProcesses.splice(index, 1);
}
});
-
+
Qt.callLater(() => {
proc.exec(proc.command);
});
}
function getDeviceStatus(callback: var): void {
- executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], (result) => {
- if (callback) callback(result.output);
+ executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], result => {
+ if (callback)
+ callback(result.output);
});
}
function getWirelessInterfaces(callback: var): void {
- executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], (result) => {
+ executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], result => {
const interfaces = parseDeviceStatusOutput(result.output, root.deviceTypeWifi);
root.wirelessInterfaces = interfaces;
- if (callback) callback(interfaces);
+ if (callback)
+ callback(interfaces);
});
}
function getEthernetInterfaces(callback: var): void {
- executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], (result) => {
+ executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], result => {
const interfaces = parseDeviceStatusOutput(result.output, root.deviceTypeEthernet);
const devices = [];
-
+
for (const iface of interfaces) {
const connected = isConnectedState(iface.state);
-
+
devices.push({
interface: iface.device,
type: iface.type,
@@ -248,16 +220,17 @@ Singleton {
speed: ""
});
}
-
+
root.ethernetInterfaces = interfaces;
root.ethernetDevices = devices;
- if (callback) callback(interfaces);
+ if (callback)
+ callback(interfaces);
});
}
function connectEthernet(connectionName: string, interfaceName: string, callback: var): void {
if (connectionName && connectionName.length > 0) {
- executeCommand([root.nmcliCommandConnection, "up", connectionName], (result) => {
+ executeCommand([root.nmcliCommandConnection, "up", connectionName], result => {
if (result.success) {
Qt.callLater(() => {
getEthernetInterfaces(() => {});
@@ -268,10 +241,11 @@ Singleton {
}
}, 500);
}
- if (callback) callback(result);
+ if (callback)
+ callback(result);
});
} else if (interfaceName && interfaceName.length > 0) {
- executeCommand([root.nmcliCommandDevice, "connect", interfaceName], (result) => {
+ executeCommand([root.nmcliCommandDevice, "connect", interfaceName], result => {
if (result.success) {
Qt.callLater(() => {
getEthernetInterfaces(() => {});
@@ -280,62 +254,94 @@ Singleton {
}, 1000);
}, 500);
}
- if (callback) callback(result);
+ if (callback)
+ callback(result);
});
} else {
- if (callback) callback({ success: false, output: "", error: "No connection name or interface specified", exitCode: -1 });
+ if (callback)
+ callback({
+ success: false,
+ output: "",
+ error: "No connection name or interface specified",
+ exitCode: -1
+ });
}
}
function disconnectEthernet(connectionName: string, callback: var): void {
if (!connectionName || connectionName.length === 0) {
- if (callback) callback({ success: false, output: "", error: "No connection name specified", exitCode: -1 });
+ if (callback)
+ callback({
+ success: false,
+ output: "",
+ error: "No connection name specified",
+ exitCode: -1
+ });
return;
}
-
- executeCommand([root.nmcliCommandConnection, "down", connectionName], (result) => {
+
+ executeCommand([root.nmcliCommandConnection, "down", connectionName], result => {
if (result.success) {
root.ethernetDeviceDetails = null;
Qt.callLater(() => {
getEthernetInterfaces(() => {});
}, 500);
}
- if (callback) callback(result);
+ if (callback)
+ callback(result);
});
}
function getAllInterfaces(callback: var): void {
- executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], (result) => {
+ executeCommand(["-t", "-f", root.deviceStatusFields, root.nmcliCommandDevice, "status"], result => {
const interfaces = parseDeviceStatusOutput(result.output, "both");
- if (callback) callback(interfaces);
+ if (callback)
+ callback(interfaces);
});
}
function isInterfaceConnected(interfaceName: string, callback: var): void {
- executeCommand([root.nmcliCommandDevice, "status"], (result) => {
+ executeCommand([root.nmcliCommandDevice, "status"], result => {
const lines = result.output.trim().split("\n");
for (const line of lines) {
const parts = line.split(/\s+/);
if (parts.length >= 3 && parts[0] === interfaceName) {
const connected = isConnectedState(parts[2]);
- if (callback) callback(connected);
+ if (callback)
+ callback(connected);
return;
}
}
- if (callback) callback(false);
+ if (callback)
+ callback(false);
});
}
function connectToNetworkWithPasswordCheck(ssid: string, isSecure: bool, callback: var, bssid: string): void {
if (isSecure) {
const hasBssid = bssid !== undefined && bssid !== null && bssid.length > 0;
- connectWireless(ssid, "", bssid, (result) => {
+ connectWireless(ssid, "", bssid, result => {
if (result.success) {
- if (callback) callback({ success: true, usedSavedPassword: true, output: result.output, error: "", exitCode: 0 });
+ if (callback)
+ callback({
+ success: true,
+ usedSavedPassword: true,
+ output: result.output,
+ error: "",
+ exitCode: 0
+ });
} else if (result.needsPassword) {
- if (callback) callback({ success: false, needsPassword: true, output: result.output, error: result.error, exitCode: result.exitCode });
+ if (callback)
+ callback({
+ success: false,
+ needsPassword: true,
+ output: result.output,
+ error: result.error,
+ exitCode: result.exitCode
+ });
} else {
- if (callback) callback(result);
+ if (callback)
+ callback(result);
}
});
} else {
@@ -351,72 +357,68 @@ Singleton {
const hasBssid = bssid !== undefined && bssid !== null && bssid.length > 0;
const retries = retryCount !== undefined ? retryCount : 0;
const maxRetries = 2;
-
+
if (callback) {
- root.pendingConnection = { ssid: ssid, bssid: hasBssid ? bssid : "", callback: callback, retryCount: retries };
+ root.pendingConnection = {
+ ssid: ssid,
+ bssid: hasBssid ? bssid : "",
+ callback: callback,
+ retryCount: retries
+ };
connectionCheckTimer.start();
immediateCheckTimer.checkCount = 0;
immediateCheckTimer.start();
}
-
+
if (password && password.length > 0 && hasBssid) {
const bssidUpper = bssid.toUpperCase();
createConnectionWithPassword(ssid, bssidUpper, password, callback);
return;
}
-
+
let cmd = [root.nmcliCommandDevice, root.nmcliCommandWifi, "connect", ssid];
if (password && password.length > 0) {
cmd.push(root.connectionParamPassword, password);
}
- executeCommand(cmd, (result) => {
+ executeCommand(cmd, result => {
if (result.needsPassword && callback) {
- if (callback) callback(result);
+ if (callback)
+ callback(result);
return;
}
-
+
if (!result.success && root.pendingConnection && retries < maxRetries) {
- log("Connection failed, retrying... (attempt " + (retries + 1) + "/" + maxRetries + ")");
+ console.warn("[NMCLI] Connection failed, retrying... (attempt " + (retries + 1) + "/" + maxRetries + ")");
Qt.callLater(() => {
connectWireless(ssid, password, bssid, callback, retries + 1);
}, 1000);
- } else if (!result.success && root.pendingConnection) {
- } else if (result.success && callback) {
- } else if (!result.success && !root.pendingConnection) {
- if (callback) callback(result);
+ } else if (!result.success && root.pendingConnection) {} else if (result.success && callback) {} else if (!result.success && !root.pendingConnection) {
+ if (callback)
+ callback(result);
}
});
}
function createConnectionWithPassword(ssid: string, bssidUpper: string, password: string, callback: var): void {
checkAndDeleteConnection(ssid, () => {
- const cmd = [root.nmcliCommandConnection, "add",
- root.connectionParamType, root.deviceTypeWifi,
- root.connectionParamConName, ssid,
- root.connectionParamIfname, "*",
- root.connectionParamSsid, ssid,
- root.connectionParamBssid, bssidUpper,
- root.securityKeyMgmt, root.keyMgmtWpaPsk,
- root.securityPsk, password];
-
- executeCommand(cmd, (result) => {
+ const cmd = [root.nmcliCommandConnection, "add", root.connectionParamType, root.deviceTypeWifi, root.connectionParamConName, ssid, root.connectionParamIfname, "*", root.connectionParamSsid, ssid, root.connectionParamBssid, bssidUpper, root.securityKeyMgmt, root.keyMgmtWpaPsk, root.securityPsk, password];
+
+ executeCommand(cmd, result => {
if (result.success) {
loadSavedConnections(() => {});
activateConnection(ssid, callback);
} else {
- const hasDuplicateWarning = result.error && (
- result.error.includes("another connection with the name") ||
- result.error.includes("Reference the connection by its uuid")
- );
-
+ const hasDuplicateWarning = result.error && (result.error.includes("another connection with the name") || result.error.includes("Reference the connection by its uuid"));
+
if (hasDuplicateWarning || (result.exitCode > 0 && result.exitCode < 10)) {
loadSavedConnections(() => {});
activateConnection(ssid, callback);
} else {
- log("Connection profile creation failed, trying fallback...");
+ console.warn("[NMCLI] Connection profile creation failed, trying fallback...");
let fallbackCmd = [root.nmcliCommandDevice, root.nmcliCommandWifi, "connect", ssid, root.connectionParamPassword, password];
- executeCommand(fallbackCmd, (fallbackResult) => {
- if (callback) callback(fallbackResult);
+ executeCommand(fallbackCmd, fallbackResult => {
+ if (callback)
+ callback(fallbackResult);
});
}
}
@@ -425,34 +427,38 @@ Singleton {
}
function checkAndDeleteConnection(ssid: string, callback: var): void {
- executeCommand([root.nmcliCommandConnection, "show", ssid], (result) => {
+ executeCommand([root.nmcliCommandConnection, "show", ssid], result => {
if (result.success) {
- executeCommand([root.nmcliCommandConnection, "delete", ssid], (deleteResult) => {
+ executeCommand([root.nmcliCommandConnection, "delete", ssid], deleteResult => {
Qt.callLater(() => {
- if (callback) callback();
+ if (callback)
+ callback();
}, 300);
});
} else {
- if (callback) callback();
+ if (callback)
+ callback();
}
});
}
function activateConnection(connectionName: string, callback: var): void {
- executeCommand([root.nmcliCommandConnection, "up", connectionName], (result) => {
- if (callback) callback(result);
+ executeCommand([root.nmcliCommandConnection, "up", connectionName], result => {
+ if (callback)
+ callback(result);
});
}
function loadSavedConnections(callback: var): void {
- executeCommand(["-t", "-f", root.connectionListFields, root.nmcliCommandConnection, "show"], (result) => {
+ executeCommand(["-t", "-f", root.connectionListFields, root.nmcliCommandConnection, "show"], result => {
if (!result.success) {
root.savedConnections = [];
root.savedConnectionSsids = [];
- if (callback) callback([]);
+ if (callback)
+ callback([]);
return;
}
-
+
parseConnectionList(result.output, callback);
});
}
@@ -461,22 +467,22 @@ Singleton {
const lines = output.trim().split("\n").filter(line => line.length > 0);
const wifiConnections = [];
const connections = [];
-
+
for (const line of lines) {
const parts = line.split(":");
if (parts.length >= 2) {
const name = parts[0];
const type = parts[1];
connections.push(name);
-
+
if (type === root.connectionTypeWireless) {
wifiConnections.push(name);
}
}
}
-
+
root.savedConnections = connections;
-
+
if (wifiConnections.length > 0) {
root.wifiConnectionQueue = wifiConnections;
root.currentSsidQueryIndex = 0;
@@ -485,7 +491,8 @@ Singleton {
} else {
root.savedConnectionSsids = [];
root.wifiConnectionQueue = [];
- if (callback) callback(root.savedConnectionSsids);
+ if (callback)
+ callback(root.savedConnectionSsids);
}
}
@@ -493,8 +500,8 @@ Singleton {
if (root.currentSsidQueryIndex < root.wifiConnectionQueue.length) {
const connectionName = root.wifiConnectionQueue[root.currentSsidQueryIndex];
root.currentSsidQueryIndex++;
-
- executeCommand(["-t", "-f", root.wirelessSsidField, root.nmcliCommandConnection, "show", connectionName], (result) => {
+
+ executeCommand(["-t", "-f", root.wirelessSsidField, root.nmcliCommandConnection, "show", connectionName], result => {
if (result.success) {
processSsidOutput(result.output);
}
@@ -503,7 +510,8 @@ Singleton {
} else {
root.wifiConnectionQueue = [];
root.currentSsidQueryIndex = 0;
- if (callback) callback(root.savedConnectionSsids);
+ if (callback)
+ callback(root.savedConnectionSsids);
}
}
@@ -530,70 +538,73 @@ Singleton {
return false;
}
const ssidLower = ssid.toLowerCase().trim();
-
+
if (root.active && root.active.ssid) {
const activeSsidLower = root.active.ssid.toLowerCase().trim();
if (activeSsidLower === ssidLower) {
return true;
}
}
-
- const hasSsid = root.savedConnectionSsids.some(savedSsid =>
- savedSsid && savedSsid.toLowerCase().trim() === ssidLower
- );
-
+
+ const hasSsid = root.savedConnectionSsids.some(savedSsid => savedSsid && savedSsid.toLowerCase().trim() === ssidLower);
+
if (hasSsid) {
return true;
}
-
- const hasConnectionName = root.savedConnections.some(connName =>
- connName && connName.toLowerCase().trim() === ssidLower
- );
-
+
+ const hasConnectionName = root.savedConnections.some(connName => connName && connName.toLowerCase().trim() === ssidLower);
+
return hasConnectionName;
}
function forgetNetwork(ssid: string, callback: var): void {
if (!ssid || ssid.length === 0) {
- if (callback) callback({ success: false, output: "", error: "No SSID specified", exitCode: -1 });
+ if (callback)
+ callback({
+ success: false,
+ output: "",
+ error: "No SSID specified",
+ exitCode: -1
+ });
return;
}
-
- const connectionName = root.savedConnections.find(conn =>
- conn && conn.toLowerCase().trim() === ssid.toLowerCase().trim()
- ) || ssid;
-
- executeCommand([root.nmcliCommandConnection, "delete", connectionName], (result) => {
+
+ const connectionName = root.savedConnections.find(conn => conn && conn.toLowerCase().trim() === ssid.toLowerCase().trim()) || ssid;
+
+ executeCommand([root.nmcliCommandConnection, "delete", connectionName], result => {
if (result.success) {
Qt.callLater(() => {
loadSavedConnections(() => {});
}, 500);
}
- if (callback) callback(result);
+ if (callback)
+ callback(result);
});
}
function disconnect(interfaceName: string, callback: var): void {
if (interfaceName && interfaceName.length > 0) {
- executeCommand([root.nmcliCommandDevice, "disconnect", interfaceName], (result) => {
- if (callback) callback(result.success ? result.output : "");
+ executeCommand([root.nmcliCommandDevice, "disconnect", interfaceName], result => {
+ if (callback)
+ callback(result.success ? result.output : "");
});
} else {
- executeCommand([root.nmcliCommandDevice, "disconnect", root.deviceTypeWifi], (result) => {
- if (callback) callback(result.success ? result.output : "");
+ executeCommand([root.nmcliCommandDevice, "disconnect", root.deviceTypeWifi], result => {
+ if (callback)
+ callback(result.success ? result.output : "");
});
}
}
function disconnectFromNetwork(): void {
if (active && active.ssid) {
- executeCommand([root.nmcliCommandConnection, "down", active.ssid], (result) => {
+ executeCommand([root.nmcliCommandConnection, "down", active.ssid], result => {
if (result.success) {
getNetworks(() => {});
}
});
} else {
- executeCommand([root.nmcliCommandDevice, "disconnect", root.deviceTypeWifi], (result) => {
+ executeCommand([root.nmcliCommandDevice, "disconnect", root.deviceTypeWifi], result => {
if (result.success) {
getNetworks(() => {});
}
@@ -602,13 +613,14 @@ Singleton {
}
function getDeviceDetails(interfaceName: string, callback: var): void {
- executeCommand([root.nmcliCommandDevice, "show", interfaceName], (result) => {
- if (callback) callback(result.output);
+ executeCommand([root.nmcliCommandDevice, "show", interfaceName], result => {
+ if (callback)
+ callback(result.output);
});
}
function refreshStatus(callback: var): void {
- getDeviceStatus((output) => {
+ getDeviceStatus(output => {
const lines = output.trim().split("\n");
let connected = false;
let activeIf = "";
@@ -631,31 +643,48 @@ Singleton {
root.activeInterface = activeIf;
root.activeConnection = activeConn;
- if (callback) callback({ connected, interface: activeIf, connection: activeConn });
+ if (callback)
+ callback({
+ connected,
+ interface: activeIf,
+ connection: activeConn
+ });
});
}
function bringInterfaceUp(interfaceName: string, callback: var): void {
if (interfaceName && interfaceName.length > 0) {
- executeCommand([root.nmcliCommandDevice, "connect", interfaceName], (result) => {
+ executeCommand([root.nmcliCommandDevice, "connect", interfaceName], result => {
if (callback) {
callback(result);
}
});
} else {
- if (callback) callback({ success: false, output: "", error: "No interface specified", exitCode: -1 });
+ if (callback)
+ callback({
+ success: false,
+ output: "",
+ error: "No interface specified",
+ exitCode: -1
+ });
}
}
function bringInterfaceDown(interfaceName: string, callback: var): void {
if (interfaceName && interfaceName.length > 0) {
- executeCommand([root.nmcliCommandDevice, "disconnect", interfaceName], (result) => {
+ executeCommand([root.nmcliCommandDevice, "disconnect", interfaceName], result => {
if (callback) {
callback(result);
}
});
} else {
- if (callback) callback({ success: false, output: "", error: "No interface specified", exitCode: -1 });
+ if (callback)
+ callback({
+ success: false,
+ output: "",
+ error: "No interface specified",
+ exitCode: -1
+ });
}
}
@@ -664,7 +693,7 @@ Singleton {
if (interfaceName && interfaceName.length > 0) {
cmd.push(root.connectionParamIfname, interfaceName);
}
- executeCommand(cmd, (result) => {
+ executeCommand(cmd, result => {
if (callback) {
callback(result);
}
@@ -677,14 +706,16 @@ Singleton {
function enableWifi(enabled: bool, callback: var): void {
const cmd = enabled ? "on" : "off";
- executeCommand([root.nmcliCommandRadio, root.nmcliCommandWifi, cmd], (result) => {
+ executeCommand([root.nmcliCommandRadio, root.nmcliCommandWifi, cmd], result => {
if (result.success) {
- getWifiStatus((status) => {
+ getWifiStatus(status => {
root.wifiEnabled = status;
- if (callback) callback(result);
+ if (callback)
+ callback(result);
});
} else {
- if (callback) callback(result);
+ if (callback)
+ callback(result);
}
});
}
@@ -695,33 +726,32 @@ Singleton {
}
function getWifiStatus(callback: var): void {
- executeCommand([root.nmcliCommandRadio, root.nmcliCommandWifi], (result) => {
+ executeCommand([root.nmcliCommandRadio, root.nmcliCommandWifi], result => {
if (result.success) {
const enabled = result.output.trim() === "enabled";
root.wifiEnabled = enabled;
- if (callback) callback(enabled);
+ if (callback)
+ callback(enabled);
} else {
- if (callback) callback(root.wifiEnabled);
+ if (callback)
+ callback(root.wifiEnabled);
}
});
}
function getNetworks(callback: var): void {
- executeCommand(["-g", root.networkDetailFields, "d", "w"], (result) => {
+ executeCommand(["-g", root.networkDetailFields, "d", "w"], result => {
if (!result.success) {
- if (callback) callback([]);
+ if (callback)
+ callback([]);
return;
}
-
+
const allNetworks = parseNetworkOutput(result.output);
const networks = deduplicateNetworks(allNetworks);
const rNetworks = root.networks;
-
- const destroyed = rNetworks.filter(rn => !networks.find(n =>
- n.frequency === rn.frequency &&
- n.ssid === rn.ssid &&
- n.bssid === rn.bssid
- ));
+
+ const destroyed = rNetworks.filter(rn => !networks.find(n => n.frequency === rn.frequency && n.ssid === rn.ssid && n.bssid === rn.bssid));
for (const network of destroyed) {
const index = rNetworks.indexOf(network);
if (index >= 0) {
@@ -729,13 +759,9 @@ Singleton {
network.destroy();
}
}
-
+
for (const network of networks) {
- const match = rNetworks.find(n =>
- n.frequency === network.frequency &&
- n.ssid === network.ssid &&
- n.bssid === network.bssid
- );
+ const match = rNetworks.find(n => n.frequency === network.frequency && n.ssid === network.ssid && n.bssid === network.bssid);
if (match) {
match.lastIpcObject = network;
} else {
@@ -744,8 +770,9 @@ Singleton {
}));
}
}
-
- if (callback) callback(root.networks);
+
+ if (callback)
+ callback(root.networks);
checkPendingConnection();
});
}
@@ -755,19 +782,21 @@ Singleton {
if (interfaceName && interfaceName.length > 0) {
cmd.push(root.connectionParamIfname, interfaceName);
}
- executeCommand(cmd, (result) => {
+ executeCommand(cmd, result => {
if (!result.success) {
- if (callback) callback([]);
+ if (callback)
+ callback([]);
return;
}
-
+
const ssids = [];
const lines = result.output.trim().split("\n");
const seenSSIDs = new Set();
-
+
for (const line of lines) {
- if (!line || line.length === 0) continue;
-
+ if (!line || line.length === 0)
+ continue;
+
const parts = line.split(":");
if (parts.length >= 1) {
const ssid = parts[0].trim();
@@ -785,12 +814,13 @@ Singleton {
}
}
}
-
+
ssids.sort((a, b) => {
return b.signalValue - a.signalValue;
});
-
- if (callback) callback(ssids);
+
+ if (callback)
+ callback(ssids);
});
}
@@ -798,13 +828,13 @@ Singleton {
if (!proc || !error || error.length === 0) {
return false;
}
-
+
if (!isConnectionCommand(proc.command) || !root.pendingConnection || !root.pendingConnection.callback) {
return false;
}
-
+
const needsPassword = detectPasswordRequired(error);
-
+
if (needsPassword && !proc.callbackCalled && root.pendingConnection) {
connectionCheckTimer.stop();
immediateCheckTimer.stop();
@@ -827,77 +857,79 @@ Singleton {
}
return true;
}
-
+
return false;
}
component CommandProcess: Process {
id: proc
+
property var callback: null
property list<string> command: []
property bool callbackCalled: false
property int exitCode: 0
+
signal processFinished
environment: ({
- LANG: "C.UTF-8",
- LC_ALL: "C.UTF-8"
- })
+ LANG: "C.UTF-8",
+ LC_ALL: "C.UTF-8"
+ })
stdout: StdioCollector {
id: stdoutCollector
- onStreamFinished: {
- }
}
stderr: StdioCollector {
id: stderrCollector
+
onStreamFinished: {
const error = text.trim();
if (error && error.length > 0) {
const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : "";
- handlePasswordRequired(proc, error, output, -1);
+ root.handlePasswordRequired(proc, error, output, -1);
}
}
}
- onExited: {
- proc.exitCode = exitCode;
+ onExited: code => {
+ exitCode = code;
+
Qt.callLater(() => {
- if (proc.callbackCalled) {
- proc.processFinished();
+ if (callbackCalled) {
+ processFinished();
return;
}
-
+
if (proc.callback) {
const output = (stdoutCollector && stdoutCollector.text) ? stdoutCollector.text : "";
const error = (stderrCollector && stderrCollector.text) ? stderrCollector.text : "";
- const success = proc.exitCode === 0;
+ const success = exitCode === 0;
const cmdIsConnection = isConnectionCommand(proc.command);
-
- if (handlePasswordRequired(proc, error, output, proc.exitCode)) {
- proc.processFinished();
+
+ if (root.handlePasswordRequired(proc, error, output, exitCode)) {
+ processFinished();
return;
}
-
- const needsPassword = cmdIsConnection && detectPasswordRequired(error);
-
+
+ const needsPassword = cmdIsConnection && root.detectPasswordRequired(error);
+
if (!success && cmdIsConnection && root.pendingConnection) {
const failedSsid = root.pendingConnection.ssid;
root.connectionFailed(failedSsid);
}
-
- proc.callbackCalled = true;
- proc.callback({
+
+ callbackCalled = true;
+ callback({
success: success,
output: output,
error: error,
exitCode: proc.exitCode,
needsPassword: needsPassword || false
});
- proc.processFinished();
+ processFinished();
} else {
- proc.processFinished();
+ processFinished();
}
});
}
@@ -905,6 +937,7 @@ Singleton {
Component {
id: commandProc
+
CommandProcess {}
}
@@ -921,16 +954,18 @@ Singleton {
Component {
id: apComp
+
AccessPoint {}
}
Timer {
id: connectionCheckTimer
+
interval: 4000
onTriggered: {
if (root.pendingConnection) {
const connected = root.active && root.active.ssid === root.pendingConnection.ssid;
-
+
if (!connected && root.pendingConnection.callback) {
let foundPasswordError = false;
for (let i = 0; i < root.activeProcesses.length; i++) {
@@ -938,9 +973,9 @@ Singleton {
if (proc && proc.stderr && proc.stderr.text) {
const error = proc.stderr.text.trim();
if (error && error.length > 0) {
- if (isConnectionCommand(proc.command)) {
- const needsPassword = detectPasswordRequired(error);
-
+ if (root.isConnectionCommand(proc.command)) {
+ const needsPassword = root.detectPasswordRequired(error);
+
if (needsPassword && !proc.callbackCalled && root.pendingConnection) {
const pending = root.pendingConnection;
root.pendingConnection = null;
@@ -967,7 +1002,7 @@ Singleton {
}
}
}
-
+
if (!foundPasswordError) {
const pending = root.pendingConnection;
const failedSsid = pending.ssid;
@@ -975,10 +1010,10 @@ Singleton {
immediateCheckTimer.stop();
immediateCheckTimer.checkCount = 0;
root.connectionFailed(failedSsid);
- pending.callback({
- success: false,
- output: "",
- error: "Connection timeout",
+ pending.callback({
+ success: false,
+ output: "",
+ error: "Connection timeout",
exitCode: -1,
needsPassword: false
});
@@ -994,22 +1029,29 @@ Singleton {
Timer {
id: immediateCheckTimer
+
+ property int checkCount: 0
+
interval: 500
repeat: true
triggeredOnStart: false
- property int checkCount: 0
onTriggered: {
if (root.pendingConnection) {
checkCount++;
const connected = root.active && root.active.ssid === root.pendingConnection.ssid;
-
+
if (connected) {
connectionCheckTimer.stop();
immediateCheckTimer.stop();
immediateCheckTimer.checkCount = 0;
if (root.pendingConnection.callback) {
- root.pendingConnection.callback({ success: true, output: "Connected", error: "", exitCode: 0 });
+ root.pendingConnection.callback({
+ success: true,
+ output: "Connected",
+ error: "",
+ exitCode: 0
+ });
}
root.pendingConnection = null;
} else {
@@ -1018,9 +1060,9 @@ Singleton {
if (proc && proc.stderr && proc.stderr.text) {
const error = proc.stderr.text.trim();
if (error && error.length > 0) {
- if (isConnectionCommand(proc.command)) {
- const needsPassword = detectPasswordRequired(error);
-
+ if (root.isConnectionCommand(proc.command)) {
+ const needsPassword = root.detectPasswordRequired(error);
+
if (needsPassword && !proc.callbackCalled && root.pendingConnection && root.pendingConnection.callback) {
connectionCheckTimer.stop();
immediateCheckTimer.stop();
@@ -1047,7 +1089,7 @@ Singleton {
}
}
}
-
+
if (checkCount >= 6) {
immediateCheckTimer.stop();
immediateCheckTimer.checkCount = 0;
@@ -1069,7 +1111,12 @@ Singleton {
immediateCheckTimer.stop();
immediateCheckTimer.checkCount = 0;
if (root.pendingConnection.callback) {
- root.pendingConnection.callback({ success: true, output: "Connected", error: "", exitCode: 0 });
+ root.pendingConnection.callback({
+ success: true,
+ output: "Connected",
+ error: "",
+ exitCode: 0
+ });
}
root.pendingConnection = null;
} else {
@@ -1086,13 +1133,13 @@ Singleton {
if (isNaN(cidrNum) || cidrNum < 0 || cidrNum > 32) {
return "";
}
-
+
const mask = (0xffffffff << (32 - cidrNum)) >>> 0;
const octet1 = (mask >>> 24) & 0xff;
const octet2 = (mask >>> 16) & 0xff;
const octet3 = (mask >>> 8) & 0xff;
const octet4 = mask & 0xff;
-
+
return `${octet1}.${octet2}.${octet3}.${octet4}`;
}
@@ -1104,21 +1151,24 @@ Singleton {
if (activeInterface && activeInterface.device) {
interfaceName = activeInterface.device;
} else {
- if (callback) callback(null);
+ if (callback)
+ callback(null);
return;
}
}
-
- executeCommand(["device", "show", interfaceName], (result) => {
+
+ executeCommand(["device", "show", interfaceName], result => {
if (!result.success || !result.output) {
root.wirelessDeviceDetails = null;
- if (callback) callback(null);
+ if (callback)
+ callback(null);
return;
}
-
+
const details = parseDeviceDetails(result.output, false);
root.wirelessDeviceDetails = details;
- if (callback) callback(details);
+ if (callback)
+ callback(details);
});
}
@@ -1130,21 +1180,24 @@ Singleton {
if (activeInterface && activeInterface.device) {
interfaceName = activeInterface.device;
} else {
- if (callback) callback(null);
+ if (callback)
+ callback(null);
return;
}
}
-
- executeCommand(["device", "show", interfaceName], (result) => {
+
+ executeCommand(["device", "show", interfaceName], result => {
if (!result.success || !result.output) {
root.ethernetDeviceDetails = null;
- if (callback) callback(null);
+ if (callback)
+ callback(null);
return;
}
-
+
const details = parseDeviceDetails(result.output, true);
root.ethernetDeviceDetails = details;
- if (callback) callback(details);
+ if (callback)
+ callback(details);
});
}
@@ -1157,20 +1210,20 @@ Singleton {
macAddress: "",
speed: ""
};
-
+
if (!output || output.length === 0) {
return details;
}
-
+
const lines = output.trim().split("\n");
-
+
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const parts = line.split(":");
if (parts.length >= 2) {
const key = parts[0].trim();
const value = parts.slice(1).join(":").trim();
-
+
if (key.startsWith("IP4.ADDRESS")) {
const ipParts = value.split("/");
details.ipAddress = ipParts[0] || "";
@@ -1196,46 +1249,36 @@ Singleton {
}
}
}
-
+
return details;
}
Process {
id: rescanProc
+
command: ["nmcli", "dev", root.nmcliCommandWifi, "list", "--rescan", "yes"]
- onExited: {
- getNetworks(() => {});
- }
+ onExited: root.getNetworks()
}
Process {
id: monitorProc
+
running: true
command: ["nmcli", "monitor"]
environment: ({
- LANG: "C.UTF-8",
- LC_ALL: "C.UTF-8"
- })
-
+ LANG: "C.UTF-8",
+ LC_ALL: "C.UTF-8"
+ })
stdout: SplitParser {
- onRead: {
- log("Connection state change detected, refreshing...");
- root.refreshOnConnectionChange();
- }
- }
-
- onExited: {
- log("Monitor process exited, restarting...");
- Qt.callLater(() => {
- monitorProc.running = true;
- }, 2000);
+ onRead: root.refreshOnConnectionChange()
}
+ onExited: Qt.callLater(() => monitorProc.running = true, 2000)
}
function refreshOnConnectionChange(): void {
- getNetworks((networks) => {
+ getNetworks(networks => {
const newActive = root.active;
-
+
if (newActive && newActive.active) {
Qt.callLater(() => {
if (root.wirelessInterfaces.length > 0) {
@@ -1246,7 +1289,7 @@ Singleton {
getWirelessDeviceDetails(activeWireless.device, () => {});
}
}
-
+
if (root.ethernetInterfaces.length > 0) {
const activeEthernet = root.ethernetInterfaces.find(iface => {
return isConnectedState(iface.state);
@@ -1260,7 +1303,7 @@ Singleton {
root.wirelessDeviceDetails = null;
root.ethernetDeviceDetails = null;
}
-
+
getWirelessInterfaces(() => {});
getEthernetInterfaces(() => {
if (root.activeEthernet && root.activeEthernet.connected) {
@@ -1277,7 +1320,7 @@ Singleton {
getNetworks(() => {});
loadSavedConnections(() => {});
getEthernetInterfaces(() => {});
-
+
Qt.callLater(() => {
if (root.wirelessInterfaces.length > 0) {
const activeWireless = root.wirelessInterfaces.find(iface => {
@@ -1287,7 +1330,7 @@ Singleton {
getWirelessDeviceDetails(activeWireless.device, () => {});
}
}
-
+
if (root.ethernetInterfaces.length > 0) {
const activeEthernet = root.ethernetInterfaces.find(iface => {
return isConnectedState(iface.state);
@@ -1299,4 +1342,3 @@ Singleton {
}, 2000);
}
}
-