// The facts about one connection that otherwise need a terminal. // // IP address, gateway, DNS and MAC are the four things people leave this app // for, and they were the reason the Connections page still pointed at GNOME. // They are read-only here: editing them properly means static addressing, which // is a page of its own rather than four fields smuggled into a details drawer. // // Nothing here is ever a secret. panama-network's `details` verb returns // addresses only -- no PSK, no enterprise password -- so this component can be // shown for any connection without deciding what is safe to draw. // // The values are set in the interface face with tabular figures rather than a // monospaced one. Theme bans monospaced text outright (fontMono is the icon // face, not a text face), and an address only needs its digits to line up. import QtQuick import qs.config Column { id: root // { ip4, gateway, dns: [], mac, macRandomized } as the helper reports it, // or null while the read has not come back. Null is NOT "no address": the // component says it is still reading rather than claiming an answer. property var details: null // [{ key, value, note }] -- only the facts that actually have a value, so a // connection with no gateway shows three rows rather than a blank one. readonly property var facts: { const source = root.details; if (!source) return []; const rows = []; const ip4 = String(source.ip4 ?? ""); if (ip4 !== "") rows.push({ key: "IPv4 address", value: ip4, note: "" }); const ip6 = String(source.ip6 ?? ""); if (ip6 !== "") rows.push({ key: "IPv6 address", value: ip6, note: "" }); const gateway = String(source.gateway ?? ""); if (gateway !== "") rows.push({ key: "Gateway", value: gateway, note: "" }); const dns = Array.isArray(source.dns) ? source.dns.map(entry => String(entry)).filter(entry => entry !== "") : []; if (dns.length > 0) rows.push({ key: dns.length === 1 ? "DNS" : "DNS servers", value: dns.join(" · "), note: "" }); const mac = String(source.mac ?? ""); if (mac !== "") rows.push({ key: "MAC address", value: mac, note: source.macRandomized === true ? "randomized" : "" }); return rows; } width: parent ? parent.width : 620 spacing: 5 topPadding: 8 bottomPadding: 10 Repeater { model: root.facts Item { id: fact required property var modelData width: parent.width implicitHeight: Math.max(key.implicitHeight, value.implicitHeight) Text { id: key anchors.left: parent.left anchors.top: parent.top width: 132 text: String(fact.modelData.key ?? "") color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall elide: Text.ElideRight } Text { id: value anchors.left: key.right anchors.right: parent.right anchors.top: parent.top text: String(fact.modelData.value ?? "") + (String(fact.modelData.note ?? "") !== "" ? " · " + String(fact.modelData.note) : "") color: Theme.fg font.family: Theme.fontFamily font.features: Theme.tabularFigures font.pixelSize: Theme.fontSizeSmall wrapMode: Text.WrapAnywhere } } } // Two honest empty states, and they say different things. "Still reading" // is not "no address", and a page that renders the first as the second is // how a working connection comes to look broken for half a second. Text { width: parent.width visible: !root.details text: "Reading this connection's addresses…" color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall } Text { width: parent.width visible: !!root.details && root.facts.length === 0 text: "NetworkManager reports no addresses for this connection." color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall wrapMode: Text.WordWrap } // The helper's own aside -- chiefly "this takes effect on the next // reconnect" after a MAC randomization change. It belongs to the answer, // so it is shown with the answer rather than guessed at by the page. Text { width: parent.width visible: String(root.details?.note ?? "") !== "" topPadding: 4 text: String(root.details?.note ?? "") color: Theme.fgMuted font.family: Theme.fontFamily font.pixelSize: Theme.fontSizeSmall wrapMode: Text.WordWrap } }