controlcenter: added connection information to wireless to match ethernet panel

This commit is contained in:
ATMDA 2025-11-11 16:18:32 -05:00
parent bcb2bd494a
commit 5af1e9222e
2 changed files with 214 additions and 1 deletions

View file

@ -16,6 +16,31 @@ Item {
required property Session session
readonly property var network: session.network.active
Component.onCompleted: {
if (network && network.active) {
Network.updateWirelessDeviceDetails();
}
}
onNetworkChanged: {
if (network && network.active) {
Network.updateWirelessDeviceDetails();
} else {
Network.wirelessDeviceDetails = null;
}
}
Connections {
target: Network
function onActiveChanged() {
if (root.network && root.network.active && Network.active && Network.active.ssid === root.network.ssid) {
Network.updateWirelessDeviceDetails();
} else if (!root.network || !root.network.active) {
Network.wirelessDeviceDetails = null;
}
}
}
StyledFlickable {
anchors.fill: parent
@ -198,6 +223,82 @@ Item {
}
}
}
StyledText {
Layout.topMargin: Appearance.spacing.large
text: qsTr("Connection information")
font.pointSize: Appearance.font.size.larger
font.weight: 500
}
StyledText {
text: qsTr("Network connection details")
color: Colours.palette.m3outline
}
StyledRect {
Layout.fillWidth: true
implicitHeight: connectionInfo.implicitHeight + Appearance.padding.large * 2
radius: Appearance.rounding.normal
color: Colours.tPalette.m3surfaceContainer
ColumnLayout {
id: connectionInfo
anchors.left: parent.left
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.margins: Appearance.padding.large
spacing: Appearance.spacing.small / 2
StyledText {
text: qsTr("IP Address")
}
StyledText {
text: Network.wirelessDeviceDetails?.ipAddress || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Appearance.font.size.small
}
StyledText {
Layout.topMargin: Appearance.spacing.normal
text: qsTr("Subnet Mask")
}
StyledText {
text: Network.wirelessDeviceDetails?.subnet || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Appearance.font.size.small
}
StyledText {
Layout.topMargin: Appearance.spacing.normal
text: qsTr("Gateway")
}
StyledText {
text: Network.wirelessDeviceDetails?.gateway || qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Appearance.font.size.small
}
StyledText {
Layout.topMargin: Appearance.spacing.normal
text: qsTr("DNS Servers")
}
StyledText {
text: (Network.wirelessDeviceDetails && Network.wirelessDeviceDetails.dns && Network.wirelessDeviceDetails.dns.length > 0) ? Network.wirelessDeviceDetails.dns.join(", ") : qsTr("Not available")
color: Colours.palette.m3outline
font.pointSize: Appearance.font.size.small
wrapMode: Text.Wrap
Layout.maximumWidth: parent.width
}
}
}
}
}

View file

@ -25,6 +25,7 @@ Singleton {
property string ethernetDebugInfo: ""
property bool ethernetProcessRunning: false
property var ethernetDeviceDetails: null
property var wirelessDeviceDetails: null
function enableWifi(enabled: bool): void {
const cmd = enabled ? "on" : "off";
@ -111,6 +112,11 @@ Singleton {
}
}
function updateWirelessDeviceDetails(): void {
// Find the wireless interface by looking for wifi devices
findWirelessInterfaceProc.exec(["nmcli", "device", "status"]);
}
function cidrToSubnetMask(cidr: string): string {
// Convert CIDR notation (e.g., "24") to subnet mask (e.g., "255.255.255.0")
const cidrNum = parseInt(cidr);
@ -587,7 +593,7 @@ Singleton {
};
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const line = lines[i];
const parts = line.split(":");
if (parts.length >= 2) {
const key = parts[0].trim();
@ -625,6 +631,112 @@ Singleton {
}
}
Process {
id: findWirelessInterfaceProc
environment: ({
LANG: "C.UTF-8",
LC_ALL: "C.UTF-8"
})
stdout: StdioCollector {
onStreamFinished: {
const output = text.trim();
if (!output || output.length === 0) {
root.wirelessDeviceDetails = null;
return;
}
// Find the connected wifi interface from device status
const lines = output.split("\n");
let wifiInterface = "";
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
const parts = line.split(/\s+/);
// Format: DEVICE TYPE STATE CONNECTION
// Look for wifi devices that are connected
if (parts.length >= 3 && parts[1] === "wifi" && parts[2] === "connected") {
wifiInterface = parts[0];
break;
}
}
if (wifiInterface && wifiInterface.length > 0) {
getWirelessDetailsProc.exec(["nmcli", "device", "show", wifiInterface]);
} else {
root.wirelessDeviceDetails = null;
}
}
}
onExited: {
if (exitCode !== 0) {
root.wirelessDeviceDetails = null;
}
}
}
Process {
id: getWirelessDetailsProc
environment: ({
LANG: "C.UTF-8",
LC_ALL: "C.UTF-8"
})
stdout: StdioCollector {
onStreamFinished: {
const output = text.trim();
if (!output || output.length === 0) {
root.wirelessDeviceDetails = null;
return;
}
const lines = output.split("\n");
const details = {
ipAddress: "",
gateway: "",
dns: [],
subnet: "",
macAddress: "",
speed: ""
};
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")) {
// Extract IP and subnet from format like "10.13.1.45/24"
const ipParts = value.split("/");
details.ipAddress = ipParts[0] || "";
if (ipParts[1]) {
// Convert CIDR notation to subnet mask
details.subnet = root.cidrToSubnetMask(ipParts[1]);
} else {
details.subnet = "";
}
} else if (key === "IP4.GATEWAY") {
details.gateway = value;
} else if (key.startsWith("IP4.DNS")) {
details.dns.push(value);
} else if (key === "GENERAL.HWADDR") {
details.macAddress = value;
}
}
}
root.wirelessDeviceDetails = details;
}
}
onExited: {
if (exitCode !== 0) {
root.wirelessDeviceDetails = null;
}
}
}
component AccessPoint: QtObject {
required property var lastIpcObject
readonly property string ssid: lastIpcObject.ssid