mmplugin: Remove and port to plasma-nm cellular lib

Replace mmplugin with shared plasma-nm cellular library: https://invent.kde.org/plasma/plasma-nm/-/merge_requests/522
This commit is contained in:
Devin Lin 2026-02-11 23:19:36 -05:00
parent 1705d6c187
commit 23833a6b54
10 changed files with 90 additions and 779 deletions

View file

@ -4,7 +4,6 @@
add_subdirectory(waydroidintegrationplugin) add_subdirectory(waydroidintegrationplugin)
add_subdirectory(hapticsplugin) add_subdirectory(hapticsplugin)
add_subdirectory(mmplugin)
add_subdirectory(mobileshell) add_subdirectory(mobileshell)
add_subdirectory(mobileshellstate) add_subdirectory(mobileshellstate)
add_subdirectory(quicksettingsplugin) add_subdirectory(quicksettingsplugin)

View file

@ -1,21 +0,0 @@
# SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
# SPDX-License-Identifier: GPL-2.0-or-later
ecm_add_qml_module(ppc-mmqmlplugin URI org.kde.plasma.mm GENERATE_PLUGIN_SOURCE)
target_sources(ppc-mmqmlplugin PRIVATE
signalindicator.cpp
profilesettings.cpp
)
target_link_libraries(ppc-mmqmlplugin PRIVATE
Qt::Qml
KF6::ModemManagerQt
KF6::NetworkManagerQt
KF6::CoreAddons
KF6::I18n
QCoro::DBus
)
ecm_finalize_qml_module(ppc-mmqmlplugin)

View file

@ -1,139 +0,0 @@
// SPDX-FileCopyrightText: 2022 Devin Lin <espidev@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "profilesettings.h"
#include <KLocalizedString>
ProfileSettings::ProfileSettings(QObject *parent,
const QString &name,
const QString &apn,
const QString &user,
const QString &password,
NetworkManager::GsmSetting::NetworkType networkType,
const 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())
{
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() const
{
return m_name;
}
QString ProfileSettings::apn() const
{
return m_apn;
}
void ProfileSettings::setApn(const QString &apn)
{
if (apn != m_apn) {
m_apn = apn;
Q_EMIT apnChanged();
}
}
QString ProfileSettings::user() const
{
return m_user;
}
void ProfileSettings::setUser(const QString &user)
{
if (user != m_user) {
m_user = user;
Q_EMIT userChanged();
}
}
QString ProfileSettings::password() const
{
return m_password;
}
void ProfileSettings::setPassword(const QString &password)
{
if (password != m_password) {
m_password = password;
Q_EMIT passwordChanged();
}
}
QString ProfileSettings::networkType() const
{
return m_networkType;
}
void ProfileSettings::setNetworkType(const QString &networkType)
{
if (networkType != m_networkType) {
m_networkType = networkType;
Q_EMIT networkTypeChanged();
}
}
QString ProfileSettings::connectionUni() const
{
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,75 +0,0 @@
// SPDX-FileCopyrightText: 2021-2023 Devin Lin <espidev@gmail.com>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#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,
const QString &name,
const QString &apn,
const QString &user,
const QString &password,
NetworkManager::GsmSetting::NetworkType networkType,
const QString &connectionUni);
ProfileSettings(QObject *parent, NetworkManager::Setting::Ptr settings, NetworkManager::Connection::Ptr connection);
QString name() const;
QString apn() const;
void setApn(const QString &apn);
QString user() const;
void setUser(const QString &user);
QString password() const;
void setPassword(const QString &password);
QString networkType() const;
void setNetworkType(const QString &ipType);
QString connectionUni() const;
// 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,405 +0,0 @@
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
// SPDX-FileCopyrightText: 2022-2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "signalindicator.h"
#include <NetworkManagerQt/GsmSetting>
#include <NetworkManagerQt/Manager>
#include <NetworkManagerQt/Settings>
#include <NetworkManagerQt/Utils>
#include <QDBusReply>
#include <QPointer>
#include <KUser>
#include "signalindicator.h"
SignalIndicator::SignalIndicator(QObject *parent)
: QObject{parent}
, m_nmModem{nullptr}
, m_modemDevice{nullptr}
, m_modem{nullptr}
, m_3gppModem{nullptr}
{
connect(ModemManager::notifier(), &ModemManager::Notifier::modemAdded, this, &SignalIndicator::updateModemManagerModem);
connect(ModemManager::notifier(), &ModemManager::Notifier::modemRemoved, this, &SignalIndicator::updateModemManagerModem);
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &SignalIndicator::mobileDataEnabledChanged);
connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionRemoved, this, &SignalIndicator::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &SignalIndicator::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionRemoved, this, &SignalIndicator::mobileDataEnabledChanged);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &SignalIndicator::updateNetworkManagerModem);
connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &SignalIndicator::updateNetworkManagerModem);
updateModemManagerModem();
}
int SignalIndicator::strength() const
{
if (!m_modem) {
return 0;
}
return m_modem->signalQuality().signal;
}
QString SignalIndicator::name() const
{
return m_3gppModem ? m_3gppModem->operatorName() : QString();
}
bool SignalIndicator::modemAvailable() const
{
return !m_modem.isNull();
}
bool SignalIndicator::simLocked() const
{
if (!m_modem) {
return false;
}
return m_modem->unlockRequired() == MM_MODEM_LOCK_SIM_PIN;
}
bool SignalIndicator::simEmpty() const
{
return !m_modemDevice || !m_modemDevice->sim() || (m_modemDevice->sim()->uni() == QStringLiteral("/"));
}
bool SignalIndicator::mobileDataSupported() const
{
return m_nmModem && !simEmpty();
}
bool SignalIndicator::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 (#182)
return false;
}
bool SignalIndicator::needsAPNAdded() const
{
return m_nmModem && mobileDataSupported() && m_nmModem->availableConnections().count() == 0;
}
void SignalIndicator::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();
}
}
QString SignalIndicator::activeConnectionUni() const
{
if (m_nmModem && m_nmModem->activeConnection() && m_nmModem->activeConnection()->connection()) {
return m_nmModem->activeConnection()->connection()->uuid();
}
return QString();
}
QList<ProfileSettings *> &SignalIndicator::profileList()
{
return m_profileList;
}
void SignalIndicator::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> SignalIndicator::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 << ".";
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
QPointer<SignalIndicator> guard(this);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::activateConnection(con->path(), m_nmModem->uni(), {});
if (!guard) {
co_return;
}
if (!reply.isValid()) {
qWarning() << QStringLiteral("Error activating connection:") << reply.error().message();
co_return;
}
}
QCoro::Task<void> SignalIndicator::addProfile(const QString &name, const QString &apn, const QString &username, const QString &password, const 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->setInitialized(true);
QPointer<SignalIndicator> guard(this);
QDBusReply<QDBusObjectPath> reply = co_await NetworkManager::addAndActivateConnection(settings->toMap(), m_nmModem->uni(), {});
if (!guard) {
co_return;
}
if (!reply.isValid()) {
qWarning() << "Error adding connection:" << reply.error().message();
} else {
qDebug() << "Successfully added a new connection" << name << "with APN" << apn << ".";
}
}
QCoro::Task<void> SignalIndicator::removeProfile(const QString &connectionUni)
{
NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionUni);
if (!con) {
qWarning() << "Could not find connection" << connectionUni << "to update!";
co_return;
}
QPointer<SignalIndicator> guard(this);
QDBusPendingReply reply = co_await con->remove();
if (!guard) {
co_return;
}
if (!reply.isValid()) {
qWarning() << "Error removing connection" << reply.error().message();
}
}
QCoro::Task<void> SignalIndicator::updateProfile(const QString &connectionUni,
const QString &name,
const QString &apn,
const QString &username,
const QString &password,
const QString &networkType)
{
NetworkManager::Connection::Ptr con = NetworkManager::findConnectionByUuid(connectionUni);
if (!con) {
qWarning() << "Could not find connection" << connectionUni << "to update!";
co_return;
}
NetworkManager::ConnectionSettings::Ptr conSettings = con->settings();
if (!conSettings) {
qWarning() << "Could not find connection settings for" << connectionUni << "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.isEmpty() ? NetworkManager::Setting::NotRequired : NetworkManager::Setting::AgentOwned);
gsmSetting->setNetworkType(ProfileSettings::networkTypeFlag(networkType));
gsmSetting->setInitialized(true);
QPointer<SignalIndicator> guard(this);
QDBusPendingReply reply = co_await con->update(conSettings->toMap());
if (!guard) {
co_return;
}
if (!reply.isValid()) {
qWarning() << "Error updating connection settings for" << connectionUni << ":" << reply.error().message() << ".";
} else {
qDebug() << "Successfully updated connection settings" << connectionUni << ".";
}
}
void SignalIndicator::updateModemManagerModem()
{
m_modemDevice = nullptr;
m_modem = nullptr;
m_3gppModem = nullptr;
if (ModemManager::modemDevices().isEmpty()) {
qWarning() << "No modems available";
return;
}
// TODO: we assume that there is a single modem for the time being
m_modemDevice = ModemManager::modemDevices()[0];
m_modem = m_modemDevice->modemInterface();
m_3gppModem = m_modemDevice->interface(ModemManager::ModemDevice::GsmInterface).objectCast<ModemManager::Modem3gpp>();
connect(m_modemDevice->sim().get(), &ModemManager::Sim::simIdentifierChanged, this, &SignalIndicator::simEmptyChanged);
if (m_modem) {
connect(m_modem.get(), &ModemManager::Modem::signalQualityChanged, this, &SignalIndicator::strengthChanged);
connect(m_modem.get(), &ModemManager::Modem::unlockRequiredChanged, this, &SignalIndicator::simLockedChanged);
}
if (m_3gppModem) {
connect(m_3gppModem.get(), &ModemManager::Modem3gpp::operatorNameChanged, this, &SignalIndicator::nameChanged);
}
updateNetworkManagerModem();
Q_EMIT nameChanged();
Q_EMIT strengthChanged();
Q_EMIT modemAvailableChanged();
}
void SignalIndicator::updateNetworkManagerModem()
{
m_nmModem = nullptr;
if (!m_modemDevice) {
return;
}
// find networkmanager modem
for (NetworkManager::Device::Ptr nmDevice : NetworkManager::networkInterfaces()) {
if (nmDevice->udi() == m_modemDevice->uni()) {
m_nmModem = nmDevice.objectCast<NetworkManager::ModemDevice>();
connect(m_nmModem.get(), &NetworkManager::Device::autoconnectChanged, this, &SignalIndicator::mobileDataEnabledChanged);
connect(m_nmModem.get(), &NetworkManager::Device::stateChanged, this, &SignalIndicator::mobileDataEnabledChanged);
connect(m_nmModem.get(), &NetworkManager::Device::availableConnectionAppeared, this, &SignalIndicator::mobileDataEnabledChanged);
connect(m_nmModem.get(), &NetworkManager::Device::availableConnectionDisappeared, this, &SignalIndicator::mobileDataEnabledChanged);
connect(m_nmModem.data(), &NetworkManager::ModemDevice::availableConnectionChanged, this, &SignalIndicator::refreshProfiles);
connect(m_nmModem.data(), &NetworkManager::ModemDevice::activeConnectionChanged, this, [this]() -> void {
refreshProfiles();
Q_EMIT activeConnectionUniChanged();
});
refreshProfiles();
}
}
Q_EMIT mobileDataSupportedChanged();
Q_EMIT mobileDataEnabledChanged();
}

View file

@ -1,88 +0,0 @@
// SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de>
// SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <ModemManagerQt/Manager>
#include <ModemManagerQt/Modem3Gpp>
#include <NetworkManagerQt/Connection>
#include <NetworkManagerQt/ModemDevice>
#include <QCoroDBusPendingReply>
#include <QObject>
#include <qqmlregistration.h>
#include "profilesettings.h"
// We make the assumption that there is only one modem.
class SignalIndicator : public QObject
{
Q_OBJECT
QML_ELEMENT
QML_SINGLETON
Q_PROPERTY(int strength READ strength NOTIFY strengthChanged)
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(bool modemAvailable READ modemAvailable NOTIFY modemAvailableChanged)
Q_PROPERTY(bool simLocked READ simLocked NOTIFY simLockedChanged)
Q_PROPERTY(bool simEmpty READ simEmpty NOTIFY simEmptyChanged)
Q_PROPERTY(bool mobileDataSupported READ mobileDataSupported NOTIFY mobileDataSupportedChanged)
Q_PROPERTY(bool mobileDataEnabled READ mobileDataEnabled WRITE setMobileDataEnabled NOTIFY mobileDataEnabledChanged)
Q_PROPERTY(bool needsAPNAdded READ needsAPNAdded NOTIFY mobileDataEnabledChanged)
Q_PROPERTY(QList<ProfileSettings *> profiles READ profileList NOTIFY profileListChanged)
Q_PROPERTY(QString activeConnectionUni READ activeConnectionUni NOTIFY activeConnectionUniChanged)
public:
SignalIndicator(QObject *parent = nullptr);
int strength() const;
QString name() const;
bool modemAvailable() const;
bool simLocked() const;
bool simEmpty() const;
bool mobileDataSupported() const;
bool mobileDataEnabled() const;
bool needsAPNAdded() const;
QString activeConnectionUni() const;
void setMobileDataEnabled(bool enabled);
// connection profiles
QList<ProfileSettings *> &profileList();
void refreshProfiles();
Q_INVOKABLE QCoro::Task<void> activateProfile(const QString &connectionUni);
Q_INVOKABLE QCoro::Task<void> addProfile(const QString &name, const QString &apn, const QString &username, const QString &password, const QString &networkType);
Q_INVOKABLE QCoro::Task<void> removeProfile(const QString &connectionUni);
Q_INVOKABLE QCoro::Task<void> updateProfile(const QString &connectionUni,
const QString &name,
const QString &apn,
const QString &username,
const QString &password,
const QString &networkType);
Q_SIGNALS:
void strengthChanged();
void nameChanged();
void modemAvailableChanged();
void simLockedChanged();
void simEmptyChanged();
void mobileDataSupportedChanged();
void mobileDataEnabledChanged();
void profileListChanged();
void activeConnectionUniChanged();
private:
NetworkManager::ModemDevice::Ptr m_nmModem;
ModemManager::ModemDevice::Ptr m_modemDevice;
ModemManager::Modem::Ptr m_modem;
ModemManager::Modem3gpp::Ptr m_3gppModem;
QList<ProfileSettings *> m_profileList;
void updateModemManagerModem();
void updateNetworkManagerModem();
};

View file

@ -9,13 +9,18 @@
pragma Singleton pragma Singleton
import QtQuick 2.1 import QtQuick 2.1
import org.kde.plasma.mm import org.kde.plasma.networkmanagement.cellular as Cellular
QtObject { QtObject {
readonly property string icon: "network-mobile-" + Math.floor(SignalIndicator.strength / 20) * 20 property Cellular.CellularModemList _modemList: Cellular.CellularModemList {}
readonly property string label: SignalIndicator.simLocked ? i18n("SIM Locked") : SignalIndicator.name readonly property string icon: "network-mobile-" + Math.floor((_modemList.primaryModem ? _modemList.primaryModem.signalStrength : 0) / 20) * 20
readonly property bool showIndicator: SignalIndicator.modemAvailable readonly property string label: {
if (!_modemList.primaryModem) return "";
if (_modemList.primaryModem.simLocked) return i18n("SIM Locked");
return _modemList.primaryModem.operatorName;
}
readonly property bool showIndicator: _modemList.modemAvailable
} }

View file

@ -7,22 +7,44 @@ import QtQuick.Controls 2.12 as Controls
import org.kde.kirigami 2.19 as Kirigami import org.kde.kirigami 2.19 as Kirigami
import org.kde.plasma.mm as PlasmaMM import org.kde.plasma.networkmanagement.cellular as Cellular
Kirigami.Dialog { Kirigami.Dialog {
id: dialog id: dialog
title: i18n("Edit APN") title: editConnectionUni ? i18n("Edit APN") : i18n("Add APN")
clip: true clip: true
property var profile property Cellular.CellularModem modem
property string editConnectionUni: ""
// Look up the profile data from the model when editing
property int _profileIndex: modem && editConnectionUni ? modem.profiles.indexOfConnection(editConnectionUni) : -1
standardButtons: Controls.Dialog.Ok | Controls.Dialog.Cancel standardButtons: Controls.Dialog.Ok | Controls.Dialog.Cancel
onOpened: {
if (_profileIndex >= 0) {
let idx = modem.profiles.index(_profileIndex, 0);
profileName.text = modem.profiles.data(idx, Cellular.CellularConnectionProfile.ConnectionName) ?? "";
profileApn.text = modem.profiles.data(idx, Cellular.CellularConnectionProfile.ConnectionAPN) ?? "";
profileUsername.text = modem.profiles.data(idx, Cellular.CellularConnectionProfile.ConnectionUser) ?? "";
profilePassword.text = modem.profiles.data(idx, Cellular.CellularConnectionProfile.ConnectionPassword) ?? "";
let nt = modem.profiles.data(idx, Cellular.CellularConnectionProfile.ConnectionNetworkType) ?? "";
profileNetworkType.currentIndex = profileNetworkType.indexOfValue(nt);
} else {
profileName.text = "";
profileApn.text = "";
profileUsername.text = "";
profilePassword.text = "";
profileNetworkType.currentIndex = 0;
}
}
onAccepted: { onAccepted: {
if (profile === null) { // create new profile if (!editConnectionUni) {
PlasmaMM.SignalIndicator.addProfile(profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.value); modem.addProfile(profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.currentValue);
} else { // edit existing profile } else {
PlasmaMM.SignalIndicator.updateProfile(profile.connectionUni, profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.value); modem.updateProfile(editConnectionUni, profileName.text, profileApn.text, profileUsername.text, profilePassword.text, profileNetworkType.currentValue);
} }
} }
preferredWidth: Kirigami.Units.gridUnit * 20 preferredWidth: Kirigami.Units.gridUnit * 20
@ -36,30 +58,23 @@ Kirigami.Dialog {
Controls.TextField { Controls.TextField {
id: profileName id: profileName
Kirigami.FormData.label: i18n("Name") Kirigami.FormData.label: i18n("Name")
text: profile !== null ? profile.name : ""
} }
Controls.TextField { Controls.TextField {
id: profileApn id: profileApn
Kirigami.FormData.label: i18n("APN") Kirigami.FormData.label: i18n("APN")
text: profile != null ? profile.apn : ""
} }
Controls.TextField { Controls.TextField {
id: profileUsername id: profileUsername
Kirigami.FormData.label: i18n("Username") Kirigami.FormData.label: i18n("Username")
text: profile != null ? profile.user : ""
} }
Controls.TextField { Controls.TextField {
id: profilePassword id: profilePassword
Kirigami.FormData.label: i18n("Password") Kirigami.FormData.label: i18n("Password")
text: profile != null ? profile.password : ""
} }
Controls.ComboBox { Controls.ComboBox {
id: profileNetworkType id: profileNetworkType
Kirigami.FormData.label: i18n("Network type") Kirigami.FormData.label: i18n("Network type")
model: [i18n("4G/3G/2G"), i18n("3G/2G"), i18n("2G"), i18n("Only 4G"), i18n("Only 3G"), i18n("Only 2G"), i18n("Any")] 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);
}
} }
} }
} }

View file

@ -7,30 +7,35 @@ import QtQuick.Layouts
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.kirigamiaddons.formcard 1 as FormCard import org.kde.kirigamiaddons.formcard 1 as FormCard
import org.kde.plasma.mm as PlasmaMM import org.kde.plasma.networkmanagement.cellular as Cellular
import org.kde.plasma.mobileinitialstart.initialstart import org.kde.plasma.mobileinitialstart.initialstart
InitialStartModule { InitialStartModule {
name: i18n("Cellular") name: i18n("Cellular")
available: PlasmaMM.SignalIndicator.modemAvailable available: modemList.modemAvailable
contentItem: Item { contentItem: Item {
id: root id: root
Cellular.CellularModemList {
id: modemList
}
property Cellular.CellularModem modem: modemList.primaryModem
readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2) readonly property real cardWidth: Math.min(Kirigami.Units.gridUnit * 30, root.width - Kirigami.Units.gridUnit * 2)
function toggleMobileData() { function toggleMobileData() {
if (PlasmaMM.SignalIndicator.needsAPNAdded || !PlasmaMM.SignalIndicator.mobileDataSupported) { if (!root.modem || root.modem.needsAPNAdded || !root.modem.mobileDataSupported) {
// open settings if unable to toggle mobile data
MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network"); MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network");
} else { } else {
PlasmaMM.SignalIndicator.mobileDataEnabled = !PlasmaMM.SignalIndicator.mobileDataEnabled; root.modem.mobileDataEnabled = !root.modem.mobileDataEnabled;
} }
} }
EditProfileDialog { EditProfileDialog {
id: profileDialog id: profileDialog
profile: null modem: root.modem
} }
ColumnLayout { ColumnLayout {
@ -51,11 +56,13 @@ InitialStartModule {
wrapMode: Text.Wrap wrapMode: Text.Wrap
horizontalAlignment: Text.AlignHCenter horizontalAlignment: Text.AlignHCenter
text: { text: {
if (PlasmaMM.SignalIndicator.needsAPNAdded) { if (!root.modem) {
return i18n("Your device does not have a modem available.");
} else if (root.modem.needsAPNAdded) {
return i18n("Please configure your APN below for mobile data, further information will be available with your carrier."); return i18n("Please configure your APN below for mobile data, further information will be available with your carrier.");
} else if (PlasmaMM.SignalIndicator.mobileDataSupported) { } else if (root.modem.mobileDataSupported) {
return i18n("You are connected to the mobile network."); return i18n("You are connected to the mobile network.");
} else if (PlasmaMM.SignalIndicator.simEmpty) { } else if (root.modem.simEmpty) {
return i18n("Please insert a SIM card into your device."); return i18n("Please insert a SIM card into your device.");
} else { } else {
return i18n("Your device does not have a modem available."); return i18n("Your device does not have a modem available.");
@ -64,16 +71,16 @@ InitialStartModule {
} }
FormCard.FormCard { FormCard.FormCard {
visible: PlasmaMM.SignalIndicator.modemAvailable && PlasmaMM.SignalIndicator.mobileDataSupported visible: root.modem && root.modem.mobileDataSupported
maximumWidth: root.cardWidth maximumWidth: root.cardWidth
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
FormCard.FormSwitchDelegate { FormCard.FormSwitchDelegate {
text: i18n("Mobile Data") text: i18n("Mobile Data")
checked: PlasmaMM.SignalIndicator.mobileDataEnabled checked: root.modem ? root.modem.mobileDataEnabled : false
onCheckedChanged: { onCheckedChanged: {
if (checked !== PlasmaMM.SignalIndicator.mobileDataEnabled) { if (root.modem && checked !== root.modem.mobileDataEnabled) {
root.toggleMobileData(); root.toggleMobileData();
} }
} }
@ -81,7 +88,7 @@ InitialStartModule {
} }
FormCard.FormCard { FormCard.FormCard {
visible: PlasmaMM.SignalIndicator.modemAvailable && !PlasmaMM.SignalIndicator.simEmpty visible: root.modem && !root.modem.simEmpty
maximumWidth: root.cardWidth maximumWidth: root.cardWidth
Layout.fillHeight: true Layout.fillHeight: true
@ -95,18 +102,23 @@ InitialStartModule {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
model: PlasmaMM.SignalIndicator.profiles model: root.modem ? root.modem.profiles : null
delegate: FormCard.FormRadioDelegate { delegate: FormCard.FormRadioDelegate {
required property int index
required property string connectionName
required property string connectionAPN
required property string connectionUni
width: listView.width width: listView.width
text: modelData.name text: connectionName
description: modelData.apn description: connectionAPN
checked: modem.activeConnectionUni == modelData.connectionUni checked: root.modem && root.modem.activeConnectionUni === connectionUni
onCheckedChanged: { onCheckedChanged: {
if (checked) { if (checked && root.modem) {
PlasmaMM.SignalIndicator.activateProfile(modelData.connectionUni); root.modem.activateProfile(connectionUni);
checked = Qt.binding(() => { return modem.activeConnectionUni == modelData.connectionUni }); checked = Qt.binding(() => { return root.modem && root.modem.activeConnectionUni === connectionUni });
} }
} }
@ -115,14 +127,14 @@ InitialStartModule {
icon.name: "entry-edit" icon.name: "entry-edit"
text: i18n("Edit") text: i18n("Edit")
onClicked: { onClicked: {
profileDialog.profile = modelData; profileDialog.editConnectionUni = connectionUni;
profileDialog.open(); profileDialog.open();
} }
} }
ToolButton { ToolButton {
icon.name: "delete" icon.name: "delete"
text: i18n("Delete") text: i18n("Delete")
onClicked: PlasmaMM.SignalIndicator.removeProfile(modelData.connectionUni) onClicked: root.modem.removeProfile(connectionUni)
} }
} }
} }
@ -132,7 +144,7 @@ InitialStartModule {
icon.name: "list-add" icon.name: "list-add"
text: i18n("Add APN") text: i18n("Add APN")
onClicked: { onClicked: {
profileDialog.profile = null; profileDialog.editConnectionUni = "";
profileDialog.open(); profileDialog.open();
} }
} }

View file

@ -3,21 +3,29 @@
import QtQuick 2.15 import QtQuick 2.15
import org.kde.plasma.mm as PlasmaMM import org.kde.plasma.networkmanagement.cellular as Cellular
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS
QS.QuickSetting { QS.QuickSetting {
id: root
Cellular.CellularModemList {
id: modemList
}
property Cellular.CellularModem modem: modemList.primaryModem
text: i18n("Mobile Data") text: i18n("Mobile Data")
icon: "network-modem" icon: "network-modem"
status: { status: {
if (!PlasmaMM.SignalIndicator.modemAvailable) { if (!modemList.modemAvailable) {
return i18n("Not Available"); return i18n("Not Available");
} else if (PlasmaMM.SignalIndicator.needsAPNAdded) { } else if (modem.needsAPNAdded) {
return i18n("APN needs to be configured in the settings"); return i18n("APN needs to be configured in the settings");
} else if (PlasmaMM.SignalIndicator.mobileDataSupported) { } else if (modem.mobileDataSupported) {
return enabled ? i18n("On") : i18n("Off"); return enabled ? i18n("On") : i18n("Off");
} else if (PlasmaMM.SignalIndicator.simEmpty) { } else if (modem.simEmpty) {
return i18n("No SIM inserted"); return i18n("No SIM inserted");
} else { } else {
return i18n("Not Available"); return i18n("Not Available");
@ -25,14 +33,14 @@ QS.QuickSetting {
} }
settingsCommand: "plasma-open-settings kcm_cellular_network" settingsCommand: "plasma-open-settings kcm_cellular_network"
enabled: PlasmaMM.SignalIndicator.mobileDataEnabled enabled: modem ? modem.mobileDataEnabled : false
function toggle() { function toggle() {
if (PlasmaMM.SignalIndicator.needsAPNAdded || !PlasmaMM.SignalIndicator.mobileDataSupported) { if (!modem || modem.needsAPNAdded || !modem.mobileDataSupported) {
// open settings if unable to toggle mobile data // open settings if unable to toggle mobile data
MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network"); MobileShell.ShellUtil.executeCommand("plasma-open-settings kcm_cellular_network");
} else { } else {
PlasmaMM.SignalIndicator.mobileDataEnabled = !PlasmaMM.SignalIndicator.mobileDataEnabled; modem.mobileDataEnabled = !modem.mobileDataEnabled;
} }
} }
} }