File indexing completed on 2024-04-21 16:20:06
0001 /* 0002 SPDX-FileCopyrightText: 2009 Will Stephenson <wstephenson@kde.org> 0003 SPDX-FileCopyrightText: 2013 Daniel Nicoletti <dantti12@gmail.com> 0004 SPDX-FileCopyrightText: 2013 Lukas Tinkl <ltinkl@redhat.com> 0005 SPDX-FileCopyrightText: 2013 Jan Grulich <jgrulich@redhat.com> 0006 0007 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0008 */ 0009 0010 #include "notification.h" 0011 #include "plasma_nm_kded.h" 0012 0013 #include <uiutils.h> 0014 0015 #include <NetworkManagerQt/Manager> 0016 0017 #include <KLocalizedString> 0018 #include <KNotification> 0019 0020 #include <QDBusConnection> 0021 #include <QIcon> 0022 #include <QTimer> 0023 0024 #include <algorithm> 0025 #include <chrono> 0026 0027 using namespace std::chrono_literals; 0028 0029 Notification::Notification(QObject *parent) 0030 : QObject(parent) 0031 { 0032 // devices 0033 for (const NetworkManager::Device::Ptr &device : NetworkManager::networkInterfaces()) { 0034 addDevice(device); 0035 } 0036 0037 connect(NetworkManager::notifier(), &NetworkManager::Notifier::deviceAdded, this, &Notification::deviceAdded); 0038 0039 // connections 0040 for (const NetworkManager::ActiveConnection::Ptr &ac : NetworkManager::activeConnections()) { 0041 addActiveConnection(ac); 0042 } 0043 0044 connect(NetworkManager::notifier(), 0045 &NetworkManager::Notifier::activeConnectionAdded, 0046 this, 0047 QOverload<const QString &>::of(&Notification::addActiveConnection)); 0048 0049 QDBusConnection::systemBus().connect(QStringLiteral("org.freedesktop.login1"), 0050 QStringLiteral("/org/freedesktop/login1"), 0051 QStringLiteral("org.freedesktop.login1.Manager"), 0052 QStringLiteral("PrepareForSleep"), 0053 this, 0054 SLOT(onPrepareForSleep(bool))); 0055 0056 // After 10 seconds we can consider it to not have "just launched" anymore 0057 QTimer::singleShot(10s, this, [this]() { 0058 m_justLaunched = false; 0059 }); 0060 } 0061 0062 void Notification::deviceAdded(const QString &uni) 0063 { 0064 NetworkManager::Device::Ptr device = NetworkManager::findNetworkInterface(uni); 0065 addDevice(device); 0066 } 0067 0068 void Notification::addDevice(const NetworkManager::Device::Ptr &device) 0069 { 0070 connect(device.data(), &NetworkManager::Device::stateChanged, this, &Notification::stateChanged); 0071 } 0072 0073 void Notification::stateChanged(NetworkManager::Device::State newstate, 0074 NetworkManager::Device::State oldstate, 0075 NetworkManager::Device::StateChangeReason reason) 0076 { 0077 Q_UNUSED(oldstate) 0078 0079 auto device = qobject_cast<NetworkManager::Device *>(sender()); 0080 if (newstate == NetworkManager::Device::Activated && m_notifications.contains(device->uni())) { 0081 KNotification *notify = m_notifications.value(device->uni()); 0082 notify->close(); 0083 return; 0084 } else if (newstate != NetworkManager::Device::Failed) { 0085 return; 0086 } 0087 0088 const QString identifier = UiUtils::prettyInterfaceName(device->type(), device->interfaceName()); 0089 QString text; 0090 switch (reason) { 0091 case NetworkManager::Device::NoReason: 0092 case NetworkManager::Device::UnknownReason: 0093 case NetworkManager::Device::NowManagedReason: 0094 case NetworkManager::Device::NowUnmanagedReason: 0095 return; 0096 case NetworkManager::Device::ConfigFailedReason: 0097 text = i18nc("@info:status Notification when the device failed due to ConfigFailedReason", "The device could not be configured"); 0098 break; 0099 case NetworkManager::Device::ConfigUnavailableReason: 0100 text = i18nc("@info:status Notification when the device failed due to ConfigUnavailableReason", "IP configuration was unavailable"); 0101 break; 0102 case NetworkManager::Device::ConfigExpiredReason: 0103 text = i18nc("@info:status Notification when the device failed due to ConfigExpiredReason", "IP configuration expired"); 0104 break; 0105 case NetworkManager::Device::NoSecretsReason: 0106 text = i18nc("@info:status Notification when the device failed due to NoSecretsReason", "No secrets were provided"); 0107 break; 0108 case NetworkManager::Device::AuthSupplicantDisconnectReason: 0109 text = i18nc("@info:status Notification when the device failed due to AuthSupplicantDisconnectReason", "Authorization supplicant disconnected"); 0110 break; 0111 case NetworkManager::Device::AuthSupplicantConfigFailedReason: 0112 text = i18nc("@info:status Notification when the device failed due to AuthSupplicantConfigFailedReason", 0113 "Authorization supplicant's configuration failed"); 0114 break; 0115 case NetworkManager::Device::AuthSupplicantFailedReason: 0116 text = i18nc("@info:status Notification when the device failed due to AuthSupplicantFailedReason", "Authorization supplicant failed"); 0117 break; 0118 case NetworkManager::Device::AuthSupplicantTimeoutReason: 0119 text = i18nc("@info:status Notification when the device failed due to AuthSupplicantTimeoutReason", "Authorization supplicant timed out"); 0120 break; 0121 case NetworkManager::Device::PppStartFailedReason: 0122 text = i18nc("@info:status Notification when the device failed due to PppStartFailedReason", "PPP failed to start"); 0123 break; 0124 case NetworkManager::Device::PppDisconnectReason: 0125 text = i18nc("@info:status Notification when the device failed due to PppDisconnectReason", "PPP disconnected"); 0126 break; 0127 case NetworkManager::Device::PppFailedReason: 0128 text = i18nc("@info:status Notification when the device failed due to PppFailedReason", "PPP failed"); 0129 break; 0130 case NetworkManager::Device::DhcpStartFailedReason: 0131 text = i18nc("@info:status Notification when the device failed due to DhcpStartFailedReason", "DHCP failed to start"); 0132 break; 0133 case NetworkManager::Device::DhcpErrorReason: 0134 text = i18nc("@info:status Notification when the device failed due to DhcpErrorReason", "A DHCP error occurred"); 0135 break; 0136 case NetworkManager::Device::DhcpFailedReason: 0137 text = i18nc("@info:status Notification when the device failed due to DhcpFailedReason", "DHCP failed "); 0138 break; 0139 case NetworkManager::Device::SharedStartFailedReason: 0140 text = i18nc("@info:status Notification when the device failed due to SharedStartFailedReason", "The shared service failed to start"); 0141 break; 0142 case NetworkManager::Device::SharedFailedReason: 0143 text = i18nc("@info:status Notification when the device failed due to SharedFailedReason", "The shared service failed"); 0144 break; 0145 case NetworkManager::Device::AutoIpStartFailedReason: 0146 text = i18nc("@info:status Notification when the device failed due to AutoIpStartFailedReason", "The auto IP service failed to start"); 0147 break; 0148 case NetworkManager::Device::AutoIpErrorReason: 0149 text = i18nc("@info:status Notification when the device failed due to AutoIpErrorReason", "The auto IP service reported an error"); 0150 break; 0151 case NetworkManager::Device::AutoIpFailedReason: 0152 text = i18nc("@info:status Notification when the device failed due to AutoIpFailedReason", "The auto IP service failed"); 0153 break; 0154 case NetworkManager::Device::ModemBusyReason: 0155 text = i18nc("@info:status Notification when the device failed due to ModemBusyReason", "The modem is busy"); 0156 break; 0157 case NetworkManager::Device::ModemNoDialToneReason: 0158 text = i18nc("@info:status Notification when the device failed due to ModemNoDialToneReason", "The modem has no dial tone"); 0159 break; 0160 case NetworkManager::Device::ModemNoCarrierReason: 0161 text = i18nc("@info:status Notification when the device failed due to ModemNoCarrierReason", "The modem shows no carrier"); 0162 break; 0163 case NetworkManager::Device::ModemDialTimeoutReason: 0164 text = i18nc("@info:status Notification when the device failed due to ModemDialTimeoutReason", "The modem dial timed out"); 0165 break; 0166 case NetworkManager::Device::ModemDialFailedReason: 0167 text = i18nc("@info:status Notification when the device failed due to ModemDialFailedReason", "The modem dial failed"); 0168 break; 0169 case NetworkManager::Device::ModemInitFailedReason: 0170 text = i18nc("@info:status Notification when the device failed due to ModemInitFailedReason", "The modem could not be initialized"); 0171 break; 0172 case NetworkManager::Device::GsmApnSelectFailedReason: 0173 text = i18nc("@info:status Notification when the device failed due to GsmApnSelectFailedReason", "The GSM APN could not be selected"); 0174 break; 0175 case NetworkManager::Device::GsmNotSearchingReason: 0176 text = i18nc("@info:status Notification when the device failed due to GsmNotSearchingReason", "The GSM modem is not searching"); 0177 break; 0178 case NetworkManager::Device::GsmRegistrationDeniedReason: 0179 text = i18nc("@info:status Notification when the device failed due to GsmRegistrationDeniedReason", "GSM network registration was denied"); 0180 break; 0181 case NetworkManager::Device::GsmRegistrationTimeoutReason: 0182 text = i18nc("@info:status Notification when the device failed due to GsmRegistrationTimeoutReason", "GSM network registration timed out"); 0183 break; 0184 case NetworkManager::Device::GsmRegistrationFailedReason: 0185 text = i18nc("@info:status Notification when the device failed due to GsmRegistrationFailedReason", "GSM registration failed"); 0186 break; 0187 case NetworkManager::Device::GsmPinCheckFailedReason: 0188 text = i18nc("@info:status Notification when the device failed due to GsmPinCheckFailedReason", "The GSM PIN check failed"); 0189 break; 0190 case NetworkManager::Device::FirmwareMissingReason: 0191 text = i18nc("@info:status Notification when the device failed due to FirmwareMissingReason", "Device firmware is missing"); 0192 break; 0193 case NetworkManager::Device::DeviceRemovedReason: 0194 text = i18nc("@info:status Notification when the device failed due to DeviceRemovedReason", "The device was removed"); 0195 break; 0196 case NetworkManager::Device::SleepingReason: 0197 text = i18nc("@info:status Notification when the device failed due to SleepingReason", "The networking system is now sleeping"); 0198 break; 0199 case NetworkManager::Device::ConnectionRemovedReason: 0200 text = i18nc("@info:status Notification when the device failed due to ConnectionRemovedReason", "The connection was removed"); 0201 break; 0202 case NetworkManager::Device::UserRequestedReason: 0203 return; 0204 case NetworkManager::Device::CarrierReason: 0205 text = i18nc("@info:status Notification when the device failed due to CarrierReason", "The cable was disconnected"); 0206 break; 0207 case NetworkManager::Device::ConnectionAssumedReason: 0208 case NetworkManager::Device::SupplicantAvailableReason: 0209 return; 0210 case NetworkManager::Device::ModemNotFoundReason: 0211 text = i18nc("@info:status Notification when the device failed due to ModemNotFoundReason", "The modem could not be found"); 0212 break; 0213 case NetworkManager::Device::BluetoothFailedReason: 0214 text = i18nc("@info:status Notification when the device failed due to BluetoothFailedReason", "The bluetooth connection failed or timed out"); 0215 break; 0216 case NetworkManager::Device::GsmSimNotInserted: 0217 text = i18nc("@info:status Notification when the device failed due to GsmSimNotInserted", "GSM Modem's SIM Card not inserted"); 0218 break; 0219 case NetworkManager::Device::GsmSimPinRequired: 0220 text = i18nc("@info:status Notification when the device failed due to GsmSimPinRequired", "GSM Modem's SIM Pin required"); 0221 break; 0222 case NetworkManager::Device::GsmSimPukRequired: 0223 text = i18nc("@info:status Notification when the device failed due to GsmSimPukRequired", "GSM Modem's SIM Puk required"); 0224 break; 0225 case NetworkManager::Device::GsmSimWrong: 0226 text = i18nc("@info:status Notification when the device failed due to GsmSimWrong", "GSM Modem's SIM wrong"); 0227 break; 0228 case NetworkManager::Device::InfiniBandMode: 0229 text = i18nc("@info:status Notification when the device failed due to InfiniBandMode", "InfiniBand device does not support connected mode"); 0230 break; 0231 case NetworkManager::Device::DependencyFailed: 0232 text = i18nc("@info:status Notification when the device failed due to DependencyFailed", "A dependency of the connection failed"); 0233 break; 0234 case NetworkManager::Device::Br2684Failed: 0235 text = i18nc("@info:status Notification when the device failed due to Br2684Failed", "Problem with the RFC 2684 Ethernet over ADSL bridge"); 0236 break; 0237 case NetworkManager::Device::ModemManagerUnavailable: 0238 text = i18nc("@info:status Notification when the device failed due to ModemManagerUnavailable", "ModemManager not running"); 0239 break; 0240 case NetworkManager::Device::SsidNotFound: 0241 text = i18nc("@info:status Notification when the device failed due to SsidNotFound", "The WiFi network could not be found"); 0242 break; 0243 case NetworkManager::Device::SecondaryConnectionFailed: 0244 text = 0245 i18nc("@info:status Notification when the device failed due to SecondaryConnectionFailed", "A secondary connection of the base connection failed"); 0246 break; 0247 case NetworkManager::Device::DcbFcoeFailed: 0248 text = i18nc("@info:status Notification when the device failed due to DcbFcoeFailed", "DCB or FCoE setup failed"); 0249 break; 0250 case NetworkManager::Device::TeamdControlFailed: 0251 text = i18nc("@info:status Notification when the device failed due to TeamdControlFailed", "teamd control failed"); 0252 break; 0253 case NetworkManager::Device::ModemFailed: 0254 text = i18nc("@info:status Notification when the device failed due to ModemFailed", "Modem failed or no longer available"); 0255 break; 0256 case NetworkManager::Device::ModemAvailable: 0257 text = i18nc("@info:status Notification when the device failed due to ModemAvailable", "Modem now ready and available"); 0258 break; 0259 case NetworkManager::Device::SimPinIncorrect: 0260 text = i18nc("@info:status Notification when the device failed due to SimPinIncorrect", "The SIM PIN was incorrect"); 0261 break; 0262 case NetworkManager::Device::NewActivation: 0263 text = i18nc("@info:status Notification when the device failed due to NewActivation", "A new connection activation was enqueued"); 0264 break; 0265 case NetworkManager::Device::ParentChanged: 0266 text = i18nc("@info:status Notification when the device failed due to ParentChanged", "The device's parent changed"); 0267 break; 0268 case NetworkManager::Device::ParentManagedChanged: 0269 text = i18nc("@info:status Notification when the device failed due to ParentManagedChanged", "The device parent's management changed"); 0270 break; 0271 case NetworkManager::Device::Reserved: 0272 return; 0273 } 0274 0275 if (m_notifications.contains(device->uni())) { 0276 KNotification *notify = m_notifications.value(device->uni()); 0277 notify->setText(text.toHtmlEscaped()); 0278 notify->update(); 0279 } else { 0280 auto notify = new KNotification(QStringLiteral("DeviceFailed"), KNotification::CloseOnTimeout); 0281 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0282 notify->setProperty("uni", device->uni()); 0283 notify->setComponentName(QStringLiteral("networkmanagement")); 0284 notify->setIconName(QStringLiteral("dialog-warning")); 0285 notify->setTitle(identifier); 0286 notify->setText(text.toHtmlEscaped()); 0287 m_notifications[device->uni()] = notify; 0288 notify->sendEvent(); 0289 } 0290 } 0291 0292 void Notification::addActiveConnection(const QString &path) 0293 { 0294 NetworkManager::ActiveConnection::Ptr ac = NetworkManager::findActiveConnection(path); 0295 if (ac && ac->isValid()) { 0296 addActiveConnection(ac); 0297 } 0298 } 0299 0300 void Notification::addActiveConnection(const NetworkManager::ActiveConnection::Ptr &ac) 0301 { 0302 if (ac->vpn()) { 0303 NetworkManager::VpnConnection::Ptr vpnConnection = ac.objectCast<NetworkManager::VpnConnection>(); 0304 connect(vpnConnection.data(), &NetworkManager::VpnConnection::stateChanged, this, &Notification::onVpnConnectionStateChanged); 0305 } else if (ac->type() != NetworkManager::ConnectionSettings::Bond // 0306 && ac->type() != NetworkManager::ConnectionSettings::Bridge // 0307 && ac->type() != NetworkManager::ConnectionSettings::Generic // 0308 && ac->type() != NetworkManager::ConnectionSettings::Infiniband // 0309 && ac->type() != NetworkManager::ConnectionSettings::Team // 0310 && ac->type() != NetworkManager::ConnectionSettings::Vlan // 0311 && ac->type() != NetworkManager::ConnectionSettings::Tun) { 0312 connect(ac.data(), &NetworkManager::ActiveConnection::stateChanged, this, &Notification::onActiveConnectionStateChanged); 0313 } 0314 } 0315 0316 void Notification::onActiveConnectionStateChanged(NetworkManager::ActiveConnection::State state) 0317 { 0318 auto ac = qobject_cast<NetworkManager::ActiveConnection *>(sender()); 0319 0320 QString eventId, text, iconName; 0321 const QString acName = ac->id(); 0322 const QString connectionId = ac->id(); 0323 0324 if (state == NetworkManager::ActiveConnection::Activated) { 0325 // Don't send notifications about activated connections just because the 0326 // daemon was launched as these were not explicitly user-initiated actions, 0327 // and notifications for automatic actions and background processes are 0328 // annoying and unnecessary 0329 if (m_justLaunched) { 0330 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection activated notification as the daemon was just launched"; 0331 return; 0332 } 0333 0334 // Also don't notify for re-made connections after waking up from sleep 0335 auto foundConnection = std::find_if(m_activeConnectionsBeforeSleep.constBegin(), m_activeConnectionsBeforeSleep.constEnd(), [ac](const QString &uuid) { 0336 return uuid == ac->uuid(); 0337 }); 0338 0339 if (foundConnection != m_activeConnectionsBeforeSleep.constEnd()) { 0340 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection activated notification as the connection was active prior to suspend"; 0341 return; 0342 } 0343 0344 eventId = QStringLiteral("ConnectionActivated"); 0345 text = i18n("Connection '%1' activated.", acName); 0346 0347 switch (ac->type()) { 0348 case NetworkManager::ConnectionSettings::Wireless: 0349 iconName = QStringLiteral("network-wireless-on"); 0350 break; 0351 case NetworkManager::ConnectionSettings::Wired: 0352 iconName = QStringLiteral("network-wired-activated"); 0353 break; 0354 case NetworkManager::ConnectionSettings::WireGuard: 0355 iconName = QStringLiteral("network-vpn"); 0356 break; 0357 default: // silence warning 0358 break; 0359 } 0360 } else if (state == NetworkManager::ActiveConnection::Deactivated) { 0361 if (m_preparingForSleep) { 0362 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection deactivated notification as we're about to suspend"; 0363 return; 0364 } 0365 0366 if (m_checkActiveConnectionOnResumeTimer && m_checkActiveConnectionOnResumeTimer->isActive()) { 0367 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection deactivated notification as we've just woken up from suspend"; 0368 return; 0369 } 0370 0371 eventId = QStringLiteral("ConnectionDeactivated"); 0372 text = i18n("Connection '%1' deactivated.", acName); 0373 0374 switch (ac->type()) { 0375 case NetworkManager::ConnectionSettings::Wireless: 0376 iconName = QStringLiteral("network-wireless-disconnected"); 0377 break; 0378 case NetworkManager::ConnectionSettings::Wired: 0379 iconName = QStringLiteral("network-unavailable"); 0380 break; 0381 default: // silence warning 0382 break; 0383 } 0384 } else { 0385 qCWarning(PLASMA_NM_KDED_LOG) << "Unhandled active connection state change: " << state; 0386 return; 0387 } 0388 0389 KNotification *notify = m_notifications.value(connectionId); 0390 0391 if (!notify) { 0392 notify = new KNotification(eventId, KNotification::CloseOnTimeout); 0393 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0394 notify->setProperty("uni", connectionId); 0395 notify->setComponentName(QStringLiteral("networkmanagement")); 0396 m_notifications[connectionId] = notify; 0397 } 0398 0399 if (!iconName.isEmpty()) { 0400 notify->setIconName(iconName); 0401 } else { 0402 if (state == NetworkManager::ActiveConnection::Activated) { 0403 notify->setIconName(QStringLiteral("dialog-information")); 0404 } else { 0405 notify->setIconName(QStringLiteral("dialog-warning")); 0406 } 0407 } 0408 notify->setTitle(acName); 0409 notify->setText(text.toHtmlEscaped()); 0410 notify->sendEvent(); 0411 } 0412 0413 void Notification::onVpnConnectionStateChanged(NetworkManager::VpnConnection::State state, NetworkManager::VpnConnection::StateChangeReason reason) 0414 { 0415 auto vpn = qobject_cast<NetworkManager::VpnConnection *>(sender()); 0416 0417 QString eventId, text; 0418 const QString vpnName = vpn->connection()->name(); 0419 const QString connectionId = vpn->path(); 0420 0421 if (state == NetworkManager::VpnConnection::Activated) { 0422 eventId = QStringLiteral("ConnectionActivated"); 0423 text = i18n("VPN connection '%1' activated.", vpnName); 0424 } else if (state == NetworkManager::VpnConnection::Failed) { 0425 eventId = QStringLiteral("FailedToActivateConnection"); 0426 text = i18n("VPN connection '%1' failed to activate.", vpnName); 0427 } else if (state == NetworkManager::VpnConnection::Disconnected) { 0428 eventId = QStringLiteral("ConnectionDeactivated"); 0429 text = i18n("VPN connection '%1' deactivated.", vpnName); 0430 } else { 0431 qCWarning(PLASMA_NM_KDED_LOG) << "Unhandled VPN connection state change: " << state; 0432 return; 0433 } 0434 0435 switch (reason) { 0436 case NetworkManager::VpnConnection::UserDisconnectedReason: 0437 text = i18n("VPN connection '%1' deactivated.", vpnName); 0438 break; 0439 case NetworkManager::VpnConnection::DeviceDisconnectedReason: 0440 text = i18n("VPN connection '%1' was deactivated because the device it was using was disconnected.", vpnName); 0441 break; 0442 case NetworkManager::VpnConnection::ServiceStoppedReason: 0443 text = i18n("The service providing the VPN connection '%1' was stopped.", vpnName); 0444 break; 0445 case NetworkManager::VpnConnection::IpConfigInvalidReason: 0446 text = i18n("The IP config of the VPN connection '%1', was invalid.", vpnName); 0447 break; 0448 case NetworkManager::VpnConnection::ConnectTimeoutReason: 0449 text = i18n("The connection attempt to the VPN service timed out."); 0450 break; 0451 case NetworkManager::VpnConnection::ServiceStartTimeoutReason: 0452 text = i18n("A timeout occurred while starting the service providing the VPN connection '%1'.", vpnName); 0453 break; 0454 case NetworkManager::VpnConnection::ServiceStartFailedReason: 0455 text = i18n("Starting the service providing the VPN connection '%1' failed.", vpnName); 0456 break; 0457 case NetworkManager::VpnConnection::NoSecretsReason: 0458 text = i18n("Necessary secrets for the VPN connection '%1' were not provided.", vpnName); 0459 break; 0460 case NetworkManager::VpnConnection::LoginFailedReason: 0461 text = i18n("Authentication to the VPN server failed."); 0462 break; 0463 case NetworkManager::VpnConnection::ConnectionRemovedReason: 0464 text = i18n("The connection was deleted."); 0465 break; 0466 default: 0467 case NetworkManager::VpnConnection::UnknownReason: 0468 case NetworkManager::VpnConnection::NoneReason: 0469 break; 0470 } 0471 0472 auto notify = new KNotification(eventId, KNotification::CloseOnTimeout); 0473 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0474 notify->setProperty("uni", connectionId); 0475 notify->setComponentName(QStringLiteral("networkmanagement")); 0476 if (state == NetworkManager::VpnConnection::Activated) { 0477 notify->setIconName(QStringLiteral("dialog-information")); 0478 } else if (state == NetworkManager::VpnConnection::Disconnected && reason == NetworkManager::VpnConnection::UserDisconnectedReason) { 0479 // Don't show warning icon if the user explicitly disconnected 0480 notify->setIconName(QStringLiteral("dialog-information")); 0481 } else { 0482 notify->setIconName(QStringLiteral("dialog-warning")); 0483 } 0484 notify->setTitle(vpnName); 0485 notify->setText(text.toHtmlEscaped()); 0486 m_notifications[connectionId] = notify; 0487 notify->sendEvent(); 0488 } 0489 0490 void Notification::notificationClosed() 0491 { 0492 auto notify = qobject_cast<KNotification *>(sender()); 0493 m_notifications.remove(notify->property("uni").toString()); 0494 } 0495 0496 void Notification::onPrepareForSleep(bool sleep) 0497 { 0498 m_preparingForSleep = sleep; 0499 0500 if (m_checkActiveConnectionOnResumeTimer) { 0501 m_checkActiveConnectionOnResumeTimer->stop(); 0502 } 0503 0504 if (sleep) { 0505 // store all active notifications so we don't show a "is connected" notification 0506 // on resume if we were connected previously 0507 m_activeConnectionsBeforeSleep.clear(); 0508 const auto &connections = NetworkManager::activeConnections(); 0509 for (const auto &connection : connections) { 0510 if (!connection->vpn() && connection->state() == NetworkManager::ActiveConnection::State::Activated) { 0511 m_activeConnectionsBeforeSleep << connection->uuid(); 0512 } 0513 } 0514 } else { 0515 if (!m_checkActiveConnectionOnResumeTimer) { 0516 m_checkActiveConnectionOnResumeTimer = new QTimer(this); 0517 m_checkActiveConnectionOnResumeTimer->setInterval(10s); 0518 m_checkActiveConnectionOnResumeTimer->setSingleShot(true); 0519 connect(m_checkActiveConnectionOnResumeTimer, &QTimer::timeout, this, &Notification::onCheckActiveConnectionOnResume); 0520 } 0521 0522 m_checkActiveConnectionOnResumeTimer->start(); 0523 } 0524 } 0525 0526 void Notification::onCheckActiveConnectionOnResume() 0527 { 0528 if (m_activeConnectionsBeforeSleep.isEmpty()) { 0529 // if we weren't connected before, don't bother telling us now :) 0530 return; 0531 } 0532 0533 m_activeConnectionsBeforeSleep.clear(); 0534 0535 const auto ac = NetworkManager::activeConnections(); 0536 if (std::any_of(ac.constBegin(), ac.constEnd(), [](const auto &connection) { 0537 return connection->state() == NetworkManager::ActiveConnection::State::Activated 0538 || connection->state() == NetworkManager::ActiveConnection::State::Activating; 0539 })) { 0540 // we have an active or activating connection, don't tell the user we're no longer connected 0541 return; 0542 } 0543 0544 auto notify = new KNotification(QStringLiteral("NoLongerConnected"), KNotification::CloseOnTimeout); 0545 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0546 const QString uni = QStringLiteral("offlineNotification"); 0547 notify->setProperty("uni", uni); 0548 notify->setComponentName(QStringLiteral("networkmanagement")); 0549 notify->setIconName(QStringLiteral("dialog-warning")); 0550 notify->setTitle(i18n("No Network Connection")); 0551 notify->setText(i18n("You are no longer connected to a network.")); 0552 m_notifications[uni] = notify; 0553 notify->sendEvent(); 0554 }