kcms/cellularnetwork: Port to qcoro to make it async

Fixes https://invent.kde.org/plasma/plasma-mobile/-/issues/284
This commit is contained in:
Devin Lin 2023-12-14 21:15:39 -08:00
parent 71eb05e624
commit 30262da8a5
7 changed files with 130 additions and 120 deletions

View file

@ -77,6 +77,9 @@ find_package(KWayland CONFIG REQUIRED)
find_package(PkgConfig REQUIRED)
find_package(QCoro6 REQUIRED COMPONENTS DBus)
qcoro_enable_coroutines()
pkg_check_modules(GOBJECT gobject-2.0 REQUIRED IMPORTED_TARGET)
pkg_check_modules(GIO gio-2.0 REQUIRED IMPORTED_TARGET)

View file

@ -22,4 +22,5 @@ target_link_libraries(kcm_cellular_network PRIVATE
KF6::NetworkManagerQt
KF6::ModemManagerQt
KF6::KCMUtilsQuick
QCoro::DBus
)

View file

@ -7,6 +7,9 @@
#include <KLocalizedString>
#include <KUser>
#include <QDBusReply>
#include <QCoroDBusPendingReply>
Modem::Modem(QObject *parent)
: QObject{parent}
@ -116,12 +119,13 @@ QString Modem::activeConnectionUni() const
return QString();
}
void Modem::reset()
QCoro::Task<void> Modem::reset()
{
qDebug() << QStringLiteral("Resetting the modem...");
QDBusPendingReply<void> reply = m_mmInterface->reset();
reply.waitForFinished();
if (reply.isError()) {
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()));
}
@ -207,51 +211,43 @@ void Modem::setMobileDataEnabled(bool enabled)
bool Modem::isRoaming() const
{
if (!m_nmModem) {
if (!m_nmModem || !m_nmModem->activeConnection() || !m_nmModem->activeConnection()->connection()) {
return false;
}
if (m_nmModem->activeConnection() && m_nmModem->activeConnection()->connection()) {
auto connection = m_nmModem->activeConnection()->connection();
NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
if (gsmSetting) {
return !gsmSetting->homeOnly();
}
}
auto connection = m_nmModem->activeConnection()->connection();
NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
return false;
return gsmSetting ? !gsmSetting->homeOnly() : false;
}
void Modem::setIsRoaming(bool roaming)
QCoro::Task<void> Modem::setIsRoaming(bool roaming)
{
if (!m_nmModem) {
return;
if (!m_nmModem || !m_nmModem->activeConnection() || !m_nmModem->activeConnection()->connection()) {
co_return;
}
if (m_nmModem->activeConnection() && m_nmModem->activeConnection()->connection()) {
auto connection = m_nmModem->activeConnection()->connection();
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
NetworkManager::GsmSetting::Ptr gsmSetting = connection->settings()->setting(NetworkManager::Setting::Gsm).dynamicCast<NetworkManager::GsmSetting>();
if (gsmSetting) {
gsmSetting->setHomeOnly(!roaming); // set roaming setting
QDBusPendingReply reply = connection->update(connection->settings()->toMap());
reply.waitForFinished();
if (reply.isError()) {
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(".");
}
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();
}
// the connection uni has changed, refresh the profiles list
refreshProfiles();
Q_EMIT activeConnectionUniChanged();
}
bool Modem::hasSim() const
@ -287,11 +283,11 @@ void Modem::refreshProfiles()
Q_EMIT profileListChanged();
}
void Modem::activateProfile(const QString &connectionUni)
QCoro::Task<void> Modem::activateProfile(const QString &connectionUni)
{
if (!m_nmModem) {
qWarning() << "Cannot activate profile since there is no NetworkManager modem";
return;
co_return;
}
qDebug() << QStringLiteral("Activating profile on modem") << m_nmModem->uni() << QStringLiteral("for connection") << connectionUni << ".";
@ -313,28 +309,27 @@ void Modem::activateProfile(const QString &connectionUni)
if (!con) {
qDebug() << QStringLiteral("Connection") << connectionUni << QStringLiteral("not found.");
return;
co_return;
}
// activate connection manually
// despite the documentation saying otherwise, activateConnection seems to need the DBus path, not uuid of the connection
QDBusPendingReply<QDBusObjectPath> reply = NetworkManager::activateConnection(con->path(), m_nmModem->uni(), "");
reply.waitForFinished();
if (reply.isError()) {
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()));
return;
co_return;
}
// set roaming settings separately (since it changes the uni)
setIsRoaming(roaming);
co_await setIsRoaming(roaming);
}
void Modem::addProfile(QString name, QString apn, QString username, QString password, QString networkType)
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";
return;
co_return;
}
NetworkManager::ConnectionSettings::Ptr settings{new NetworkManager::ConnectionSettings(NetworkManager::ConnectionSettings::Gsm)};
@ -353,9 +348,8 @@ void Modem::addProfile(QString name, QString apn, QString username, QString pass
gsmSetting->setInitialized(true);
QDBusPendingReply<QDBusObjectPath> reply = NetworkManager::addAndActivateConnection(settings->toMap(), m_nmModem->uni(), "");
reply.waitForFinished();
if (reply.isError()) {
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 {
@ -363,34 +357,33 @@ void Modem::addProfile(QString name, QString apn, QString username, QString pass
}
}
void Modem::removeProfile(const QString &connectionUni)
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!");
return;
co_return;
}
QDBusPendingReply reply = con->remove();
reply.waitForFinished();
if (reply.isError()) {
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()));
}
}
void Modem::updateProfile(QString connectionUni, QString name, QString apn, QString username, QString password, QString networkType)
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!");
return;
co_return;
}
NetworkManager::ConnectionSettings::Ptr conSettings = con->settings();
if (!conSettings) {
qWarning() << QStringLiteral("Could not find connection settings for") << connectionUni << QStringLiteral("to update!");
return;
co_return;
}
conSettings->setId(name);
@ -405,9 +398,8 @@ void Modem::updateProfile(QString connectionUni, QString name, QString apn, QStr
gsmSetting->setInitialized(true);
QDBusPendingReply reply = con->update(conSettings->toMap());
reply.waitForFinished();
if (reply.isError()) {
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,

View file

@ -23,6 +23,8 @@
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
#include <QCoroDBusPendingReply>
class ProfileSettings;
class Sim;
class AvailableNetwork;
@ -55,7 +57,7 @@ public:
QString uni() const;
QString activeConnectionUni() const;
Q_INVOKABLE void reset();
Q_INVOKABLE QCoro::Task<void> reset();
bool mobileDataEnabled() const;
void setMobileDataEnabled(bool enabled);
@ -63,16 +65,16 @@ public:
bool needsAPNAdded() const;
bool isRoaming() const;
void setIsRoaming(bool roaming);
QCoro::Task<void> setIsRoaming(bool roaming);
bool hasSim() const;
// connection profiles
QList<ProfileSettings *> &profileList();
void refreshProfiles();
Q_INVOKABLE void activateProfile(const QString &connectionUni);
Q_INVOKABLE void addProfile(QString name, QString apn, QString username, QString password, QString networkType);
Q_INVOKABLE void removeProfile(const QString &connectionUni);
Q_INVOKABLE void updateProfile(QString connectionUni, QString name, QString apn, QString username, QString password, QString networkType);
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();

View file

@ -5,6 +5,8 @@
#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}
@ -12,23 +14,27 @@ Sim::Sim(QObject *parent, Modem *modem, ModemManager::Sim::Ptr mmSim, ModemManag
, m_mmModem{mmModem}
, m_mmModem3gpp{mmModem3gpp}
{
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_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();
});
}
connect(m_mmModem.data(), &ModemManager::Modem::unlockRequiredChanged, this, [this]() -> void {
Q_EMIT lockedChanged();
Q_EMIT lockedReasonChanged();
});
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 {
@ -49,16 +55,20 @@ bool Sim::pinEnabled()
int Sim::unlockRetriesLeft()
{
return m_mmModem->unlockRetries()[MM_MODEM_LOCK_SIM_PIN];
return m_mmModem && m_mmModem->unlockRetries()[MM_MODEM_LOCK_SIM_PIN];
}
bool Sim::locked()
{
return m_mmModem->unlockRequired() == MM_MODEM_LOCK_SIM_PIN;
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.");
@ -95,32 +105,32 @@ QString Sim::lockedReason()
case MM_MODEM_LOCK_PH_NETSUB_PUK:
return i18n("Modem requires the network subset PUK code.");
}
return QString{};
return {};
}
QString Sim::imsi()
{
return m_mmSim->imsi();
return m_mmSim ? m_mmSim->imsi() : QString{};
}
QString Sim::eid()
{
return ""; // TODO add in mm-qt
return {}; // TODO add in mm-qt
}
QString Sim::operatorIdentifier()
{
return m_mmSim->operatorIdentifier();
return m_mmSim ? m_mmSim->operatorIdentifier() : QString{};
}
QString Sim::operatorName()
{
return m_mmSim->operatorName();
return m_mmSim ? m_mmSim->operatorName() : QString{};
}
QString Sim::simIdentifier()
{
return m_mmSim->simIdentifier();
return m_mmSim ? m_mmSim->simIdentifier() : QString{};
}
QStringList Sim::emergencyNumbers()
@ -130,7 +140,7 @@ QStringList Sim::emergencyNumbers()
QString Sim::uni()
{
return m_mmSim->uni();
return m_mmSim ? m_mmSim->uni() : QString{};
}
QString Sim::displayId()
@ -145,47 +155,47 @@ Modem *Sim::modem()
return m_modem;
}
void Sim::togglePinEnabled(const QString &pin)
QCoro::Task<void> Sim::togglePinEnabled(const QString &pin)
{
bool isPinEnabled = pinEnabled();
QDBusPendingReply reply = m_mmSim->enablePin(pin, !isPinEnabled);
reply.waitForFinished();
if (reply.isError()) {
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()));
}
}
void Sim::changePin(const QString &oldPin, const QString &newPin)
QCoro::Task<void> Sim::changePin(const QString &oldPin, const QString &newPin)
{
QDBusPendingReply reply = m_mmSim->changePin(oldPin, newPin);
reply.waitForFinished();
if (reply.isError()) {
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()));
}
}
void Sim::sendPin(const QString &pin)
QCoro::Task<void> Sim::sendPin(const QString &pin)
{
if (m_mmModem->unlockRequired() != MM_MODEM_LOCK_NONE) {
QDBusPendingReply reply = m_mmSim->sendPin(pin);
reply.waitForFinished();
if (reply.isError()) {
qWarning() << QStringLiteral("Error sending the PIN:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error sending the PIN: %1", reply.error().message()));
}
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()));
}
}
void Sim::sendPuk(const QString &pin, const QString &puk)
QCoro::Task<void> Sim::sendPuk(const QString &pin, const QString &puk)
{
if (m_mmModem->unlockRequired() != MM_MODEM_LOCK_NONE) {
QDBusPendingReply reply = m_mmSim->sendPuk(pin, puk);
reply.waitForFinished();
if (reply.isError()) {
qWarning() << QStringLiteral("Error sending the PUK:") << reply.error().message();
CellularNetworkSettings::instance()->addMessage(InlineMessage::Error, i18n("Error sending the PUK: %1", reply.error().message()));
}
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

@ -20,6 +20,8 @@
#include <ModemManagerQt/Modem3Gpp>
#include <ModemManagerQt/ModemDevice>
#include <QCoroDBusPendingReply>
class Modem;
class Sim : public QObject
@ -62,10 +64,10 @@ public:
QString displayId();
Modem *modem();
Q_INVOKABLE void togglePinEnabled(const QString &pin);
Q_INVOKABLE void changePin(const QString &oldPin, const QString &newPin);
Q_INVOKABLE void sendPin(const QString &pin);
Q_INVOKABLE void sendPuk(const QString &pin, const QString &puk);
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();

View file

@ -89,7 +89,7 @@ KCM.SimpleKCM {
checked = shouldBeChecked;
}
enabled: kcm.selectedModem.mobileDataSupported && !kcm.selectedModem.needsAPNAdded
enabled: kcm.selectedModem && kcm.selectedModem.mobileDataSupported && !kcm.selectedModem.needsAPNAdded
checked: shouldBeChecked
onCheckedChanged: {