You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
205 lines
6.8 KiB
205 lines
6.8 KiB
/* |
|
* Copyright 2018-2019 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 "notificationserver_p.h" |
|
|
|
#include "debug.h" |
|
|
|
#include "notificationsadaptor.h" |
|
|
|
#include "notification.h" |
|
#include "notification_p.h" |
|
|
|
#include "notificationserver.h" |
|
|
|
#include <QDBusConnection> |
|
#include <QDBusServiceWatcher> |
|
|
|
using namespace NotificationManager; |
|
|
|
NotificationServerPrivate::NotificationServerPrivate(QObject *parent) |
|
: QObject(parent) |
|
, m_inhibitionWatcher(new QDBusServiceWatcher(this)) |
|
{ |
|
new NotificationsAdaptor(this); |
|
|
|
if (!QDBusConnection::sessionBus().registerObject(QStringLiteral("/org/freedesktop/Notifications"), this)) { |
|
qCWarning(NOTIFICATIONMANAGER) << "Failed to register Notification DBus object"; |
|
return; |
|
} |
|
|
|
if (!QDBusConnection::sessionBus().registerService(QStringLiteral("org.freedesktop.Notifications"))) { |
|
qCWarning(NOTIFICATIONMANAGER) << "Failed to register Notification service on DBus"; |
|
return; |
|
} |
|
|
|
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; |
|
|
|
uint NotificationServerPrivate::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) |
|
{ |
|
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 |
|
++m_highestNotificationId; |
|
notificationId = m_highestNotificationId; |
|
} |
|
|
|
Notification notification(notificationId); |
|
notification.setSummary(summary); |
|
notification.setBody(body); |
|
// we actually use that as notification icon (unless an image pixmap is provided in hints) |
|
notification.setIconName(app_icon); |
|
notification.setApplicationName(app_name); |
|
|
|
notification.setActions(actions); |
|
|
|
notification.setTimeout(timeout); |
|
|
|
// might override some of the things we set above (like application name) |
|
notification.d->processHints(hints); |
|
|
|
if (wasReplaced) { |
|
notification.setUpdated(); |
|
emit static_cast<NotificationServer*>(parent())->notificationReplaced(replaces_id, notification); |
|
} else { |
|
emit static_cast<NotificationServer*>(parent())->notificationAdded(notification); |
|
} |
|
|
|
return notificationId; |
|
} |
|
|
|
void NotificationServerPrivate::CloseNotification(uint id) |
|
{ |
|
// spec says "If the notification no longer exists, an empty D-BUS Error message is sent back." |
|
static_cast<NotificationServer*>(parent())->closeNotification(id, NotificationServer::CloseReason::Revoked); |
|
} |
|
|
|
QStringList NotificationServerPrivate::GetCapabilities() const |
|
{ |
|
// should this be configurable somehow so the UI can tell what it implements? |
|
return QStringList{ |
|
QStringLiteral("body"), |
|
QStringLiteral("body-hyperlinks"), |
|
QStringLiteral("body-markup"), |
|
QStringLiteral("body-images"), |
|
QStringLiteral("icon-static"), |
|
QStringLiteral("actions"), |
|
// should we support "persistence" where notification stays present with "resident" |
|
// but that is basically an SNI isn't it? |
|
|
|
QStringLiteral("x-kde-urls"), |
|
|
|
QStringLiteral("inhibitions") |
|
}; |
|
} |
|
|
|
QString NotificationServerPrivate::GetServerInformation(QString &vendor, QString &version, QString &specVersion) const |
|
{ |
|
vendor = QStringLiteral("KDE"); |
|
version = QLatin1String(PROJECT_VERSION); |
|
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(); |
|
}
|
|
|