File indexing completed on 2024-04-28 16:52:22
0001 // SPDX-FileCopyrightText: 2021 Tobias Fella <fella@posteo.de> 0002 // SPDX-FileCopyrightText: 2022 Devin Lin <devin@kde.org> 0003 // SPDX-License-Identifier: GPL-2.0-or-later 0004 0005 #include <NetworkManagerQt/GsmSetting> 0006 #include <NetworkManagerQt/Manager> 0007 #include <NetworkManagerQt/Settings> 0008 #include <NetworkManagerQt/Utils> 0009 0010 #include "signalindicator.h" 0011 0012 SignalIndicator::SignalIndicator(QObject *parent) 0013 : QObject{parent} 0014 , m_nmModem{nullptr} 0015 , m_modemDevice{nullptr} 0016 , m_modem{nullptr} 0017 , m_3gppModem{nullptr} 0018 { 0019 connect(ModemManager::notifier(), &ModemManager::Notifier::modemAdded, this, &SignalIndicator::updateModemManagerModem); 0020 connect(ModemManager::notifier(), &ModemManager::Notifier::modemRemoved, this, &SignalIndicator::updateModemManagerModem); 0021 0022 connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionAdded, this, &SignalIndicator::mobileDataEnabledChanged); 0023 connect(NetworkManager::settingsNotifier(), &NetworkManager::SettingsNotifier::connectionRemoved, this, &SignalIndicator::mobileDataEnabledChanged); 0024 connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionAdded, this, &SignalIndicator::mobileDataEnabledChanged); 0025 connect(NetworkManager::notifier(), &NetworkManager::Notifier::activeConnectionRemoved, this, &SignalIndicator::mobileDataEnabledChanged); 0026 connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &SignalIndicator::updateNetworkManagerModem); 0027 connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceRemoved, this, &SignalIndicator::updateNetworkManagerModem); 0028 0029 updateModemManagerModem(); 0030 } 0031 0032 int SignalIndicator::strength() const 0033 { 0034 if (!m_modem) { 0035 return 0; 0036 } 0037 return m_modem->signalQuality().signal; 0038 } 0039 0040 QString SignalIndicator::name() const 0041 { 0042 return m_3gppModem ? m_3gppModem->operatorName() : QString(); 0043 } 0044 0045 bool SignalIndicator::modemAvailable() const 0046 { 0047 return !m_modem.isNull(); 0048 } 0049 0050 bool SignalIndicator::simLocked() const 0051 { 0052 if (!m_modem) { 0053 return false; 0054 } 0055 return m_modem->unlockRequired() == MM_MODEM_LOCK_SIM_PIN; 0056 } 0057 0058 bool SignalIndicator::simEmpty() const 0059 { 0060 return !m_modemDevice || !m_modemDevice->sim() || (m_modemDevice->sim()->uni() == QStringLiteral("/")); 0061 } 0062 0063 bool SignalIndicator::mobileDataSupported() const 0064 { 0065 return m_nmModem && !simEmpty(); 0066 } 0067 0068 bool SignalIndicator::mobileDataEnabled() const 0069 { 0070 // no modem -> no mobile data -> report disabled 0071 if (!m_nmModem) { 0072 return false; 0073 } 0074 0075 // mobile data already activated -> report enabled 0076 if (m_nmModem->state() == NetworkManager::Device::Activated) { 0077 return true; 0078 } 0079 0080 // autoconnect disabled on the entire modem -> report disabled 0081 if (!m_nmModem->autoconnect()) { 0082 return false; 0083 } 0084 0085 // at least one connection set to autoconnect -> report enabled 0086 for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) { 0087 if (con->settings()->autoconnect()) { 0088 return true; 0089 } 0090 } 0091 0092 // modem, but no connection, set to autoconnect -> report disabled (#182) 0093 return false; 0094 } 0095 0096 bool SignalIndicator::needsAPNAdded() const 0097 { 0098 return m_nmModem && mobileDataSupported() && m_nmModem->availableConnections().count() == 0; 0099 } 0100 0101 void SignalIndicator::setMobileDataEnabled(bool enabled) 0102 { 0103 if (!m_nmModem) { 0104 return; 0105 } 0106 if (!enabled) { 0107 m_nmModem->setAutoconnect(false); 0108 // we need to also set all connections to not autoconnect (#182) 0109 for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) { 0110 con->settings()->setAutoconnect(false); 0111 con->update(con->settings()->toMap()); 0112 } 0113 m_nmModem->disconnectInterface(); 0114 } else { 0115 m_nmModem->setAutoconnect(true); 0116 // activate the connection that was last used 0117 QDateTime latestTimestamp; 0118 NetworkManager::Connection::Ptr latestCon; 0119 for (NetworkManager::Connection::Ptr con : m_nmModem->availableConnections()) { 0120 QDateTime timestamp = con->settings()->timestamp(); 0121 // if con was not used yet, skip it, otherwise: 0122 // if we have no latestTimestamp yet, con is the latest 0123 // otherwise, compare the timestamps 0124 // in case of a tie, use the first connection that was found 0125 if (!timestamp.isNull() && (latestTimestamp.isNull() || timestamp > latestTimestamp)) { 0126 latestTimestamp = timestamp; 0127 latestCon = con; 0128 } 0129 } 0130 // if we found the last used connection 0131 if (!latestCon.isNull()) { 0132 // set it to autoconnect and connect it immediately 0133 latestCon->settings()->setAutoconnect(true); 0134 latestCon->update(latestCon->settings()->toMap()); 0135 NetworkManager::activateConnection(latestCon->path(), m_nmModem->uni(), ""); 0136 } 0137 } 0138 } 0139 0140 void SignalIndicator::updateModemManagerModem() 0141 { 0142 m_modemDevice = nullptr; 0143 m_modem = nullptr; 0144 m_3gppModem = nullptr; 0145 0146 if (ModemManager::modemDevices().isEmpty()) { 0147 qWarning() << "No modems available"; 0148 return; 0149 } 0150 0151 // TODO: we assume that there is a single modem for the time being 0152 m_modemDevice = ModemManager::modemDevices()[0]; 0153 m_modem = m_modemDevice->modemInterface(); 0154 m_3gppModem = m_modemDevice->interface(ModemManager::ModemDevice::GsmInterface).objectCast<ModemManager::Modem3gpp>(); 0155 0156 connect(m_modemDevice->sim().get(), &ModemManager::Sim::simIdentifierChanged, this, &SignalIndicator::simEmptyChanged); 0157 0158 if (m_modem) { 0159 connect(m_modem.get(), &ModemManager::Modem::signalQualityChanged, this, &SignalIndicator::strengthChanged); 0160 connect(m_modem.get(), &ModemManager::Modem::unlockRequiredChanged, this, &SignalIndicator::simLockedChanged); 0161 } 0162 if (m_3gppModem) { 0163 connect(m_3gppModem.get(), &ModemManager::Modem3gpp::operatorNameChanged, this, &SignalIndicator::nameChanged); 0164 } 0165 0166 updateNetworkManagerModem(); 0167 0168 Q_EMIT nameChanged(); 0169 Q_EMIT strengthChanged(); 0170 Q_EMIT modemAvailableChanged(); 0171 } 0172 0173 void SignalIndicator::updateNetworkManagerModem() 0174 { 0175 m_nmModem = nullptr; 0176 if (!m_modemDevice) { 0177 return; 0178 } 0179 0180 // find networkmanager modem 0181 for (NetworkManager::Device::Ptr nmDevice : NetworkManager::networkInterfaces()) { 0182 if (nmDevice->udi() == m_modemDevice->uni()) { 0183 m_nmModem = nmDevice.objectCast<NetworkManager::ModemDevice>(); 0184 0185 connect(m_nmModem.get(), &NetworkManager::Device::autoconnectChanged, this, &SignalIndicator::mobileDataEnabledChanged); 0186 connect(m_nmModem.get(), &NetworkManager::Device::stateChanged, this, &SignalIndicator::mobileDataEnabledChanged); 0187 connect(m_nmModem.get(), &NetworkManager::Device::availableConnectionAppeared, this, &SignalIndicator::mobileDataEnabledChanged); 0188 connect(m_nmModem.get(), &NetworkManager::Device::availableConnectionDisappeared, this, &SignalIndicator::mobileDataEnabledChanged); 0189 } 0190 } 0191 0192 Q_EMIT mobileDataSupportedChanged(); 0193 Q_EMIT mobileDataEnabledChanged(); 0194 }