Begin on inhibition / do not disturb stuff

- Also moe the NotificationPopup item back to the root folder
- Implement tracking of unknown apps, ie. once an app shows a notificaton it will show up
  in the KCM so it can be configured
- Make blacklisting of notification popups (via setting in KCM) work
- Start on inhibition stuff (DBus API proposal sent to XDG mailing list)
wilder-5.19
Kai Uwe Broulik 7 years ago
parent 1b9b7bcc56
commit eab8338950
  1. 0
      applets/newnotifications/package/contents/ui/NotificationPopup.qml
  2. 10
      applets/newnotifications/package/contents/ui/popups/PopupHandler.qml
  3. 5
      libnotificationmanager/CMakeLists.txt
  4. 23
      libnotificationmanager/dbus/org.freedesktop.Notifications.xml
  5. 19
      libnotificationmanager/dbus/org.kde.Notifications.xml
  6. 54
      libnotificationmanager/inhibitionserver.cpp
  7. 66
      libnotificationmanager/inhibitionserver.h
  8. 7
      libnotificationmanager/notification.cpp
  9. 2
      libnotificationmanager/notification.h
  10. 1
      libnotificationmanager/notification_p.h
  11. 23
      libnotificationmanager/notificationfilterproxymodel.cpp
  12. 5
      libnotificationmanager/notificationfilterproxymodel_p.h
  13. 1
      libnotificationmanager/notificationmodel.cpp
  14. 12
      libnotificationmanager/notifications.cpp
  15. 12
      libnotificationmanager/notifications.h
  16. 2
      libnotificationmanager/notificationserver.cpp
  17. 95
      libnotificationmanager/notificationserver_p.cpp
  18. 39
      libnotificationmanager/notificationserver_p.h
  19. 62
      libnotificationmanager/settings.cpp
  20. 16
      libnotificationmanager/settings.h

@ -29,6 +29,8 @@ import org.kde.kquickcontrolsaddons 2.0
import org.kde.notificationmanager 1.0 as NotificationManager
import ".."
QtObject {
id: popupHandler
@ -78,6 +80,7 @@ QtObject {
limit: Math.ceil(popupHandler.screenRect.height / (theme.mSize(theme.defaultFont).height * 4))
showExpired: false
showDismissed: false
blacklistedDesktopEntries: notificationSettings.popupBlacklistedApplications
showJobs: notificationSettings.jobsInNotifications
groupMode: NotificationManager.Notifications.GroupDisabled
urgencies: NotificationManager.Notifications.NormalUrgency | NotificationManager.Notifications.CriticalUrgency
@ -212,6 +215,13 @@ QtObject {
onHeightChanged: Qt.callLater(positionPopups)
onWidthChanged: Qt.callLater(positionPopups)
Component.onCompleted: {
// Register apps that were seen spawning a popup so they can be configured later
if (model.desktopEntry) {
notificationSettings.registerKnownApplication(model.desktopEntry);
}
}
}
onObjectAdded: {
// also needed for it to correctly layout its contents

@ -19,8 +19,6 @@ set(notificationmanager_LIB_SRCS
notificationgroupingproxymodel.cpp
limitedrowcountproxymodel.cpp
inhibitionserver.cpp
settings.cpp
)
@ -36,8 +34,7 @@ kconfig_add_kcfg_files(notificationmanager_LIB_SRCS kcfg/jobsettings.kcfgc)
kconfig_add_kcfg_files(notificationmanager_LIB_SRCS kcfg/badgesettings.kcfgc)
# DBus
qt5_add_dbus_adaptor(notificationmanager_LIB_SRCS dbus/org.freedesktop.Notifications.xml notificationserver_p.h NotificationManager::NotificationServerPrivate fdonotificationsadaptor)
qt5_add_dbus_adaptor(notificationmanager_LIB_SRCS dbus/org.kde.Notifications.xml inhibitionserver.h NotificationManager::InhibitionServer kdenotificationsadaptor InhibitionAdaptor)
qt5_add_dbus_adaptor(notificationmanager_LIB_SRCS dbus/org.freedesktop.Notifications.xml notificationserver_p.h NotificationManager::NotificationServerPrivate)
add_library(notificationmanager ${notificationmanager_LIB_SRCS})
add_library(PW::LibNotificationManager ALIAS notificationmanager)

@ -33,5 +33,28 @@
<arg type="s" name="version" direction="out"/>
<arg type="s" name="spec_version" direction="out"/>
</method>
<!-- Inhibitions -->
<method name="Inhibit">
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
<arg type="u" direction="out"/>
<arg name="desktop_entry" type="s" direction="in"/>
<arg name="reason" type="s" direction="in"/>
<arg name="hints" type="a{sv}" direction="in"/>
</method>
<method name="UnInhibit">
<arg type="u" direction="in"/>
</method>
<property name="Inhibited" type="b" access="read">
<annotation name="org.freedesktop.DBus.Property.EmitsChangedSignal" value="true"/>
</property>
<method name="ListInhibitors">
<annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="QList&lt;Inhibition&gt;"/>
<arg name="inhibitors" type="a(ssa{sv})" direction="out"/>
</method>
</interface>
</node>

@ -1,19 +0,0 @@
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
<node>
<interface name="org.kde.Notifications.Inhibit">
<method name="Inhibit">
<annotation name="org.qtproject.QtDBus.QtTypeName.In2" value="QVariantMap"/>
<!-- Desktop entry of the application, e.g. org.kde.okular -->
<arg name="desktop_entry" type="s" direction="in"/>
<!-- Human-readable reason for the inhibition, e.g. "Giving a presentation -->
<arg name="reason" type="s" direction="in"/>
<!-- Reserved -->
<arg name="hints" type="a{sv}" direction="in"/>
<arg name="fd" type="h" direction="out"/>
</method>
<!-- TODO property for whether it is currently enabled? -->
</interface>
</node>

@ -1,54 +0,0 @@
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "inhibitionserver.h"
#include "kdenotificationsadaptor.h"
#include "notification.h"
#include <QDBusConnection>
using namespace NotificationManager;
InhibitionServer::InhibitionServer(QObject *parent)
: QObject(parent)
{
new InhibitionAdaptor(this);
QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/kde/Notifications"), this);
if (!QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.Notifications.Inhibit"))) {
qWarning() << "Failed to register Notification Inhibit service";
}
}
InhibitionServer::~InhibitionServer() = default;
InhibitionServer &InhibitionServer::self()
{
static InhibitionServer s_self;
return s_self;
}
QDBusUnixFileDescriptor InhibitionServer::Inhibit(const QString &app_name, const QString &reason, const QVariantMap &hints)
{
qDebug() << "INHIBIT" << app_name << reason << hints;
return QDBusUnixFileDescriptor();
}

@ -1,66 +0,0 @@
/*
* Copyright 2018 Kai Uwe Broulik <kde@privat.broulik.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <QObject>
#include <QDBusContext>
#include <QDBusUnixFileDescriptor>
#include <QVector>
//#include "notificationmanager_export.h"
namespace NotificationManager
{
class Notification;
/**
* @short Registers an inhibition server on the DBus
*
* TODO
*
* @author Kai Uwe Broulik <kde@privat.broulik.de>
**/
class InhibitionServer : public QObject, protected QDBusContext
{
Q_OBJECT
public:
~InhibitionServer() override;
static InhibitionServer &self();
// DBus
QDBusUnixFileDescriptor Inhibit(const QString &app_name, const QString &reason, const QVariantMap &hints);
Q_SIGNALS:
void inhibitionAdded();
void inhibitionRemoved();
private:
explicit InhibitionServer(QObject *parent = nullptr);
Q_DISABLE_COPY(InhibitionServer)
// FIXME we also need to disable move and other stuff?
// TODO list of fds
};
} // namespace NotificationManager

@ -218,7 +218,7 @@ void Notification::Private::processHints(const QVariantMap &hints)
{
auto end = hints.end();
const QString desktopEntry = hints.value(QStringLiteral("desktop-entry")).toString();
desktopEntry = hints.value(QStringLiteral("desktop-entry")).toString();
if (!desktopEntry.isEmpty()) {
KService::Ptr service = KService::serviceByStorageId(desktopEntry);
if (service) {
@ -406,6 +406,11 @@ void Notification::setImage(const QImage &image)
d->image = image;
}
QString Notification::desktopEntry() const
{
return d->desktopEntry;
}
QString Notification::applicationName() const
{
return d->applicationName;

@ -77,6 +77,8 @@ public:
QImage image() const;
void setImage(const QImage &image);
QString desktopEntry() const;
QString applicationName() const;
void setApplicationName(const QString &applicationName);

@ -57,6 +57,7 @@ public:
QImage image;
QString applicationName;
QString desktopEntry;
QString serviceName;
QString applicationIconName;

@ -72,6 +72,20 @@ void NotificationFilterProxyModel::setShowDismissed(bool show)
}
}
QStringList NotificationFilterProxyModel::blacklistedDesktopEntries() const
{
return m_blacklistedDesktopEntries;
}
void NotificationFilterProxyModel::setBlackListedDesktopEntries(const QStringList &blacklistedDesktopEntries)
{
if (m_blacklistedDesktopEntries != blacklistedDesktopEntries) {
m_blacklistedDesktopEntries = blacklistedDesktopEntries;
invalidateFilter();
emit blacklistedDesktopEntriesChanged();
}
}
bool NotificationFilterProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
{
const QModelIndex sourceIdx = sourceModel()->index(source_row, 0, source_parent);
@ -107,5 +121,14 @@ bool NotificationFilterProxyModel::filterAcceptsRow(int source_row, const QModel
}
}
if (!m_blacklistedDesktopEntries.isEmpty()) {
const QString desktopEntry = sourceIdx.data(Notifications::DesktopEntryRole).toString();
if (!desktopEntry.isEmpty()) {
if (m_blacklistedDesktopEntries.contains(desktopEntry)) {
return false;
}
}
}
return true;
}

@ -44,10 +44,14 @@ public:
bool showDismissed() const;
void setShowDismissed(bool show);
QStringList blacklistedDesktopEntries() const;
void setBlackListedDesktopEntries(const QStringList &blacklistedDesktopEntries);
signals:
void urgenciesChanged();
void showExpiredChanged();
void showDismissedChanged();
void blacklistedDesktopEntriesChanged();
protected:
bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override;
@ -58,6 +62,7 @@ private:
| Notifications::CriticalUrgency;
bool m_showDismissed = false;
bool m_showExpired = false;
QStringList m_blacklistedDesktopEntries;
};

@ -203,6 +203,7 @@ QVariant NotificationModel::data(const QModelIndex &index, int role) const
return notification.image();
}
break;
case Notifications::DesktopEntryRole: return notification.desktopEntry();
case Notifications::ApplicationNameRole: return notification.applicationName();
case Notifications::ApplicationIconNameRole: return notification.applicationIconName();

@ -106,6 +106,7 @@ void Notifications::Private::initModels()
connect(filterModel, &NotificationFilterProxyModel::urgenciesChanged, q, &Notifications::urgenciesChanged);
connect(filterModel, &NotificationFilterProxyModel::showExpiredChanged, q, &Notifications::showExpiredChanged);
connect(filterModel, &NotificationFilterProxyModel::showDismissedChanged, q, &Notifications::showDismissedChanged);
connect(filterModel, &NotificationFilterProxyModel::blacklistedDesktopEntriesChanged, q, &Notifications::blacklistedDesktopEntriesChanged);
filterModel->setSourceModel(notificationsAndJobsModel);
}
@ -290,6 +291,16 @@ void Notifications::setShowDismissed(bool show)
d->filterModel->setShowDismissed(show);
}
QStringList Notifications::blacklistedDesktopEntries() const
{
return d->filterModel->blacklistedDesktopEntries();
}
void Notifications::setBlacklistedDesktopEntries(const QStringList &blacklistedDesktopEntries)
{
d->filterModel->setBlackListedDesktopEntries(blacklistedDesktopEntries);
}
bool Notifications::showSuppressed() const
{
// TODO
@ -484,6 +495,7 @@ QHash<int, QByteArray> Notifications::roleNames() const
{BodyRole, QByteArrayLiteral("body")},
{IconNameRole, QByteArrayLiteral("iconName")},
{ImageRole, QByteArrayLiteral("image")},
{DesktopEntryRole, QByteArrayLiteral("desktopEntry")},
{ApplicationNameRole, QByteArrayLiteral("applicationName")},
{ApplicationIconNameRole, QByteArrayLiteral("applicationIconName")},

@ -71,6 +71,11 @@ class NOTIFICATIONMANAGER_EXPORT Notifications : public QSortFilterProxyModel, p
*/
Q_PROPERTY(bool showDismissed READ showDismissed WRITE setShowDismissed NOTIFY showDismissedChanged)
/**
* A list of desktop entries for which no notifications should be shown.
*/
Q_PROPERTY(QStringList blacklistedDesktopEntries READ blacklistedDesktopEntries WRITE setBlacklistedDesktopEntries NOTIFY blacklistedDesktopEntriesChanged)
/**
* Whether to show suppressed notifications.
*
@ -127,7 +132,8 @@ public:
BodyRole = Qt::UserRole + 6,
IconNameRole = Qt::UserRole + 7,
ImageRole = Qt::DecorationRole,
ApplicationNameRole = Qt::UserRole + 8,
DesktopEntryRole = Qt::UserRole + 8,
ApplicationNameRole,
ApplicationIconNameRole,
// Jobs
@ -215,6 +221,9 @@ public:
bool showDismissed() const;
void setShowDismissed(bool show);
QStringList blacklistedDesktopEntries() const;
void setBlacklistedDesktopEntries(const QStringList &blacklistedDesktopEntries);
bool showSuppressed() const;
void setShowSuppressed(bool show);
@ -259,6 +268,7 @@ signals:
void limitChanged();
void showExpiredChanged();
void showDismissedChanged();
void blacklistedDesktopEntriesChanged();
void showSuppressedChanged();
void showJobsChanged();
void urgenciesChanged();

@ -44,7 +44,7 @@ NotificationServer &NotificationServer::self()
bool NotificationServer::isValid() const
{
return d->valid;
return d->m_valid;
}
void NotificationServer::closeNotification(uint notificationId, CloseReason reason)

@ -22,7 +22,7 @@
#include "debug.h"
#include "fdonotificationsadaptor.h"
#include "notificationsadaptor.h"
#include "notification.h"
#include "notification_p.h"
@ -30,11 +30,13 @@
#include "notificationserver.h"
#include <QDBusConnection>
#include <QDBusServiceWatcher>
using namespace NotificationManager;
NotificationServerPrivate::NotificationServerPrivate(QObject *parent)
: QObject(parent)
, m_inhibitionWatcher(new QDBusServiceWatcher(this))
{
new NotificationsAdaptor(this);
@ -48,8 +50,12 @@ NotificationServerPrivate::NotificationServerPrivate(QObject *parent)
return;
}
qCInfo(NOTIFICATIONMANAGER) << "Registered Notification service on DBus";
valid = true;
m_inhibitionWatcher->setConnection(QDBusConnection::sessionBus());
m_inhibitionWatcher->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
connect(m_inhibitionWatcher, &QDBusServiceWatcher::serviceUnregistered, this, &NotificationServerPrivate::onServiceUnregistered);
qCDebug(NOTIFICATIONMANAGER) << "Registered Notification service on DBus";
m_valid = true;
}
NotificationServerPrivate::~NotificationServerPrivate() = default;
@ -58,16 +64,14 @@ uint NotificationServerPrivate::Notify(const QString &app_name, uint replaces_id
const QString &summary, const QString &body, const QStringList &actions,
const QVariantMap &hints, int timeout)
{
Q_ASSERT(calledFromDBus());
const bool wasReplaced = replaces_id > 0;
int notificationId = 0;
if (wasReplaced) {
notificationId = replaces_id;
} else {
// TODO according to spec should wrap around once INT_MAX is exceeded
++highestNotificationId;
notificationId = highestNotificationId;
++m_highestNotificationId;
notificationId = m_highestNotificationId;
}
Notification notification(notificationId);
@ -113,7 +117,9 @@ QStringList NotificationServerPrivate::GetCapabilities() const
// should we support "persistence" where notification stays present with "resident"
// but that is basically an SNI isn't it?
QStringLiteral("x-kde-urls")
QStringLiteral("x-kde-urls"),
QStringLiteral("inhibitions")
};
}
@ -124,3 +130,76 @@ QString NotificationServerPrivate::GetServerInformation(QString &vendor, QString
specVersion = QStringLiteral("1.2");
return QStringLiteral("Plasma");
}
uint NotificationServerPrivate::Inhibit(const QString &desktop_entry, const QString &reason, const QVariantMap &hints)
{
const QString service = message().service();
qCDebug(NOTIFICATIONMANAGER) << "Request inhibit from service" << service << "which is" << desktop_entry << "with reason" << reason;
// should we check for this and/or if it's actually a valid service?
if (desktop_entry.isEmpty()) {
// TODO return error
return 0;
}
m_inhibitionWatcher->addWatchedService(service);
++m_highestInhibitionCookie;
m_inhibitions.insert(m_highestInhibitionCookie, {
desktop_entry,
reason,
hints
});
m_inhibitionServices.insert(m_highestInhibitionCookie, service);
emit inhibitedChanged();
return m_highestInhibitionCookie;
}
void NotificationServerPrivate::onServiceUnregistered(const QString &serviceName)
{
qCDebug(NOTIFICATIONMANAGER) << "Inhibition service unregistered" << serviceName;
const uint cookie = m_inhibitionServices.key(serviceName);
if (!cookie) {
qCInfo(NOTIFICATIONMANAGER) << "Unknown inhibition service unregistered" << serviceName;
return;
}
// We do lookups in there again...
UnInhibit(cookie);
}
void NotificationServerPrivate::UnInhibit(uint cookie)
{
qCDebug(NOTIFICATIONMANAGER) << "Request release inhibition for cookie" << cookie;
const QString service = m_inhibitionServices.value(cookie);
if (service.isEmpty()) {
qCInfo(NOTIFICATIONMANAGER) << "Requested to release inhibition with cookie" << cookie << "that doesn't exist";
// TODO if called from dbus raise error
return;
}
m_inhibitionWatcher->removeWatchedService(service);
m_inhibitions.remove(cookie);
m_inhibitionServices.remove(cookie);
if (m_inhibitions.isEmpty()) {
emit inhibitedChanged();
}
}
QList<Inhibition> NotificationServerPrivate::ListInhibitors() const
{
return {};
}
bool NotificationServerPrivate::inhibited() const
{
return !m_inhibitions.isEmpty();
}

@ -23,6 +23,15 @@
#include <QObject>
#include <QDBusContext>
class QDBusServiceWatcher;
struct Inhibition
{
QString desktopEntry;
QString reason;
QVariantMap hints;
};
namespace NotificationManager
{
@ -32,6 +41,10 @@ class Q_DECL_HIDDEN NotificationServerPrivate : public QObject, protected QDBusC
{
Q_OBJECT
// DBus
// Inhibitions
Q_PROPERTY(bool Inhibited READ inhibited NOTIFY inhibitedChanged)
public:
NotificationServerPrivate(QObject *parent);
~NotificationServerPrivate() override;
@ -44,14 +57,34 @@ public:
QStringList GetCapabilities() const;
QString GetServerInformation(QString &vendor, QString &version, QString &specVersion) const;
// Inhibitions
uint Inhibit(const QString &desktop_entry,
const QString &reason,
const QVariantMap &hints);
void UnInhibit(uint cookie);
QList<Inhibition> ListInhibitors() const;
bool inhibited() const; // property getter
Q_SIGNALS:
// DBus
void NotificationClosed(uint id, uint reason);
void ActionInvoked(uint id, const QString &actionKey);
public:
int highestNotificationId = 0;
bool valid = false;
// FIXME connect this to properties changed dbus signal
void inhibitedChanged();
public: // stuff used by public class
bool m_valid = false;
private:
void onServiceUnregistered(const QString &serviceName);
uint m_highestNotificationId = 0;
QDBusServiceWatcher *m_inhibitionWatcher = nullptr;
uint m_highestInhibitionCookie = 0;
QHash<uint /*cookie*/, Inhibition> m_inhibitions;
QHash<uint /*cookie*/, QString> m_inhibitionServices;
};

@ -23,6 +23,9 @@
#include <QDebug>
#include <KConfigWatcher>
#include <KService>
#include "debug.h"
// Settings
#include "donotdisturbsettings.h"
@ -86,9 +89,23 @@ void Settings::Private::setGroupBehavior(KConfigGroup &group, const Settings::No
return;
}
group.writeEntry("ShowPopups", behavior.testFlag(Settings::ShowPopups));
group.writeEntry("ShowPopupsInDndMode", behavior.testFlag(Settings::ShowPopupsInDoNotDisturbMode));
group.writeEntry("ShowBadges", behavior.testFlag(Settings::ShowBadges));
if (behavior.testFlag(Settings::ShowPopups)) {
group.revertToDefault("ShowPopups", KConfigBase::Notify);
} else {
group.writeEntry("ShowPopups", false, KConfigBase::Notify);
}
if (behavior.testFlag(Settings::ShowPopupsInDoNotDisturbMode)) {
group.writeEntry("ShowPopupsInDndMode", true, KConfigBase::Notify);
} else {
group.revertToDefault("ShowPopupsInDndMode", KConfigBase::Notify);
}
if (behavior.testFlag(Settings::ShowBadges)) {
group.revertToDefault("ShowBadges", KConfigBase::Notify);
} else {
group.writeEntry("ShowBadges", false, KConfigBase::Notify);
}
setDirty(true);
}
@ -178,6 +195,26 @@ void Settings::setServiceBehavior(const QString &notifyRcName, NotificationBehav
d->setGroupBehavior(group, behaviors);
}
void Settings::registerKnownApplication(const QString &desktopEntry)
{
KService::Ptr service = KService::serviceByDesktopName(desktopEntry);
if (!service) {
qCDebug(NOTIFICATIONMANAGER) << "Application" << desktopEntry << "cannot be registered as seen application since there is no service for it";
return;
}
if (knownApplications().contains(desktopEntry)) {
return;
}
// have to write something...
d->applicatonsGroup().group(desktopEntry).writeEntry("Seen", true);
// TODO don't sync right away?
d->config->sync();
emit knownApplicationsChanged();
}
void Settings::load()
{
@ -344,3 +381,22 @@ void Settings::setBadgesInTaskManager(bool enable)
BadgeSettings::setInTaskManager(enable);
d->setDirty(true);
}
QStringList Settings::knownApplications() const
{
return d->applicatonsGroup().groupList();
}
QStringList Settings::popupBlacklistedApplications() const
{
QStringList blacklist;
const QStringList apps = knownApplications();
for (const QString &app : apps) {
if (!d->groupBehavior(d->applicatonsGroup().group(app)).testFlag(ShowPopups)) {
blacklist.append(app);
}
}
return blacklist;
}

@ -65,6 +65,14 @@ class NOTIFICATIONMANAGER_EXPORT Settings : public QObject
Q_PROPERTY(bool badgesInTaskManager READ badgesInTaskManager WRITE setBadgesInTaskManager NOTIFY settingsChanged)
/**
* A list of desktop entries of applications that have been seen sending a notification.
*/
Q_PROPERTY(QStringList knownApplications READ knownApplications NOTIFY knownApplicationsChanged)
// TODO check how heavy this is
Q_PROPERTY(QStringList popupBlacklistedApplications READ popupBlacklistedApplications NOTIFY settingsChanged)
Q_PROPERTY(bool dirty READ dirty NOTIFY dirtyChanged)
public:
@ -98,6 +106,8 @@ public:
Q_INVOKABLE NotificationBehaviors serviceBehavior(const QString &desktopEntry) const;
Q_INVOKABLE void setServiceBehavior(const QString &desktopEntry, NotificationBehaviors behaviors);
Q_INVOKABLE void registerKnownApplication(const QString &desktopEntry);
Q_INVOKABLE void load();
Q_INVOKABLE void save();
Q_INVOKABLE void defaults();
@ -132,9 +142,15 @@ public:
bool badgesInTaskManager() const;
void setBadgesInTaskManager(bool enable);
QStringList knownApplications() const;
QStringList popupBlacklistedApplications() const;
signals:
void settingsChanged();
void knownApplicationsChanged();
void dirtyChanged();
private:

Loading…
Cancel
Save