From 7f7d22984397c39ec721d7bb0f421df2c6a52b33 Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 12 Dec 2016 12:06:04 +0000 Subject: [PATCH] Add a notication service to inhibit certain notifications based on metadata Summary: Sometimes we get notifications for events that are also displayed by Plasma, giving us some rather annoying popups. This patch provides a service on the notification dataengine so that other plasmoids can block the notification applet from processing those notifications. Intended use case is for the network manager plasomid to not show a notification whilst the dialog is open, as notifications come from kded. However it's kept generic enough that other plasmoids can filter on other hints, such as category or desktop file. Test Plan: Wrote relevant patch for plasma-nm Didn't get notification toggling a network whilst the popup was open Did after I closed the popup Reviewers: #plasma, mart Reviewed By: mart Subscribers: plasma-devel Tags: #plasma Differential Revision: https://phabricator.kde.org/D3589 --- .../notifications/notificationaction.cpp | 5 +++++ .../notifications/notifications.operations | 7 +++++++ .../notifications/notificationsengine.cpp | 21 +++++++++++++++++++ .../notifications/notificationsengine.h | 19 +++++++++++++++++ 4 files changed, 52 insertions(+) diff --git a/dataengines/notifications/notificationaction.cpp b/dataengines/notifications/notificationaction.cpp index 99b53a798..b197ccb24 100644 --- a/dataengines/notifications/notificationaction.cpp +++ b/dataengines/notifications/notificationaction.cpp @@ -77,6 +77,11 @@ void NotificationAction::start() } else if (operationName() == QLatin1String("configureNotification")) { m_engine->configureNotification(parameters()[QStringLiteral("appRealName")].toString(), parameters()[QStringLiteral("eventId")].toString()); + } else if (operationName() == QLatin1String("inhibit")) { + const QString hint = parameters()[QStringLiteral("hint")].toString(); + const QString value = parameters()[QStringLiteral("value")].toString(); + auto t = m_engine->createInhibition(hint, value); + setResult(QVariant::fromValue(t)); } emitResult(); diff --git a/dataengines/notifications/notifications.operations b/dataengines/notifications/notifications.operations index 67ff88277..636bfb068 100644 --- a/dataengines/notifications/notifications.operations +++ b/dataengines/notifications/notifications.operations @@ -47,4 +47,11 @@ + + + + + + + diff --git a/dataengines/notifications/notificationsengine.cpp b/dataengines/notifications/notificationsengine.cpp index 968965ad5..ca3d7929d 100644 --- a/dataengines/notifications/notificationsengine.cpp +++ b/dataengines/notifications/notificationsengine.cpp @@ -186,6 +186,13 @@ uint NotificationsEngine::Notify(const QString &app_name, uint replaces_id, const QString &app_icon, const QString &summary, const QString &body, const QStringList &actions, const QVariantMap &hints, int timeout) { + foreach(NotificationInhibiton *ni, m_inhibitions) { + if (hints[ni->hint] == ni->value) { + qDebug() << "notification inhibited. Skipping"; + return -1; + } + } + uint partOf = 0; const QString appRealName = hints[QStringLiteral("x-kde-appname")].toString(); const QString eventId = hints[QStringLiteral("x-kde-eventId")].toString(); @@ -413,6 +420,20 @@ void NotificationsEngine::configureNotification(const QString &appName, const QS } } +QSharedPointer NotificationsEngine::createInhibition(const QString &hint, const QString &value) { + auto ni = new NotificationInhibiton; + ni->hint = hint; + ni->value = value; + + QSharedPointer rc(ni, [this](NotificationInhibiton *ni) { + m_inhibitions.removeOne(ni); + delete ni; + }); + m_inhibitions.append(ni); + return rc; +} + + K_EXPORT_PLASMA_DATAENGINE_WITH_JSON(notifications, NotificationsEngine, "plasma-dataengine-notifications.json") #include "notificationsengine.moc" diff --git a/dataengines/notifications/notificationsengine.h b/dataengines/notifications/notificationsengine.h index 68364c3b1..9eb197215 100644 --- a/dataengines/notifications/notificationsengine.h +++ b/dataengines/notifications/notificationsengine.h @@ -25,6 +25,14 @@ #include #include +struct NotificationInhibiton +{ + QString hint; + QString value; +}; + +typedef QSharedPointer NotificationInhibitonPtr; + /** * Engine which provides data sources for notifications. * Each notification is represented by one source. @@ -58,6 +66,13 @@ public: void configureNotification(const QString &appName, const QString &eventId = QString()); + /* + * Block all notification where a given notification hint matches a given value. + * + * Inhibition is dropped when dereferenced. + */ + NotificationInhibitonPtr createInhibition(const QString &hint, const QString &value); + public Q_SLOTS: void removeNotification(uint id, uint closeReason); bool registerDBusService(); @@ -90,7 +105,11 @@ private: */ QHash m_notificationsFromReplaceableApp; + QList m_inhibitions; + friend class NotificationAction; }; +Q_DECLARE_METATYPE(NotificationInhibitonPtr); + #endif