File indexing completed on 2023-12-03 05:42:05
0001 // SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0002 // SPDX-FileCopyrightText: 2020-2021 Harald Sitter <sitter@kde.org> 0003 0004 #include "smartnotifier.h" 0005 0006 #include <KIO/ApplicationLauncherJob> 0007 #include <KLocalizedString> 0008 #include <KNotification> 0009 #include <KService> 0010 0011 #include <QDebug> 0012 0013 #include "device.h" 0014 #include "smartmonitor.h" 0015 0016 class FailureNotification : public QObject 0017 { 0018 Q_OBJECT 0019 public: 0020 FailureNotification(const Device *device, QObject *parent = nullptr) 0021 : QObject(parent) 0022 { 0023 m_notification->setComponentName("org.kde.kded.smart"); 0024 if (device->failed()) { 0025 m_notification->setIconName(QStringLiteral("data-warning")); 0026 } else { 0027 m_notification->setIconName(QStringLiteral("data-information")); 0028 } 0029 m_notification->setTitle(i18nc("@title notification", "Storage Device Problems")); 0030 if (device->failed()) { 0031 m_notification->setText(xi18nc("@info notification; text %1 is a pretty product name; %2 the device path e.g. /dev/sda", 0032 "The storage device <emphasis>%1</emphasis> (<filename>%2</filename>) is likely to fail soon!", 0033 device->product(), 0034 device->path())); 0035 } else { 0036 m_notification->setText(xi18nc("@info notification; text %1 is a pretty product name; %2 the device path e.g. /dev/sda", 0037 "The storage device <emphasis>%1</emphasis> (<filename>%2</filename>) is showing indications of instability.", 0038 device->product(), 0039 device->path())); 0040 } 0041 0042 KService::Ptr kcm = KService::serviceByStorageId(QStringLiteral("smart")); 0043 Q_ASSERT(kcm); // there's a bug or installation is broken; mustn't happen in production 0044 m_notification->setActions({i18nc("@action:button notification action to manage device problems", "Manage")}); 0045 connect(m_notification, &KNotification::action1Activated, this, [kcm] { 0046 KIO::ApplicationLauncherJob(kcm).start(); 0047 }); 0048 0049 connect(m_notification, &KNotification::closed, this, [this] { 0050 deleteLater(); 0051 m_notification = nullptr; 0052 }); 0053 0054 m_notification->sendEvent(); 0055 } 0056 0057 ~FailureNotification() override 0058 { 0059 if (m_notification) { 0060 m_notification->close(); 0061 } 0062 } 0063 0064 private: 0065 KNotification *m_notification = new KNotification{QStringLiteral("imminentDeviceFailure"), KNotification::Persistent, nullptr}; 0066 }; 0067 0068 SMARTNotifier::SMARTNotifier(SMARTMonitor *monitor, QObject *parent) 0069 : QObject(parent) 0070 { 0071 connect(monitor, &SMARTMonitor::deviceAdded, this, [this](const Device *device) { 0072 connect(device, &Device::failedChanged, this, &SMARTNotifier::onMaybeFailed); 0073 // The device may already be in failure state. Make sure we display it if applicable. 0074 maybeFailed(device); 0075 }); 0076 // upon removal the devices are deleted which takes care of disconnecting 0077 } 0078 0079 void SMARTNotifier::onMaybeFailed() 0080 { 0081 maybeFailed(qobject_cast<Device *>(sender())); 0082 } 0083 0084 void SMARTNotifier::maybeFailed(const Device *device) 0085 { 0086 Q_ASSERT(device); 0087 // NB: do not notify on instabilities in 5.22 it's shown to raise false positives or at least be annoying when 0088 // failure seems unlikely. fixing it properly requires larger changes to the UI and strings 0089 // https://bugs.kde.org/show_bug.cgi?id=438539 0090 if ((!device->failed() /*&& device->instabilities().isEmpty()*/) || device->ignore()) { 0091 return; 0092 } 0093 0094 new FailureNotification(device, this); // auto-deletes 0095 // once displayed we'll not want to trigger any more notifications 0096 device->disconnect(this); 0097 } 0098 0099 #include "smartnotifier.moc"