Move cellularnetwork kcm to plasma-nm

This commit is contained in:
Carl Schwan 2025-02-25 00:11:15 +01:00 committed by Luigi Toscano
parent 9a35cca1b6
commit cfdb1ae516
24 changed files with 0 additions and 3941 deletions

View file

@ -2,7 +2,6 @@
# SPDX-License-Identifier: GPL-2.0-or-later # SPDX-License-Identifier: GPL-2.0-or-later
add_subdirectory(mobileshell) add_subdirectory(mobileshell)
add_subdirectory(cellularnetwork)
add_subdirectory(info) add_subdirectory(info)
add_subdirectory(powermanagement) add_subdirectory(powermanagement)
add_subdirectory(time) add_subdirectory(time)

View file

@ -1,26 +0,0 @@
# SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
# SPDX-License-Identifier: GPL-2.0-or-later
kcmutils_add_qml_kcm(kcm_cellular_network)
target_sources(kcm_cellular_network PRIVATE
cellularnetworksettings.cpp
modem.cpp
modemdetails.cpp
sim.cpp
mobileproviders.cpp
profilesettings.cpp
)
target_link_libraries(kcm_cellular_network PRIVATE
Qt::DBus
Qt::Gui
Qt::Quick
Qt::Qml
Qt::Xml
Plasma::Plasma
KF6::I18n
KF6::NetworkManagerQt
KF6::ModemManagerQt
KF6::KCMUtilsQuick
QCoro::DBus
)

View file

@ -1,4 +0,0 @@
#!/usr/bin/env bash
# SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
# SPDX-License-Identifier: GPL-2.0-or-later
$XGETTEXT `find . -name \*.cpp -o -name \*.qml` -o $podir/kcm_cellular_network.pot

View file

@ -1,154 +0,0 @@
/*
SPDX-FileCopyrightText: 2018 Martin Kacej <m.kacej@atlas.sk>
SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "cellularnetworksettings.h"
#include <KLocalizedString>
#include <KPluginFactory>
#include <KUser>
#include <QQmlEngine>
K_PLUGIN_CLASS_WITH_JSON(CellularNetworkSettings, "kcm_cellular_network.json")
CellularNetworkSettings *CellularNetworkSettings::staticInst = nullptr;
CellularNetworkSettings::CellularNetworkSettings(QObject *parent, const KPluginMetaData &metaData)
: KQuickConfigModule(parent, metaData)
, m_modemList{}
, m_simList{}
{
setButtons({});
CellularNetworkSettings::staticInst = this;
qmlRegisterType<ProfileSettings>("cellularnetworkkcm", 1, 0, "ProfileSettings");
qmlRegisterType<Modem>("cellularnetworkkcm", 1, 0, "Modem");
qmlRegisterType<ModemDetails>("cellularnetworkkcm", 1, 0, "ModemDetails");
qmlRegisterType<AvailableNetwork>("cellularnetworkkcm", 1, 0, "AvailableNetwork");
qmlRegisterType<Sim>("cellularnetworkkcm", 1, 0, "Sim");
qmlRegisterType<InlineMessage>("cellularnetworkkcm", 1, 0, "InlineMessage");
// find modems
updateModemList();
connect(ModemManager::notifier(), &ModemManager::Notifier::modemAdded, this, &CellularNetworkSettings::updateModemList);
connect(ModemManager::notifier(), &ModemManager::Notifier::modemRemoved, this, &CellularNetworkSettings::updateModemList);
}
CellularNetworkSettings *CellularNetworkSettings::instance()
{
return CellularNetworkSettings::staticInst;
}
Modem *CellularNetworkSettings::selectedModem()
{
// TODO: we are currently assuming there is a single modem
if (m_modemList.count() > 0) {
return m_modemList[0];
}
return nullptr;
}
QList<Modem *> CellularNetworkSettings::modems()
{
return m_modemList;
}
QList<Sim *> CellularNetworkSettings::sims()
{
return m_simList;
}
bool CellularNetworkSettings::modemFound()
{
return !m_modemList.empty();
}
void CellularNetworkSettings::updateModemList()
{
// loop over every modem
for (ModemManager::ModemDevice::Ptr device : ModemManager::modemDevices()) {
ModemManager::Modem::Ptr modem = device->modemInterface();
qDebug() << QStringLiteral("Found modem:") << device->uni();
m_modemList.push_back(new Modem(this, device, modem));
// update sims list if modem's list changes
connect(m_modemList[m_modemList.size() - 1], &Modem::simsChanged, this, [this]() -> void {
fillSims();
});
}
if (m_modemList.empty()) {
qDebug() << QStringLiteral("No modems found.");
}
// fill sim list
fillSims();
// update the currently selected modem
Q_EMIT selectedModemChanged();
}
void CellularNetworkSettings::fillSims()
{
for (auto p : m_simList) {
delete p;
}
m_simList.clear();
qDebug() << QStringLiteral("Scanning SIMs list...");
for (auto modem : m_modemList) {
auto sims = modem->sims();
for (auto sim : sims) {
qDebug() << QStringLiteral("Found SIM") << sim->uni() << sim->imsi();
m_simList.push_back(sim);
}
}
Q_EMIT simsChanged();
}
QList<InlineMessage *> CellularNetworkSettings::messages()
{
return m_messages;
}
void CellularNetworkSettings::addMessage(InlineMessage::Type type, QString msg)
{
m_messages.push_back(new InlineMessage{this, type, msg});
Q_EMIT messagesChanged();
}
void CellularNetworkSettings::removeMessage(int index)
{
if (index >= 0 && index < m_messages.size()) {
m_messages.removeAt(index);
Q_EMIT messagesChanged();
}
}
InlineMessage::InlineMessage(QObject *parent, Type type, QString message)
: QObject{parent}
, m_type{type}
, m_message{message}
{
}
InlineMessage::Type InlineMessage::type()
{
return m_type;
}
QString InlineMessage::message()
{
return m_message;
}
#include "cellularnetworksettings.moc"

View file

@ -1,101 +0,0 @@
/*
SPDX-FileCopyrightText: 2018 Martin Kacej <m.kacej@atlas.sk>
SPDX-FileCopyrightText: 2020-2021 Devin Lin <espidev@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include <QSharedPointer>
#include <KQuickConfigModule>
#include "mobileproviders.h"
#include "modem.h"
#include "modemdetails.h"
#include "sim.h"
#include <NetworkManagerQt/CdmaSetting>
#include <NetworkManagerQt/ConnectionSettings>
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/ModemDevice>
#include <NetworkManagerQt/Settings>
#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/ModemDevice>
class Sim;
class Modem;
class MobileProviders;
class InlineMessage : public QObject
{
Q_OBJECT
Q_PROPERTY(int type READ type NOTIFY typeChanged)
Q_PROPERTY(QString message READ message NOTIFY messageChanged)
public:
enum Type {
Information,
Positive,
Warning,
Error,
};
InlineMessage(QObject *parent = nullptr, Type type = Information, QString message = "");
Type type();
QString message();
Q_SIGNALS:
void typeChanged();
void messageChanged();
private:
Type m_type;
QString m_message;
};
class CellularNetworkSettings : public KQuickConfigModule
{
Q_OBJECT
Q_PROPERTY(bool modemFound READ modemFound NOTIFY modemFoundChanged)
Q_PROPERTY(Modem *selectedModem READ selectedModem NOTIFY selectedModemChanged)
Q_PROPERTY(QList<Sim *> sims READ sims NOTIFY simsChanged)
Q_PROPERTY(QList<InlineMessage *> messages READ messages NOTIFY messagesChanged)
public:
CellularNetworkSettings(QObject *parent, const KPluginMetaData &metaData);
static CellularNetworkSettings *instance();
Modem *selectedModem();
QList<Modem *> modems();
QList<Sim *> sims();
bool modemFound();
QList<InlineMessage *> messages();
void addMessage(InlineMessage::Type type, QString msg);
Q_INVOKABLE void removeMessage(int index);
Q_SIGNALS:
void modemFoundChanged();
void selectedModemChanged();
void simsChanged();
void messagesChanged();
private:
void updateModemList();
void fillSims();
QList<Modem *> m_modemList;
QList<Sim *> m_simList;
QList<InlineMessage *> m_messages;
static CellularNetworkSettings *staticInst;
};

View file

@ -1,114 +0,0 @@
{
"Categories": "Qt;KDE;X-KDE-settings-system;",
"KPlugin": {
"Description": "Management of cellular networks",
"Description[ca@valencia]": "Gestió de xarxes de telefonia mòbil",
"Description[ca]": "Gestió de xarxes de telefonia mòbil",
"Description[cs]": "Spravovat vaše mobilní sítě",
"Description[de]": "Verwaltung von Mobilfunknetzen",
"Description[en_GB]": "Management of cellular networks",
"Description[eo]": "Administrado de ĉelaj retoj",
"Description[es]": "Gestión de redes móviles",
"Description[eu]": "Mugikorrerako sareen kudeaketa",
"Description[fi]": "Matkapuhelinverkkojen hallinta",
"Description[fr]": "Gestion de réseaux cellulaires",
"Description[gl]": "Xestión de redes móbiles.",
"Description[he]": "ניהול רשתות סלולריות",
"Description[hu]": "Mobilhálózatok kezelése",
"Description[ia]": "Gestion de retes cellular",
"Description[is]": "Umsjón farsímaneta",
"Description[it]": "Gestione delle reti cellulari",
"Description[ka]": "ფიჭური ქსელების მართვა",
"Description[ko]": "모바일 네트워크 관리",
"Description[lv]": "Pārvaldīt mobilos tīklus",
"Description[nl]": "Beheer van cellulaire netwerken",
"Description[nn]": "Handsaming av mobilnettverk",
"Description[pa]": "ਸੈਲੂਲਰ ਨੈੱਟਵਰਕਾਂ ਦਾ ਇੰਤਜ਼ਾਮ",
"Description[pl]": "Zarządzanie sieciami komórkowymi",
"Description[pt_BR]": "Gerenciamento de redes celulares",
"Description[ru]": "Управление сетями сотовой связи",
"Description[sa]": "सेलुलरजालस्य प्रबन्धनम्",
"Description[sk]": "Správa mobilných sietí",
"Description[sl]": "Upravljanje celičnih omrežij",
"Description[sv]": "Hantering av mobilnät",
"Description[tr]": "Hücresel ağların yönetimi",
"Description[uk]": "Керування стільниковими мережами",
"Description[x-test]": "xxManagement of cellular networksxx",
"Description[zh_CN]": "管理移动网络",
"Description[zh_TW]": "行動網路的管理",
"FormFactors": [
"handset",
"tablet",
"mediacenter"
],
"Icon": "smartphone",
"Name": "Cellular Network",
"Name[ar]": "شبكة خليوية",
"Name[ca@valencia]": "Xarxa de telefonia mòbil",
"Name[ca]": "Xarxa de telefonia mòbil",
"Name[cs]": "Mobilní síť",
"Name[de]": "Mobilfunknetz",
"Name[en_GB]": "Cellular Network",
"Name[eo]": "Ĉela Reto",
"Name[es]": "Red móvil",
"Name[eu]": "Mugikorrerako sarea",
"Name[fi]": "Matkapuhelinverkko",
"Name[fr]": "Réseau cellulaire",
"Name[gl]": "Rede móbil",
"Name[he]": "רשת סלולרית",
"Name[hu]": "Mobilhálózat",
"Name[ia]": "Rete Cellular",
"Name[is]": "Farsímakerfi",
"Name[it]": "Rete cellulare",
"Name[ka]": "ფიჭური ქსელი",
"Name[ko]": "모바일 네트워크",
"Name[lv]": "Mobilais tīkls",
"Name[nl]": "Cellulair netwerk",
"Name[nn]": "Mobilnettverk",
"Name[pa]": "ਸੈਲੂਲਰ ਨੈੱਟਵਰਕ",
"Name[pl]": "Sieć komórkowa",
"Name[pt_BR]": "Rede celular",
"Name[ru]": "Сеть сотовой связи",
"Name[sa]": "सेलुलर नेटवर्क",
"Name[sk]": "Mobilná sieť",
"Name[sl]": "Celično omrežje",
"Name[sv]": "Mobilnät",
"Name[ta]": "கைபேசி பிணையம்",
"Name[tr]": "Hücresel Ağ",
"Name[uk]": "Стільникова мережа",
"Name[x-test]": "xxCellular Networkxx",
"Name[zh_CN]": "移动网络",
"Name[zh_TW]": "行動網路"
},
"X-KDE-Keywords": "mobile,data,network",
"X-KDE-Keywords[ca@valencia]": "mòbil,dades,xarxa",
"X-KDE-Keywords[ca]": "mòbil,dades,xarxa",
"X-KDE-Keywords[cs]": "mobilní,data,síť",
"X-KDE-Keywords[en_GB]": "mobile,data,network",
"X-KDE-Keywords[es]": "móvil,datos,red",
"X-KDE-Keywords[eu]": "mugikorra,telefono mugikorra,datuak,sarea",
"X-KDE-Keywords[fi]": "mobiili,data,mobiilidata,verkko",
"X-KDE-Keywords[fr]": "mobile, data, réseau",
"X-KDE-Keywords[gl]": "móbil,datos,rede",
"X-KDE-Keywords[he]": "נייד,נתונים,רשת,פס רחב",
"X-KDE-Keywords[hu]": "mobil,adat,hálózat",
"X-KDE-Keywords[ia]": "mobile,data,network",
"X-KDE-Keywords[it]": "mobile,dati,rete",
"X-KDE-Keywords[ka]": "mobile,data,network,მობილური ინტერნეტი,ქსელი",
"X-KDE-Keywords[ko]": "mobile,data,network,모바일,데이터,네트워크",
"X-KDE-Keywords[lv]": "mobilie,dati,tīkls",
"X-KDE-Keywords[nl]": "mobiel,gegevens,netwerk",
"X-KDE-Keywords[nn]": "mobil,mobilt,data,nettverk",
"X-KDE-Keywords[pl]": "komórkowa,mobilna,dane,sieć",
"X-KDE-Keywords[ru]": "mobile,data,network,мобильный,данные,сеть",
"X-KDE-Keywords[sa]": "मोबाइल,डेटा,जाल",
"X-KDE-Keywords[sl]": "mobilnik,podatki,omrežje",
"X-KDE-Keywords[sv]": "mobil,data,nätverk",
"X-KDE-Keywords[tr]": "mobil,cep,taşınabilir,veri,ağ",
"X-KDE-Keywords[uk]": "mobile,data,network,мобільний,дані,мережа",
"X-KDE-Keywords[x-test]": "xxmobilexx,xxdataxx,xxnetworkxx",
"X-KDE-Keywords[zh_CN]": "mobile,data,network,yidong,shuju,wangluo,fengwo,shouji,liuliang,移动,数据,流量,网络,蜂窝,手机",
"X-KDE-Keywords[zh_TW]": "行動,資料,網路",
"X-KDE-System-Settings-Parent-Category": "network",
"X-KDE-Weight": 70
}

View file

@ -1,336 +0,0 @@
/*
SPDX-FileCopyrightText: 2010-2012 Lamarque Souza <lamarque@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "mobileproviders.h"
#include <QDebug>
#include <QFile>
#include <QLocale>
#include <QRegularExpression>
#include <QTextStream>
const QString MobileProviders::ProvidersFile = QStringLiteral("/usr/share/mobile-broadband-provider-info/serviceproviders.xml");
// adapted from https://invent.kde.org/plasma/plasma-nm/-/blob/master/libs/editor/mobileproviders.cpp
// we only use gsm, ignore cdma
bool localeAwareCompare(const QString &one, const QString &two)
{
return one.localeAwareCompare(two) < 0;
}
MobileProviders::MobileProviders()
{
for (int c = 1; c <= QLocale::LastCountry; c++) {
const auto country = static_cast<QLocale::Territory>(c);
QLocale locale(QLocale::AnyLanguage, country);
if (locale.territory() == country) {
const QString localeName = locale.name();
const auto idx = localeName.indexOf(QLatin1Char('_'));
if (idx != -1) {
const QString countryCode = localeName.mid(idx + 1);
QString countryName = locale.nativeTerritoryName();
if (countryName.isEmpty()) {
countryName = QLocale::territoryToString(country);
}
mCountries.insert(countryCode, countryName);
}
}
}
mError = Success;
QFile file2(ProvidersFile);
if (file2.open(QIODevice::ReadOnly)) {
if (mDocProviders.setContent(&file2)) {
docElement = mDocProviders.documentElement();
if (docElement.isNull()) {
qWarning() << ProvidersFile << ": document is null";
mError = ProvidersIsNull;
} else {
if (docElement.isNull() || docElement.tagName() != "serviceproviders") {
qWarning() << ProvidersFile << ": wrong format";
mError = ProvidersWrongFormat;
} else {
if (docElement.attribute("format") != "2.0") {
qWarning() << ProvidersFile << ": mobile broadband provider database format '" << docElement.attribute("format") << "' not supported.";
mError = ProvidersFormatNotSupported;
} else {
// qCDebug(PLASMA_NM) << "Everything is alright so far";
}
}
}
}
file2.close();
} else {
qWarning() << "Error opening providers file" << ProvidersFile;
mError = ProvidersMissing;
}
}
MobileProviders::~MobileProviders()
{
}
QStringList MobileProviders::getCountryList() const
{
QStringList temp = mCountries.values();
std::sort(temp.begin(), temp.end(), localeAwareCompare);
return temp;
}
QString MobileProviders::countryFromLocale() const
{
const QString localeName = QLocale().name();
const auto idx = localeName.indexOf(QLatin1Char('_'));
if (idx != -1) {
return localeName.mid(idx + 1);
}
return QString();
}
QStringList MobileProviders::getApns(const QString &provider)
{
mApns.clear();
mNetworkIds.clear();
if (!mProvidersGsm.contains(provider)) {
return QStringList();
}
QDomNode n = mProvidersGsm[provider];
while (!n.isNull()) {
QDomElement e = n.toElement(); // <gsm | cdma>
if (!e.isNull() && e.tagName().toLower() == "gsm") {
QDomNode n2 = e.firstChild();
while (!n2.isNull()) {
QDomElement e2 = n2.toElement(); // <apn | network-id>
if (!e2.isNull() && e2.tagName().toLower() == "apn") {
bool isInternet = true;
QDomNode n3 = e2.firstChild();
while (!n3.isNull()) {
QDomElement e3 = n3.toElement(); // <usage>
if (!e3.isNull() && e3.tagName().toLower() == "usage" && !e3.attribute("type").isNull()
&& e3.attribute("type").toLower() != "internet") {
// qCDebug(PLASMA_NM) << "apn" << e2.attribute("value") << "ignored because of usage" << e3.attribute("type");
isInternet = false;
break;
}
n3 = n3.nextSibling();
}
if (isInternet) {
mApns.insert(e2.attribute("value"), e2.firstChild());
}
} else if (!e2.isNull() && e2.tagName().toLower() == "network-id") {
mNetworkIds.append(e2.attribute("mcc") + '-' + e2.attribute("mnc"));
}
n2 = n2.nextSibling();
}
}
n = n.nextSibling();
}
QStringList temp = mApns.keys();
temp.sort();
return temp;
}
ProviderData MobileProviders::parseProvider(const QDomNode &providerNode)
{
ProviderData result;
QMap<QString, QString> localizedProviderNames;
QDomNode c = providerNode.firstChild(); // <name | gsm | cdma>
bool hasGsm = false;
while (!c.isNull()) {
QDomElement ce = c.toElement();
if (ce.tagName().toLower() == QLatin1String("gsm")) {
QDomNode gsmNode = c.firstChild();
while (!gsmNode.isNull()) {
QDomElement gsmElement = gsmNode.toElement();
if (gsmElement.tagName().toLower() == QLatin1String("network-id")) {
result.mccmncs.append(gsmElement.attribute("mcc") + gsmElement.attribute("mnc"));
}
gsmNode = gsmNode.nextSibling();
}
hasGsm = true;
} else if (ce.tagName().toLower() == QLatin1String("name")) {
QString lang = ce.attribute("xml:lang");
if (lang.isEmpty()) {
lang = "en"; // English is default
} else {
lang = lang.toLower();
lang.remove(QRegularExpression(QStringLiteral("\\-.*$"))); // Remove everything after '-' in xml:lang attribute.
}
localizedProviderNames.insert(lang, ce.text());
}
c = c.nextSibling();
}
result.name = getNameByLocale(localizedProviderNames);
const QString name = result.name;
if (hasGsm) {
mProvidersGsm.insert(name, providerNode.firstChild());
}
return result;
}
QStringList MobileProviders::getProvidersFromMCCMNC(const QString &targetMccMnc)
{
QStringList result;
QDomNode n = docElement.firstChild();
while (!n.isNull()) {
QDomElement e = n.toElement(); // <country ...>
if (!e.isNull()) {
QDomNode n2 = e.firstChild();
while (!n2.isNull()) {
QDomElement e2 = n2.toElement(); // <provider ...>
if (!e2.isNull() && e2.tagName().toLower() == "provider") {
ProviderData data = parseProvider(e2);
if (data.mccmncs.contains(targetMccMnc)) {
result << data.name;
}
}
n2 = n2.nextSibling();
}
}
n = n.nextSibling();
}
return result;
}
QStringList MobileProviders::getNetworkIds(const QString &provider)
{
if (mNetworkIds.isEmpty()) {
getApns(provider);
}
return mNetworkIds;
}
QVariantMap MobileProviders::getApnInfo(const QString &apn)
{
QVariantMap temp;
QDomNode n = mApns[apn];
QStringList dnsList;
QMap<QString, QString> localizedPlanNames;
while (!n.isNull()) {
QDomElement e = n.toElement(); // <name|username|password|dns(*)>
if (!e.isNull()) {
if (e.tagName().toLower() == "name") {
QString lang = e.attribute("xml:lang");
if (lang.isEmpty()) {
lang = "en"; // English is default
} else {
lang = lang.toLower();
lang.remove(QRegularExpression(QStringLiteral("\\-.*$"))); // Remove everything after '-' in xml:lang attribute.
}
localizedPlanNames.insert(lang, e.text());
} else if (e.tagName().toLower() == "username") {
temp.insert("username", e.text());
} else if (e.tagName().toLower() == "password") {
temp.insert("password", e.text());
} else if (e.tagName().toLower() == "dns") {
dnsList.append(e.text());
} else if (e.tagName().toLower() == "usage") {
temp.insert("usageType", e.attribute("type"));
}
}
n = n.nextSibling();
}
QString name = getNameByLocale(localizedPlanNames);
if (!name.isEmpty()) {
temp.insert("name", QVariant::fromValue(name));
}
temp.insert("number", getGsmNumber());
temp.insert("apn", apn);
temp.insert("dnsList", dnsList);
return temp;
}
QVariantMap MobileProviders::getCdmaInfo(const QString &provider)
{
if (!mProvidersCdma.contains(provider)) {
return QVariantMap();
}
QVariantMap temp;
QDomNode n = mProvidersCdma[provider];
QStringList sidList;
while (!n.isNull()) {
QDomElement e = n.toElement(); // <gsm or cdma ...>
if (!e.isNull() && e.tagName().toLower() == "cdma") {
QDomNode n2 = e.firstChild();
while (!n2.isNull()) {
QDomElement e2 = n2.toElement(); // <name | username | password | sid>
if (!e2.isNull()) {
if (e2.tagName().toLower() == "username") {
temp.insert("username", e2.text());
} else if (e2.tagName().toLower() == "password") {
temp.insert("password", e2.text());
} else if (e2.tagName().toLower() == "sid") {
sidList.append(e2.text());
}
}
n2 = n2.nextSibling();
}
}
n = n.nextSibling();
}
temp.insert("number", getCdmaNumber());
temp.insert("sidList", sidList);
return temp;
}
QString MobileProviders::getNameByLocale(const QMap<QString, QString> &localizedNames) const
{
QString name;
const QStringList locales = QLocale().uiLanguages();
for (const QString &locale : locales) {
QString language = locale.split(QLatin1Char('-')).at(0);
if (localizedNames.contains(language)) {
return localizedNames[language];
}
}
name = localizedNames["en"];
// Use any language if no proper localized name were found.
if (name.isEmpty() && !localizedNames.isEmpty()) {
name = localizedNames.constBegin().value();
}
return name;
}

View file

@ -1,81 +0,0 @@
/*
SPDX-FileCopyrightText: 2010-2012 Lamarque Souza <lamarque@kde.org>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#ifndef PLASMA_NM_MOBILE_PROVIDERS_H
#define PLASMA_NM_MOBILE_PROVIDERS_H
#include <QDomDocument>
#include <QHash>
#include <QStringList>
#include <QVariantMap>
#include <NetworkManagerQt/ConnectionSettings>
// adapted from https://invent.kde.org/plasma/plasma-nm/-/blob/master/libs/editor/mobileproviders.h
// we only use gsm, ignore cdma
struct ProviderData {
QStringList mccmncs;
QString name;
};
class Q_DECL_EXPORT MobileProviders
{
public:
static const QString ProvidersFile;
enum ErrorCodes {
Success,
CountryCodesMissing,
ProvidersMissing,
ProvidersIsNull,
ProvidersWrongFormat,
ProvidersFormatNotSupported,
};
MobileProviders();
~MobileProviders();
QStringList getCountryList() const;
QString countryFromLocale() const;
QString getCountryName(const QString &key) const
{
return mCountries.value(key);
}
QStringList getApns(const QString &provider);
QStringList getNetworkIds(const QString &provider);
QVariantMap getApnInfo(const QString &apn);
QVariantMap getCdmaInfo(const QString &provider);
QStringList getProvidersFromMCCMNC(const QString &mccmnc);
QString getGsmNumber() const
{
return QString("*99#");
}
QString getCdmaNumber() const
{
return QString("#777");
}
inline ErrorCodes getError()
{
return mError;
}
private:
ProviderData parseProvider(const QDomNode &providerNode);
QHash<QString, QString> mCountries;
QHash<QString, QString> mMccMncToName;
QMap<QString, QDomNode> mProvidersGsm;
QMap<QString, QDomNode> mProvidersCdma;
QMap<QString, QDomNode> mApns;
QStringList mNetworkIds;
QDomDocument mDocProviders;
QDomElement docElement;
ErrorCodes mError;
QString getNameByLocale(const QMap<QString, QString> &names) const;
};
#endif // PLASMA_NM_MOBILE_PROVIDERS_H

View file

@ -1,549 +0,0 @@
// SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "modem.h"
#include <utility>
#include <KLocalizedString>
#include <KUser>
#include <QDBusReply>
#include <QCoroDBusPendingReply>
Modem::Modem(QObject *parent)
: QObject{parent}
{
}
Modem::Modem(QObject *parent, ModemManager::ModemDevice::Ptr mmModem, ModemManager::Modem::Ptr mmInterface)
: QObject{parent}
, m_mmModem{mmModem}
, m_nmModem{nullptr}
, m_mmInterface{mmInterface}
{
// TODO multi-sim support
m_sims = {new Sim{this, this, m_mmModem->sim(), m_mmInterface, m_mm3gppDevice}};
connect(m_mmModem.data(), &ModemManager::ModemDevice::simAdded, this, &Modem::simsChanged);
connect(m_mmModem.data(), &ModemManager::ModemDevice::simAdded, this, &Modem::hasSimChanged);
connect(m_mmModem.data(), &ModemManager::ModemDevice::simRemoved, this, &Modem::simsChanged);
connect(m_mmModem.data(), &ModemManager::ModemDevice::simRemoved, this, &Modem::hasSimChanged);
if (m_mmModem->sim()) {
connect(m_mmModem->sim().get(), &ModemManager::Sim::simIdentifierChanged, this, &Modem::hasSimChanged);
}
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &Modem::mobileDataEnabledChanged);
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionRemoved, this, &Modem::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &Modem::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionRemoved, this, &Modem::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &Modem::findNetworkManagerDevice);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &Modem::findNetworkManagerDevice);
// this is guaranteed to be a GSM modem
m_mm3gppDevice = m_mmModem->interface(ModemManager::ModemDevice::GsmInterface).objectCast<ModemManager::Modem3gpp>();
// if no sim is inserted, m_mm3gppDevice is nullptr
if (m_mm3gppDevice) {
m_mm3gppDevice->setTimeout(60000); // scanning networks likely takes longer than the default timeout
}
// find networkmanager modem, if it exists
findNetworkManagerDevice();
// we need to initialize it after m_mm3gppDevice has been set
m_details = new ModemDetails(this, this);
}
void Modem::findNetworkManagerDevice()
{
m_nmModem = nullptr;
// find networkmanager modem device
for (NetworkManager::Device::Ptr nmDevice : NetworkManager::networkInterfaces()) {
if (nmDevice->udi() == m_mmModem->uni()) {
m_nmModem = nmDevice.objectCast<NetworkManager::ModemDevice>();
}
}
if (m_nmModem) {
connect(m_nmModem.data(), &NetworkManager::Device::autoconnectChanged, this, &Modem::mobileDataEnabledChanged);
connect(m_nmModem.data(), &NetworkManager::Device::stateChanged, this, &Modem::mobileDataEnabledChanged);
connect(m_nmModem.data(), &NetworkManager::Device::availableConnectionAppeared, this, &Modem::mobileDataEnabledChanged);
connect(m_nmModem.data(), &NetworkManager::Device::availableConnectionDisappeared, this, &Modem::mobileDataEnabledChanged);
connect(m_nmModem.data(), &NetworkManager::ModemDevice::availableConnectionChanged, this, [this]() -> void {
refreshProfiles();
});
connect(m_nmModem.data(), &NetworkManager::ModemDevice::activeConnectionChanged, this, [this]() -> void {
refreshProfiles();
Q_EMIT activeConnectionUniChanged();
});
connect(m_nmModem.data(), &NetworkManager::ModemDevice::stateChanged, this, [this](auto newstate, auto oldstate, auto reason) -> void {
qDebug() << QStringLiteral("Modem") << m_nmModem->uni() << QStringLiteral("changed state:") << nmDeviceStateStr(oldstate) << QStringLiteral("->")
<< nmDeviceStateStr(newstate) << QStringLiteral("due to:") << reason;
});
// add connection profiles
refreshProfiles();
}
Q_EMIT nmModemChanged();
Q_EMIT mobileDataEnabledChanged();
Q_EMIT mobileDataSupportedChanged();
}
ModemDetails *Modem::modemDetails() const
{
return m_details;
}
QString Modem::displayId() const
{
// in the form /org/freedesktop/ModemManager1/Modem/0
QStringList uniSplit = uni().split("/");
return uniSplit.count() == 0 ? QStringLiteral("(empty)") : QString(uniSplit[uniSplit.size() - 1]);
}
QString Modem::uni() const
{
return m_mmInterface->uni();
}
QString Modem::activeConnectionUni() const
{
if (m_nmModem && m_nmModem->activeConnection() && m_nmModem->activeConnection()->connection()) {
return m_nmModem->activeConnection()->connection()->uuid();
}
return QString();
}
QCoro::Task<void> Modem::reset()
{
qDebug() << QStringLiteral("Resetting the modem...");
QDBusReply<void> reply = co_await m_mmInterface->reset();
if (!reply.isValid()) {
qDebug() << QStringLiteral("Error resetting the modem:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error resetting the modem: %1", reply.error().message()));
}
}
bool Modem::mobileDataSupported() const
{
return m_nmModem && hasSim();
}
bool Modem::needsAPNAdded() const
{
return m_nmModem && mobileDataSupported() && m_nmModem->availableConnections().count() == 0;
}
bool Modem::mobileDataEnabled() const
{
// if wwan is globally disabled
if (!NetworkManager::isWwanEnabled()) {
return false;
}
// no modem -> no mobile data -> report disabled
if (!m_nmModem) {
return false;
}
// mobile data already activated -> report enabled
if (m_nmModem->state() == NetworkManager::Device::Activated) {
return true;
}
// autoconnect disabled on the entire modem -> report disabled
if (!m_nmModem->autoconnect()) {
return false;
}
// at least one connection set to autoconnect -> report enabled
for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) {
if (con->settings()->autoconnect()) {
return true;
}
}
// modem, but no connection, set to autoconnect -> report disabled
return false;
}
void Modem::setMobileDataEnabled(bool enabled)
{
// ensure that wwan is on
if (enabled && !NetworkManager::isWwanEnabled()) {
NetworkManager::setWwanEnabled(true);
}
if (!m_nmModem) {
return;
}
if (enabled) {
// enable mobile data...
m_nmModem->setAutoconnect(true);
// activate the connection that was last used
QDateTime latestTimestamp;
NetworkManager::Connection::Ptr latestCon;
for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) {
QDateTime timestamp = con->settings()->timestamp();
// if con was not used yet, skip it, otherwise:
// if we have no latestTimestamp yet, con is the latest
// otherwise, compare the timestamps
// in case of a tie, use the first connection that was found
if (!timestamp.isNull() && (latestTimestamp.isNull() || timestamp > latestTimestamp)) {
latestTimestamp = timestamp;
latestCon = con;
}
}
// if we found the last used connection
if (!latestCon.isNull()) {
// set it to autoconnect and connect it immediately
latestCon->settings()->setAutoconnect(true);
latestCon->update(latestCon->settings()->toMap());
NetworkManager::activateConnection(latestCon->path(), m_nmModem->uni(), "");
}
} else {
// disable mobile data...
// we do not call NetworkManager::setWwanEnabled(false), because it turns off cellular
// turn off autoconnect
m_nmModem->setAutoconnect(false);
// we need to also set all connections to not autoconnect (#182)
for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) {
con->settings()->setAutoconnect(false);
con->update(con->settings()->toMap());
}
// disconnect network
m_nmModem->disconnectInterface();
}
}
bool Modem::isRoaming() const
{
if (!m_nmModem || !m_nmModem->activeConnection() || !m_nmModem->activeConnection()->connection()) {
return false;
}
auto connection = m_nmModem->activeConnection()->connection();
NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
return gsmSetting ? !gsmSetting->homeOnly() : false;
}
QCoro::Task<void> Modem::setIsRoaming(bool roaming)
{
if (!m_nmModem || !m_nmModem->activeConnection() || !m_nmModem->activeConnection()->connection()) {
co_return;
}
auto connection = m_nmModem->activeConnection()->connection();
NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
if (gsmSetting) {
gsmSetting->setHomeOnly(!roaming); // set roaming setting
QDBusReply<void> reply = co_await connection->update(connection->settings()->toMap());
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error updating connection settings for") << connection->uuid() << QStringLiteral(":") << reply.error().message()
<< QStringLiteral(".");
CellularNetworkSettings::instance()->addMessage(
InlineMessage::Error,
i18n("Error updating connection settings for %1: %2.", connection->uuid(), reply.error().message()));
} else {
qDebug() << QStringLiteral("Successfully updated connection settings") << connection->uuid() << QStringLiteral(".");
}
}
// the connection uni has changed, refresh the profiles list
refreshProfiles();
Q_EMIT activeConnectionUniChanged();
}
bool Modem::hasSim() const
{
if (!m_mmModem) {
return false;
}
return m_mmModem && m_mmModem->sim() && m_mmModem->sim()->uni() != QStringLiteral("/");
}
QList<ProfileSettings *> &Modem::profileList()
{
return m_profileList;
}
void Modem::refreshProfiles()
{
m_profileList.clear();
if (!m_nmModem) {
Q_EMIT profileListChanged();
qWarning() << "No NetworkManager modem found, cannot refresh profiles.";
return;
}
for (auto connection : m_nmModem->availableConnections()) {
for (auto setting : connection->settings()->settings()) {
if (setting.dynamicCast<NetworkManager::GsmSetting>()) {
m_profileList.append(new ProfileSettings(this, setting.dynamicCast<NetworkManager::GsmSetting>(), connection));
}
}
}
Q_EMIT profileListChanged();
}
QCoro::Task<void> Modem::activateProfile(const QString &connectionUni)
{
if (!m_nmModem) {
qWarning() << "Cannot activate profile since there is no NetworkManager modem";
co_return;
}
qDebug() << QStringLiteral("Activating profile on modem") << m_nmModem->uni() << QStringLiteral("for connection") << connectionUni << ".";
// cache roaming setting
bool roaming = isRoaming();
NetworkManager::Connection::Ptr con;
// disable autoconnect for all other connections
for (auto connection : m_nmModem->availableConnections()) {
if (connection->uuid() == connectionUni) {
connection->settings()->setAutoconnect(true);
con = connection;
} else {
connection->settings()->setAutoconnect(false);
}
}
if (!con) {
qDebug() << QStringLiteral("Connection") << connectionUni << QStringLiteral("not found.");
co_return;
}
// activate connection manually
// despite the documentation saying otherwise, activateConnection seems to need the DBus path, not uuid of the connection
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::activateConnection(con->path(), m_nmModem->uni(), "");
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error activating connection:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error activating connection: %1", reply.error().message()));
co_return;
}
// set roaming settings separately (since it changes the uni)
co_await setIsRoaming(roaming);
}
QCoro::Task<void> Modem::addProfile(QString name, QString apn, QString username, QString password, QString networkType)
{
if (!m_nmModem) {
qWarning() << "Cannot add profile since there is no NetworkManager modem";
co_return;
}
NetworkManager::ConnectionSettings::Ptr settings{new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Gsm)};
settings->setId(name);
settings->setUuid(NetworkManager::ConnectionSettings::createNewUuid());
settings->setAutoconnect(true);
settings->addToPermissions(KUser().loginName(), QString());
NetworkManager::GsmSetting::Ptr gsmSetting = settings->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
gsmSetting->setApn(apn);
gsmSetting->setUsername(username);
gsmSetting->setPassword(password);
gsmSetting->setPasswordFlags(password.isEmpty() ? NetworkManager::Setting::NotRequired : NetworkManager::Setting::AgentOwned);
gsmSetting->setNetworkType(ProfileSettings::networkTypeFlag(networkType));
gsmSetting->setHomeOnly(!isRoaming());
gsmSetting->setInitialized(true);
NetworkManager::Ipv6Setting::Ptr ipv6Setting = settings->setting(NetworkManager::Setting::Ipv6).dynamicCast<NetworkManager::Ipv6Setting>();
ipv6Setting->setMethod(NetworkManager::Ipv6Setting::ConfigMethod::Automatic);
ipv6Setting->setInitialized(true);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), m_nmModem->uni(), "");
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error adding connection:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error adding connection: %1", reply.error().message()));
} else {
qDebug() << QStringLiteral("Successfully added a new connection") << name << QStringLiteral("with APN") << apn << ".";
}
}
QCoro::Task<void> Modem::removeProfile(const QString &connectionUni)
{
NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionUni);
if (!con) {
qWarning() << QStringLiteral("Could not find connection") << connectionUni << QStringLiteral("to update!");
co_return;
}
QDBusReply<void> reply = co_await con->remove();
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error removing connection") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error removing connection: %1", reply.error().message()));
}
}
QCoro::Task<void> Modem::updateProfile(QString connectionUni, QString name, QString apn, QString username, QString password, QString networkType)
{
NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionUni);
if (!con) {
qWarning() << QStringLiteral("Could not find connection") << connectionUni << QStringLiteral("to update!");
co_return;
}
NetworkManager::ConnectionSettings::Ptr conSettings = con->settings();
if (!conSettings) {
qWarning() << QStringLiteral("Could not find connection settings for") << connectionUni << QStringLiteral("to update!");
co_return;
}
conSettings->setId(name);
NetworkManager::GsmSetting::Ptr gsmSetting = conSettings->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
gsmSetting->setApn(apn);
gsmSetting->setUsername(username);
gsmSetting->setPassword(password);
gsmSetting->setPasswordFlags(password == "" ? NetworkManager::Setting::NotRequired : NetworkManager::Setting::AgentOwned);
gsmSetting->setNetworkType(ProfileSettings::networkTypeFlag(networkType));
gsmSetting->setHomeOnly(!isRoaming());
gsmSetting->setInitialized(true);
NetworkManager::Ipv6Setting::Ptr ipv6Setting = conSettings->setting(NetworkManager::Setting::Ipv6).dynamicCast<NetworkManager::Ipv6Setting>();
ipv6Setting->setMethod(NetworkManager::Ipv6Setting::ConfigMethod::Automatic);
ipv6Setting->setInitialized(true);
QDBusReply<void> reply = con->update(conSettings->toMap());
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error updating connection settings for") << connectionUni << QStringLiteral(":") << reply.error().message()
<< QStringLiteral(".");
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error,
i18n("Error updating connection settings for %1: %2.", connectionUni, reply.error().message()));
} else {
qDebug() << QStringLiteral("Successfully updated connection settings") << connectionUni << QStringLiteral(".");
}
}
void Modem::addDetectedProfileSettings()
{
if (!m_mmModem) {
qWarning() << "ModemManager device missing, cannot detect profile settings";
return;
}
if (!hasSim() || !m_mmModem->sim()) {
qWarning() << "No SIM found, cannot detect profile settings";
return;
}
if (!m_mm3gppDevice) {
qWarning() << "3gpp object not found, cannot detect profile settings";
return;
}
bool found = false;
static MobileProviders mobileProviders{};
QString operatorCode = m_mmModem->sim()->operatorIdentifier();
qWarning() << QStringLiteral("Detecting profile settings. Using MCCMNC:") << operatorCode;
// lookup apns with mccmnc codes
for (QString &provider : mobileProviders.getProvidersFromMCCMNC(operatorCode)) {
qWarning() << QStringLiteral("Provider:") << provider;
for (auto apn : mobileProviders.getApns(provider)) {
QVariantMap apnInfo = mobileProviders.getApnInfo(apn);
qWarning() << QStringLiteral("Found gsm profile settings. Type:") << apnInfo[QStringLiteral("usageType")];
// only add mobile data apns (not mms)
if (apnInfo[QStringLiteral("usageType")].toString() == QStringLiteral("internet")) {
found = true;
QString name = provider;
if (!apnInfo[QStringLiteral("name")].isNull()) {
name += " - " + apnInfo[QStringLiteral("name")].toString();
}
addProfile(name,
apn,
apnInfo[QStringLiteral("username")].toString(),
apnInfo[QStringLiteral("password")].toString(),
QStringLiteral("4G/3G/2G"));
}
// TODO in the future for MMS settings, add else if here for == "mms"
}
}
if (!found) {
qDebug() << QStringLiteral("No profiles were found.");
Q_EMIT couldNotAutodetectSettings();
}
}
QList<Sim *> Modem::sims()
{
return m_sims;
}
ModemManager::ModemDevice::Ptr Modem::mmModemDevice()
{
return m_mmModem;
}
NetworkManager::ModemDevice::Ptr Modem::nmModemDevice()
{
return m_nmModem;
}
ModemManager::Modem::Ptr Modem::mmModemInterface()
{
return m_mmInterface;
}
QString Modem::nmDeviceStateStr(NetworkManager::Device::State state)
{
if (state == NetworkManager::Device::State::UnknownState)
return i18n("Unknown");
else if (state == NetworkManager::Device::State::Unmanaged)
return i18n("Unmanaged");
else if (state == NetworkManager::Device::State::Unavailable)
return i18n("Unavailable");
else if (state == NetworkManager::Device::State::Disconnected)
return i18n("Disconnected");
else if (state == NetworkManager::Device::State::Preparing)
return i18n("Preparing");
else if (state == NetworkManager::Device::State::ConfiguringHardware)
return i18n("ConfiguringHardware");
else if (state == NetworkManager::Device::State::NeedAuth)
return i18n("NeedAuth");
else if (state == NetworkManager::Device::State::ConfiguringIp)
return i18n("ConfiguringIp");
else if (state == NetworkManager::Device::State::CheckingIp)
return i18n("CheckingIp");
else if (state == NetworkManager::Device::State::WaitingForSecondaries)
return i18n("WaitingForSecondaries");
else if (state == NetworkManager::Device::State::Activated)
return i18n("Activated");
else if (state == NetworkManager::Device::State::Deactivating)
return i18n("Deactivating");
else if (state == NetworkManager::Device::State::Failed)
return i18n("Failed");
else
return "";
}

View file

@ -1,120 +0,0 @@
// SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "cellularnetworksettings.h"
#include "modemdetails.h"
#include "profilesettings.h"
#include "sim.h"
#include <QList>
#include <QString>
#include <NetworkManagerQt/CdmaSetting>
#include <NetworkManagerQt/ConnectionSettings>
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Ipv6Setting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/ModemDevice>
#include <NetworkManagerQt/Settings>
#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
#include <QCoroDBusPendingReply>
class ProfileSettings;
class Sim;
class AvailableNetwork;
class ModemDetails;
class MobileProviders;
// only supports GSM/UMTS/LTE
class Modem : public QObject
{
Q_OBJECT
Q_PROPERTY(ModemDetails *details READ modemDetails NOTIFY modemDetailsChanged)
Q_PROPERTY(QString uni READ uni NOTIFY uniChanged)
Q_PROPERTY(QString displayId READ displayId NOTIFY displayIdChanged)
Q_PROPERTY(bool isRoaming READ isRoaming WRITE setIsRoaming NOTIFY isRoamingChanged)
Q_PROPERTY(bool hasSim READ hasSim NOTIFY hasSimChanged)
Q_PROPERTY(QList<ProfileSettings *> profiles READ profileList NOTIFY profileListChanged)
Q_PROPERTY(QString activeConnectionUni READ activeConnectionUni NOTIFY activeConnectionUniChanged)
Q_PROPERTY(bool mobileDataEnabled READ mobileDataEnabled WRITE setMobileDataEnabled NOTIFY mobileDataEnabledChanged)
Q_PROPERTY(bool mobileDataSupported READ mobileDataSupported NOTIFY mobileDataSupportedChanged)
Q_PROPERTY(bool needsAPNAdded READ needsAPNAdded NOTIFY mobileDataEnabledChanged)
public:
Modem(QObject *parent = nullptr);
Modem(QObject *parent, ModemManager::ModemDevice::Ptr mmModem, ModemManager::Modem::Ptr m_mmInterface);
ModemDetails *modemDetails() const;
QString displayId() const; // splits uni and obtains the number suffix
QString uni() const;
QString activeConnectionUni() const;
Q_INVOKABLE QCoro::Task<void> reset();
bool mobileDataEnabled() const;
void setMobileDataEnabled(bool enabled);
bool mobileDataSupported() const;
bool needsAPNAdded() const;
bool isRoaming() const;
QCoro::Task<void> setIsRoaming(bool roaming);
bool hasSim() const;
// connection profiles
QList<ProfileSettings *> &profileList();
void refreshProfiles();
Q_INVOKABLE QCoro::Task<void> activateProfile(const QString &connectionUni);
Q_INVOKABLE QCoro::Task<void> addProfile(QString name, QString apn, QString username, QString password, QString networkType);
Q_INVOKABLE QCoro::Task<void> removeProfile(const QString &connectionUni);
Q_INVOKABLE QCoro::Task<void> updateProfile(QString connectionUni, QString name, QString apn, QString username, QString password, QString networkType);
Q_INVOKABLE void addDetectedProfileSettings(); // detect modem connection settings (ex. apn) and add a new connection
QList<Sim *> sims();
ModemManager::ModemDevice::Ptr mmModemDevice();
NetworkManager::ModemDevice::Ptr nmModemDevice();
ModemManager::Modem::Ptr mmModemInterface();
Q_SIGNALS:
void modemDetailsChanged();
void uniChanged();
void displayIdChanged();
void activeConnectionUniChanged();
void nmModemChanged();
void mobileDataEnabledChanged();
void mobileDataSupportedChanged();
void isRoamingChanged();
void simsChanged();
void hasSimChanged();
void profileListChanged();
void couldNotAutodetectSettings();
private:
void findNetworkManagerDevice();
QString nmDeviceStateStr(NetworkManager::Device::State state);
ModemDetails *m_details;
ModemManager::ModemDevice::Ptr m_mmModem;
NetworkManager::ModemDevice::Ptr m_nmModem; // may be a nullptr if the nm modem hasn't been found yet
ModemManager::Modem::Ptr m_mmInterface = nullptr;
ModemManager::Modem3gpp::Ptr m_mm3gppDevice = nullptr; // this may be a nullptr if no sim is inserted
QList<Sim *> m_sims;
QList<ProfileSettings *> m_profileList;
friend class ModemDetails;
};

View file

@ -1,554 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "modemdetails.h"
#include <KLocalizedString>
#include <QDBusPendingCallWatcher>
ModemDetails::ModemDetails(QObject *parent, Modem *modem)
: QObject{parent}
, m_modem{modem}
, m_scanNetworkWatcher{nullptr}
, m_isScanningNetworks{false}
, m_cachedScannedNetworks{}
{
auto mmInterfacePointer = m_modem->m_mmInterface.data();
connect(mmInterfacePointer, &ModemManager::Modem::accessTechnologiesChanged, this, [this]() -> void {
Q_EMIT accessTechnologiesChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::deviceChanged, this, [this]() -> void {
Q_EMIT deviceChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::deviceIdentifierChanged, this, [this]() -> void {
Q_EMIT deviceIdentifierChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::driversChanged, this, [this]() -> void {
Q_EMIT driversChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::equipmentIdentifierChanged, this, [this]() -> void {
Q_EMIT equipmentIdentifierChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::manufacturerChanged, this, [this]() -> void {
Q_EMIT manufacturerChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::modelChanged, this, [this]() -> void {
Q_EMIT modelChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::ownNumbersChanged, this, [this]() -> void {
Q_EMIT ownNumbersChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::pluginChanged, this, [this]() -> void {
Q_EMIT pluginChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::powerStateChanged, this, [this]() -> void {
Q_EMIT powerStateChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::revisionChanged, this, [this]() -> void {
Q_EMIT revisionChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::signalQualityChanged, this, [this]() -> void {
Q_EMIT signalQualityChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::simPathChanged, this, [this]() -> void {
Q_EMIT simPathChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::stateChanged, this, [this]() -> void {
Q_EMIT stateChanged();
});
connect(mmInterfacePointer, &ModemManager::Modem::stateFailedReasonChanged, this, [this]() -> void {
Q_EMIT stateFailedReasonChanged();
});
if (m_modem->m_mm3gppDevice) {
connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::operatorCodeChanged, this, [this]() -> void {
Q_EMIT operatorCodeChanged();
});
connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::operatorNameChanged, this, [this]() -> void {
Q_EMIT operatorNameChanged();
});
connect(m_modem->m_mm3gppDevice.data(), &ModemManager::Modem3gpp::registrationStateChanged, this, [this]() -> void {
Q_EMIT registrationStateChanged();
Q_EMIT m_modem->isRoamingChanged();
});
} else {
qWarning() << QStringLiteral("3gpp device not found!");
}
// m_modem->m_nmModem may be nullptr, listen for updates
connect(m_modem, &Modem::nmModemChanged, this, &ModemDetails::updateNMSignals);
updateNMSignals();
}
void ModemDetails::updateNMSignals()
{
if (m_modem->m_nmModem) {
connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::firmwareVersionChanged, this, [this]() -> void {
Q_EMIT firmwareVersionChanged();
});
connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::interfaceNameChanged, this, [this]() -> void {
Q_EMIT interfaceNameChanged();
});
connect(m_modem->m_nmModem.data(), &NetworkManager::ModemDevice::meteredChanged, this, [this]() -> void {
Q_EMIT meteredChanged();
});
}
}
ModemDetails &ModemDetails::operator=(ModemDetails &&other)
{
swap(other);
return *this;
}
void ModemDetails::swap(ModemDetails &other)
{
std::swap(m_modem, other.m_modem);
std::swap(m_cachedScannedNetworks, other.m_cachedScannedNetworks);
std::swap(m_isScanningNetworks, other.m_isScanningNetworks);
std::swap(m_scanNetworkWatcher, other.m_scanNetworkWatcher);
}
QStringList ModemDetails::accessTechnologies()
{
QStringList list;
auto flags = m_modem->m_mmInterface->accessTechnologies();
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN) {
list.push_back(i18n("Unknown"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_POTS) {
list.push_back(i18n("POTS"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GSM) {
list.push_back(i18n("GSM"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT) {
list.push_back(i18n("GSM Compact"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_GPRS) {
list.push_back(i18n("GPRS"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EDGE) {
list.push_back(i18n("EDGE"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_UMTS) {
list.push_back(i18n("UMTS"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSDPA) {
list.push_back(i18n("HSDPA"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSUPA) {
list.push_back(i18n("HSUPA"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSPA) {
list.push_back(i18n("HSPA"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS) {
list.push_back(i18n("HSPA+"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_1XRTT) {
list.push_back(i18n("CDMA2000 1xRTT"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDO0) {
list.push_back(i18n("CDMA2000 EVDO-0"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDOA) {
list.push_back(i18n("CDMA2000 EVDO-A"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_EVDOB) {
list.push_back(i18n("CDMA2000 EVDO-B"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_LTE) {
list.push_back(i18n("LTE"));
}
if (flags & MM_MODEM_ACCESS_TECHNOLOGY_5GNR) {
list.push_back(i18n("5GNR"));
}
return list;
}
QString ModemDetails::device()
{
return m_modem->m_mmInterface->device();
}
QString ModemDetails::deviceIdentifier()
{
return m_modem->m_mmInterface->deviceIdentifier();
}
QStringList ModemDetails::drivers()
{
return m_modem->m_mmInterface->drivers();
}
QString ModemDetails::equipmentIdentifier()
{
return m_modem->m_mmInterface->equipmentIdentifier();
}
bool ModemDetails::isEnabled()
{
return m_modem->m_mmInterface->isEnabled();
}
QString ModemDetails::manufacturer()
{
return m_modem->m_mmInterface->manufacturer();
}
QString ModemDetails::model()
{
return m_modem->m_mmInterface->model();
}
QStringList ModemDetails::ownNumbers()
{
return m_modem->m_mmInterface->ownNumbers();
}
QString ModemDetails::plugin()
{
return m_modem->m_mmInterface->plugin();
}
QString ModemDetails::powerState()
{
switch (m_modem->m_mmInterface->powerState()) {
case MM_MODEM_POWER_STATE_UNKNOWN:
return i18n("Unknown");
case MM_MODEM_POWER_STATE_OFF:
return i18n("Off");
case MM_MODEM_POWER_STATE_LOW:
return i18n("Low-power mode");
case MM_MODEM_POWER_STATE_ON:
return i18n("Full power mode");
}
return {};
}
QString ModemDetails::revision()
{
return m_modem->m_mmInterface->revision();
}
uint ModemDetails::signalQuality()
{
return m_modem->m_mmInterface->signalQuality().signal;
}
QString ModemDetails::simPath()
{
return m_modem->m_mmInterface->simPath();
}
QString ModemDetails::state()
{
switch (m_modem->m_mmInterface->state()) {
case MM_MODEM_STATE_FAILED:
return i18n("Failed");
case MM_MODEM_STATE_UNKNOWN:
return i18n("Unknown");
case MM_MODEM_STATE_INITIALIZING:
return i18n("Initializing");
case MM_MODEM_STATE_LOCKED:
return i18n("Locked");
case MM_MODEM_STATE_DISABLED:
return i18n("Disabled");
case MM_MODEM_STATE_DISABLING:
return i18n("Disabling");
case MM_MODEM_STATE_ENABLING:
return i18n("Enabling");
case MM_MODEM_STATE_ENABLED:
return i18n("Enabled");
case MM_MODEM_STATE_SEARCHING:
return i18n("Searching for network provider");
case MM_MODEM_STATE_REGISTERED:
return i18n("Registered with network provider");
case MM_MODEM_STATE_DISCONNECTING:
return i18n("Disconnecting");
case MM_MODEM_STATE_CONNECTING:
return i18n("Connecting");
case MM_MODEM_STATE_CONNECTED:
return i18n("Connected");
}
return {};
}
QString ModemDetails::stateFailedReason()
{
switch (m_modem->m_mmInterface->stateFailedReason()) {
case MM_MODEM_STATE_FAILED_REASON_NONE:
return i18n("No error.");
case MM_MODEM_STATE_FAILED_REASON_UNKNOWN:
return i18n("Unknown error.");
case MM_MODEM_STATE_FAILED_REASON_SIM_MISSING:
return i18n("SIM is required but missing.");
case MM_MODEM_STATE_FAILED_REASON_SIM_ERROR:
return i18n("SIM is available but unusable.");
case MM_MODEM_STATE_FAILED_REASON_UNKNOWN_CAPABILITIES:
return i18n("Unknown modem capabilities.");
case MM_MODEM_STATE_FAILED_REASON_ESIM_WITHOUT_PROFILES:
return i18n("eSIM is not initialized.");
}
return {};
}
QString ModemDetails::operatorCode()
{
return m_modem->m_mm3gppDevice ? m_modem->m_mm3gppDevice->operatorCode() : QString{};
}
QString ModemDetails::operatorName()
{
return m_modem->m_mm3gppDevice ? m_modem->m_mm3gppDevice->operatorName() : QString{};
}
QString ModemDetails::registrationState()
{
if (!m_modem->m_mm3gppDevice) {
return QString{};
}
switch (m_modem->m_mm3gppDevice->registrationState()) {
case MM_MODEM_3GPP_REGISTRATION_STATE_IDLE:
return i18n("Not registered, not searching for new operator to register.");
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME:
return i18n("Registered on home network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_SEARCHING:
return i18n("Not registered, searching for new operator to register with.");
case MM_MODEM_3GPP_REGISTRATION_STATE_DENIED:
return i18n("Registration denied.");
case MM_MODEM_3GPP_REGISTRATION_STATE_UNKNOWN:
return i18n("Unknown registration status.");
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING:
return i18n("Registered on a roaming network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_SMS_ONLY:
return i18n("Registered for \"SMS only\", on home network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_SMS_ONLY:
return i18n("Registered for \"SMS only\", roaming network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_EMERGENCY_ONLY:
return i18n("Emergency services only.");
case MM_MODEM_3GPP_REGISTRATION_STATE_HOME_CSFB_NOT_PREFERRED:
return i18n("Registered for \"CSFB not preferred\", home network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_ROAMING_CSFB_NOT_PREFERRED:
return i18n("Registered for \"CSFB not preferred\", roaming network.");
case MM_MODEM_3GPP_REGISTRATION_STATE_ATTACHED_RLOS:
return i18n("Attached for access to Restricted Local Operator Services.");
}
return {};
}
Q_DECLARE_METATYPE(MMModem3gppNetworkAvailability)
Q_DECLARE_METATYPE(MMModemAccessTechnology)
QList<AvailableNetwork *> ModemDetails::networks()
{
return m_cachedScannedNetworks;
}
Q_INVOKABLE void ModemDetails::scanNetworks()
{
for (auto p : m_cachedScannedNetworks) {
p->deleteLater();
}
m_cachedScannedNetworks.clear();
if (m_modem->m_mm3gppDevice) {
qDebug() << QStringLiteral("Scanning for available networks...");
QDBusPendingReply<ModemManager::QVariantMapList> reply = m_modem->m_mm3gppDevice->scan();
m_isScanningNetworks = true;
Q_EMIT isScanningNetworksChanged();
m_scanNetworkWatcher = new QDBusPendingCallWatcher(reply, this);
connect(m_scanNetworkWatcher, &QDBusPendingCallWatcher::finished, this, &ModemDetails::scanNetworksFinished);
}
Q_EMIT networksChanged();
}
void ModemDetails::scanNetworksFinished(QDBusPendingCallWatcher *call)
{
QDBusPendingReply<ModemManager::QVariantMapList> reply = *call;
if (reply.isError()) {
qDebug() << QStringLiteral("Scanning failed:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Scanning networks failed: %1", reply.error().message()));
} else {
ModemManager::QVariantMapList list = reply.value();
for (auto &var : list) {
auto status = var[QStringLiteral("status")].value<MMModem3gppNetworkAvailability>();
if (status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT || status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_AVAILABLE) {
auto network = new AvailableNetwork{this,
m_modem->m_mm3gppDevice,
status == MM_MODEM_3GPP_NETWORK_AVAILABILITY_CURRENT,
var[QStringLiteral("operator-long")].toString(),
var[QStringLiteral("operator-short")].toString(),
var[QStringLiteral("operator-code")].toString(),
var[QStringLiteral("access-technology")].value<MMModemAccessTechnology>()};
m_cachedScannedNetworks.push_back(network);
}
}
}
m_isScanningNetworks = false;
Q_EMIT networksChanged();
Q_EMIT isScanningNetworksChanged();
call->deleteLater();
}
bool ModemDetails::isScanningNetworks()
{
return m_isScanningNetworks;
}
QString ModemDetails::firmwareVersion()
{
if (!m_modem->m_nmModem) {
return QString{};
}
return m_modem->m_nmModem->firmwareVersion();
}
QString ModemDetails::interfaceName()
{
if (!m_modem->m_nmModem) {
return QString{};
}
return m_modem->m_nmModem->interfaceName();
}
QString ModemDetails::metered()
{
if (!m_modem->m_nmModem) {
return QString{};
}
switch (m_modem->m_nmModem->metered()) {
case NetworkManager::Device::MeteredStatus::UnknownStatus:
return i18n("Unknown");
case NetworkManager::Device::MeteredStatus::Yes:
return i18n("Yes");
case NetworkManager::Device::MeteredStatus::No:
return i18n("No");
case NetworkManager::Device::MeteredStatus::GuessYes:
return i18n("GuessYes");
case NetworkManager::Device::MeteredStatus::GuessNo:
return i18n("GuessNo");
}
return QString{};
}
AvailableNetwork::AvailableNetwork(QObject *parent,
ModemManager::Modem3gpp::Ptr mm3gppDevice,
bool isCurrentlyUsed,
QString operatorLong,
QString operatorShort,
QString operatorCode,
MMModemAccessTechnology accessTechnology)
: QObject{parent}
, m_isCurrentlyUsed{isCurrentlyUsed}
, m_operatorLong{operatorLong}
, m_operatorShort{operatorShort}
, m_operatorCode{operatorCode}
, m_accessTechnology{}
, m_mm3gppDevice{mm3gppDevice}
{
switch (accessTechnology) {
case MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN:
m_accessTechnology = i18n("Unknown");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_POTS:
m_accessTechnology = i18n("POTS");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_GSM:
m_accessTechnology = i18n("2G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_GSM_COMPACT:
m_accessTechnology = i18n("2G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_GPRS:
m_accessTechnology = i18n("2G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_EDGE:
m_accessTechnology = i18n("2G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_UMTS:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_HSDPA:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_HSUPA:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_HSPA:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_HSPA_PLUS:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_1XRTT:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_EVDO0:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_EVDOA:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_EVDOB:
m_accessTechnology = i18n("3G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_LTE:
m_accessTechnology = i18n("4G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_5GNR:
m_accessTechnology = i18n("5G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_ANY:
m_accessTechnology = i18n("Any");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_LTE_CAT_M:
m_accessTechnology = i18n("4G");
break;
case MM_MODEM_ACCESS_TECHNOLOGY_LTE_NB_IOT:
m_accessTechnology = i18n("4G");
break;
}
}
bool AvailableNetwork::isCurrentlyUsed()
{
return m_isCurrentlyUsed;
}
QString AvailableNetwork::operatorLong()
{
return m_operatorLong;
}
QString AvailableNetwork::operatorShort()
{
return m_operatorShort;
}
QString AvailableNetwork::operatorCode()
{
return m_operatorCode;
}
QString AvailableNetwork::accessTechnology()
{
return m_accessTechnology;
}
void AvailableNetwork::registerToNetwork()
{
if (!m_isCurrentlyUsed && m_mm3gppDevice) {
m_mm3gppDevice->registerToNetwork(m_operatorCode);
}
}

View file

@ -1,178 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "modem.h"
#include "sim.h"
#include <QList>
#include <QString>
#include <NetworkManagerQt/CdmaSetting>
#include <NetworkManagerQt/ConnectionSettings>
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/ModemDevice>
#include <NetworkManagerQt/Settings>
#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
class Modem;
class AvailableNetwork;
class ModemDetails : public QObject
{
Q_OBJECT
// modemmanager device
Q_PROPERTY(QStringList accessTechnologies READ accessTechnologies NOTIFY accessTechnologiesChanged) // currently used tech
Q_PROPERTY(QString device READ device NOTIFY deviceChanged)
Q_PROPERTY(QString deviceIdentifier READ deviceIdentifier NOTIFY deviceIdentifierChanged)
Q_PROPERTY(QStringList drivers READ drivers NOTIFY driversChanged)
Q_PROPERTY(QString equipmentIdentifier READ equipmentIdentifier NOTIFY equipmentIdentifierChanged)
// TODO add bands
Q_PROPERTY(bool isEnabled READ isEnabled NOTIFY isEnabledChanged)
Q_PROPERTY(QString manufacturer READ manufacturer NOTIFY manufacturerChanged)
Q_PROPERTY(QString model READ model NOTIFY modelChanged)
Q_PROPERTY(QStringList ownNumbers READ ownNumbers NOTIFY ownNumbersChanged)
Q_PROPERTY(QString plugin READ plugin NOTIFY pluginChanged)
Q_PROPERTY(QString powerState READ powerState NOTIFY powerStateChanged)
Q_PROPERTY(QString revision READ revision NOTIFY revisionChanged)
Q_PROPERTY(uint signalQuality READ signalQuality NOTIFY signalQualityChanged)
Q_PROPERTY(QString simPath READ simPath NOTIFY simPathChanged)
Q_PROPERTY(QString state READ state NOTIFY stateChanged)
Q_PROPERTY(QString stateFailedReason READ stateFailedReason NOTIFY stateFailedReasonChanged)
// modemmanager 3gpp device
Q_PROPERTY(QString operatorCode READ operatorCode NOTIFY operatorCodeChanged)
Q_PROPERTY(QString operatorName READ operatorName NOTIFY operatorNameChanged)
Q_PROPERTY(QString registrationState READ registrationState NOTIFY registrationStateChanged)
Q_PROPERTY(QList<AvailableNetwork *> networks READ networks NOTIFY networksChanged)
Q_PROPERTY(bool isScanningNetworks READ isScanningNetworks NOTIFY isScanningNetworksChanged)
// networkmanager device
Q_PROPERTY(QString firmwareVersion READ firmwareVersion NOTIFY firmwareVersionChanged)
Q_PROPERTY(QString interfaceName READ interfaceName NOTIFY interfaceNameChanged)
Q_PROPERTY(QString metered READ metered NOTIFY meteredChanged)
public:
ModemDetails(QObject *parent = nullptr, Modem *modem = nullptr);
ModemDetails &operator=(ModemDetails &&other);
void swap(ModemDetails &other);
QStringList accessTechnologies();
QString device();
QString deviceIdentifier();
QStringList drivers();
QString equipmentIdentifier();
bool isEnabled();
QString manufacturer();
uint maxActiveBearers();
uint maxBearers();
QString model();
QStringList ownNumbers();
QString plugin();
QString powerState();
QString revision();
uint signalQuality();
QString simPath();
QString state();
QString stateFailedReason();
QString operatorCode();
QString operatorName();
QString registrationState();
Q_INVOKABLE void scanNetworks();
QList<AvailableNetwork *> networks();
bool isScanningNetworks();
void scanNetworksFinished(QDBusPendingCallWatcher *call);
QString firmwareVersion();
QString interfaceName();
QString metered();
Q_SIGNALS:
void accessTechnologiesChanged();
void deviceChanged();
void deviceIdentifierChanged();
void driversChanged();
void equipmentIdentifierChanged();
void isEnabledChanged();
void manufacturerChanged();
void modelChanged();
void ownNumbersChanged();
void pluginChanged();
void powerStateChanged();
void revisionChanged();
void signalQualityChanged();
void simPathChanged();
void stateChanged();
void stateFailedReasonChanged();
void supportedCapabilitiesChanged();
void operatorCodeChanged();
void operatorNameChanged();
void registrationStateChanged();
void networksChanged();
void isScanningNetworksChanged();
void firmwareVersionChanged();
void interfaceNameChanged();
void meteredChanged();
private:
void updateNMSignals();
Modem *m_modem;
QDBusPendingCallWatcher *m_scanNetworkWatcher;
bool m_isScanningNetworks;
QList<AvailableNetwork *> m_cachedScannedNetworks;
};
class AvailableNetwork : public QObject
{
Q_OBJECT
Q_PROPERTY(bool isCurrentlyUsed READ isCurrentlyUsed NOTIFY isCurrentlyUsedChanged)
Q_PROPERTY(QString operatorLong READ operatorLong NOTIFY operatorLongChanged)
Q_PROPERTY(QString operatorShort READ operatorShort NOTIFY operatorShortChanged)
Q_PROPERTY(QString operatorCode READ operatorCode NOTIFY operatorCodeChanged)
Q_PROPERTY(QString accessTechnology READ accessTechnology NOTIFY accessTechnologyChanged)
public:
AvailableNetwork(QObject *parent = nullptr,
ModemManager::Modem3gpp::Ptr mm3gppDevice = nullptr,
bool isCurrentlyUsed = false,
QString operatorLong = "",
QString operatorShort = "",
QString operatorCode = "",
MMModemAccessTechnology accessTechnology = MM_MODEM_ACCESS_TECHNOLOGY_UNKNOWN);
bool isCurrentlyUsed();
QString operatorLong();
QString operatorShort();
QString operatorCode();
QString accessTechnology();
Q_INVOKABLE void registerToNetwork();
Q_SIGNALS:
void isCurrentlyUsedChanged();
void operatorLongChanged();
void operatorShortChanged();
void operatorCodeChanged();
void accessTechnologyChanged();
private:
bool m_isCurrentlyUsed;
QString m_operatorLong;
QString m_operatorShort;
QString m_operatorCode;
QString m_accessTechnology;
ModemManager::Modem3gpp::Ptr m_mm3gppDevice; // this may be a nullptr if no sim is inserted
};

View file

@ -1,141 +0,0 @@
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "profilesettings.h"
#include <KLocalizedString>
ProfileSettings::ProfileSettings(QObject *parent,
QString name,
QString apn,
QString user,
QString password,
NetworkManager::GsmSetting::NetworkType networkType,
QString connectionUni)
: QObject{parent}
, m_name(name)
, m_apn(apn)
, m_user(user)
, m_password(password)
, m_networkType(networkTypeStr(networkType))
, m_connectionUni(connectionUni)
{
setParent(parent);
}
ProfileSettings::ProfileSettings(QObject *parent, NetworkManager::Setting::Ptr setting, NetworkManager::Connection::Ptr connection)
: QObject{parent}
, m_connectionUni(connection->uuid())
{
setParent(parent);
NetworkManager::GsmSetting::Ptr gsmSetting = setting.staticCast<NetworkManager::GsmSetting>();
m_name = connection->name();
m_apn = gsmSetting->apn();
m_user = gsmSetting->username();
m_password = gsmSetting->password();
m_networkType = networkTypeStr(gsmSetting->networkType());
}
QString ProfileSettings::name()
{
return m_name;
}
QString ProfileSettings::apn()
{
return m_apn;
}
void ProfileSettings::setApn(QString apn)
{
if (apn != m_apn) {
m_apn = apn;
Q_EMIT apnChanged();
}
}
QString ProfileSettings::user()
{
return m_user;
}
void ProfileSettings::setUser(QString user)
{
if (user != m_user) {
m_user = user;
Q_EMIT userChanged();
}
}
QString ProfileSettings::password()
{
return m_password;
}
void ProfileSettings::setPassword(QString password)
{
if (password != m_password) {
m_password = password;
Q_EMIT passwordChanged();
}
}
QString ProfileSettings::networkType()
{
return m_networkType;
}
void ProfileSettings::setNetworkType(QString networkType)
{
if (networkType != m_networkType) {
m_networkType = networkType;
Q_EMIT networkTypeChanged();
}
}
QString ProfileSettings::connectionUni()
{
return m_connectionUni;
}
QString ProfileSettings::networkTypeStr(NetworkManager::GsmSetting::NetworkType networkType)
{
if (networkType == NetworkManager::GsmSetting::NetworkType::Any) {
return QStringLiteral("Any");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::GprsEdgeOnly) {
return QStringLiteral("Only 2G");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::Only3G) {
return QStringLiteral("Only 3G");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::Only4GLte) {
return QStringLiteral("Only 4G");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::Prefer2G) {
return QStringLiteral("2G");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::Prefer3G) {
return QStringLiteral("3G/2G");
} else if (networkType == NetworkManager::GsmSetting::NetworkType::Prefer4GLte) {
return QStringLiteral("4G/3G/2G");
}
return QStringLiteral("Any");
}
NetworkManager::GsmSetting::NetworkType ProfileSettings::networkTypeFlag(const QString &networkType)
{
if (networkType == QStringLiteral("Any")) {
return NetworkManager::GsmSetting::NetworkType::Any;
} else if (networkType == QStringLiteral("Only 2G")) {
return NetworkManager::GsmSetting::NetworkType::GprsEdgeOnly;
} else if (networkType == QStringLiteral("Only 3G")) {
return NetworkManager::GsmSetting::NetworkType::Only3G;
} else if (networkType == QStringLiteral("Only 4G")) {
return NetworkManager::GsmSetting::NetworkType::Only4GLte;
} else if (networkType == QStringLiteral("2G")) {
return NetworkManager::GsmSetting::NetworkType::Prefer2G;
} else if (networkType == QStringLiteral("3G/2G")) {
return NetworkManager::GsmSetting::NetworkType::Prefer3G;
} else if (networkType == QStringLiteral("4G/3G/2G")) {
return NetworkManager::GsmSetting::NetworkType::Prefer4GLte;
}
return NetworkManager::GsmSetting::NetworkType::Any;
}

View file

@ -1,79 +0,0 @@
// SPDX-FileCopyrightText: 2021-2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "cellularnetworksettings.h"
#include "modemdetails.h"
#include "sim.h"
#include <QList>
#include <QString>
#include <NetworkManagerQt/CdmaSetting>
#include <NetworkManagerQt/ConnectionSettings>
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/ModemDevice>
#include <NetworkManagerQt/Settings>
#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
class ProfileSettings : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString apn READ apn WRITE setApn NOTIFY apnChanged)
Q_PROPERTY(QString user READ user WRITE setUser NOTIFY userChanged)
Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
Q_PROPERTY(QString networkType READ networkType WRITE setNetworkType NOTIFY networkTypeChanged)
Q_PROPERTY(QString connectionUni READ connectionUni NOTIFY connectionUniChanged)
public:
ProfileSettings(QObject *parent = nullptr)
: QObject{parent}
{
}
ProfileSettings(QObject *parent,
QString name,
QString apn,
QString user,
QString password,
NetworkManager::GsmSetting::NetworkType networkType,
QString connectionUni);
ProfileSettings(QObject *parent, NetworkManager::Setting::Ptr settings, NetworkManager::Connection::Ptr connection);
QString name();
QString apn();
void setApn(QString apn);
QString user();
void setUser(QString user);
QString password();
void setPassword(QString password);
QString networkType();
void setNetworkType(QString ipType);
QString connectionUni();
// utilities
static QString networkTypeStr(NetworkManager::GsmSetting::NetworkType networkType);
static NetworkManager::GsmSetting::NetworkType networkTypeFlag(const QString &networkType);
Q_SIGNALS:
void nameChanged();
void apnChanged();
void userChanged();
void passwordChanged();
void networkTypeChanged();
void connectionUniChanged();
private:
QString m_name;
QString m_apn;
QString m_user;
QString m_password;
QString m_networkType;
QString m_connectionUni;
};

View file

@ -1,201 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "sim.h"
#include <KLocalizedString>
#include <QDBusReply>
Sim::Sim(QObject *parent, Modem *modem, ModemManager::Sim::Ptr mmSim, ModemManager::Modem::Ptr mmModem, ModemManager::Modem3gpp::Ptr mmModem3gpp)
: QObject{parent}
, m_modem{modem}
, m_mmSim{mmSim}
, m_mmModem{mmModem}
, m_mmModem3gpp{mmModem3gpp}
{
if (m_mmSim) {
connect(m_mmSim.data(), &ModemManager::Sim::imsiChanged, this, [this]() -> void {
Q_EMIT imsiChanged();
});
connect(m_mmSim.data(), &ModemManager::Sim::operatorIdentifierChanged, this, [this]() -> void {
Q_EMIT operatorIdentifierChanged();
});
connect(m_mmSim.data(), &ModemManager::Sim::operatorNameChanged, this, [this]() -> void {
Q_EMIT operatorNameChanged();
});
connect(m_mmSim.data(), &ModemManager::Sim::simIdentifierChanged, this, [this]() -> void {
Q_EMIT simIdentifierChanged();
});
}
if (m_mmModem) {
connect(m_mmModem.data(), &ModemManager::Modem::unlockRequiredChanged, this, [this]() -> void {
Q_EMIT lockedChanged();
Q_EMIT lockedReasonChanged();
});
}
if (m_mmModem3gpp) {
connect(m_mmModem3gpp.data(), &ModemManager::Modem3gpp::enabledFacilityLocksChanged, this, [this]() -> void {
Q_EMIT pinEnabledChanged();
});
}
}
bool Sim::enabled()
{
return uni() != QStringLiteral("/");
}
bool Sim::pinEnabled()
{
return m_mmModem3gpp && (m_mmModem3gpp->enabledFacilityLocks() & MM_MODEM_3GPP_FACILITY_SIM);
}
int Sim::unlockRetriesLeft()
{
return m_mmModem && m_mmModem->unlockRetries()[MM_MODEM_LOCK_SIM_PIN];
}
bool Sim::locked()
{
return m_mmModem && m_mmModem->unlockRequired() == MM_MODEM_LOCK_SIM_PIN;
}
QString Sim::lockedReason()
{
if (!m_mmModem) {
return {};
}
switch (m_mmModem->unlockRequired()) {
case MM_MODEM_LOCK_UNKNOWN:
return i18n("Lock reason unknown.");
case MM_MODEM_LOCK_NONE:
return i18n("Modem is unlocked.");
case MM_MODEM_LOCK_SIM_PIN:
return i18n("SIM requires the PIN code.");
case MM_MODEM_LOCK_SIM_PIN2:
return i18n("SIM requires the PIN2 code.");
case MM_MODEM_LOCK_SIM_PUK:
return i18n("SIM requires the PUK code.");
case MM_MODEM_LOCK_SIM_PUK2:
return i18n("SIM requires the PUK2 code.");
case MM_MODEM_LOCK_PH_SP_PIN:
return i18n("Modem requires the service provider PIN code.");
case MM_MODEM_LOCK_PH_SP_PUK:
return i18n("Modem requires the service provider PUK code.");
case MM_MODEM_LOCK_PH_NET_PIN:
return i18n("Modem requires the network PIN code.");
case MM_MODEM_LOCK_PH_NET_PUK:
return i18n("Modem requires the network PUK code.");
case MM_MODEM_LOCK_PH_SIM_PIN:
return i18n("Modem requires the PIN code.");
case MM_MODEM_LOCK_PH_CORP_PIN:
return i18n("Modem requires the corporate PIN code.");
case MM_MODEM_LOCK_PH_CORP_PUK:
return i18n("Modem requires the corporate PUK code.");
case MM_MODEM_LOCK_PH_FSIM_PIN:
return i18n("Modem requires the PH-FSIM PIN code.");
case MM_MODEM_LOCK_PH_FSIM_PUK:
return i18n("Modem requires the PH-FSIM PUK code.");
case MM_MODEM_LOCK_PH_NETSUB_PIN:
return i18n("Modem requires the network subset PIN code.");
case MM_MODEM_LOCK_PH_NETSUB_PUK:
return i18n("Modem requires the network subset PUK code.");
}
return {};
}
QString Sim::imsi()
{
return m_mmSim ? m_mmSim->imsi() : QString{};
}
QString Sim::eid()
{
return {}; // TODO add in mm-qt
}
QString Sim::operatorIdentifier()
{
return m_mmSim ? m_mmSim->operatorIdentifier() : QString{};
}
QString Sim::operatorName()
{
return m_mmSim ? m_mmSim->operatorName() : QString{};
}
QString Sim::simIdentifier()
{
return m_mmSim ? m_mmSim->simIdentifier() : QString{};
}
QStringList Sim::emergencyNumbers()
{
return {}; // TODO add in mm-qt
}
QString Sim::uni()
{
return m_mmSim ? m_mmSim->uni() : QString{};
}
QString Sim::displayId()
{
// in the form /org/freedesktop/ModemManager1/Sim/0
QStringList uniSplit = uni().split(QStringLiteral("/"));
return (uniSplit.count() == 0 || uni() == "/") ? i18n("(empty)") : QString(uniSplit[uniSplit.size() - 1]);
}
Modem *Sim::modem()
{
return m_modem;
}
QCoro::Task<void> Sim::togglePinEnabled(const QString &pin)
{
bool isPinEnabled = pinEnabled();
QDBusReply<void> reply = co_await m_mmSim->enablePin(pin, !isPinEnabled);
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error toggling SIM lock to") << isPinEnabled << QStringLiteral(":") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error toggling SIM lock: %1", reply.error().message()));
}
}
QCoro::Task<void> Sim::changePin(const QString &oldPin, const QString &newPin)
{
QDBusReply<void> reply = co_await m_mmSim->changePin(oldPin, newPin);
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error changing the PIN:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error changing the PIN: %1", reply.error().message()));
}
}
QCoro::Task<void> Sim::sendPin(const QString &pin)
{
if (!m_mmModem || !m_mmSim || m_mmModem->unlockRequired() == MM_MODEM_LOCK_NONE) {
co_return;
}
QDBusReply<void> reply = co_await m_mmSim->sendPin(pin);
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error sending the PIN:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error sending the PIN: %1", reply.error().message()));
}
}
QCoro::Task<void> Sim::sendPuk(const QString &pin, const QString &puk)
{
if (!m_mmModem || !m_mmSim || m_mmModem->unlockRequired() != MM_MODEM_LOCK_NONE) {
co_return;
}
QDBusReply<void> reply = co_await m_mmSim->sendPuk(pin, puk);
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error sending the PUK:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error sending the PUK: %1", reply.error().message()));
}
}

View file

@ -1,93 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "modem.h"
#include <QList>
#include <QString>
#include <NetworkManagerQt/CdmaSetting>
#include <NetworkManagerQt/ConnectionSettings>
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/ModemDevice>
#include <NetworkManagerQt/Settings>
#include <ModemManagerQt/GenericTypes>
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
#include <QCoroDBusPendingReply>
class Modem;
class Sim : public QObject
{
Q_OBJECT
Q_PROPERTY(bool enabled READ enabled NOTIFY enabledChanged)
Q_PROPERTY(bool pinEnabled READ pinEnabled NOTIFY pinEnabledChanged) // if there is a PIN set on the SIM
Q_PROPERTY(int unlockRetriesLeft READ unlockRetriesLeft NOTIFY unlockRetriesLeftChanged)
Q_PROPERTY(bool locked READ locked NOTIFY lockedChanged) // if the SIM is currently locked (requires entering PIN)
Q_PROPERTY(QString lockedReason READ lockedReason NOTIFY lockedReasonChanged)
Q_PROPERTY(QString imsi READ imsi NOTIFY imsiChanged)
Q_PROPERTY(QString eid READ eid NOTIFY eidChanged) // TODO (not in mm-qt)
Q_PROPERTY(QString operatorIdentifier READ operatorIdentifier NOTIFY operatorIdentifierChanged)
Q_PROPERTY(QString operatorName READ operatorName NOTIFY operatorNameChanged)
Q_PROPERTY(QString simIdentifier READ simIdentifier NOTIFY simIdentifierChanged)
Q_PROPERTY(QStringList emergencyNumbers READ emergencyNumbers NOTIFY emergencyNumbersChanged)
Q_PROPERTY(QString uni READ uni NOTIFY uniChanged)
Q_PROPERTY(QString displayId READ displayId NOTIFY displayIdChanged)
Q_PROPERTY(Modem *modem READ modem NOTIFY modemChanged)
public:
Sim(QObject *parent = nullptr,
Modem *modem = nullptr,
ModemManager::Sim::Ptr mmSim = ModemManager::Sim::Ptr{nullptr},
ModemManager::Modem::Ptr mmModem = ModemManager::Modem::Ptr{nullptr},
ModemManager::Modem3gpp::Ptr mmModem3gpp = ModemManager::Modem3gpp::Ptr{nullptr});
bool enabled();
bool pinEnabled();
int unlockRetriesLeft();
bool locked();
QString lockedReason();
QString imsi();
QString eid(); // TODO add in mm-qt
QString operatorIdentifier();
QString operatorName();
QString simIdentifier();
QStringList emergencyNumbers(); // TODO add in mm-qt
QString uni();
QString displayId();
Modem *modem();
Q_INVOKABLE QCoro::Task<void> togglePinEnabled(const QString &pin);
Q_INVOKABLE QCoro::Task<void> changePin(const QString &oldPin, const QString &newPin);
Q_INVOKABLE QCoro::Task<void> sendPin(const QString &pin);
Q_INVOKABLE QCoro::Task<void> sendPuk(const QString &pin, const QString &puk);
Q_SIGNALS:
void enabledChanged();
void pinEnabledChanged();
void unlockRetriesLeftChanged();
void lockedChanged();
void lockedReasonChanged();
void imsiChanged();
void eidChanged();
void operatorIdentifierChanged();
void operatorNameChanged();
void simIdentifierChanged();
void emergencyNumbersChanged();
void uniChanged();
void displayIdChanged();
void modemChanged();
private:
Modem *m_modem;
ModemManager::Sim::Ptr m_mmSim;
ModemManager::Modem::Ptr m_mmModem;
ModemManager::Modem3gpp::Ptr m_mmModem3gpp; // this may be a nullptr if no sim is inserted
};

View file

@ -1,75 +0,0 @@
// SPDX-FileCopyrightText: 2021-2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
import org.kde.kcmutils
import org.kde.kirigamiaddons.formcard 1 as FormCard
import cellularnetworkkcm 1.0
Kirigami.ScrollablePage {
id: root
title: i18n("Available Networks")
property Modem modem
property Sim sim
ListView {
id: listView
header: ColumnLayout {
anchors.left: parent.left
anchors.right: parent.right
spacing: 0
MessagesList {
visible: count != 0
Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing
model: kcm.messages
}
}
Kirigami.PlaceholderMessage {
anchors.centerIn: parent
visible: !modem.details.isScanningNetworks && listView.count == 0
icon.name: "network-mobile-100"
text: i18n("Current operator: %1", modem.details.operatorName ? modem.details.operatorName : i18n("none"))
helpfulAction: Kirigami.Action {
icon.name: "view-refresh"
text: i18n("Scan For Networks")
enabled: !modem.details.isScanningNetworks
onTriggered: modem.details.scanNetworks()
}
}
Controls.BusyIndicator {
anchors.centerIn: parent
visible: modem.details.isScanningNetworks
implicitWidth: Kirigami.Units.iconSizes.large
implicitHeight: implicitWidth
}
model: modem.details.networks
delegate: FormCard.FormRadioDelegate {
width: listView.width
checked: modelData.isCurrentlyUsed
onClicked: {
if (!modelData.isCurrentlyUsed) {
modelData.registerToNetwork();
modem.details.scanNetworks();
}
}
text: modelData.operatorLong + " | " + modelData.operatorShort + "(" + modelData.operatorCode + ")"
description: modelData.accessTechnology
}
}
}

View file

@ -1,87 +0,0 @@
// SPDX-FileCopyrightText: 2020-2022 Devin Lin <espidev@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.12
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.12 as Controls
import org.kde.kirigami 2.19 as Kirigami
import org.kde.kirigamiaddons.formcard 1 as FormCard
import cellularnetworkkcm 1.0
FormCard.FormCardPage {
id: editProfile
title: profile != null ? i18n("Edit APN") : i18n("New APN")
topPadding: Kirigami.Units.gridUnit
bottomPadding: Kirigami.Units.gridUnit
leftPadding: 0
rightPadding: 0
property Modem modem
property ProfileSettings profile
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.gridUnit
FormCard.FormTextFieldDelegate {
id: profileName
label: i18n("Name")
text: profile != null ? profile.name : ""
}
FormCard.FormDelegateSeparator { above: profileName; below: profileApn }
FormCard.FormTextFieldDelegate {
id: profileApn
label: i18n("APN")
text: profile != null ? profile.apn : ""
}
FormCard.FormDelegateSeparator { above: profileApn; below: profileUsername }
FormCard.FormTextFieldDelegate {
id: profileUsername
label: i18n("Username")
text: profile != null ? profile.user : ""
}
FormCard.FormDelegateSeparator { above: profileUsername; below: profilePassword }
FormCard.FormTextFieldDelegate {
id: profilePassword
label: i18n("Password")
text: profile != null ? profile.password : ""
}
FormCard.FormDelegateSeparator { above: profilePassword; below: profileNetworkType }
FormCard.FormComboBoxDelegate {
id: profileNetworkType
text: i18n("Network type")
model: [i18n("4G/3G/2G"), i18n("3G/2G"), i18n("2G"), i18n("Only 4G"), i18n("Only 3G"), i18n("Only 2G"), i18n("Any")]
Component.onCompleted: {
if (profile != null) {
currentIndex = indexOfValue(profile.networkType)
}
}
}
FormCard.FormDelegateSeparator { above: profileNetworkType; below: profileSave }
FormCard.FormButtonDelegate {
id: profileSave
text: i18n("Save profile")
icon.name: "document-save"
onClicked: {
if (profile == null) { // create new profile
modem.addProfile(profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.currentText);
} else { // edit existing profile
modem.updateProfile(profile.connectionUni, profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.currentText);
}
kcm.pop()
}
}
}
}

View file

@ -1,48 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.12
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.12 as Controls
import org.kde.kirigami 2.12 as Kirigami
import cellularnetworkkcm 1.0
ColumnLayout {
id: root
property var model
property alias count: repeater.count
spacing: 0
visible: count > 0
Repeater {
id: repeater
model: root.model
delegate: Kirigami.InlineMessage {
Layout.bottomMargin: Kirigami.Units.largeSpacing
Layout.fillWidth: true
visible: true
text: modelData.message
type: {
switch (modelData.type) {
case InlineMessage.Information: return Kirigami.MessageType.Information;
case InlineMessage.Positive: return Kirigami.MessageType.Positive;
case InlineMessage.Warning: return Kirigami.MessageType.Warning;
case InlineMessage.Error: return Kirigami.MessageType.Error;
}
return Kirigami.MessageType.Error;
}
actions: [
Kirigami.Action {
icon.name: "dialog-close"
onTriggered: kcm.removeMessage(model.index)
}
]
}
}
}

View file

@ -1,279 +0,0 @@
// SPDX-FileCopyrightText: 2021-2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami 2 as Kirigami
import org.kde.kcmutils
import org.kde.kirigamiaddons.formcard 1 as FormCard
import cellularnetworkkcm
FormCard.FormCardPage {
id: modemPage
property Modem modem
property bool showExtra: false
title: i18n("Modem %1", modem.displayId)
MessagesList {
Layout.fillWidth: true
Layout.margins: Kirigami.Units.smallSpacing
visible: count != 0
model: kcm.messages
}
FormCard.FormHeader {
title: i18n("Modem Control")
}
FormCard.FormCard {
FormCard.FormButtonDelegate {
id: modemRestartButton
text: i18n("Force Modem Restart")
onClicked: modem.reset()
}
}
FormCard.FormHeader {
title: i18n("Modem Details")
}
FormCard.FormCard {
FormCard.AbstractFormDelegate {
id: accessTechnologiesText
background: null
contentItem: ColumnLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
Controls.Label {
Layout.fillWidth: true
text: i18n("Access Technologies")
elide: Text.ElideRight
}
Repeater {
model: modem.details.accessTechnologies
Controls.Label {
Layout.fillWidth: true
text: modelData
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
}
}
}
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: imeiText
text: i18n("IMEI")
description: modem.details.equipmentIdentifier
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: enabledText
text: i18n("Enabled")
description: modem.details.isEnabled
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: manufacturerText
text: i18n("Manufacturer")
description: modem.details.manufacturer
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: modelText
text: i18n("Model")
description: modem.details.model
}
FormCard.FormDelegateSeparator {}
FormCard.AbstractFormDelegate {
id: ownedNumbersText
background: null
contentItem: ColumnLayout {
spacing: Kirigami.Units.smallSpacing
Controls.Label {
Layout.fillWidth: true
text: i18n("Owned Numbers:")
elide: Text.ElideRight
}
Repeater {
model: modem.details.ownNumbers
Controls.Label {
Layout.fillWidth: true
text: modelData
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
}
}
}
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: revisionText
text: i18n("Revision")
description: modem.details.revision
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: signalQualityText
text: i18n("Signal Quality")
description: modem.details.signalQuality
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: stateText
text: i18n("State")
description: modem.details.state
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: failureReasonText
text: i18n("Failure Reason")
description: modem.details.stateFailedReason
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: registrationStateText
text: i18n("Registration State")
description: modem.details.registrationState
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: roamingText
text: i18n("Roaming")
description: modem.isRoaming ? i18n("Yes") : i18n("No")
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: firmwareVersionText
text: i18n("Firmware Version")
description: modem.details.firmwareVersion
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: interfaceNameText
text: i18n("Interface Name")
description: modem.details.interfaceName
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: meteredText
text: i18n("Metered")
description: modem.details.metered
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: activeNMConnectionText
text: i18n("Active NetworkManager Connection")
description: modem.activeConnectionUni
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: deviceText
text: i18n("Device")
description: modem.details.device
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: deviceIdText
text: i18n("Device ID")
description: modem.details.deviceIdentifier
}
FormCard.FormDelegateSeparator {}
FormCard.AbstractFormDelegate {
id: driversText
background: null
contentItem: ColumnLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
Controls.Label {
Layout.fillWidth: true
text: i18n("Drivers:")
elide: Text.ElideRight
}
Repeater {
model: modem.details.drivers
Controls.Label {
Layout.fillWidth: true
text: modelData
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
}
}
}
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: pluginText
text: i18n("Plugin")
description: modem.details.plugin
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: powerStateText
text: i18n("Power State")
description: modem.details.powerState
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: simPathText
text: i18n("SIM Path")
description: modem.details.simPath
}
}
}

View file

@ -1,123 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.kirigami as Kirigami
import cellularnetworkkcm
import org.kde.kirigamiaddons.formcard 1 as FormCard
Kirigami.ScrollablePage {
id: root
topPadding: Kirigami.Units.gridUnit
bottomPadding: Kirigami.Units.gridUnit
leftPadding: 0
rightPadding: 0
property Modem modem
property bool editMode: false
title: i18n("APNs")
actions: [
Kirigami.Action {
text: i18n("Edit")
icon.name: 'entry-edit'
checkable: true
onCheckedChanged: root.editMode = checked
}
]
ColumnLayout {
spacing: 0
MessagesList {
id: messagesList
visible: count != 0
Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing
model: kcm.messages
}
Kirigami.InlineMessage {
id: cannotFindWarning
Layout.margins: visible ? Kirigami.Units.largeSpacing : 0
Layout.topMargin: visible && !messagesList.visible ? Kirigami.Units.largeSpacing : 0
Layout.fillWidth: true
visible: false
type: Kirigami.MessageType.Warning
showCloseButton: true
text: i18n("Unable to autodetect connection settings for your carrier. Please find your carrier's APN settings by either contacting support or searching online.")
Connections {
target: modem
function onCouldNotAutodetectSettings() {
cannotFindWarning.visible = true;
}
}
}
FormCard.FormHeader {
title: i18n("APN List")
}
FormCard.FormCard {
Repeater {
id: profilesRepeater
model: modem.profiles
delegate: FormCard.FormRadioDelegate {
text: modelData.name
description: modelData.apn
checked: modem.activeConnectionUni == modelData.connectionUni
onClicked: {
modem.activateProfile(modelData.connectionUni);
// reapply binding
checked = Qt.binding(() => { return modem.activeConnectionUni == modelData.connectionUni });
}
trailing: RowLayout {
Controls.ToolButton {
visible: root.editMode
icon.name: "entry-edit"
text: i18n("Edit")
display: Controls.ToolButton.IconOnly
onClicked: {
kcm.push("EditProfilePage.qml", { "profile": modelData, "modem": modem });
}
}
Controls.ToolButton {
visible: root.editMode
icon.name: "delete"
text: i18n("Delete")
display: Controls.ToolButton.IconOnly
onClicked: modem.removeProfile(modelData.connectionUni)
}
}
}
}
FormCard.FormButtonDelegate {
text: i18n("Add APN")
icon.name: 'list-add'
onClicked: {
kcm.push("EditProfilePage.qml", { "profile": null, "modem": modem });
}
}
FormCard.FormButtonDelegate {
text: i18n("Automatically detect APN")
icon.name: 'list-add'
onClicked: {
modem.addDetectedProfileSettings();
}
}
}
}
}

View file

@ -1,233 +0,0 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.12 as Controls
import org.kde.kirigami 2.19 as Kirigami
import org.kde.kcmutils
import org.kde.kirigamiaddons.formcard 1.0 as FormCard
import cellularnetworkkcm 1.0
FormCard.FormCardPage {
id: root
property Sim sim
title: i18n("SIM Lock")
MessagesList {
Layout.fillWidth: true
Layout.margins: Kirigami.Units.gridUnit
model: kcm.messages
}
ColumnLayout {
id: unlockSimPlaceholder
visible: sim.locked
// HACK: prevent infinite binding loop?
Component.onCompleted: unlockSimPlaceholder.Layout.preferredHeight = root.height
Kirigami.PlaceholderMessage {
Layout.margins: Kirigami.Units.gridUnit * 2
Layout.fillWidth: true
Layout.fillHeight: true
text: i18n("SIM is locked")
explanation: i18n("In order to use this SIM, you must first unlock it.")
icon.name: "lock"
helpfulAction: Kirigami.Action {
icon.name: "unlock"
text: "Unlock SIM"
onTriggered: unlockPinDialog.open() // TODO replace custom unlock pin dialog with just opening the system unlock PIN dialog
}
}
}
ColumnLayout {
id: notLockedSimPlaceholder
visible: !sim.pinEnabled && !unlockSimPlaceholder.visible
Layout.fillWidth: true
// HACK: prevent infinite binding loop?
Component.onCompleted: notLockedSimPlaceholder.Layout.preferredHeight = root.height
Kirigami.PlaceholderMessage {
Layout.margins: Kirigami.Units.gridUnit * 2
Layout.fillWidth: true
Layout.fillHeight: true
text: i18n("SIM is not locked")
explanation: i18n("You can lock your SIM to require a set PIN code for phone calls and mobile data.")
icon.name: "unlock"
helpfulAction: Kirigami.Action {
icon.name: "lock"
text: i18n("Lock SIM")
onTriggered: createPinDialog.open()
}
}
}
FormCard.FormCard {
visible: !notLockedSimPlaceholder.visible && !unlockSimPlaceholder.visible
Layout.fillWidth: true
FormCard.FormButtonDelegate {
id: disableSimLockButton
text: i18n("Disable SIM Lock")
description: i18n("Disable the SIM lock feature and remove the passcode on the SIM.")
onClicked: removePinDialog.open();
}
Kirigami.Separator {
Layout.leftMargin: Kirigami.Units.largeSpacing
Layout.rightMargin: Kirigami.Units.largeSpacing
opacity: (!disableSimLockButton.controlHovered && !changePinButton.controlHovered) ? 0.5 : 0
}
FormCard.FormButtonDelegate {
id: changePinButton
text: i18n("Change PIN")
description: i18n("Change the passcode set on the SIM.")
onClicked: changePinDialog.open()
}
}
data: [
RegularExpressionValidator {
id: pinValidator
regularExpression: /[0-9]+/
},
// dialogs
Kirigami.Dialog {
id: unlockPinDialog
title: i18n("Unlock SIM")
standardButtons: Controls.Dialog.Ok | Controls.Dialog.Cancel
padding: Kirigami.Units.largeSpacing
onAccepted: sim.sendPin(unlockPinCurPin.text)
ColumnLayout {
Controls.Label {
text: i18n("Attempts left: %1", sim.unlockRetriesLeft)
}
Kirigami.PasswordField {
id: unlockPinCurPin
placeholderText: i18n("Enter PIN")
validator: pinValidator
}
}
},
Kirigami.Dialog {
id: changePinDialog
title: i18n("Change SIM PIN")
standardButtons: isValid ? Controls.Dialog.Ok | Controls.Dialog.Cancel : Controls.Dialog.Cancel
padding: Kirigami.Units.largeSpacing
property bool isValid: changePinNewPin.text == changePinConfirmPin.text &&
changePinNewPin.text.length >= 4 && changePinNewPin.text.length <= 8 // SIM PINs are between 4-8 digits
onAccepted: {
if (isValid) {
sim.changePin(changePinCurPin.text, changePinNewPin.text);
}
}
ColumnLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.InlineMessage {
id: changePinMatch
Layout.fillWidth: true
visible: changePinNewPin.text != changePinConfirmPin.text
text: i18n("PINs don't match!")
type: Kirigami.MessageType.Error
}
Kirigami.InlineMessage {
Layout.fillWidth: true
visible: !changePinMatch.visible && changePinNewPin.text.length != 0 && (changePinNewPin.text.length < 4 || changePinNewPin.text.length > 8)
text: i18n("PINs must be between 4 and 8 digits!")
type: Kirigami.MessageType.Error
}
Kirigami.PasswordField {
id: changePinCurPin
placeholderText: i18n("Current PIN")
validator: pinValidator
}
Kirigami.PasswordField {
id: changePinNewPin
placeholderText: i18n("New PIN")
validator: pinValidator
}
Kirigami.PasswordField {
id: changePinConfirmPin
placeholderText: i18n("Confirm PIN")
validator: pinValidator
}
}
},
Kirigami.Dialog {
id: removePinDialog
title: i18n("Remove SIM PIN")
standardButtons: Controls.Dialog.Ok | Controls.Dialog.Cancel
padding: Kirigami.Units.largeSpacing
onAccepted: sim.togglePinEnabled(removePinCurPin.text);
ColumnLayout {
Kirigami.PasswordField {
id: removePinCurPin
placeholderText: i18n("Current PIN")
validator: pinValidator
}
}
},
Kirigami.Dialog {
id: createPinDialog
title: i18n("Add SIM PIN")
standardButtons: isValid ? Controls.Dialog.Ok | Controls.Dialog.Cancel : Controls.Dialog.Cancel
padding: Kirigami.Units.largeSpacing
property bool isValid: createPinNewPin.text == createPinConfirmPin.text &&
createPinNewPin.text.length >= 4 && createPinNewPin.text.length <= 8 // SIM PINs are between 4-8 digits
onAccepted: {
if (isValid) {
sim.togglePinEnabled(createPinNewPin.text);
}
}
ColumnLayout {
spacing: Kirigami.Units.smallSpacing
Kirigami.InlineMessage {
id: createPinMatch
Layout.fillWidth: true
visible: createPinNewPin.text != createPinConfirmPin.text
text: i18n("PINs don't match!")
type: Kirigami.MessageType.Error
}
Kirigami.InlineMessage {
Layout.fillWidth: true
visible: !createPinMatch.visible && createPinNewPin.text.length != 0 && (createPinNewPin.text.length < 4 || createPinNewPin.text.length > 8)
text: i18n("PINs must be between 4 and 8 digits!")
type: Kirigami.MessageType.Error
}
Kirigami.PasswordField {
id: createPinNewPin
placeholderText: i18n("New PIN")
validator: pinValidator
}
Kirigami.PasswordField {
id: createPinConfirmPin
placeholderText: i18n("Confirm PIN")
validator: pinValidator
}
}
}
]
}

View file

@ -1,208 +0,0 @@
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as Controls
import org.kde.plasma.networkmanagement as PlasmaNM
import org.kde.kcmutils
import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard 1 as FormCard
import org.kde.kirigamiaddons.components 1 as Components
import cellularnetworkkcm 1.0
FormCard.FormCardPage {
id: simPage
property Sim sim: null
property string displayId: sim ? sim.displayId : ""
property bool simEnabled: sim ? sim.enabled : false
property bool isRoaming: sim ? (sim.modem ? sim.modem.isRoaming : false) : false
property bool simLocked: sim ? sim.locked : false
property string simImsi: sim ? sim.imsi : ""
property string simEid: sim ? sim.eid : ""
property string operatorCode: sim ? (sim.modem ? sim.modem.details.operatorCode : "") : ""
property string operatorName: sim ? (sim.modem ? sim.modem.details.operatorName : "") : ""
property string simOperatorIdentifier: sim ? sim.operatorIdentifier : ""
property string simOperatorName: sim ? sim.operatorName : ""
property string simIdentifier: sim ? sim.simIdentifier : ""
property var simEmergencyNumbers: sim ? sim.emergencyNumbers : []
title: i18n("SIM") + " " + displayId
data: PlasmaNM.EnabledConnections {
id: enabledConnections
}
header: Components.Banner {
width: parent.width
visible: !simEnabled
type: Kirigami.MessageType.Error
text: i18n("This SIM slot is empty, a SIM card needs to be inserted in order for it to be used.")
}
MessagesList {
id: messagesList
Layout.fillWidth: true
Layout.margins: Kirigami.Units.gridUnit
model: kcm.messages
}
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.gridUnit
FormCard.FormSwitchDelegate {
id: dataRoamingCheckBox
text: i18n("Data Roaming")
description: i18n("Allow your device to use networks other than your carrier.")
enabled: simEnabled
checked: isRoaming
onCheckedChanged: sim.modem.isRoaming = checked
}
FormCard.FormDelegateSeparator { above: dataRoamingCheckBox; below: apnButton }
FormCard.FormButtonDelegate {
id: apnButton
icon.name: "globe"
text: i18n("Modify APNs")
description: i18n("Configure access point names for your carrier.")
enabled: simEnabled
onClicked: kcm.push("ProfileList.qml", { "modem": sim.modem });
}
FormCard.FormDelegateSeparator { above: apnButton; below: networksButton }
FormCard.FormButtonDelegate {
id: networksButton
icon.name: "network-mobile-available"
text: i18n("Networks")
description: i18n("Select a network operator.")
enabled: simEnabled
onClicked: kcm.push("AvailableNetworks.qml", { "modem": sim.modem, "sim": sim });
}
FormCard.FormDelegateSeparator { above: networksButton; below: simLockButton }
FormCard.FormButtonDelegate {
id: simLockButton
icon.name: "unlock"
text: i18n("SIM Lock")
description: i18n("Modify SIM lock settings.")
enabled: simEnabled
onClicked: kcm.push("SimLockPage.qml", { "sim": sim });
}
FormCard.FormDelegateSeparator { above: simLockButton; below: modemDetailsButton }
FormCard.FormButtonDelegate {
id: modemDetailsButton
icon.name: "network-modem"
text: i18n("Modem Details")
description: i18n("View the details of the modem this SIM is connected to.")
onClicked: kcm.push("ModemPage.qml", { "modem": sim.modem })
}
}
FormCard.FormHeader {
title: i18n("SIM Details")
}
FormCard.FormCard {
FormCard.FormTextDelegate {
id: lockedText
text: i18n("Locked")
description: simLocked ? i18n("Yes") : i18n("No")
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: imsiText
text: i18n("IMSI")
description: simImsi
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: eidText
text: i18n("EID")
description: simEid
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: opCodeModemText
text: i18n("Operator Code (modem)")
description: operatorCode
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: opNameModemText
text: i18n("Operator Name (modem)")
description: operatorName
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: opCodeSimText
text: i18n("Operator Code (provided by SIM)")
description: simOperatorIdentifier
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: opNameSimText
text: i18n("Operator Name (provided by SIM)")
description: simOperatorName
}
FormCard.FormDelegateSeparator {}
FormCard.FormTextDelegate {
id: simIdText
text: i18n("SIM ID")
description: simIdentifier
}
FormCard.FormDelegateSeparator {}
FormCard.AbstractFormDelegate {
id: emergencyNumbersText
background: null
contentItem: ColumnLayout {
Layout.fillWidth: true
spacing: Kirigami.Units.smallSpacing
Controls.Label {
Layout.fillWidth: true
text: i18n("Emergency Numbers")
elide: Text.ElideRight
}
Repeater {
model: simEmergencyNumbers
Controls.Label {
Layout.fillWidth: true
text: modelData
color: Kirigami.Theme.disabledTextColor
font: Kirigami.Theme.smallFont
elide: Text.ElideRight
}
}
}
}
}
}

View file

@ -1,156 +0,0 @@
// SPDX-FileCopyrightText: 2018 Martin Kacej <m.kacej@atlas.sk>
// SPDX-FileCopyrightText: 2020 Dimitris Kardarakos <dimkard@posteo.net>
// SPDX-FileCopyrightText: 2021-2022 Devin Lin <espidev@gmail.com>
// SPDX-FileCopyrightText: 2023 Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick 2.12
import QtQuick.Layouts 1.2
import QtQuick.Controls 2.12 as Controls
import org.kde.plasma.networkmanagement as PlasmaNM
import org.kde.kirigami as Kirigami
import org.kde.kcmutils as KCM
import org.kde.kirigamiaddons.formcard 1 as FormCard
import cellularnetworkkcm 1.0
KCM.SimpleKCM {
id: root
objectName: "mobileDataMain"
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
PlasmaNM.Handler {
id: nmHandler
}
PlasmaNM.AvailableDevices {
id: availableDevices
}
PlasmaNM.EnabledConnections {
id: enabledConnections
}
SimPage {
id: simPage
visible: false
}
Kirigami.PlaceholderMessage {
id: noModem
anchors.centerIn: parent
width: parent.width - Kirigami.Units.gridUnit * 4
visible: !enabledConnections.wwanHwEnabled || !availableDevices.modemDeviceAvailable || !kcm.modemFound
icon.name: "auth-sim-missing"
text: i18n("Modem not available")
}
ColumnLayout {
spacing: 0
width: root.width
visible: !noModem.visible
MessagesList {
Layout.fillWidth: true
Layout.margins: Kirigami.Units.largeSpacing
model: kcm.messages
}
FormCard.FormCard {
Layout.topMargin: Kirigami.Units.gridUnit
FormCard.FormSwitchDelegate {
id: mobileDataSwitch
text: i18n("Mobile data")
description: {
if (!kcm.modemFound) {
return "";
} else if (!kcm.selectedModem.hasSim) {
return i18n("No SIM is inserted.")
} if (!kcm.selectedModem.mobileDataSupported) {
return i18n("Mobile data is not available with this modem.")
} else if (kcm.selectedModem.needsAPNAdded) {
return i18n("An APN needs to be configured to have mobile data.");
} else {
return i18n("Whether mobile data is enabled.");
}
}
property bool manuallySet: false
property bool shouldBeChecked: kcm.selectedModem && kcm.selectedModem.mobileDataEnabled
onShouldBeCheckedChanged: {
checked = shouldBeChecked;
}
enabled: kcm.selectedModem && kcm.selectedModem.mobileDataSupported && !kcm.selectedModem.needsAPNAdded
checked: shouldBeChecked
onCheckedChanged: {
// prevent binding loops
if (manuallySet) {
manuallySet = false;
return;
}
if (kcm.selectedModem.mobileDataEnabled != checked) {
manuallySet = true;
kcm.selectedModem.mobileDataEnabled = checked;
}
}
}
FormCard.FormDelegateSeparator { above: mobileDataSwitch; below: dataUsageButton }
FormCard.FormButtonDelegate {
id: dataUsageButton
text: i18n("Data Usage")
description: i18n("View data usage.")
icon.name: "office-chart-bar"
enabled: false
}
}
FormCard.FormHeader {
title: i18np("SIM", "SIMs", kcm.sims.count)
visible: repeater.count > 0
}
FormCard.FormCard {
visible: repeater.count > 0
Repeater {
id: repeater
model: kcm.sims
delegate: ColumnLayout {
Layout.fillWidth: true
FormCard.FormDelegateSeparator {
visible: model.index !== 0
opacity: (!(model.index && repeater.itemAt(model.index - 1).controlHovered) && !simDelegate.controlHovered) ? 0.5 : 0
}
FormCard.FormButtonDelegate {
id: simDelegate
text: i18n("SIM %1", modelData.displayId)
description: i18n("View SIM %1 details.", modelData.displayId)
icon.name: "auth-sim-symbolic"
onClicked: {
simPage.sim = modelData;
simPage.visible = true;
kcm.push(simPage);
}
}
}
}
}
}
}