diff --git a/libs/editor/connectioneditorbase.cpp b/libs/editor/connectioneditorbase.cpp index f3f4c4e5..433f94af 100644 --- a/libs/editor/connectioneditorbase.cpp +++ b/libs/editor/connectioneditorbase.cpp @@ -1,498 +1,498 @@ /* Copyright 2013-2016 Jan Grulich Copyright 2013, 2014 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "connectioneditorbase.h" #include "debug.h" #include "settings/bondwidget.h" #include "settings/bridgewidget.h" #include "settings/btwidget.h" #include "settings/cdmawidget.h" #include "settings/connectionwidget.h" #include "settings/gsmwidget.h" #include "settings/infinibandwidget.h" #include "settings/ipv4widget.h" #include "settings/ipv6widget.h" #include "settings/pppwidget.h" #include "settings/pppoewidget.h" #include "settings/teamwidget.h" #include "settings/vlanwidget.h" #include "settings/wificonnectionwidget.h" #include "settings/wifisecurity.h" #include "settings/wiredconnectionwidget.h" #include "settings/wiredsecurity.h" #include "settings/wireguardinterfacewidget.h" #include "vpnuiplugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include ConnectionEditorBase::ConnectionEditorBase(const NetworkManager::ConnectionSettings::Ptr &connection, QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) , m_initialized(false) , m_valid(false) , m_pendingReplies(0) , m_connection(connection) { } ConnectionEditorBase::ConnectionEditorBase(QWidget *parent, Qt::WindowFlags f) : QWidget(parent, f) { } ConnectionEditorBase::~ConnectionEditorBase() { m_connection.clear(); } void ConnectionEditorBase::setConnection(const NetworkManager::ConnectionSettings::Ptr &connection) { // Set connection settings m_connection.clear(); m_connection = connection; m_initialized = false; // Reset UI setting widgets delete m_connectionWidget; m_connectionWidget = nullptr; qDeleteAll(m_settingWidgets); m_settingWidgets.clear(); initialize(); } NMVariantMapMap ConnectionEditorBase::setting() const { NMVariantMapMap settings = m_connectionWidget->setting(); for (SettingWidget *widget : m_settingWidgets) { const QString type = widget->type(); if (type != NetworkManager::Setting::typeAsString(NetworkManager::Setting::Security8021x) && type != NetworkManager::Setting::typeAsString(NetworkManager::Setting::WirelessSecurity)) { settings.insert(type, widget->setting()); } // add 802.1x security if needed QVariantMap security8021x; if (type == NetworkManager::Setting::typeAsString(NetworkManager::Setting::WirelessSecurity)) { WifiSecurity *wifiSecurity = static_cast(widget); if (wifiSecurity->enabled()) { settings.insert(type, wifiSecurity->setting()); } if (wifiSecurity->enabled8021x()) { security8021x = static_cast(widget)->setting8021x(); settings.insert(NetworkManager::Setting::typeAsString(NetworkManager::Setting::Security8021x), security8021x); } } else if (type == NetworkManager::Setting::typeAsString(NetworkManager::Setting::Security8021x)) { WiredSecurity *wiredSecurity = static_cast(widget); if (wiredSecurity->enabled8021x()) { security8021x = static_cast(widget)->setting(); settings.insert(NetworkManager::Setting::typeAsString(NetworkManager::Setting::Security8021x), security8021x); } } } // Set properties which are not returned from setting widgets NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(m_connection->connectionType())); connectionSettings->fromMap(settings); connectionSettings->setId(connectionName()); if (connectionSettings->connectionType() == NetworkManager::ConnectionSettings::WireGuard) connectionSettings->setInterfaceName(connectionName()); connectionSettings->setUuid(m_connection->uuid()); if (connectionSettings->connectionType() == NetworkManager::ConnectionSettings::Wireless) { NetworkManager::WirelessSecuritySetting::Ptr securitySetting = connectionSettings->setting(NetworkManager::Setting::WirelessSecurity).staticCast(); NetworkManager::WirelessSetting::Ptr wirelessSetting = connectionSettings->setting(NetworkManager::Setting::Wireless).staticCast(); if (securitySetting && wirelessSetting) { if (securitySetting->keyMgmt() != NetworkManager::WirelessSecuritySetting::WirelessSecuritySetting::Unknown) { wirelessSetting->setSecurity("802-11-wireless-security"); } } } return connectionSettings->toMap(); } bool ConnectionEditorBase::isInitialized() const { return m_initialized; } bool ConnectionEditorBase::isValid() const { return m_valid; } void ConnectionEditorBase::addConnectionWidget(ConnectionWidget *widget, const QString &text) { m_connectionWidget = widget; connect(widget, &ConnectionWidget::settingChanged, this, &ConnectionEditorBase::settingChanged); addWidget(widget, text); } void ConnectionEditorBase::addSettingWidget(SettingWidget *widget, const QString &text) { m_settingWidgets << widget; connect(widget, &SettingWidget::settingChanged, this, &ConnectionEditorBase::settingChanged); addWidget(widget, text); } void ConnectionEditorBase::initialize() { const bool emptyConnection = m_connection->id().isEmpty(); const NetworkManager::ConnectionSettings::ConnectionType type = m_connection->connectionType(); if (emptyConnection) { m_connection->addToPermissions(KUser().loginName(), QString()); } // General configuration common to all connection types ConnectionWidget *connectionWidget = new ConnectionWidget(m_connection); addConnectionWidget(connectionWidget, i18nc("General", "General configuration")); // Add the rest of widgets QString serviceType; if (type == NetworkManager::ConnectionSettings::Wired) { WiredConnectionWidget *wiredWidget = new WiredConnectionWidget(m_connection->setting(NetworkManager::Setting::Wired), this); addSettingWidget(wiredWidget, i18n("Wired")); WiredSecurity *wiredSecurity = new WiredSecurity(m_connection->setting(NetworkManager::Setting::Security8021x).staticCast(), this); addSettingWidget(wiredSecurity, i18n("802.1x Security")); } else if (type == NetworkManager::ConnectionSettings::Wireless) { WifiConnectionWidget *wifiWidget = new WifiConnectionWidget(m_connection->setting(NetworkManager::Setting::Wireless), this); addSettingWidget(wifiWidget, i18n("Wi-Fi")); WifiSecurity *wifiSecurity = new WifiSecurity(m_connection->setting(NetworkManager::Setting::WirelessSecurity), m_connection->setting(NetworkManager::Setting::Security8021x).staticCast(), this); addSettingWidget(wifiSecurity, i18n("Wi-Fi Security")); connect(wifiWidget, QOverload::of(&WifiConnectionWidget::ssidChanged), wifiSecurity, &WifiSecurity::onSsidChanged); } else if (type == NetworkManager::ConnectionSettings::Pppoe) { // DSL PppoeWidget *pppoeWidget = new PppoeWidget(m_connection->setting(NetworkManager::Setting::Pppoe), this); addSettingWidget(pppoeWidget, i18n("DSL")); WiredConnectionWidget *wiredWidget = new WiredConnectionWidget(m_connection->setting(NetworkManager::Setting::Wired), this); addSettingWidget(wiredWidget, i18n("Wired")); } else if (type == NetworkManager::ConnectionSettings::Gsm) { // GSM GsmWidget *gsmWidget = new GsmWidget(m_connection->setting(NetworkManager::Setting::Gsm), this); addSettingWidget(gsmWidget, i18n("Mobile Broadband (%1)", m_connection->typeAsString(m_connection->connectionType()))); } else if (type == NetworkManager::ConnectionSettings::Cdma) { // CDMA CdmaWidget *cdmaWidget = new CdmaWidget(m_connection->setting(NetworkManager::Setting::Cdma), this); addSettingWidget(cdmaWidget, i18n("Mobile Broadband (%1)", m_connection->typeAsString(m_connection->connectionType()))); } else if (type == NetworkManager::ConnectionSettings::Bluetooth) { // Bluetooth BtWidget *btWidget = new BtWidget(m_connection->setting(NetworkManager::Setting::Bluetooth), this); addSettingWidget(btWidget, i18n("Bluetooth")); NetworkManager::BluetoothSetting::Ptr btSetting = m_connection->setting(NetworkManager::Setting::Bluetooth).staticCast(); if (btSetting->profileType() == NetworkManager::BluetoothSetting::Dun) { GsmWidget *gsmWidget = new GsmWidget(m_connection->setting(NetworkManager::Setting::Gsm), this); addSettingWidget(gsmWidget, i18n("GSM")); PPPWidget *pppWidget = new PPPWidget(m_connection->setting(NetworkManager::Setting::Ppp), this); addSettingWidget(pppWidget, i18n("PPP")); } } else if (type == NetworkManager::ConnectionSettings::Infiniband) { // Infiniband InfinibandWidget *infinibandWidget = new InfinibandWidget(m_connection->setting(NetworkManager::Setting::Infiniband), this); addSettingWidget(infinibandWidget, i18n("Infiniband")); } else if (type == NetworkManager::ConnectionSettings::Bond) { // Bond - BondWidget *bondWidget = new BondWidget(m_connection->uuid(), m_connection->setting(NetworkManager::Setting::Bond), this); + BondWidget *bondWidget = new BondWidget(m_connection->uuid(), m_connection->id(), m_connection->setting(NetworkManager::Setting::Bond), this); addSettingWidget(bondWidget, i18n("Bond")); } else if (type == NetworkManager::ConnectionSettings::Bridge) { // Bridge - BridgeWidget *bridgeWidget = new BridgeWidget(m_connection->uuid(), m_connection->setting(NetworkManager::Setting::Bridge), this); + BridgeWidget *bridgeWidget = new BridgeWidget(m_connection->uuid(), m_connection->id(), m_connection->setting(NetworkManager::Setting::Bridge), this); addSettingWidget(bridgeWidget, i18n("Bridge")); } else if (type == NetworkManager::ConnectionSettings::Vlan) { // Vlan VlanWidget *vlanWidget = new VlanWidget(m_connection->setting(NetworkManager::Setting::Vlan), this); addSettingWidget(vlanWidget, i18n("Vlan")); } else if (type == NetworkManager::ConnectionSettings::Team) { // Team - TeamWidget *teamWidget = new TeamWidget(m_connection->uuid(), m_connection->setting(NetworkManager::Setting::Team), this); + TeamWidget *teamWidget = new TeamWidget(m_connection->uuid(), m_connection->id(), m_connection->setting(NetworkManager::Setting::Team), this); addSettingWidget(teamWidget, i18n("Team")); } else if (type == NetworkManager::ConnectionSettings::WireGuard) { // WireGuard WireGuardInterfaceWidget *wireGuardInterfaceWidget = new WireGuardInterfaceWidget(m_connection->setting(NetworkManager::Setting::WireGuard), this); addSettingWidget(wireGuardInterfaceWidget, i18n("WireGuard Interface")); } else if (type == NetworkManager::ConnectionSettings::Vpn) { // VPN QString error; VpnUiPlugin *vpnPlugin = nullptr; NetworkManager::VpnSetting::Ptr vpnSetting = m_connection->setting(NetworkManager::Setting::Vpn).staticCast(); if (!vpnSetting) { qCWarning(PLASMA_NM) << "Missing VPN setting!"; } else { serviceType = vpnSetting->serviceType(); vpnPlugin = KServiceTypeTrader::createInstanceFromQuery(QString::fromLatin1("PlasmaNetworkManagement/VpnUiPlugin"), QString::fromLatin1("[X-NetworkManager-Services]=='%1'").arg(serviceType), this, QVariantList(), &error); if (vpnPlugin && error.isEmpty()) { const QString shortName = serviceType.section('.', -1); SettingWidget *vpnWidget = vpnPlugin->widget(vpnSetting, this); addSettingWidget(vpnWidget, i18n("VPN (%1)", shortName)); } else { qCWarning(PLASMA_NM) << error << ", serviceType == " << serviceType; } } } // PPP widget if (type == NetworkManager::ConnectionSettings::Pppoe || type == NetworkManager::ConnectionSettings::Cdma || type == NetworkManager::ConnectionSettings::Gsm) { PPPWidget *pppWidget = new PPPWidget(m_connection->setting(NetworkManager::Setting::Ppp), this); addSettingWidget(pppWidget, i18n("PPP")); } // IPv4 widget if (!m_connection->isSlave()) { IPv4Widget *ipv4Widget = new IPv4Widget(m_connection->setting(NetworkManager::Setting::Ipv4), this); addSettingWidget(ipv4Widget, i18n("IPv4")); } // IPv6 widget if ((type == NetworkManager::ConnectionSettings::Wired || type == NetworkManager::ConnectionSettings::Wireless || type == NetworkManager::ConnectionSettings::Infiniband || type == NetworkManager::ConnectionSettings::Team || type == NetworkManager::ConnectionSettings::Cdma || type == NetworkManager::ConnectionSettings::Gsm || type == NetworkManager::ConnectionSettings::Bond || type == NetworkManager::ConnectionSettings::Bridge || type == NetworkManager::ConnectionSettings::Vlan || type == NetworkManager::ConnectionSettings::WireGuard || (type == NetworkManager::ConnectionSettings::Vpn && serviceType == QLatin1String("org.freedesktop.NetworkManager.openvpn"))) && !m_connection->isSlave()) { IPv6Widget *ipv6Widget = new IPv6Widget(m_connection->setting(NetworkManager::Setting::Ipv6), this); addSettingWidget(ipv6Widget, i18n("IPv6")); } // Re-check validation bool valid = true; for (SettingWidget *widget : m_settingWidgets) { valid = valid && widget->isValid(); connect(widget, &SettingWidget::validChanged, this, &ConnectionEditorBase::validChanged); } m_valid = valid; Q_EMIT validityChanged(valid); KAcceleratorManager::manage(this); // If the connection is not empty (not new) we want to load its secrets if (!emptyConnection) { NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(m_connection->uuid()); if (connection) { QStringList requiredSecrets; QString settingName; QVariantMap setting; QDBusPendingReply reply; if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Adsl) { NetworkManager::AdslSetting::Ptr adslSetting = connection->settings()->setting(NetworkManager::Setting::Adsl).staticCast(); if (adslSetting && !adslSetting->needSecrets().isEmpty()) { requiredSecrets = adslSetting->needSecrets(); setting = adslSetting->toMap(); settingName = QLatin1String("adsl"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Bluetooth) { NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).staticCast(); if (gsmSetting && !gsmSetting->needSecrets().isEmpty()) { requiredSecrets = gsmSetting->needSecrets(); setting = gsmSetting->toMap(); settingName = QLatin1String("gsm"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Cdma) { NetworkManager::CdmaSetting::Ptr cdmaSetting = connection->settings()->setting(NetworkManager::Setting::Cdma).staticCast(); if (cdmaSetting && !cdmaSetting->needSecrets().isEmpty()) { requiredSecrets = cdmaSetting->needSecrets(); setting = cdmaSetting->toMap(); settingName = QLatin1String("cdma"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Gsm) { NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).staticCast(); if (gsmSetting && !gsmSetting->needSecrets().isEmpty()) { requiredSecrets = gsmSetting->needSecrets(); setting = gsmSetting->toMap(); settingName = QLatin1String("gsm"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Pppoe) { NetworkManager::PppoeSetting::Ptr pppoeSetting = connection->settings()->setting(NetworkManager::Setting::Pppoe).staticCast(); if (pppoeSetting && !pppoeSetting->needSecrets().isEmpty()) { requiredSecrets = pppoeSetting->needSecrets(); setting = pppoeSetting->toMap(); settingName = QLatin1String("pppoe"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Wired) { NetworkManager::Security8021xSetting::Ptr securitySetting = connection->settings()->setting(NetworkManager::Setting::Security8021x).staticCast(); if (securitySetting && !securitySetting->needSecrets().isEmpty()) { requiredSecrets = securitySetting->needSecrets(); setting = securitySetting->toMap(); settingName = QLatin1String("802-1x"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::WireGuard) { NetworkManager::WireGuardSetting::Ptr securitySetting = connection->settings()->setting(NetworkManager::Setting::WireGuard).staticCast(); if (securitySetting && !securitySetting->needSecrets().isEmpty()) { requiredSecrets = securitySetting->needSecrets(); setting = securitySetting->toMap(); settingName = QLatin1String("wireguard"); } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Wireless) { NetworkManager::WirelessSecuritySetting::Ptr wifiSecuritySetting = connection->settings()->setting(NetworkManager::Setting::WirelessSecurity).staticCast(); if (wifiSecuritySetting && (wifiSecuritySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WpaEap || (wifiSecuritySetting->keyMgmt() == NetworkManager::WirelessSecuritySetting::WirelessSecuritySetting::Ieee8021x && wifiSecuritySetting->authAlg() != NetworkManager::WirelessSecuritySetting::Leap))) { NetworkManager::Security8021xSetting::Ptr securitySetting = connection->settings()->setting(NetworkManager::Setting::Security8021x).staticCast(); if (securitySetting && !securitySetting->needSecrets().isEmpty()) { requiredSecrets = securitySetting->needSecrets(); setting = securitySetting->toMap(); settingName = QLatin1String("802-1x"); if (requiredSecrets.contains(NM_SETTING_802_1X_PASSWORD_RAW)) { requiredSecrets.removeAll(NM_SETTING_802_1X_PASSWORD_RAW); } } } else { if (!wifiSecuritySetting->needSecrets().isEmpty()) { requiredSecrets = wifiSecuritySetting->needSecrets(); setting = wifiSecuritySetting->toMap(); settingName = QLatin1String("802-11-wireless-security"); } } } else if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Vpn) { settingName = QLatin1String("vpn"); } if (!requiredSecrets.isEmpty() || m_connection->connectionType() == NetworkManager::ConnectionSettings::Vpn) { bool requestSecrets = false; if (m_connection->connectionType() == NetworkManager::ConnectionSettings::Vpn) { NetworkManager::VpnSetting::Ptr vpnSetting = connection->settings()->setting(NetworkManager::Setting::Vpn).staticCast(); for (const QString &key : vpnSetting->data().keys()) { if (key.endsWith(QStringLiteral("-flags"))) { NetworkManager::Setting::SecretFlagType secretFlag = (NetworkManager::Setting::SecretFlagType)vpnSetting->data().value(key).toInt(); if (secretFlag == NetworkManager::Setting::None || secretFlag == NetworkManager::Setting::AgentOwned) { requestSecrets = true; } } } } else { for (const QString &secret : requiredSecrets) { if (setting.contains(secret + QLatin1String("-flags"))) { NetworkManager::Setting::SecretFlagType secretFlag = (NetworkManager::Setting::SecretFlagType)setting.value(secret + QLatin1String("-flags")).toInt(); if (secretFlag == NetworkManager::Setting::None || secretFlag == NetworkManager::Setting::AgentOwned) { requestSecrets = true; } } else { requestSecrets = true; } } } if (requestSecrets) { m_pendingReplies++; reply = connection->secrets(settingName); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); watcher->setProperty("connection", connection->name()); watcher->setProperty("settingName", settingName); connect(watcher, &QDBusPendingCallWatcher::finished, this, &ConnectionEditorBase::replyFinished); m_valid = false; Q_EMIT validityChanged(false); return; } } } } // We should be now fully initialized as we don't wait for secrets if (m_pendingReplies == 0) { m_initialized = true; } } void ConnectionEditorBase::replyFinished(QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; const QString settingName = watcher->property("settingName").toString(); if (reply.isValid()) { NMVariantMapMap secrets = reply.argumentAt<0>(); for (const QString &key : secrets.keys()) { if (key == settingName) { NetworkManager::Setting::Ptr setting = m_connection->setting(NetworkManager::Setting::typeFromString(key)); if (setting) { setting->secretsFromMap(secrets.value(key)); for (SettingWidget *widget : m_settingWidgets) { const QString type = widget->type(); if (type == settingName || (settingName == NetworkManager::Setting::typeAsString(NetworkManager::Setting::Security8021x) && type == NetworkManager::Setting::typeAsString(NetworkManager::Setting::WirelessSecurity))) { widget->loadSecrets(setting); } } } } } } else { KNotification *notification = new KNotification("FailedToGetSecrets", KNotification::CloseOnTimeout); notification->setComponentName("networkmanagement"); notification->setTitle(i18n("Failed to get secrets for %1", watcher->property("connection").toString())); notification->setText(reply.error().message()); notification->setPixmap(QIcon::fromTheme("dialog-warning").pixmap(KIconLoader::SizeHuge)); notification->sendEvent(); } watcher->deleteLater(); validChanged(true); // We should be now fully with secrets m_pendingReplies--; m_initialized = true; } void ConnectionEditorBase::validChanged(bool valid) { if (!valid) { m_valid = false; Q_EMIT validityChanged(false); return; } else { for (SettingWidget *widget : m_settingWidgets) { if (!widget->isValid()) { m_valid = false; Q_EMIT validityChanged(false); return; } } } m_valid = true; Q_EMIT validityChanged(true); } diff --git a/libs/editor/settings/bondwidget.cpp b/libs/editor/settings/bondwidget.cpp index 847579b1..a0f2d1d3 100644 --- a/libs/editor/settings/bondwidget.cpp +++ b/libs/editor/settings/bondwidget.cpp @@ -1,305 +1,312 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "bondwidget.h" #include "ui_bond.h" #include "connectioneditordialog.h" #include "debug.h" #include #include #include #include #include #include #include #define NM_SETTING_BOND_OPTION_MII_MONITOR "mii" #define NM_SETTING_BOND_OPTION_ARP_MONITOR "arp" -BondWidget::BondWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): +BondWidget::BondWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_uuid(masterUuid), + m_id(masterId), m_ui(new Ui::BondWidget) { m_ui->setupUi(this); // Action buttons and menu m_menu = new QMenu(this); QAction * action = new QAction(i18n("Ethernet"), this); action->setData(NetworkManager::ConnectionSettings::Wired); m_menu->addAction(action); action = new QAction(i18n("InfiniBand"), this); action->setData(NetworkManager::ConnectionSettings::Infiniband); m_menu->addAction(action); m_ui->btnAdd->setMenu(m_menu); connect(m_menu, &QMenu::triggered, this, &BondWidget::addBond); connect(m_ui->btnEdit, &QPushButton::clicked, this, &BondWidget::editBond); connect(m_ui->btnDelete, &QPushButton::clicked, this, &BondWidget::deleteBond); // mode m_ui->mode->addItem(i18nc("bond mode", "Round-robin"), QLatin1String("balance-rr")); m_ui->mode->addItem(i18nc("bond mode", "Active backup"), QLatin1String("active-backup")); m_ui->mode->addItem(i18nc("bond mode", "Broadcast"), QLatin1String("broadcast")); m_ui->mode->addItem(i18nc("bond mode", "802.3ad"), QLatin1String("802.3ad")); m_ui->mode->addItem(i18nc("bond mode", "Adaptive transmit load balancing"), QLatin1String("balance-tlb")); m_ui->mode->addItem(i18nc("bond mode", "Adaptive load balancing"), QLatin1String("balance-alb")); // link monitor m_ui->linkMonitoring->addItem(i18nc("bond link monitoring", "MII (recommended)"), NM_SETTING_BOND_OPTION_MII_MONITOR); m_ui->linkMonitoring->addItem(i18nc("bond link monitoring", "ARP"), NM_SETTING_BOND_OPTION_ARP_MONITOR); // bonds populateBonds(); connect(m_ui->bonds, &QListWidget::currentItemChanged, this, &BondWidget::currentBondChanged); connect(m_ui->bonds, &QListWidget::itemDoubleClicked, this, &BondWidget::editBond); connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &BondWidget::slotWidgetChanged); connect(m_ui->arpTargets, &KLineEdit::textChanged, this, &BondWidget::slotWidgetChanged); connect(m_ui->linkMonitoring, QOverload::of(&KComboBox::currentIndexChanged), this, &BondWidget::slotWidgetChanged); // Connect for setting check watchChangedSetting(); KAcceleratorManager::manage(this); KAcceleratorManager::manage(m_menu); if (setting) { loadConfig(setting); } } BondWidget::~BondWidget() { delete m_ui; } void BondWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::BondSetting::Ptr bondSetting = setting.staticCast(); m_ui->ifaceName->setText(bondSetting->interfaceName()); const NMStringMap options = bondSetting->options(); // mode int modeIndex = m_ui->mode->findData(options.value(NM_SETTING_BOND_OPTION_MODE)); if (modeIndex == -1) modeIndex = 0; m_ui->mode->setCurrentIndex(modeIndex); const QString arpTargets = options.value(NM_SETTING_BOND_OPTION_ARP_IP_TARGET); if (!arpTargets.isEmpty()) { // ARP m_ui->linkMonitoring->setCurrentIndex(m_ui->linkMonitoring->findData(NM_SETTING_BOND_OPTION_ARP_MONITOR)); bool ok = false; const int arpMonFreq = options.value(NM_SETTING_BOND_OPTION_ARP_INTERVAL).toInt(&ok); if (ok && arpMonFreq > 0) m_ui->monitorFreq->setValue(arpMonFreq); m_ui->arpTargets->setText(arpTargets); } else { // MII m_ui->linkMonitoring->setCurrentIndex(m_ui->linkMonitoring->findData(NM_SETTING_BOND_OPTION_MII_MONITOR)); bool ok = false; const int miiMonFreq = options.value(NM_SETTING_BOND_OPTION_MIIMON).toInt(&ok); if (ok && miiMonFreq > 0) m_ui->monitorFreq->setValue(miiMonFreq); ok = false; const int upDelay = options.value(NM_SETTING_BOND_OPTION_UPDELAY).toInt(&ok); if (ok && upDelay > 0) m_ui->upDelay->setValue(upDelay); ok = false; const int downDelay = options.value(NM_SETTING_BOND_OPTION_DOWNDELAY).toInt(&ok); if (ok && downDelay > 0) m_ui->upDelay->setValue(downDelay); } } QVariantMap BondWidget::setting() const { NetworkManager::BondSetting setting; setting.setInterfaceName(m_ui->ifaceName->text()); NMStringMap options; options.insert(NM_SETTING_BOND_OPTION_MODE, m_ui->mode->itemData(m_ui->mode->currentIndex()).toString()); if (m_ui->linkMonitoring->itemData(m_ui->linkMonitoring->currentIndex()).toString() == NM_SETTING_BOND_OPTION_MII_MONITOR) { // MII options.insert(NM_SETTING_BOND_OPTION_MIIMON, QString::number(m_ui->monitorFreq->value())); const int upDelay = m_ui->upDelay->value(); if (upDelay) options.insert(NM_SETTING_BOND_OPTION_UPDELAY, QString::number(upDelay)); const int downDelay = m_ui->downDelay->value(); if (downDelay) options.insert(NM_SETTING_BOND_OPTION_DOWNDELAY, QString::number(downDelay)); } else { // ARP options.insert(NM_SETTING_BOND_OPTION_ARP_INTERVAL, QString::number(m_ui->monitorFreq->value())); const QString arpTargets = m_ui->arpTargets->text(); if (!arpTargets.isEmpty()) options.insert(NM_SETTING_BOND_OPTION_ARP_IP_TARGET, arpTargets); } setting.setOptions(options); return setting.toMap(); } void BondWidget::addBond(QAction *action) { qCDebug(PLASMA_NM) << "Adding bonded connection:" << action->data(); qCDebug(PLASMA_NM) << "Master UUID:" << m_uuid; qCDebug(PLASMA_NM) << "Slave type:" << type(); NetworkManager::ConnectionSettings::ConnectionType connectionType = static_cast(action->data().toInt()); NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connectionType)); connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings->setMaster(m_uuid); connectionSettings->setSlaveType(type()); connectionSettings->setAutoconnect(false); QPointer bondEditor = new ConnectionEditorDialog(connectionSettings); connect(bondEditor.data(), &ConnectionEditorDialog::accepted, [bondEditor, this] () { qCDebug(PLASMA_NM) << "Saving slave connection"; // qCDebug(PLASMA_NM) << bondEditor->setting(); QDBusPendingReply reply = NetworkManager::addConnection(bondEditor->setting()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BondWidget::bondAddComplete); }); connect(bondEditor.data(), &ConnectionEditorDialog::finished, [bondEditor] () { if (bondEditor) { bondEditor->deleteLater(); } }); bondEditor->setModal(true); bondEditor->show(); } void BondWidget::currentBondChanged(QListWidgetItem *current, QListWidgetItem *previous) { Q_UNUSED(previous) m_ui->btnEdit->setEnabled(current); m_ui->btnDelete->setEnabled(current); } void BondWidget::bondAddComplete(QDBusPendingCallWatcher * watcher) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { // find the slave connection with matching UUID NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(reply.value().path()); if (connection && connection->settings()->master() == m_uuid) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bonds); slaveItem->setData(Qt::UserRole, connection->uuid()); slotWidgetChanged(); } } else { qCWarning(PLASMA_NM) << "Bonded connection not added:" << reply.error().message(); } } void BondWidget::editBond() { QListWidgetItem * currentItem = m_ui->bonds->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { // qCDebug(PLASMA_NM) << "Editing bonded connection" << currentItem->text() << uuid; QPointer bondEditor = new ConnectionEditorDialog(connection->settings()); connect(bondEditor.data(), &ConnectionEditorDialog::accepted, [connection, bondEditor, this] () { connection->update(bondEditor->setting()); connect(connection.data(), &NetworkManager::Connection::updated, this, &BondWidget::populateBonds); }); connect(bondEditor.data(), &ConnectionEditorDialog::finished, [bondEditor] () { if (bondEditor) { bondEditor->deleteLater(); } }); bondEditor->setModal(true); bondEditor->show(); } } void BondWidget::deleteBond() { QListWidgetItem * currentItem = m_ui->bonds->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { // qCDebug(PLASMA_NM) << "About to delete bonded connection" << currentItem->text() << uuid; if (KMessageBox::questionYesNo(this, i18n("Do you want to remove the connection '%1'?", connection->name()), i18n("Remove Connection"), KStandardGuiItem::remove(), KStandardGuiItem::no(), QString(), KMessageBox::Dangerous) == KMessageBox::Yes) { connection->remove(); delete currentItem; slotWidgetChanged(); } } } void BondWidget::populateBonds() { m_ui->bonds->clear(); for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); - if (settings->master() == m_uuid && settings->slaveType() == type()) { + // The mapping from slave to master may be by uuid or name, try our best to + // figure out if we are master to the slave. + const QString master = settings->master(); + bool isSlave = ((master == m_uuid) || // by-uuid + (!m_id.isEmpty() && master == m_id)); // by-name + if (isSlave && (settings->slaveType() == type())) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bonds); slaveItem->setData(Qt::UserRole, connection->uuid()); } } } bool BondWidget::isValid() const { if (m_ui->linkMonitoring->itemData(m_ui->linkMonitoring->currentIndex()).toString() == NM_SETTING_BOND_OPTION_ARP_MONITOR) { const QStringList ipAddresses = m_ui->arpTargets->text().split(','); if (ipAddresses.isEmpty()) { return false; } for (const QString &ip : ipAddresses) { QHostAddress ipAddress(ip); if (ipAddress.isNull()) { return false; } } } return !m_ui->ifaceName->text().isEmpty() && m_ui->bonds->count() > 0; } diff --git a/libs/editor/settings/bondwidget.h b/libs/editor/settings/bondwidget.h index 24a8cdfc..08acf5ac 100644 --- a/libs/editor/settings/bondwidget.h +++ b/libs/editor/settings/bondwidget.h @@ -1,68 +1,70 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef PLASMA_NM_BOND_WIDGET_H #define PLASMA_NM_BOND_WIDGET_H #include #include #include #include #include #include "settingwidget.h" namespace Ui { class BondWidget; } class Q_DECL_EXPORT BondWidget : public SettingWidget { Q_OBJECT public: - explicit BondWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), + explicit BondWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), QWidget* parent = nullptr, Qt::WindowFlags f = {}); ~BondWidget() override; void loadConfig(const NetworkManager::Setting::Ptr &setting) override; QVariantMap setting() const override; bool isValid() const override; private Q_SLOTS: void addBond(QAction * action); void currentBondChanged(QListWidgetItem * current, QListWidgetItem * previous); void bondAddComplete(QDBusPendingCallWatcher * watcher); void editBond(); void deleteBond(); void populateBonds(); private: QString m_uuid; + QString m_id; Ui::BondWidget * m_ui; QMenu * m_menu; }; #endif // PLASMA_NM_BOND_WIDGET_H diff --git a/libs/editor/settings/bridgewidget.cpp b/libs/editor/settings/bridgewidget.cpp index c5871703..719a6680 100644 --- a/libs/editor/settings/bridgewidget.cpp +++ b/libs/editor/settings/bridgewidget.cpp @@ -1,241 +1,249 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "bridgewidget.h" #include "ui_bridge.h" #include "connectioneditordialog.h" #include "debug.h" #include #include #include #include #include #include #include -BridgeWidget::BridgeWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): +BridgeWidget::BridgeWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting, + QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_uuid(masterUuid), + m_id(masterId), m_ui(new Ui::BridgeWidget) { m_ui->setupUi(this); // Action buttons and menu m_menu = new QMenu(this); QAction * action = new QAction(i18n("Ethernet"), this); action->setData(NetworkManager::ConnectionSettings::Wired); m_menu->addAction(action); action = new QAction(i18n("VLAN"), this); action->setData(NetworkManager::ConnectionSettings::Vlan); m_menu->addAction(action); action = new QAction(i18n("Wi-Fi"), this); action->setData(NetworkManager::ConnectionSettings::Wireless); m_menu->addAction(action); m_ui->btnAdd->setMenu(m_menu); connect(m_menu, &QMenu::triggered, this, &BridgeWidget::addBridge); connect(m_ui->btnEdit, &QPushButton::clicked, this, &BridgeWidget::editBridge); connect(m_ui->btnDelete, &QPushButton::clicked, this, &BridgeWidget::deleteBridge); // bridges populateBridges(); connect(m_ui->bridges, &QListWidget::currentItemChanged, this, &BridgeWidget::currentBridgeChanged); connect(m_ui->bridges, &QListWidget::itemDoubleClicked, this, &BridgeWidget::editBridge); connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &BridgeWidget::slotWidgetChanged); // Connect for setting check watchChangedSetting(); KAcceleratorManager::manage(this); KAcceleratorManager::manage(m_menu); if (setting) { loadConfig(setting); } } BridgeWidget::~BridgeWidget() { delete m_ui; } void BridgeWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::BridgeSetting::Ptr bridgeSetting = setting.staticCast(); m_ui->ifaceName->setText(bridgeSetting->interfaceName()); m_ui->agingTime->setValue(bridgeSetting->agingTime()); const bool stp = bridgeSetting->stp(); m_ui->stpGroup->setChecked(stp); if (stp) { m_ui->priority->setValue(bridgeSetting->priority()); m_ui->forwardDelay->setValue(bridgeSetting->forwardDelay()); m_ui->helloTime->setValue(bridgeSetting->helloTime()); m_ui->maxAge->setValue(bridgeSetting->maxAge()); } } QVariantMap BridgeWidget::setting() const { NetworkManager::BridgeSetting setting; setting.setInterfaceName(m_ui->ifaceName->text()); setting.setAgingTime(m_ui->agingTime->value()); const bool stp = m_ui->stpGroup->isChecked(); setting.setStp(stp); if (stp) { setting.setPriority(m_ui->priority->value()); setting.setForwardDelay(m_ui->forwardDelay->value()); setting.setHelloTime(m_ui->helloTime->value()); setting.setMaxAge(m_ui->maxAge->value()); } return setting.toMap(); } void BridgeWidget::addBridge(QAction *action) { qCDebug(PLASMA_NM) << "Adding bridged connection:" << action->data(); qCDebug(PLASMA_NM) << "Master UUID:" << m_uuid; qCDebug(PLASMA_NM) << "Slave type:" << type(); NetworkManager::ConnectionSettings::ConnectionType connectionType = static_cast(action->data().toInt()); NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connectionType)); connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings->setMaster(m_uuid); connectionSettings->setSlaveType(type()); connectionSettings->setAutoconnect(false); QPointer bridgeEditor = new ConnectionEditorDialog(connectionSettings); connect(bridgeEditor.data(), &ConnectionEditorDialog::accepted, [bridgeEditor, this] () { qCDebug(PLASMA_NM) << "Saving slave connection"; // qCDebug(PLASMA_NM) << bridgeEditor->setting(); QDBusPendingReply reply = NetworkManager::addConnection(bridgeEditor->setting()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BridgeWidget::bridgeAddComplete); }); connect(bridgeEditor.data(), &ConnectionEditorDialog::finished, [bridgeEditor] () { if (bridgeEditor) { bridgeEditor->deleteLater(); } }); bridgeEditor->setModal(true); bridgeEditor->show(); } void BridgeWidget::currentBridgeChanged(QListWidgetItem *current, QListWidgetItem *previous) { Q_UNUSED(previous) m_ui->btnEdit->setEnabled(current); m_ui->btnDelete->setEnabled(current); } void BridgeWidget::bridgeAddComplete(QDBusPendingCallWatcher * watcher) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { // find the slave connection with matching UUID NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(reply.value().path()); if (connection && connection->settings()->master() == m_uuid) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bridges); slaveItem->setData(Qt::UserRole, connection->uuid()); slotWidgetChanged(); } } else { qCWarning(PLASMA_NM) << "Bridged connection not added:" << reply.error().message(); } } void BridgeWidget::editBridge() { QListWidgetItem * currentItem = m_ui->bridges->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { qCDebug(PLASMA_NM) << "Editing bridged connection" << currentItem->text() << uuid; QPointer bridgeEditor = new ConnectionEditorDialog(connection->settings()); connect(bridgeEditor.data(), &ConnectionEditorDialog::accepted, [connection, bridgeEditor, this] () { connection->update(bridgeEditor->setting()); connect(connection.data(), &NetworkManager::Connection::updated, this, &BridgeWidget::populateBridges); }); connect(bridgeEditor.data(), &ConnectionEditorDialog::finished, [bridgeEditor] () { if (bridgeEditor) { bridgeEditor->deleteLater(); } }); bridgeEditor->setModal(true); bridgeEditor->show(); } } void BridgeWidget::deleteBridge() { QListWidgetItem * currentItem = m_ui->bridges->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { // qCDebug(PLASMA_NM) << "About to delete bridged connection" << currentItem->text() << uuid; if (KMessageBox::questionYesNo(this, i18n("Do you want to remove the connection '%1'?", connection->name()), i18n("Remove Connection"), KStandardGuiItem::remove(), KStandardGuiItem::no(), QString(), KMessageBox::Dangerous) == KMessageBox::Yes) { connection->remove(); delete currentItem; slotWidgetChanged(); } } } void BridgeWidget::populateBridges() { m_ui->bridges->clear(); for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); - if (settings->master() == m_uuid && settings->slaveType() == type()) { + // The mapping from slave to master may be by uuid or name, try our best to + // figure out if we are master to the slave. + const QString master = settings->master(); + bool isSlave = ((master == m_uuid) || // by-uuid + (!m_id.isEmpty() && master == m_id)); // by-name + if (isSlave && (settings->slaveType() == type())) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->bridges); slaveItem->setData(Qt::UserRole, connection->uuid()); } } } bool BridgeWidget::isValid() const { return !m_ui->ifaceName->text().isEmpty() && m_ui->bridges->count() > 0; } diff --git a/libs/editor/settings/bridgewidget.h b/libs/editor/settings/bridgewidget.h index 2e04b9e3..bea0395b 100644 --- a/libs/editor/settings/bridgewidget.h +++ b/libs/editor/settings/bridgewidget.h @@ -1,68 +1,70 @@ /* Copyright 2013 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef PLASMA_NM_BRIDGE_WIDGET_H #define PLASMA_NM_BRIDGE_WIDGET_H #include #include #include #include #include #include "settingwidget.h" namespace Ui { class BridgeWidget; } class Q_DECL_EXPORT BridgeWidget : public SettingWidget { Q_OBJECT public: - explicit BridgeWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), - QWidget* parent = nullptr, Qt::WindowFlags f = {}); + explicit BridgeWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), + QWidget* parent = nullptr, Qt::WindowFlags f = {}); ~BridgeWidget() override; void loadConfig(const NetworkManager::Setting::Ptr &setting) override; QVariantMap setting() const override; bool isValid() const override; private Q_SLOTS: void addBridge(QAction * action); void currentBridgeChanged(QListWidgetItem * current, QListWidgetItem * previous); void bridgeAddComplete(QDBusPendingCallWatcher * watcher); void editBridge(); void deleteBridge(); void populateBridges(); private: QString m_uuid; + QString m_id; Ui::BridgeWidget * m_ui; QMenu * m_menu; }; #endif // PLASMA_NM_BRIDGE_WIDGET_H diff --git a/libs/editor/settings/teamwidget.cpp b/libs/editor/settings/teamwidget.cpp index 843a8a58..2faddf02 100644 --- a/libs/editor/settings/teamwidget.cpp +++ b/libs/editor/settings/teamwidget.cpp @@ -1,245 +1,252 @@ /* Copyright 2014 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "teamwidget.h" #include "ui_team.h" #include "connectioneditordialog.h" #include "debug.h" #include #include #include #include #include #include #include #include #include -TeamWidget::TeamWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): +TeamWidget::TeamWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting, QWidget* parent, Qt::WindowFlags f): SettingWidget(setting, parent, f), m_uuid(masterUuid), + m_id(masterId), m_ui(new Ui::TeamWidget) { m_ui->setupUi(this); // Action buttons and menu m_menu = new QMenu(this); QAction * action = new QAction(i18n("Ethernet"), this); action->setData(NetworkManager::ConnectionSettings::Wired); m_menu->addAction(action); action = new QAction(i18n("Infiniband"), this); action->setData(NetworkManager::ConnectionSettings::Infiniband); m_menu->addAction(action); action = new QAction(i18n("Wi-Fi"), this); action->setData(NetworkManager::ConnectionSettings::Wireless); m_menu->addAction(action); action = new QAction(i18n("VLAN"), this); action->setData(NetworkManager::ConnectionSettings::Vlan); m_menu->addAction(action); m_ui->btnAdd->setMenu(m_menu); connect(m_menu, &QMenu::triggered, this, &TeamWidget::addTeam); connect(m_ui->btnEdit, &QPushButton::clicked, this, &TeamWidget::editTeam); connect(m_ui->btnDelete, &QPushButton::clicked, this, &TeamWidget::deleteTeam); connect(m_ui->btnImport, &QPushButton::clicked, this, &TeamWidget::importConfig); // teams populateTeams(); connect(m_ui->teams, &QListWidget::currentItemChanged, this, &TeamWidget::currentTeamChanged); connect(m_ui->teams, &QListWidget::itemDoubleClicked, this, &TeamWidget::editTeam); connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &TeamWidget::slotWidgetChanged); // Connect for setting check watchChangedSetting(); KAcceleratorManager::manage(this); KAcceleratorManager::manage(m_menu); if (setting) { loadConfig(setting); } } TeamWidget::~TeamWidget() { delete m_ui; } void TeamWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) { NetworkManager::TeamSetting::Ptr teamSetting = setting.staticCast(); m_ui->ifaceName->setText(teamSetting->interfaceName()); m_ui->config->setPlainText(teamSetting->config()); } QVariantMap TeamWidget::setting() const { NetworkManager::TeamSetting setting; setting.setInterfaceName(m_ui->ifaceName->text()); setting.setConfig(m_ui->config->toPlainText()); return setting.toMap(); } void TeamWidget::addTeam(QAction *action) { qCDebug(PLASMA_NM) << "Adding teamed connection:" << action->data(); qCDebug(PLASMA_NM) << "Master UUID:" << m_uuid; qCDebug(PLASMA_NM) << "Slave type:" << type(); NetworkManager::ConnectionSettings::ConnectionType connectionType = static_cast(action->data().toInt()); NetworkManager::ConnectionSettings::Ptr connectionSettings = NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connectionType)); connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); connectionSettings->setMaster(m_uuid); connectionSettings->setSlaveType(type()); connectionSettings->setAutoconnect(false); QPointer teamEditor = new ConnectionEditorDialog(connectionSettings); connect(teamEditor.data(), &ConnectionEditorDialog::accepted, [teamEditor, this] () { qCDebug(PLASMA_NM) << "Saving slave connection"; // qCDebug(PLASMA_NM) << teamEditor->setting(); QDBusPendingReply reply = NetworkManager::addConnection(teamEditor->setting()); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &TeamWidget::teamAddComplete); }); connect(teamEditor.data(), &ConnectionEditorDialog::finished, [teamEditor] () { if (teamEditor) { teamEditor->deleteLater(); } }); teamEditor->setModal(true); teamEditor->show(); } void TeamWidget::currentTeamChanged(QListWidgetItem *current, QListWidgetItem *previous) { Q_UNUSED(previous) m_ui->btnEdit->setEnabled(current); m_ui->btnDelete->setEnabled(current); } void TeamWidget::teamAddComplete(QDBusPendingCallWatcher * watcher) { QDBusPendingReply reply = *watcher; if (reply.isValid()) { // find the slave connection with matching UUID NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(reply.value().path()); if (connection && connection->settings()->master() == m_uuid) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->teams); slaveItem->setData(Qt::UserRole, connection->uuid()); slotWidgetChanged(); } } else { qCWarning(PLASMA_NM) << "Teamed connection not added:" << reply.error().message(); } } void TeamWidget::editTeam() { QListWidgetItem * currentItem = m_ui->teams->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { qCDebug(PLASMA_NM) << "Editing teamed connection" << currentItem->text() << uuid; QPointer teamEditor = new ConnectionEditorDialog(connection->settings()); connect(teamEditor.data(), &ConnectionEditorDialog::accepted, [connection, teamEditor, this] () { connection->update(teamEditor->setting()); connect(connection.data(), &NetworkManager::Connection::updated, this, &TeamWidget::populateTeams); }); connect(teamEditor.data(), &ConnectionEditorDialog::finished, [teamEditor] () { if (teamEditor) { teamEditor->deleteLater(); } }); teamEditor->setModal(true); teamEditor->show(); } } void TeamWidget::deleteTeam() { QListWidgetItem * currentItem = m_ui->teams->currentItem(); if (!currentItem) return; const QString uuid = currentItem->data(Qt::UserRole).toString(); NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); if (connection) { qCDebug(PLASMA_NM) << "About to delete teamed connection" << currentItem->text() << uuid; if (KMessageBox::questionYesNo(this, i18n("Do you want to remove the connection '%1'?", connection->name()), i18n("Remove Connection"), KStandardGuiItem::remove(), KStandardGuiItem::no(), QString(), KMessageBox::Dangerous) == KMessageBox::Yes) { connection->remove(); delete currentItem; slotWidgetChanged(); } } } void TeamWidget::populateTeams() { m_ui->teams->clear(); for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); - if (settings->master() == m_uuid && settings->slaveType() == type()) { + // The mapping from slave to master may be by uuid or name, try our best to + // figure out if we are master to the slave. + const QString master = settings->master(); + bool isSlave = ((master == m_uuid) || // by-uuid + (!m_id.isEmpty() && master == m_id)); // by-name + if (isSlave && (settings->slaveType() == type())) { const QString label = QString("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); QListWidgetItem * slaveItem = new QListWidgetItem(label, m_ui->teams); slaveItem->setData(Qt::UserRole, connection->uuid()); } } } void TeamWidget::importConfig() { const QString filename = QFileDialog::getOpenFileName(this, i18n("Select file to import"), QDesktopServices::storageLocation(QDesktopServices::HomeLocation), "text/plain"); if (!filename.isEmpty()) { //qCDebug(PLASMA_NM) << "Importing" << filename; QFile file(filename); if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&file); m_ui->config->setPlainText(stream.readAll()); file.close(); } } } bool TeamWidget::isValid() const { return !m_ui->ifaceName->text().isEmpty() && m_ui->teams->count() > 0; } diff --git a/libs/editor/settings/teamwidget.h b/libs/editor/settings/teamwidget.h index aaea4e53..0f7555a5 100644 --- a/libs/editor/settings/teamwidget.h +++ b/libs/editor/settings/teamwidget.h @@ -1,70 +1,72 @@ /* Copyright 2014 Lukas Tinkl This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) version 3, or any later version accepted by the membership of KDE e.V. (or its successor approved by the membership of KDE e.V.), which shall act as a proxy defined in Section 6 of version 3 of the license. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef PLASMA_NM_TEAM_WIDGET_H #define PLASMA_NM_TEAM_WIDGET_H #include #include #include #include #include "settingwidget.h" #include namespace Ui { class TeamWidget; } class Q_DECL_EXPORT TeamWidget : public SettingWidget { Q_OBJECT public: - explicit TeamWidget(const QString & masterUuid, const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), + explicit TeamWidget(const QString & masterUuid, const QString &masterId, + const NetworkManager::Setting::Ptr &setting = NetworkManager::Setting::Ptr(), QWidget* parent = nullptr, Qt::WindowFlags f = {}); ~TeamWidget() override; void loadConfig(const NetworkManager::Setting::Ptr &setting) override; QVariantMap setting() const override; bool isValid() const override; private Q_SLOTS: void addTeam(QAction * action); void currentTeamChanged(QListWidgetItem * current, QListWidgetItem * previous); void teamAddComplete(QDBusPendingCallWatcher * watcher); void editTeam(); void deleteTeam(); void populateTeams(); void importConfig(); private: QString m_uuid; + QString m_id; Ui::TeamWidget * m_ui; QMenu * m_menu; }; #endif // PLASMA_NM_TEAM_WIDGET_H