// networksettingspage.cpp — Network configuration form #include "networksettingspage.h" #include "../transport/config_updater.h" #include #include #include #include #include #include static const char* SECTION = "server:lan"; NetworkSettingsPage::NetworkSettingsPage(QWidget* parent) : QWidget(parent) { auto* layout = new QVBoxLayout(this); layout->setSpacing(12); layout->setContentsMargins(0, 0, 0, 0); auto* title = new QLabel("Listen Address", this); title->setStyleSheet("font-weight: bold; font-size: 13px;"); layout->addWidget(title); // Interface auto* ifRow = new QHBoxLayout(); ifRow->addWidget(new QLabel("Interface:", this)); m_interfaceCombo = new QComboBox(this); m_interfaceCombo->setMinimumWidth(180); ifRow->addWidget(m_interfaceCombo, 1); layout->addLayout(ifRow); // IP auto* ipRow = new QHBoxLayout(); ipRow->addWidget(new QLabel("IP Address:", this)); m_ipCombo = new QComboBox(this); m_ipCombo->setEditable(true); m_ipCombo->setMinimumWidth(180); ipRow->addWidget(m_ipCombo, 1); layout->addLayout(ipRow); // Port auto* portRow = new QHBoxLayout(); portRow->addWidget(new QLabel("Port:", this)); m_portSpin = new QSpinBox(this); m_portSpin->setRange(1, 65535); m_portSpin->setValue(1333); m_portSpin->setMinimumWidth(100); portRow->addWidget(m_portSpin); portRow->addStretch(); layout->addLayout(portRow); // Protocol auto* protoRow = new QHBoxLayout(); protoRow->addWidget(new QLabel("Protocol:", this)); m_protoCombo = new QComboBox(this); m_protoCombo->addItems({"UDP", "TCP"}); m_protoCombo->setMinimumWidth(100); protoRow->addWidget(m_protoCombo); protoRow->addStretch(); layout->addLayout(protoRow); auto* note = new QLabel("Changes take effect after restart.", this); note->setStyleSheet("color: gray; font-size: 11px;"); layout->addWidget(note); layout->addStretch(); populateInterfaces(); connect(m_interfaceCombo, QOverload::of(&QComboBox::currentIndexChanged), this, &NetworkSettingsPage::onInterfaceChanged); } void NetworkSettingsPage::loadFromConfig(const QString& configPath) { // Read [server:lan] section from INI file QString addr, netif, transport; QFile f(configPath); if (f.open(QIODevice::ReadOnly | QIODevice::Text)) { bool inSection = false; QTextStream in(&f); while (!in.atEnd()) { QString line = in.readLine(); if (line.startsWith('[') && line.endsWith(']')) { inSection = (line.mid(1, line.length() - 2) == SECTION); continue; } if (!inSection || !line.contains('=')) continue; QString key = line.section('=', 0, 0).trimmed(); QString val = line.section('=', 1).trimmed(); if (key == "addr") addr = val; else if (key == "netif") netif = val; else if (key == "transport") transport = val; } f.close(); } // Parse addr: IP:port QString ip; if (!addr.isEmpty()) { int lastColon = addr.lastIndexOf(':'); if (lastColon > 0) { ip = addr.left(lastColon); int port = addr.mid(lastColon + 1).toInt(); if (port > 0 && port <= 65535) m_portSpin->setValue(port); } } // Set protocol int protoIdx = (transport == "tcp") ? 1 : 0; m_protoCombo->setCurrentIndex(protoIdx); // Set interface int ifIdx = m_interfaceCombo->findText(netif); if (ifIdx >= 0) m_interfaceCombo->setCurrentIndex(ifIdx); // Set IP — populate addresses first, then select populateAddresses(netif.isEmpty() ? QString() : netif); if (ip.isEmpty() || ip == "0.0.0.0") ip = "Auto (0.0.0.0)"; int ipIdx = m_ipCombo->findText(ip); if (ipIdx >= 0) m_ipCombo->setCurrentIndex(ipIdx); else m_ipCombo->setCurrentText(ip); } void NetworkSettingsPage::saveToConfig(const QString& configPath) const { // addr QString ip = m_ipCombo->currentText().trimmed(); if (ip.isEmpty() || ip == "Auto (0.0.0.0)") ip = "0.0.0.0"; config_update_option(configPath, SECTION, "addr", QString("%1:%2").arg(ip).arg(m_portSpin->value()), CONFIG_UPDATE_REPLACE); // netif: set or remove (empty value means no netif binding) QString iface = m_interfaceCombo->currentText(); if (iface.startsWith("Auto")) iface.clear(); config_update_option(configPath, SECTION, "netif", iface, CONFIG_UPDATE_REPLACE); // transport config_update_option(configPath, SECTION, "transport", m_protoCombo->currentText().toLower(), CONFIG_UPDATE_REPLACE); } void NetworkSettingsPage::onInterfaceChanged(int index) { Q_UNUSED(index); QString iface = m_interfaceCombo->currentText(); populateAddresses(iface.startsWith("Auto") ? QString() : iface); } void NetworkSettingsPage::populateInterfaces() { m_interfaceCombo->addItem("Auto (any)"); for (const QNetworkInterface& iface : QNetworkInterface::allInterfaces()) { if (iface.flags() & QNetworkInterface::IsLoopBack) continue; if (!(iface.flags() & QNetworkInterface::IsUp)) continue; m_interfaceCombo->addItem(iface.name()); } } void NetworkSettingsPage::populateAddresses(const QString& ifaceName) { QString current = m_ipCombo->currentText(); m_ipCombo->clear(); m_ipCombo->addItem("Auto (0.0.0.0)"); if (ifaceName.isEmpty()) { for (const QNetworkInterface& iface : QNetworkInterface::allInterfaces()) { if (iface.flags() & QNetworkInterface::IsLoopBack) continue; if (!(iface.flags() & QNetworkInterface::IsUp)) continue; for (const QNetworkAddressEntry& entry : iface.addressEntries()) { if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) m_ipCombo->addItem(entry.ip().toString()); } } } else { QNetworkInterface iface = QNetworkInterface::interfaceFromName(ifaceName); if (iface.isValid()) { for (const QNetworkAddressEntry& entry : iface.addressEntries()) { if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) m_ipCombo->addItem(entry.ip().toString()); } } } int idx = m_ipCombo->findText(current); if (idx >= 0) m_ipCombo->setCurrentIndex(idx); }