File indexing completed on 2024-04-28 05:33:53
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 return; 0242 case NetworkManager::Device::SecondaryConnectionFailed: 0243 text = 0244 i18nc("@info:status Notification when the device failed due to SecondaryConnectionFailed", "A secondary connection of the base connection failed"); 0245 break; 0246 case NetworkManager::Device::DcbFcoeFailed: 0247 text = i18nc("@info:status Notification when the device failed due to DcbFcoeFailed", "DCB or FCoE setup failed"); 0248 break; 0249 case NetworkManager::Device::TeamdControlFailed: 0250 text = i18nc("@info:status Notification when the device failed due to TeamdControlFailed", "teamd control failed"); 0251 break; 0252 case NetworkManager::Device::ModemFailed: 0253 text = i18nc("@info:status Notification when the device failed due to ModemFailed", "Modem failed or no longer available"); 0254 break; 0255 case NetworkManager::Device::ModemAvailable: 0256 text = i18nc("@info:status Notification when the device failed due to ModemAvailable", "Modem now ready and available"); 0257 break; 0258 case NetworkManager::Device::SimPinIncorrect: 0259 text = i18nc("@info:status Notification when the device failed due to SimPinIncorrect", "The SIM PIN was incorrect"); 0260 break; 0261 case NetworkManager::Device::NewActivation: 0262 text = i18nc("@info:status Notification when the device failed due to NewActivation", "A new connection activation was enqueued"); 0263 break; 0264 case NetworkManager::Device::ParentChanged: 0265 text = i18nc("@info:status Notification when the device failed due to ParentChanged", "The device's parent changed"); 0266 break; 0267 case NetworkManager::Device::ParentManagedChanged: 0268 text = i18nc("@info:status Notification when the device failed due to ParentManagedChanged", "The device parent's management changed"); 0269 break; 0270 case NetworkManager::Device::Reserved: 0271 return; 0272 } 0273 0274 if (m_notifications.contains(device->uni())) { 0275 KNotification *notify = m_notifications.value(device->uni()); 0276 notify->setText(text.toHtmlEscaped()); 0277 notify->sendEvent(); 0278 } else { 0279 auto notify = new KNotification(QStringLiteral("DeviceFailed"), KNotification::CloseOnTimeout); 0280 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0281 notify->setProperty("uni", device->uni()); 0282 notify->setComponentName(QStringLiteral("networkmanagement")); 0283 notify->setIconName(QStringLiteral("dialog-warning")); 0284 notify->setTitle(identifier); 0285 notify->setText(text.toHtmlEscaped()); 0286 m_notifications[device->uni()] = notify; 0287 notify->sendEvent(); 0288 } 0289 } 0290 0291 void Notification::addActiveConnection(const QString &path) 0292 { 0293 NetworkManager::ActiveConnection::Ptr ac = NetworkManager::findActiveConnection(path); 0294 if (ac && ac->isValid()) { 0295 addActiveConnection(ac); 0296 } 0297 } 0298 0299 void Notification::addActiveConnection(const NetworkManager::ActiveConnection::Ptr &ac) 0300 { 0301 if (ac->vpn()) { 0302 NetworkManager::VpnConnection::Ptr vpnConnection = ac.objectCast<NetworkManager::VpnConnection>(); 0303 connect(vpnConnection.data(), &NetworkManager::VpnConnection::stateChanged, this, &Notification::onVpnConnectionStateChanged); 0304 } else if (ac->type() != NetworkManager::ConnectionSettings::Bond // 0305 && ac->type() != NetworkManager::ConnectionSettings::Bridge // 0306 && ac->type() != NetworkManager::ConnectionSettings::Generic // 0307 && ac->type() != NetworkManager::ConnectionSettings::Infiniband // 0308 && ac->type() != NetworkManager::ConnectionSettings::Team // 0309 && ac->type() != NetworkManager::ConnectionSettings::Vlan // 0310 && ac->type() != NetworkManager::ConnectionSettings::Tun) { 0311 connect(ac.data(), &NetworkManager::ActiveConnection::stateChanged, this, &Notification::onActiveConnectionStateChanged); 0312 } 0313 } 0314 0315 void Notification::onActiveConnectionStateChanged(NetworkManager::ActiveConnection::State state) 0316 { 0317 auto ac = qobject_cast<NetworkManager::ActiveConnection *>(sender()); 0318 0319 QString eventId, text, iconName; 0320 const QString acName = ac->id(); 0321 const QString connectionId = ac->id(); 0322 0323 if (state == NetworkManager::ActiveConnection::Activated) { 0324 // Don't send notifications about activated connections just because the 0325 // daemon was launched as these were not explicitly user-initiated actions, 0326 // and notifications for automatic actions and background processes are 0327 // annoying and unnecessary 0328 if (m_justLaunched) { 0329 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection activated notification as the daemon was just launched"; 0330 return; 0331 } 0332 0333 // Also don't notify for re-made connections after waking up from sleep 0334 auto foundConnection = std::find_if(m_activeConnectionsBeforeSleep.constBegin(), m_activeConnectionsBeforeSleep.constEnd(), [ac](const QString &uuid) { 0335 return uuid == ac->uuid(); 0336 }); 0337 0338 if (foundConnection != m_activeConnectionsBeforeSleep.constEnd()) { 0339 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection activated notification as the connection was active prior to suspend"; 0340 return; 0341 } 0342 0343 eventId = QStringLiteral("ConnectionActivated"); 0344 text = i18n("Connection '%1' activated.", acName); 0345 0346 switch (ac->type()) { 0347 case NetworkManager::ConnectionSettings::Wireless: 0348 iconName = QStringLiteral("network-wireless-on"); 0349 break; 0350 case NetworkManager::ConnectionSettings::Wired: 0351 iconName = QStringLiteral("network-wired-activated"); 0352 break; 0353 case NetworkManager::ConnectionSettings::WireGuard: 0354 iconName = QStringLiteral("network-vpn"); 0355 break; 0356 default: // silence warning 0357 break; 0358 } 0359 } else if (state == NetworkManager::ActiveConnection::Deactivated) { 0360 if (m_preparingForSleep) { 0361 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection deactivated notification as we're about to suspend"; 0362 return; 0363 } 0364 0365 if (m_checkActiveConnectionOnResumeTimer && m_checkActiveConnectionOnResumeTimer->isActive()) { 0366 qCDebug(PLASMA_NM_KDED_LOG) << "Not emitting connection deactivated notification as we've just woken up from suspend"; 0367 return; 0368 } 0369 0370 eventId = QStringLiteral("ConnectionDeactivated"); 0371 text = i18n("Connection '%1' deactivated.", acName); 0372 0373 switch (ac->type()) { 0374 case NetworkManager::ConnectionSettings::Wireless: 0375 iconName = QStringLiteral("network-wireless-disconnected"); 0376 break; 0377 case NetworkManager::ConnectionSettings::Wired: 0378 iconName = QStringLiteral("network-unavailable"); 0379 break; 0380 default: // silence warning 0381 break; 0382 } 0383 } else { 0384 qCWarning(PLASMA_NM_KDED_LOG) << "Unhandled active connection state change: " << state; 0385 return; 0386 } 0387 0388 KNotification *notify = m_notifications.value(connectionId); 0389 0390 if (!notify) { 0391 notify = new KNotification(eventId, KNotification::CloseOnTimeout); 0392 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0393 notify->setProperty("uni", connectionId); 0394 notify->setComponentName(QStringLiteral("networkmanagement")); 0395 m_notifications[connectionId] = notify; 0396 } 0397 0398 if (!iconName.isEmpty()) { 0399 notify->setIconName(iconName); 0400 } else { 0401 if (state == NetworkManager::ActiveConnection::Activated) { 0402 notify->setIconName(QStringLiteral("dialog-information")); 0403 } else { 0404 notify->setIconName(QStringLiteral("dialog-warning")); 0405 } 0406 } 0407 notify->setTitle(acName); 0408 notify->setText(text.toHtmlEscaped()); 0409 notify->sendEvent(); 0410 } 0411 0412 void Notification::onVpnConnectionStateChanged(NetworkManager::VpnConnection::State state, NetworkManager::VpnConnection::StateChangeReason reason) 0413 { 0414 auto vpn = qobject_cast<NetworkManager::VpnConnection *>(sender()); 0415 0416 QString eventId, text; 0417 const QString vpnName = vpn->connection()->name(); 0418 const QString connectionId = vpn->path(); 0419 0420 if (state == NetworkManager::VpnConnection::Activated) { 0421 eventId = QStringLiteral("ConnectionActivated"); 0422 text = i18n("VPN connection '%1' activated.", vpnName); 0423 } else if (state == NetworkManager::VpnConnection::Failed) { 0424 eventId = QStringLiteral("FailedToActivateConnection"); 0425 text = i18n("VPN connection '%1' failed to activate.", vpnName); 0426 } else if (state == NetworkManager::VpnConnection::Disconnected) { 0427 eventId = QStringLiteral("ConnectionDeactivated"); 0428 text = i18n("VPN connection '%1' deactivated.", vpnName); 0429 } else { 0430 qCWarning(PLASMA_NM_KDED_LOG) << "Unhandled VPN connection state change: " << state; 0431 return; 0432 } 0433 0434 switch (reason) { 0435 case NetworkManager::VpnConnection::UserDisconnectedReason: 0436 text = i18n("VPN connection '%1' deactivated.", vpnName); 0437 break; 0438 case NetworkManager::VpnConnection::DeviceDisconnectedReason: 0439 text = i18n("VPN connection '%1' was deactivated because the device it was using was disconnected.", vpnName); 0440 break; 0441 case NetworkManager::VpnConnection::ServiceStoppedReason: 0442 text = i18n("The service providing the VPN connection '%1' was stopped.", vpnName); 0443 break; 0444 case NetworkManager::VpnConnection::IpConfigInvalidReason: 0445 text = i18n("The IP config of the VPN connection '%1', was invalid.", vpnName); 0446 break; 0447 case NetworkManager::VpnConnection::ConnectTimeoutReason: 0448 text = i18n("The connection attempt to the VPN service timed out."); 0449 break; 0450 case NetworkManager::VpnConnection::ServiceStartTimeoutReason: 0451 text = i18n("A timeout occurred while starting the service providing the VPN connection '%1'.", vpnName); 0452 break; 0453 case NetworkManager::VpnConnection::ServiceStartFailedReason: 0454 text = i18n("Starting the service providing the VPN connection '%1' failed.", vpnName); 0455 break; 0456 case NetworkManager::VpnConnection::NoSecretsReason: 0457 text = i18n("Necessary secrets for the VPN connection '%1' were not provided.", vpnName); 0458 break; 0459 case NetworkManager::VpnConnection::LoginFailedReason: 0460 text = i18n("Authentication to the VPN server failed."); 0461 break; 0462 case NetworkManager::VpnConnection::ConnectionRemovedReason: 0463 text = i18n("The connection was deleted."); 0464 break; 0465 default: 0466 case NetworkManager::VpnConnection::UnknownReason: 0467 case NetworkManager::VpnConnection::NoneReason: 0468 break; 0469 } 0470 0471 auto notify = new KNotification(eventId, KNotification::CloseOnTimeout); 0472 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0473 notify->setProperty("uni", connectionId); 0474 notify->setComponentName(QStringLiteral("networkmanagement")); 0475 if (state == NetworkManager::VpnConnection::Activated) { 0476 notify->setIconName(QStringLiteral("dialog-information")); 0477 } else if (state == NetworkManager::VpnConnection::Disconnected && reason == NetworkManager::VpnConnection::UserDisconnectedReason) { 0478 // Don't show warning icon if the user explicitly disconnected 0479 notify->setIconName(QStringLiteral("dialog-information")); 0480 } else { 0481 notify->setIconName(QStringLiteral("dialog-warning")); 0482 } 0483 notify->setTitle(vpnName); 0484 notify->setText(text.toHtmlEscaped()); 0485 m_notifications[connectionId] = notify; 0486 notify->sendEvent(); 0487 } 0488 0489 void Notification::notificationClosed() 0490 { 0491 auto notify = qobject_cast<KNotification *>(sender()); 0492 m_notifications.remove(notify->property("uni").toString()); 0493 } 0494 0495 void Notification::onPrepareForSleep(bool sleep) 0496 { 0497 m_preparingForSleep = sleep; 0498 0499 if (m_checkActiveConnectionOnResumeTimer) { 0500 m_checkActiveConnectionOnResumeTimer->stop(); 0501 } 0502 0503 if (sleep) { 0504 // store all active notifications so we don't show a "is connected" notification 0505 // on resume if we were connected previously 0506 m_activeConnectionsBeforeSleep.clear(); 0507 const auto &connections = NetworkManager::activeConnections(); 0508 for (const auto &connection : connections) { 0509 if (!connection->vpn() && connection->state() == NetworkManager::ActiveConnection::State::Activated) { 0510 m_activeConnectionsBeforeSleep << connection->uuid(); 0511 } 0512 } 0513 } else { 0514 if (!m_checkActiveConnectionOnResumeTimer) { 0515 m_checkActiveConnectionOnResumeTimer = new QTimer(this); 0516 m_checkActiveConnectionOnResumeTimer->setInterval(10s); 0517 m_checkActiveConnectionOnResumeTimer->setSingleShot(true); 0518 connect(m_checkActiveConnectionOnResumeTimer, &QTimer::timeout, this, &Notification::onCheckActiveConnectionOnResume); 0519 } 0520 0521 m_checkActiveConnectionOnResumeTimer->start(); 0522 } 0523 } 0524 0525 void Notification::onCheckActiveConnectionOnResume() 0526 { 0527 if (m_activeConnectionsBeforeSleep.isEmpty()) { 0528 // if we weren't connected before, don't bother telling us now :) 0529 return; 0530 } 0531 0532 m_activeConnectionsBeforeSleep.clear(); 0533 0534 const auto ac = NetworkManager::activeConnections(); 0535 if (std::any_of(ac.constBegin(), ac.constEnd(), [](const auto &connection) { 0536 return connection->state() == NetworkManager::ActiveConnection::State::Activated 0537 || connection->state() == NetworkManager::ActiveConnection::State::Activating; 0538 })) { 0539 // we have an active or activating connection, don't tell the user we're no longer connected 0540 return; 0541 } 0542 0543 auto notify = new KNotification(QStringLiteral("NoLongerConnected"), KNotification::CloseOnTimeout); 0544 connect(notify, &KNotification::closed, this, &Notification::notificationClosed); 0545 const QString uni = QStringLiteral("offlineNotification"); 0546 notify->setProperty("uni", uni); 0547 notify->setComponentName(QStringLiteral("networkmanagement")); 0548 notify->setIconName(QStringLiteral("dialog-warning")); 0549 notify->setTitle(i18n("No Network Connection")); 0550 notify->setText(i18n("You are no longer connected to a network.")); 0551 m_notifications[uni] = notify; 0552 notify->sendEvent(); 0553 } 0554 0555 #include "moc_notification.cpp"