File indexing completed on 2025-04-27 14:24:06
0001 /* 0002 SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0005 */ 0006 0007 #include "bridgewidget.h" 0008 #include "connectioneditordialog.h" 0009 #include "plasma_nm_editor.h" 0010 #include "ui_bridge.h" 0011 0012 #include <QDBusPendingReply> 0013 0014 #include <NetworkManagerQt/Connection> 0015 #include <NetworkManagerQt/ConnectionSettings> 0016 #include <NetworkManagerQt/GenericTypes> 0017 #include <NetworkManagerQt/Settings> 0018 0019 #include <KLocalizedString> 0020 #include <KMessageBox> 0021 #include <kwidgetsaddons_version.h> 0022 0023 BridgeWidget::BridgeWidget(const QString &masterUuid, const QString &masterId, const NetworkManager::Setting::Ptr &setting, QWidget *parent, Qt::WindowFlags f) 0024 : SettingWidget(setting, parent, f) 0025 , m_uuid(masterUuid) 0026 , m_id(masterId) 0027 , m_ui(new Ui::BridgeWidget) 0028 , m_menu(new QMenu(this)) 0029 { 0030 m_ui->setupUi(this); 0031 0032 // Action buttons and menu 0033 auto action = new QAction(i18n("Ethernet"), this); 0034 action->setData(NetworkManager::ConnectionSettings::Wired); 0035 m_menu->addAction(action); 0036 action = new QAction(i18n("VLAN"), this); 0037 action->setData(NetworkManager::ConnectionSettings::Vlan); 0038 m_menu->addAction(action); 0039 action = new QAction(i18n("Wi-Fi"), this); 0040 action->setData(NetworkManager::ConnectionSettings::Wireless); 0041 m_menu->addAction(action); 0042 m_ui->btnAdd->setMenu(m_menu); 0043 connect(m_menu, &QMenu::triggered, this, &BridgeWidget::addBridge); 0044 connect(m_ui->btnEdit, &QPushButton::clicked, this, &BridgeWidget::editBridge); 0045 connect(m_ui->btnDelete, &QPushButton::clicked, this, &BridgeWidget::deleteBridge); 0046 0047 // bridges 0048 populateBridges(); 0049 connect(m_ui->bridges, &QListWidget::currentItemChanged, this, &BridgeWidget::currentBridgeChanged); 0050 connect(m_ui->bridges, &QListWidget::itemDoubleClicked, this, &BridgeWidget::editBridge); 0051 0052 connect(m_ui->ifaceName, &KLineEdit::textChanged, this, &BridgeWidget::slotWidgetChanged); 0053 0054 // Connect for setting check 0055 watchChangedSetting(); 0056 0057 KAcceleratorManager::manage(this); 0058 KAcceleratorManager::manage(m_menu); 0059 0060 if (setting) { 0061 loadConfig(setting); 0062 } 0063 } 0064 0065 BridgeWidget::~BridgeWidget() 0066 { 0067 delete m_ui; 0068 } 0069 0070 void BridgeWidget::loadConfig(const NetworkManager::Setting::Ptr &setting) 0071 { 0072 NetworkManager::BridgeSetting::Ptr bridgeSetting = setting.staticCast<NetworkManager::BridgeSetting>(); 0073 0074 m_ui->ifaceName->setText(bridgeSetting->interfaceName()); 0075 m_ui->agingTime->setValue(bridgeSetting->agingTime()); 0076 0077 const bool stp = bridgeSetting->stp(); 0078 m_ui->stpGroup->setChecked(stp); 0079 if (stp) { 0080 m_ui->priority->setValue(bridgeSetting->priority()); 0081 m_ui->forwardDelay->setValue(bridgeSetting->forwardDelay()); 0082 m_ui->helloTime->setValue(bridgeSetting->helloTime()); 0083 m_ui->maxAge->setValue(bridgeSetting->maxAge()); 0084 } 0085 } 0086 0087 QVariantMap BridgeWidget::setting() const 0088 { 0089 NetworkManager::BridgeSetting setting; 0090 setting.setInterfaceName(m_ui->ifaceName->text()); 0091 setting.setAgingTime(m_ui->agingTime->value()); 0092 0093 const bool stp = m_ui->stpGroup->isChecked(); 0094 setting.setStp(stp); 0095 if (stp) { 0096 setting.setPriority(m_ui->priority->value()); 0097 setting.setForwardDelay(m_ui->forwardDelay->value()); 0098 setting.setHelloTime(m_ui->helloTime->value()); 0099 setting.setMaxAge(m_ui->maxAge->value()); 0100 } 0101 0102 return setting.toMap(); 0103 } 0104 0105 void BridgeWidget::addBridge(QAction *action) 0106 { 0107 qCDebug(PLASMA_NM_EDITOR_LOG) << "Adding bridged connection:" << action->data(); 0108 qCDebug(PLASMA_NM_EDITOR_LOG) << "Master UUID:" << m_uuid; 0109 qCDebug(PLASMA_NM_EDITOR_LOG) << "Slave type:" << type(); 0110 0111 NetworkManager::ConnectionSettings::ConnectionType connectionType = static_cast<NetworkManager::ConnectionSettings::ConnectionType>(action->data().toInt()); 0112 NetworkManager::ConnectionSettings::Ptr connectionSettings = 0113 NetworkManager::ConnectionSettings::Ptr(new NetworkManager::ConnectionSettings(connectionType)); 0114 connectionSettings->setUuid(NetworkManager::ConnectionSettings::createNewUuid()); 0115 connectionSettings->setMaster(m_uuid); 0116 connectionSettings->setSlaveType(type()); 0117 connectionSettings->setAutoconnect(false); 0118 0119 QPointer<ConnectionEditorDialog> bridgeEditor = new ConnectionEditorDialog(connectionSettings); 0120 bridgeEditor->setAttribute(Qt::WA_DeleteOnClose); 0121 connect(bridgeEditor.data(), &ConnectionEditorDialog::accepted, [bridgeEditor, this]() { 0122 qCDebug(PLASMA_NM_EDITOR_LOG) << "Saving slave connection"; 0123 // qCDebug(PLASMA_NM_EDITOR_LOG) << bridgeEditor->setting(); 0124 QDBusPendingReply<QDBusObjectPath> reply = NetworkManager::addConnection(bridgeEditor->setting()); 0125 auto watcher = new QDBusPendingCallWatcher(reply, this); 0126 connect(watcher, &QDBusPendingCallWatcher::finished, this, &BridgeWidget::bridgeAddComplete); 0127 }); 0128 bridgeEditor->setModal(true); 0129 bridgeEditor->show(); 0130 } 0131 0132 void BridgeWidget::currentBridgeChanged(QListWidgetItem *current, QListWidgetItem *previous) 0133 { 0134 Q_UNUSED(previous) 0135 0136 m_ui->btnEdit->setEnabled(current); 0137 m_ui->btnDelete->setEnabled(current); 0138 } 0139 0140 void BridgeWidget::bridgeAddComplete(QDBusPendingCallWatcher *watcher) 0141 { 0142 QDBusPendingReply<QDBusObjectPath> reply = *watcher; 0143 0144 if (reply.isValid()) { 0145 // find the slave connection with matching UUID 0146 NetworkManager::Connection::Ptr connection = NetworkManager::findConnection(reply.value().path()); 0147 if (connection && connection->settings()->master() == m_uuid) { 0148 const QString label = 0149 QStringLiteral("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); 0150 auto slaveItem = new QListWidgetItem(label, m_ui->bridges); 0151 slaveItem->setData(Qt::UserRole, connection->uuid()); 0152 slotWidgetChanged(); 0153 } 0154 } else { 0155 qCWarning(PLASMA_NM_EDITOR_LOG) << "Bridged connection not added:" << reply.error().message(); 0156 } 0157 } 0158 0159 void BridgeWidget::editBridge() 0160 { 0161 QListWidgetItem *currentItem = m_ui->bridges->currentItem(); 0162 if (!currentItem) 0163 return; 0164 0165 const QString uuid = currentItem->data(Qt::UserRole).toString(); 0166 NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); 0167 0168 if (connection) { 0169 qCDebug(PLASMA_NM_EDITOR_LOG) << "Editing bridged connection" << currentItem->text() << uuid; 0170 QPointer<ConnectionEditorDialog> bridgeEditor = new ConnectionEditorDialog(connection->settings()); 0171 bridgeEditor->setAttribute(Qt::WA_DeleteOnClose); 0172 connect(bridgeEditor.data(), &ConnectionEditorDialog::accepted, [connection, bridgeEditor, this]() { 0173 connection->update(bridgeEditor->setting()); 0174 connect(connection.data(), &NetworkManager::Connection::updated, this, &BridgeWidget::populateBridges); 0175 }); 0176 bridgeEditor->setModal(true); 0177 bridgeEditor->show(); 0178 } 0179 } 0180 0181 void BridgeWidget::deleteBridge() 0182 { 0183 QListWidgetItem *currentItem = m_ui->bridges->currentItem(); 0184 if (!currentItem) 0185 return; 0186 0187 const QString uuid = currentItem->data(Qt::UserRole).toString(); 0188 NetworkManager::Connection::Ptr connection = NetworkManager::findConnectionByUuid(uuid); 0189 0190 if (connection) { 0191 // qCDebug(PLASMA_NM_EDITOR_LOG) << "About to delete bridged connection" << currentItem->text() << uuid; 0192 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0193 if (KMessageBox::questionTwoActions(this, 0194 #else 0195 if (KMessageBox::questionYesNo(this, 0196 0197 #endif 0198 i18n("Do you want to remove the connection '%1'?", connection->name()), 0199 i18n("Remove Connection"), 0200 KStandardGuiItem::remove(), 0201 KStandardGuiItem::cancel(), 0202 QString(), 0203 KMessageBox::Dangerous) 0204 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0205 == KMessageBox::ButtonCode::PrimaryAction) { 0206 #else 0207 == KMessageBox::Yes) { 0208 #endif 0209 connection->remove(); 0210 delete currentItem; 0211 slotWidgetChanged(); 0212 } 0213 } 0214 } 0215 0216 void BridgeWidget::populateBridges() 0217 { 0218 m_ui->bridges->clear(); 0219 0220 for (const NetworkManager::Connection::Ptr &connection : NetworkManager::listConnections()) { 0221 NetworkManager::ConnectionSettings::Ptr settings = connection->settings(); 0222 // The mapping from slave to master may be by uuid or name, try our best to 0223 // figure out if we are master to the slave. 0224 const QString master = settings->master(); 0225 bool isSlave = ((master == m_uuid) || // by-uuid 0226 (!m_id.isEmpty() && master == m_id)); // by-name 0227 if (isSlave && (settings->slaveType() == type())) { 0228 const QString label = 0229 QStringLiteral("%1 (%2)").arg(connection->name()).arg(connection->settings()->typeAsString(connection->settings()->connectionType())); 0230 auto slaveItem = new QListWidgetItem(label, m_ui->bridges); 0231 slaveItem->setData(Qt::UserRole, connection->uuid()); 0232 } 0233 } 0234 } 0235 0236 bool BridgeWidget::isValid() const 0237 { 0238 return !m_ui->ifaceName->text().isEmpty() && m_ui->bridges->count() > 0; 0239 }