import QtQuick 2.12 import QtQuick.Controls 2.12 import QtQuick.Layouts 1.12 import "../components" Item { id: page property var devices: [] property var savedConfig: ({}) property string resultText: "" property bool resultOk: false function reload() { devices = systemInfo.networkInfo() savedConfig = systemInfo.networkConfig() var names = [] for (var i = 0; i < devices.length; ++i) names.push(devices[i].device) var prev = ifaceCombo.currentText if (savedConfig.iface) prev = savedConfig.iface ifaceCombo.model = names var idx = names.indexOf(prev) if (idx >= 0) ifaceCombo.currentIndex = idx if (savedConfig.mode) { staticSwitch.checked = savedConfig.mode === "static" addrField.text = savedConfig.address || "" prefixField.text = savedConfig.prefix ? String(savedConfig.prefix) : "24" gwField.text = savedConfig.gateway || "" dnsField.text = savedConfig.dns || "" } else { staticSwitch.checked = false } } function applyNow() { if (!ifaceCombo.currentText) { page.resultOk = false page.resultText = "Выберите интерфейс" return } var mode = staticSwitch.checked ? "static" : "dhcp" var r if (mode === "static") { r = systemInfo.applyNetwork(ifaceCombo.currentText, "static", addrField.text.trim(), parseInt(prefixField.text) || 24, gwField.text.trim(), dnsField.text.trim()) } else { r = systemInfo.applyNetwork(ifaceCombo.currentText, "dhcp") } page.resultOk = r.ok === true page.resultText = r.ok ? "Настройки применены" : ("Ошибка: " + (r.error || "неизвестно")) reloadTimer.start() } Component.onCompleted: reload() Rectangle { anchors.fill: parent color: "#161628" } Timer { id: reloadTimer interval: 1500 onTriggered: page.reload() } ScrollView { anchors.fill: parent clip: true contentWidth: availableWidth contentHeight: netColumn.implicitHeight + 16 ScrollBar.vertical.policy: ScrollBar.AsNeeded ColumnLayout { id: netColumn width: page.width - 16 x: 8 y: 8 spacing: 12 RowLayout { Layout.fillWidth: true Button { text: "\u2190 Назад"; onClicked: page.StackView.view.pop() } Label { Layout.fillWidth: true text: "Сеть (Ethernet)" font.bold: true font.pixelSize: 16 color: "#ffffff" horizontalAlignment: Text.AlignHCenter } Button { text: "\u21BB"; onClicked: page.reload() } } // ----- Current state ----- Text { Layout.fillWidth: true visible: page.devices.length === 0 text: "Ethernet-интерфейсы не найдены (или nmcli недоступен)." color: "#cccccc" wrapMode: Text.Wrap } Repeater { model: page.devices delegate: Rectangle { Layout.fillWidth: true Layout.preferredHeight: col.implicitHeight + 16 radius: 6 color: "#40222c58" border.color: "#80ffffff" border.width: 1 ColumnLayout { id: col anchors.fill: parent anchors.margins: 8 spacing: 2 Text { text: modelData.device + " (" + modelData.state + ")" color: "#ffffff" font.bold: true } Text { text: "Соединение: " + (modelData.connection || "—") color: "#cccccc" font.pixelSize: 12 } Text { text: "IP: " + (modelData.addresses || "—") color: "#cccccc" font.pixelSize: 12 } Text { text: "Шлюз: " + (modelData.gateway || "—") + " DNS: " + (modelData.dns || "—") color: "#cccccc" font.pixelSize: 12 } } } } Rectangle { Layout.fillWidth: true; height: 1; color: "#40ffffff" } // ----- Configuration form ----- Text { Layout.fillWidth: true text: "Изменение настроек может разорвать соединение и сменить IP устройства." color: "#e0a020" font.pixelSize: 12 wrapMode: Text.Wrap } RowLayout { Layout.fillWidth: true Text { text: "Интерфейс:"; color: "#ffffff"; Layout.preferredWidth: 120 } ComboBox { id: ifaceCombo Layout.fillWidth: true model: [] } } RowLayout { Layout.fillWidth: true Text { text: "Статический IP:"; color: "#ffffff"; Layout.preferredWidth: 120 } Switch { id: staticSwitch checked: false } Text { text: staticSwitch.checked ? "Статический" : "DHCP (авто)" color: "#cccccc" } Item { Layout.fillWidth: true } } GridLayout { Layout.fillWidth: true columns: 2 visible: staticSwitch.checked Text { text: "IP-адрес:"; color: "#ffffff" } TextField { id: addrField; Layout.fillWidth: true; placeholderText: "192.168.1.50" } Text { text: "Префикс:"; color: "#ffffff" } TextField { id: prefixField; Layout.fillWidth: true; text: "24"; inputMethodHints: Qt.ImhDigitsOnly } Text { text: "Шлюз:"; color: "#ffffff" } TextField { id: gwField; Layout.fillWidth: true; placeholderText: "192.168.1.1" } Text { text: "DNS:"; color: "#ffffff" } TextField { id: dnsField; Layout.fillWidth: true; placeholderText: "8.8.8.8, 1.1.1.1" } } RowLayout { Layout.fillWidth: true Button { text: "Применить" highlighted: true onClicked: confirmDialog.open() } Text { Layout.fillWidth: true text: page.resultText color: page.resultOk ? "#30c050" : "#e05050" wrapMode: Text.Wrap } } Item { Layout.fillWidth: true Layout.preferredHeight: 8 } } } Dialog { id: confirmDialog modal: true title: "Применить настройки сети?" anchors.centerIn: parent standardButtons: Dialog.Ok | Dialog.Cancel Text { width: parent ? parent.width : 300 text: "Соединение может прерваться. Продолжить?" color: "#ffffff" wrapMode: Text.Wrap } onAccepted: page.applyNow() } }