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