File indexing completed on 2023-11-26 08:54:34

0001 /*
0002     SPDX-FileCopyrightText: 2008-2010 Sebastian K├╝gler <sebas@kde.org>
0003     SPDX-FileCopyrightText: 2013-2014 Jan Grulich <jgrulich@redhat.com>
0004 
0005     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006 */
0007 
0008 // Own
0009 #include "uiutils.h"
0010 
0011 #include "configuration.h"
0012 #include "plasma_nm_editor.h"
0013 
0014 // KDE
0015 #include <KConfigGroup>
0016 #include <KLocalizedString>
0017 #include <KSharedConfig>
0018 #include <KUser>
0019 #include <KWallet>
0020 
0021 #include <NetworkManagerQt/Manager>
0022 #include <NetworkManagerQt/Security8021xSetting>
0023 
0024 #include <ModemManagerQt/Manager>
0025 #include <ModemManagerQt/Modem3Gpp>
0026 #include <ModemManagerQt/ModemCdma>
0027 #include <ModemManagerQt/ModemDevice>
0028 
0029 // Qt
0030 #include <QHostAddress>
0031 #include <QSizeF>
0032 #include <QFile>
0033 #include <QString>
0034 
0035 #include <optional>
0036 
0037 using namespace NetworkManager;
0038 
0039 UiUtils::SortedConnectionType UiUtils::connectionTypeToSortedType(NetworkManager::ConnectionSettings::ConnectionType type)
0040 {
0041     switch (type) {
0042     case NetworkManager::ConnectionSettings::Unknown:
0043         return UiUtils::Unknown;
0044         break;
0045     case NetworkManager::ConnectionSettings::Adsl:
0046         return UiUtils::Adsl;
0047         break;
0048     case NetworkManager::ConnectionSettings::Bluetooth:
0049         return UiUtils::Bluetooth;
0050         break;
0051     case NetworkManager::ConnectionSettings::Bond:
0052         return UiUtils::Bond;
0053         break;
0054     case NetworkManager::ConnectionSettings::Bridge:
0055         return UiUtils::Bridge;
0056         break;
0057     case NetworkManager::ConnectionSettings::Cdma:
0058         return UiUtils::Cdma;
0059         break;
0060     case NetworkManager::ConnectionSettings::Gsm:
0061         return UiUtils::Gsm;
0062         break;
0063     case NetworkManager::ConnectionSettings::Infiniband:
0064         return UiUtils::Infiniband;
0065         break;
0066     case NetworkManager::ConnectionSettings::OLPCMesh:
0067         return UiUtils::OLPCMesh;
0068         break;
0069     case NetworkManager::ConnectionSettings::Pppoe:
0070         return UiUtils::Pppoe;
0071         break;
0072     case NetworkManager::ConnectionSettings::Team:
0073         return UiUtils::Team;
0074         break;
0075     case NetworkManager::ConnectionSettings::Vlan:
0076         return UiUtils::Vlan;
0077         break;
0078     case NetworkManager::ConnectionSettings::Vpn:
0079         return UiUtils::Vpn;
0080         break;
0081     case NetworkManager::ConnectionSettings::Wired:
0082         return UiUtils::Wired;
0083         break;
0084     case NetworkManager::ConnectionSettings::Wireless:
0085         return UiUtils::Wireless;
0086         break;
0087     case NetworkManager::ConnectionSettings::WireGuard:
0088         return UiUtils::Wireguard;
0089         break;
0090     default:
0091         return UiUtils::Unknown;
0092         break;
0093     }
0094 }
0095 
0096 bool UiUtils::isConnectionTypeSupported(NetworkManager::ConnectionSettings::ConnectionType type)
0097 {
0098     if (type == NetworkManager::ConnectionSettings::Generic || type == NetworkManager::ConnectionSettings::Tun) {
0099         return false;
0100     }
0101 
0102     bool manageVirtualConnections = Configuration::self().manageVirtualConnections();
0103 
0104     if (type == NetworkManager::ConnectionSettings::Bond //
0105         || type == NetworkManager::ConnectionSettings::Bridge //
0106         || type == NetworkManager::ConnectionSettings::Infiniband //
0107         || type == NetworkManager::ConnectionSettings::Team //
0108         || type == NetworkManager::ConnectionSettings::Vlan) {
0109         return manageVirtualConnections;
0110     }
0111 
0112     return true;
0113 }
0114 
0115 bool UiUtils::isConnectionTypeVirtual(NetworkManager::ConnectionSettings::ConnectionType type)
0116 {
0117     if (type == NetworkManager::ConnectionSettings::Bond //
0118         || type == NetworkManager::ConnectionSettings::Bridge //
0119         || type == NetworkManager::ConnectionSettings::Infiniband //
0120         || type == NetworkManager::ConnectionSettings::Team //
0121         || type == NetworkManager::ConnectionSettings::Vlan) {
0122         return true;
0123     }
0124 
0125     return false;
0126 }
0127 
0128 QString UiUtils::interfaceTypeLabel(const NetworkManager::Device::Type type, const NetworkManager::Device::Ptr iface)
0129 {
0130     QString deviceText;
0131     switch (type) {
0132     case NetworkManager::Device::Wifi:
0133         deviceText = i18nc("title of the interface widget in nm's popup", "Wi-Fi");
0134         break;
0135     case NetworkManager::Device::Bluetooth:
0136         deviceText = i18nc("title of the interface widget in nm's popup", "Bluetooth");
0137         break;
0138     case NetworkManager::Device::InfiniBand:
0139         deviceText = i18nc("title of the interface widget in nm's popup", "Infiniband");
0140         break;
0141     case NetworkManager::Device::Adsl:
0142         deviceText = i18nc("title of the interface widget in nm's popup", "ADSL");
0143         break;
0144     case NetworkManager::Device::Bond:
0145         deviceText = i18nc("title of the interface widget in nm's popup", "Virtual (bond)");
0146         break;
0147     case NetworkManager::Device::Bridge:
0148         deviceText = i18nc("title of the interface widget in nm's popup", "Virtual (bridge)");
0149         break;
0150     case NetworkManager::Device::Vlan:
0151         deviceText = i18nc("title of the interface widget in nm's popup", "Virtual (vlan)");
0152         break;
0153     case NetworkManager::Device::Team:
0154         deviceText = i18nc("title of the interface widget in nm's popup", "Virtual (team)");
0155         break;
0156     case NetworkManager::Device::Modem: {
0157         const NetworkManager::ModemDevice::Ptr nmModemIface = iface.objectCast<NetworkManager::ModemDevice>();
0158         if (nmModemIface) {
0159             switch (modemSubType(nmModemIface->currentCapabilities())) {
0160             case NetworkManager::ModemDevice::Pots:
0161                 deviceText = i18nc("title of the interface widget in nm's popup", "Serial Modem");
0162                 break;
0163             case NetworkManager::ModemDevice::GsmUmts:
0164             case NetworkManager::ModemDevice::CdmaEvdo:
0165             case NetworkManager::ModemDevice::Lte:
0166                 deviceText = i18nc("title of the interface widget in nm's popup", "Mobile Broadband");
0167                 break;
0168             case NetworkManager::ModemDevice::NoCapability:
0169                 qCWarning(PLASMA_NM_EDITOR_LOG) << "Unhandled modem sub type: NetworkManager::ModemDevice::NoCapability";
0170                 break;
0171             }
0172         }
0173     } break;
0174     case NetworkManager::Device::Ethernet:
0175     default:
0176         deviceText = i18nc("title of the interface widget in nm's popup", "Wired Ethernet");
0177         break;
0178     }
0179     return deviceText;
0180 }
0181 
0182 QString UiUtils::iconAndTitleForConnectionSettingsType(NetworkManager::ConnectionSettings::ConnectionType type, QString &title)
0183 {
0184     QString text;
0185     QString icon = QStringLiteral("network-wired");
0186     switch (type) {
0187     case ConnectionSettings::Adsl:
0188         text = i18n("ADSL");
0189         icon = QStringLiteral("network-modem");
0190         break;
0191     case ConnectionSettings::Pppoe:
0192         text = i18n("DSL");
0193         icon = QStringLiteral("network-modem");
0194         break;
0195     case ConnectionSettings::Bluetooth:
0196         text = i18n("Bluetooth");
0197         icon = QStringLiteral("network-bluetooth");
0198         break;
0199     case ConnectionSettings::Bond:
0200         text = i18n("Bond");
0201         break;
0202     case ConnectionSettings::Bridge:
0203         text = i18n("Bridge");
0204         break;
0205     case ConnectionSettings::Gsm:
0206     case ConnectionSettings::Cdma:
0207         text = i18n("Mobile broadband");
0208         icon = QStringLiteral("smartphone");
0209         break;
0210     case ConnectionSettings::Infiniband:
0211         text = i18n("Infiniband");
0212         break;
0213     case ConnectionSettings::OLPCMesh:
0214         text = i18n("Olpc mesh");
0215         break;
0216     case ConnectionSettings::Vlan:
0217         text = i18n("VLAN");
0218         break;
0219     case ConnectionSettings::Vpn:
0220         text = i18n("VPN");
0221         icon = QStringLiteral("network-vpn");
0222         break;
0223     case ConnectionSettings::Wired:
0224         text = i18n("Wired Ethernet");
0225         icon = QStringLiteral("network-wired");
0226         break;
0227     case ConnectionSettings::Wireless:
0228         text = i18n("Wi-Fi");
0229         icon = QStringLiteral("network-wireless");
0230         break;
0231     case ConnectionSettings::Team:
0232         text = i18n("Team");
0233         break;
0234     case ConnectionSettings::WireGuard:
0235         text = i18n("WireGuard VPN");
0236         icon = QStringLiteral("network-vpn");
0237         break;
0238     default:
0239         text = i18n("Unknown connection type");
0240         break;
0241     }
0242     title = text;
0243     return icon;
0244 }
0245 
0246 QString UiUtils::prettyInterfaceName(NetworkManager::Device::Type type, const QString &interfaceName)
0247 {
0248     QString ret;
0249     switch (type) {
0250     case NetworkManager::Device::Wifi:
0251         ret = i18n("Wireless Interface (%1)", interfaceName);
0252         break;
0253     case NetworkManager::Device::Ethernet:
0254         ret = i18n("Wired Interface (%1)", interfaceName);
0255         break;
0256     case NetworkManager::Device::Bluetooth:
0257         ret = i18n("Bluetooth (%1)", interfaceName);
0258         break;
0259     case NetworkManager::Device::Modem:
0260         ret = i18n("Modem (%1)", interfaceName);
0261         break;
0262     case NetworkManager::Device::Adsl:
0263         ret = i18n("ADSL (%1)", interfaceName);
0264         break;
0265     case NetworkManager::Device::Vlan:
0266         ret = i18n("VLan (%1)", interfaceName);
0267         break;
0268     case NetworkManager::Device::Bridge:
0269         ret = i18n("Bridge (%1)", interfaceName);
0270         break;
0271     default:
0272         ret = interfaceName;
0273     }
0274     return ret;
0275 }
0276 
0277 QString UiUtils::connectionStateToString(NetworkManager::Device::State state, const QString &connectionName)
0278 {
0279     QString stateString;
0280     switch (state) {
0281     case NetworkManager::Device::UnknownState:
0282         stateString = i18nc("description of unknown network interface state", "Unknown");
0283         break;
0284     case NetworkManager::Device::Unmanaged:
0285         stateString = i18nc("description of unmanaged network interface state", "Unmanaged");
0286         break;
0287     case NetworkManager::Device::Unavailable:
0288         stateString = i18nc("description of unavailable network interface state", "Unavailable");
0289         break;
0290     case NetworkManager::Device::Disconnected:
0291         stateString = i18nc("description of unconnected network interface state", "Not connected");
0292         break;
0293     case NetworkManager::Device::Preparing:
0294         stateString = i18nc("description of preparing to connect network interface state", "Preparing to connect");
0295         break;
0296     case NetworkManager::Device::ConfiguringHardware:
0297         stateString = i18nc("description of configuring hardware network interface state", "Configuring interface");
0298         break;
0299     case NetworkManager::Device::NeedAuth:
0300         stateString = i18nc("description of waiting for authentication network interface state", "Waiting for authorization");
0301         break;
0302     case NetworkManager::Device::ConfiguringIp:
0303         stateString = i18nc("network interface doing dhcp request in most cases", "Setting network address");
0304         break;
0305     case NetworkManager::Device::CheckingIp:
0306         stateString = i18nc("is other action required to fully connect? captive portals, etc.", "Checking further connectivity");
0307         break;
0308     case NetworkManager::Device::WaitingForSecondaries:
0309         stateString = i18nc("a secondary connection (e.g. VPN) has to be activated first to continue", "Waiting for a secondary connection");
0310         break;
0311     case NetworkManager::Device::Activated:
0312         if (connectionName.isEmpty()) {
0313             stateString = i18nc("network interface connected state label", "Connected");
0314         } else {
0315             stateString = i18nc("network interface connected state label", "Connected to %1", connectionName);
0316         }
0317         break;
0318     case NetworkManager::Device::Deactivating:
0319         stateString = i18nc("network interface disconnecting state label", "Deactivating connection");
0320         break;
0321     case NetworkManager::Device::Failed:
0322         stateString = i18nc("network interface connection failed state label", "Connection Failed");
0323         break;
0324     default:
0325         stateString = i18nc("interface state", "Error: Invalid state");
0326     }
0327     return stateString;
0328 }
0329 
0330 QString UiUtils::vpnConnectionStateToString(VpnConnection::State state)
0331 {
0332     QString stateString;
0333     switch (state) {
0334     case VpnConnection::Unknown:
0335         stateString = i18nc("The state of the VPN connection is unknown", "Unknown");
0336         break;
0337     case VpnConnection::Prepare:
0338         stateString = i18nc("The VPN connection is preparing to connect", "Preparing to connect");
0339         break;
0340     case VpnConnection::NeedAuth:
0341         stateString = i18nc("The VPN connection needs authorization credentials", "Needs authorization");
0342         break;
0343     case VpnConnection::Connecting:
0344         stateString = i18nc("The VPN connection is being established", "Connecting");
0345         break;
0346     case VpnConnection::GettingIpConfig:
0347         stateString = i18nc("The VPN connection is getting an IP address", "Setting network address");
0348         break;
0349     case VpnConnection::Activated:
0350         stateString = i18nc("The VPN connection is active", "Activated");
0351         break;
0352     case VpnConnection::Failed:
0353         stateString = i18nc("The VPN connection failed", "Failed");
0354         break;
0355     case VpnConnection::Disconnected:
0356         stateString = i18nc("The VPN connection is disconnected", "Failed");
0357         break;
0358     default:
0359         stateString = i18nc("interface state", "Error: Invalid state");
0360     }
0361     return stateString;
0362 }
0363 
0364 QString UiUtils::operationModeToString(NetworkManager::WirelessDevice::OperationMode mode)
0365 {
0366     QString modeString;
0367     switch (mode) {
0368     case NetworkManager::WirelessDevice::WirelessDevice::Unknown:
0369         modeString = i18nc("wireless network operation mode", "Unknown");
0370         break;
0371     case NetworkManager::WirelessDevice::Adhoc:
0372         modeString = i18nc("wireless network operation mode", "Adhoc");
0373         break;
0374     case NetworkManager::WirelessDevice::WirelessDevice::Infra:
0375         modeString = i18nc("wireless network operation mode", "Infrastructure");
0376         break;
0377     case NetworkManager::WirelessDevice::WirelessDevice::ApMode:
0378         modeString = i18nc("wireless network operation mode", "Access point");
0379         break;
0380     default:
0381         modeString = QStringLiteral("INCORRECT MODE FIX ME");
0382     }
0383     return modeString;
0384 }
0385 
0386 QStringList UiUtils::wpaFlagsToStringList(NetworkManager::AccessPoint::WpaFlags flags)
0387 {
0388     /* for testing purposes
0389     flags = NetworkManager::AccessPoint::PairWep40
0390             | NetworkManager::AccessPoint::PairWep104
0391             | NetworkManager::AccessPoint::PairTkip
0392             | NetworkManager::AccessPoint::PairCcmp
0393             | NetworkManager::AccessPoint::GroupWep40
0394             | NetworkManager::AccessPoint::GroupWep104
0395             | NetworkManager::AccessPoint::GroupTkip
0396             | NetworkManager::AccessPoint::GroupCcmp
0397             | NetworkManager::AccessPoint::KeyMgmtPsk
0398             | NetworkManager::AccessPoint::KeyMgmt8021x; */
0399 
0400     QStringList flagList;
0401 
0402     if (flags.testFlag(NetworkManager::AccessPoint::PairWep40))
0403         flagList.append(i18nc("wireless network cipher", "Pairwise WEP40"));
0404     if (flags.testFlag(NetworkManager::AccessPoint::PairWep104))
0405         flagList.append(i18nc("wireless network cipher", "Pairwise WEP104"));
0406     if (flags.testFlag(NetworkManager::AccessPoint::PairTkip))
0407         flagList.append(i18nc("wireless network cipher", "Pairwise TKIP"));
0408     if (flags.testFlag(NetworkManager::AccessPoint::PairCcmp))
0409         flagList.append(i18nc("wireless network cipher", "Pairwise CCMP"));
0410     if (flags.testFlag(NetworkManager::AccessPoint::GroupWep40))
0411         flagList.append(i18nc("wireless network cipher", "Group WEP40"));
0412     if (flags.testFlag(NetworkManager::AccessPoint::GroupWep104))
0413         flagList.append(i18nc("wireless network cipher", "Group WEP104"));
0414     if (flags.testFlag(NetworkManager::AccessPoint::GroupTkip))
0415         flagList.append(i18nc("wireless network cipher", "Group TKIP"));
0416     if (flags.testFlag(NetworkManager::AccessPoint::GroupCcmp))
0417         flagList.append(i18nc("wireless network cipher", "Group CCMP"));
0418     if (flags.testFlag(NetworkManager::AccessPoint::KeyMgmtPsk))
0419         flagList.append(i18nc("wireless network cipher", "PSK"));
0420     if (flags.testFlag(NetworkManager::AccessPoint::KeyMgmt8021x))
0421         flagList.append(i18nc("wireless network cipher", "802.1x"));
0422 
0423     return flagList;
0424 }
0425 
0426 QString UiUtils::connectionSpeed(double bitrate)
0427 {
0428     QString out;
0429     if (bitrate < 1000) {
0430         out = i18nc("connection speed", "%1 Bit/s", bitrate);
0431     } else if (bitrate < 1000000) {
0432         out = i18nc("connection speed", "%1 MBit/s", bitrate / 1000);
0433     } else {
0434         out = i18nc("connection speed", "%1 GBit/s", bitrate / 1000000);
0435     }
0436     return out;
0437 }
0438 
0439 QString UiUtils::wirelessBandToString(NetworkManager::WirelessSetting::FrequencyBand band)
0440 {
0441     switch (band) {
0442     case NetworkManager::WirelessSetting::Automatic:
0443         return QStringLiteral("automatic");
0444         break;
0445     case NetworkManager::WirelessSetting::A:
0446         return QStringLiteral("a");
0447         break;
0448     case NetworkManager::WirelessSetting::Bg:
0449         return QStringLiteral("b/g");
0450         break;
0451     }
0452 
0453     return {};
0454 }
0455 
0456 QString UiUtils::wirelessFrequencyToString(uint frequency)
0457 {
0458     return i18nc("Wireless connection frequency", "%1 GHz", frequency / 1000.0);
0459 }
0460 
0461 QString UiUtils::convertAllowedModeToString(ModemManager::Modem::ModemModes modes)
0462 {
0463     if (modes.testFlag(MM_MODEM_MODE_4G)) {
0464         return i18nc("Gsm modes (2G/3G/any)", "LTE");
0465     } else if (modes.testFlag(MM_MODEM_MODE_3G)) {
0466         return i18nc("Gsm modes (2G/3G/any)", "UMTS/HSxPA");
0467     } else if (modes.testFlag(MM_MODEM_MODE_2G)) {
0468         return i18nc("Gsm modes (2G/3G/any)", "GPRS/EDGE");
0469     } else if (modes.testFlag(MM_MODEM_MODE_CS)) {
0470         return i18nc("Gsm modes (2G/3G/any)", "GSM");
0471     } else if (modes.testFlag(MM_MODEM_MODE_ANY)) {
0472         return i18nc("Gsm modes (2G/3G/any)", "Any");
0473     }
0474 
0475     return i18nc("Gsm modes (2G/3G/any)", "Any");
0476 }
0477 
0478 QString UiUtils::convertAccessTechnologyToString(ModemManager::Modem::AccessTechnologies tech)
0479 {
0480 #if MM_CHECK_VERSION(1, 14, 0)
0481     if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_5GNR)) {
0482         return i18nc("Cellular access technology", "5G NR");
0483     } else
0484 #endif
0485         if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_LTE)) {
0486         return i18nc("Cellular access technology", "LTE");
0487     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_EVDOB)) {
0488         return i18nc("Cellular access technology", "CDMA2000 EVDO revision B");
0489     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_EVDOA)) {
0490         return i18nc("Cellular access technology", "CDMA2000 EVDO revision A");
0491     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_EVDO0)) {
0492         return i18nc("Cellular access technology", "CDMA2000 EVDO revision 0");
0493     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_1XRTT)) {
0494         return i18nc("Cellular access technology", "CDMA2000 1xRTT");
0495     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS)) {
0496         return i18nc("Cellular access technology", "HSPA+");
0497     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_HSPA)) {
0498         return i18nc("Cellular access technology", "HSPA");
0499     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_HSUPA)) {
0500         return i18nc("Cellular access technology", "HSUPA");
0501     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_HSDPA)) {
0502         return i18nc("Cellular access technology", "HSDPA");
0503     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_UMTS)) {
0504         return i18nc("Cellular access technology", "UMTS");
0505     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_EDGE)) {
0506         return i18nc("Cellular access technology", "EDGE");
0507     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_GPRS)) {
0508         return i18nc("Cellular access technology", "GPRS");
0509     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT)) {
0510         return i18nc("Cellular access technology", "Compact GSM");
0511     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_GSM)) {
0512         return i18nc("Cellular access technology", "GSM");
0513     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_POTS)) {
0514         return i18nc("Analog wireline modem", "Analog");
0515     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN)) {
0516         return i18nc("Unknown cellular access technology", "Unknown");
0517     } else if (tech.testFlag(MM_MODEM_ACCESS_TECHNOLOGY_ANY)) {
0518         return i18nc("Any cellular access technology", "Any");
0519     }
0520 
0521     return i18nc("Unknown cellular access technology", "Unknown");
0522 }
0523 
0524 QString UiUtils::convertLockReasonToString(MMModemLock reason)
0525 {
0526     switch (reason) {
0527     case MM_MODEM_LOCK_NONE:
0528         return i18nc("possible SIM lock reason", "Modem is unlocked.");
0529     case MM_MODEM_LOCK_SIM_PIN:
0530         return i18nc("possible SIM lock reason", "SIM requires the PIN code.");
0531     case MM_MODEM_LOCK_SIM_PIN2:
0532         return i18nc("possible SIM lock reason", "SIM requires the PIN2 code.");
0533     case MM_MODEM_LOCK_SIM_PUK:
0534         return i18nc("possible SIM lock reason", "SIM requires the PUK code.");
0535     case MM_MODEM_LOCK_SIM_PUK2:
0536         return i18nc("possible SIM lock reason", "SIM requires the PUK2 code.");
0537     case MM_MODEM_LOCK_PH_SP_PIN:
0538         return i18nc("possible SIM lock reason", "Modem requires the service provider PIN code.");
0539     case MM_MODEM_LOCK_PH_SP_PUK:
0540         return i18nc("possible SIM lock reason", "Modem requires the service provider PUK code.");
0541     case MM_MODEM_LOCK_PH_NET_PIN:
0542         return i18nc("possible SIM lock reason", "Modem requires the network PIN code.");
0543     case MM_MODEM_LOCK_PH_NET_PUK:
0544         return i18nc("possible SIM lock reason", "Modem requires the network PUK code.");
0545     case MM_MODEM_LOCK_PH_SIM_PIN:
0546         return i18nc("possible SIM lock reason", "Modem requires the PIN code.");
0547     case MM_MODEM_LOCK_PH_CORP_PIN:
0548         return i18nc("possible SIM lock reason", "Modem requires the corporate PIN code.");
0549     case MM_MODEM_LOCK_PH_CORP_PUK:
0550         return i18nc("possible SIM lock reason", "Modem requires the corporate PUK code.");
0551     case MM_MODEM_LOCK_PH_FSIM_PIN:
0552         return i18nc("possible SIM lock reason", "Modem requires the PH-FSIM PIN code.");
0553     case MM_MODEM_LOCK_PH_FSIM_PUK:
0554         return i18nc("possible SIM lock reason", "Modem requires the PH-FSIM PUK code.");
0555     case MM_MODEM_LOCK_PH_NETSUB_PIN:
0556         return i18nc("possible SIM lock reason", "Modem requires the network subset PIN code.");
0557     case MM_MODEM_LOCK_PH_NETSUB_PUK:
0558         return i18nc("possible SIM lock reason", "Modem requires the network subset PUK code.");
0559     case MM_MODEM_LOCK_UNKNOWN:
0560     default:
0561         return i18nc("possible SIM lock reason", "Lock reason unknown.");
0562     }
0563 }
0564 
0565 NetworkManager::ModemDevice::Capability UiUtils::modemSubType(NetworkManager::ModemDevice::Capabilities modemCaps)
0566 {
0567     if (modemCaps & NetworkManager::ModemDevice::Lte) {
0568         return NetworkManager::ModemDevice::Lte;
0569     } else if (modemCaps & NetworkManager::ModemDevice::CdmaEvdo) {
0570         return NetworkManager::ModemDevice::CdmaEvdo;
0571     } else if (modemCaps & NetworkManager::ModemDevice::GsmUmts) {
0572         return NetworkManager::ModemDevice::GsmUmts;
0573     } else if (modemCaps & NetworkManager::ModemDevice::Pots) {
0574         return NetworkManager::ModemDevice::Pots;
0575     }
0576     return NetworkManager::ModemDevice::NoCapability;
0577 }
0578 
0579 QString UiUtils::labelFromWirelessSecurity(NetworkManager::WirelessSecurityType type)
0580 {
0581     QString tip;
0582     switch (type) {
0583     case NetworkManager::NoneSecurity:
0584         tip = i18nc("@label no security", "Insecure");
0585         break;
0586     case NetworkManager::StaticWep:
0587         tip = i18nc("@label WEP security", "WEP");
0588         break;
0589     case NetworkManager::Leap:
0590         tip = i18nc("@label LEAP security", "LEAP");
0591         break;
0592     case NetworkManager::DynamicWep:
0593         tip = i18nc("@label Dynamic WEP security", "Dynamic WEP");
0594         break;
0595     case NetworkManager::WpaPsk:
0596         tip = i18nc("@label WPA-PSK security", "WPA-PSK");
0597         break;
0598     case NetworkManager::WpaEap:
0599         tip = i18nc("@label WPA-EAP security", "WPA-EAP");
0600         break;
0601     case NetworkManager::Wpa2Psk:
0602         tip = i18nc("@label WPA2-PSK security", "WPA2-PSK");
0603         break;
0604     case NetworkManager::Wpa2Eap:
0605         tip = i18nc("@label WPA2-EAP security", "WPA2-EAP");
0606         break;
0607     case NetworkManager::SAE:
0608         tip = i18nc("@label WPA3-SAE security", "WPA3-SAE");
0609         break;
0610     case NetworkManager::Wpa3SuiteB192:
0611         tip = i18nc("@label WPA3-EAP-SUITE-B-192 security", "WPA3-EAP-SUITE-B-192");
0612         break;
0613     default:
0614         tip = i18nc("@label unknown security", "Unknown security type");
0615         break;
0616     }
0617     return tip;
0618 }
0619 
0620 QString UiUtils::formatDateRelative(const QDateTime &lastUsed)
0621 {
0622     QString lastUsedText;
0623     if (lastUsed.isValid()) {
0624         const QDateTime now = QDateTime::currentDateTime();
0625         if (lastUsed.daysTo(now) == 0) {
0626             const int secondsAgo = lastUsed.secsTo(now);
0627             if (secondsAgo < (60 * 60)) {
0628                 const int minutesAgo = secondsAgo / 60;
0629                 lastUsedText = i18ncp("Label for last used time for a network connection used in the last hour, as the number of minutes since usage",
0630                                       "One minute ago",
0631                                       "%1 minutes ago",
0632                                       minutesAgo);
0633             } else {
0634                 const int hoursAgo = secondsAgo / (60 * 60);
0635                 lastUsedText = i18ncp("Label for last used time for a network connection used in the last day, as the number of hours since usage",
0636                                       "One hour ago",
0637                                       "%1 hours ago",
0638                                       hoursAgo);
0639             }
0640         } else if (lastUsed.daysTo(now) == 1) {
0641             lastUsedText = i18nc("Label for last used time for a network connection used the previous day", "Yesterday");
0642         } else {
0643             lastUsedText = QLocale().toString(lastUsed.date(), QLocale::ShortFormat);
0644         }
0645     } else {
0646         lastUsedText = i18nc(
0647             "Label for last used time for a "
0648             "network connection that has never been used",
0649             "Never");
0650     }
0651     return lastUsedText;
0652 }
0653 
0654 QString UiUtils::formatLastUsedDateRelative(const QDateTime &lastUsed)
0655 {
0656     QString lastUsedText;
0657     if (lastUsed.isValid()) {
0658         const QDateTime now = QDateTime::currentDateTime();
0659         if (lastUsed.daysTo(now) == 0) {
0660             const int secondsAgo = lastUsed.secsTo(now);
0661             if (secondsAgo < (60 * 60)) {
0662                 const int minutesAgo = secondsAgo / 60;
0663                 lastUsedText = i18ncp("Label for last used time for a network connection used in the last hour, as the number of minutes since usage",
0664                                       "Last used one minute ago",
0665                                       "Last used %1 minutes ago",
0666                                       minutesAgo);
0667             } else {
0668                 const int hoursAgo = secondsAgo / (60 * 60);
0669                 lastUsedText = i18ncp("Label for last used time for a network connection used in the last day, as the number of hours since usage",
0670                                       "Last used one hour ago",
0671                                       "Last used %1 hours ago",
0672                                       hoursAgo);
0673             }
0674         } else if (lastUsed.daysTo(now) == 1) {
0675             lastUsedText = i18nc("Label for last used time for a network connection used the previous day", "Last used yesterday");
0676         } else {
0677             lastUsedText = i18n("Last used on %1", QLocale().toString(lastUsed.date(), QLocale::ShortFormat));
0678         }
0679     } else {
0680         lastUsedText = i18nc(
0681             "Label for last used time for a "
0682             "network connection that has never been used",
0683             "Never used");
0684     }
0685     return lastUsedText;
0686 }
0687 
0688 bool UiUtils::isLiveImage()
0689 {
0690     static std::optional<bool> liveImage = std::nullopt;
0691     if (liveImage.has_value()) {
0692         return liveImage.value();
0693     }
0694 
0695     QFile cmdFile(QStringLiteral("/proc/cmdline"));
0696     cmdFile.open(QIODevice::ReadOnly);
0697 
0698     if (!cmdFile.isOpen()) {
0699         return false;
0700     }
0701 
0702     const QString cmdFileOutput = cmdFile.readAll();
0703     cmdFile.close();
0704 
0705     if (cmdFileOutput.contains(QStringLiteral("rd.live.image"))) {
0706         liveImage = true;
0707         return true;
0708     }
0709 
0710     liveImage = false;
0711     return false;
0712 }
0713 
0714 void UiUtils::setConnectionDefaultPermissions(NetworkManager::ConnectionSettings::Ptr &settings)
0715 {
0716     auto wifiSecurity = settings->setting(NetworkManager::Setting::WirelessSecurity).dynamicCast<NetworkManager::WirelessSecuritySetting>();
0717     auto security8021x = settings->setting(NetworkManager::Setting::Security8021x).dynamicCast<NetworkManager::Security8021xSetting>();
0718 
0719     if (!wifiSecurity || !security8021x) {
0720         return;
0721     }
0722 
0723     if (Configuration::self().systemConnectionsByDefault() || !KWallet::Wallet::isEnabled() || isLiveImage()) {
0724         auto modifySystem = NetworkManager::permissions().value(QStringLiteral("org.freedesktop.NetworkManager.settings.modify.system"));
0725         if (modifySystem == QLatin1String("yes")) {
0726             wifiSecurity->setLeapPasswordFlags(NetworkManager::Setting::SecretFlagType::None);
0727             wifiSecurity->setPskFlags(NetworkManager::Setting::SecretFlagType::None);
0728             wifiSecurity->setWepKeyFlags(NetworkManager::Setting::SecretFlagType::None);
0729             security8021x->setPasswordFlags(NetworkManager::Setting::SecretFlagType::None);
0730             return;
0731         }
0732     }
0733 
0734     settings->addToPermissions(KUser().loginName(), QString());
0735     wifiSecurity->setLeapPasswordFlags(NetworkManager::Setting::SecretFlagType::AgentOwned);
0736     wifiSecurity->setPskFlags(NetworkManager::Setting::SecretFlagType::AgentOwned);
0737     wifiSecurity->setWepKeyFlags(NetworkManager::Setting::SecretFlagType::AgentOwned);
0738     security8021x->setPasswordFlags(NetworkManager::Setting::SecretFlagType::AgentOwned);
0739 }