File indexing completed on 2024-07-14 09:00:24

0001 /*
0002     SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com>
0003     SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include "ssidcombobox.h"
0009 #include "uiutils.h"
0010 
0011 #include <NetworkManagerQt/Manager>
0012 #include <NetworkManagerQt/WirelessDevice>
0013 
0014 #include <KLocalizedString>
0015 
0016 bool signalCompare(const NetworkManager::WirelessNetwork::Ptr &one, const NetworkManager::WirelessNetwork::Ptr &two)
0017 {
0018     return one->signalStrength() > two->signalStrength();
0019 }
0020 
0021 SsidComboBox::SsidComboBox(QWidget *parent)
0022     : KComboBox(parent)
0023 {
0024     setEditable(true);
0025     setInsertPolicy(QComboBox::NoInsert);
0026 
0027     connect(this, &SsidComboBox::editTextChanged, this, &SsidComboBox::slotEditTextChanged);
0028     connect(this, QOverload<int>::of(&SsidComboBox::activated), this, &SsidComboBox::slotCurrentIndexChanged);
0029 }
0030 
0031 QString SsidComboBox::ssid() const
0032 {
0033     if (currentIndex() == 0 || currentText() != itemData(currentIndex()).toString()) {
0034         return currentText();
0035     } else {
0036         return itemData(currentIndex()).toString();
0037     }
0038 }
0039 
0040 void SsidComboBox::slotEditTextChanged(const QString &text)
0041 {
0042     if (!text.contains(QLatin1String("Security:")) && !text.contains(QLatin1String("Frequency:"))) {
0043         Q_EMIT ssidChanged();
0044     }
0045 }
0046 
0047 void SsidComboBox::slotCurrentIndexChanged(int)
0048 {
0049     setEditText(itemData(currentIndex()).toString());
0050 }
0051 
0052 void SsidComboBox::init(const QString &ssid)
0053 {
0054     m_initialSsid = ssid;
0055 
0056     // qCDebug(PLASMA_NM_EDITOR_LOG) << "Initial ssid:" << m_initialSsid;
0057 
0058     QList<NetworkManager::WirelessNetwork::Ptr> networks;
0059 
0060     for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) {
0061         if (device->type() == NetworkManager::Device::Wifi) {
0062             NetworkManager::WirelessDevice::Ptr wifiDevice = device.objectCast<NetworkManager::WirelessDevice>();
0063 
0064             for (const NetworkManager::WirelessNetwork::Ptr &newNetwork : wifiDevice->networks()) {
0065                 bool found = false;
0066                 for (const NetworkManager::WirelessNetwork::Ptr &existingNetwork : networks) {
0067                     if (newNetwork->ssid() == existingNetwork->ssid()) {
0068                         if (newNetwork->signalStrength() > existingNetwork->signalStrength()) {
0069                             networks.removeOne(existingNetwork);
0070                             break;
0071                         } else {
0072                             found = true;
0073                             break;
0074                         }
0075                     }
0076                 }
0077                 if (!found) {
0078                     networks << newNetwork;
0079                 }
0080             }
0081         }
0082     }
0083 
0084     std::sort(networks.begin(), networks.end(), signalCompare);
0085     addSsidsToCombo(networks);
0086 
0087     int index = findData(m_initialSsid);
0088     if (index == -1) {
0089         insertItem(0, m_initialSsid, m_initialSsid);
0090         setCurrentIndex(0);
0091     } else {
0092         setCurrentIndex(index);
0093     }
0094     setEditText(m_initialSsid);
0095 }
0096 
0097 void SsidComboBox::addSsidsToCombo(const QList<NetworkManager::WirelessNetwork::Ptr> &networks)
0098 {
0099     QList<NetworkManager::WirelessDevice::Ptr> wifiDevices;
0100 
0101     for (const NetworkManager::Device::Ptr &dev : NetworkManager::networkInterfaces()) {
0102         if (dev->type() == NetworkManager::Device::Wifi) {
0103             wifiDevices << dev.objectCast<NetworkManager::WirelessDevice>();
0104         }
0105     }
0106 
0107     bool empty = true;
0108 
0109     for (const NetworkManager::WirelessNetwork::Ptr &network : networks) {
0110         NetworkManager::AccessPoint::Ptr accessPoint = network->referenceAccessPoint();
0111 
0112         if (!accessPoint) {
0113             continue;
0114         }
0115 
0116         for (const NetworkManager::WirelessDevice::Ptr &wifiDev : std::as_const(wifiDevices)) {
0117             if (wifiDev->findNetwork(network->ssid()) == network) {
0118                 if (!empty) {
0119                     insertSeparator(count());
0120                 }
0121                 empty = false;
0122 
0123                 NetworkManager::WirelessSecurityType security =
0124                     NetworkManager::findBestWirelessSecurity(wifiDev->wirelessCapabilities(),
0125                                                              true,
0126                                                              (wifiDev->mode() == NetworkManager::WirelessDevice::Adhoc),
0127                                                              accessPoint->capabilities(),
0128                                                              accessPoint->wpaFlags(),
0129                                                              accessPoint->rsnFlags());
0130                 if (security != NetworkManager::UnknownSecurity && security != NetworkManager::NoneSecurity) {
0131                     const QString text = i18n("%1 (%2%)\nSecurity: %3\nFrequency: %4 Mhz",
0132                                               accessPoint->ssid(),
0133                                               network->signalStrength(),
0134                                               UiUtils::labelFromWirelessSecurity(security),
0135                                               accessPoint->frequency());
0136                     addItem(QIcon::fromTheme(QStringLiteral("object-locked")), text, accessPoint->ssid());
0137                 } else {
0138                     const QString text =
0139                         i18n("%1 (%2%)\nSecurity: Insecure\nFrequency: %3 Mhz", accessPoint->ssid(), network->signalStrength(), accessPoint->frequency());
0140                     addItem(QIcon::fromTheme(QStringLiteral("object-unlocked")), text, accessPoint->ssid());
0141                 }
0142             }
0143         }
0144     }
0145 }
0146 
0147 #include "moc_ssidcombobox.cpp"