Warning, file /plasma/plasma-nm/libs/editor/settings/teamwidget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

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 }