diff --git a/libnotificationmanager/CMakeLists.txt b/libnotificationmanager/CMakeLists.txt --- a/libnotificationmanager/CMakeLists.txt +++ b/libnotificationmanager/CMakeLists.txt @@ -20,6 +20,8 @@ notificationgroupingproxymodel.cpp notificationgroupcollapsingproxymodel.cpp + notificationwatcher.cpp + jobsmodel.cpp jobsmodel_p.cpp job.cpp diff --git a/libnotificationmanager/dbus/org.freedesktop.Notifications.xml b/libnotificationmanager/dbus/org.freedesktop.Notifications.xml --- a/libnotificationmanager/dbus/org.freedesktop.Notifications.xml +++ b/libnotificationmanager/dbus/org.freedesktop.Notifications.xml @@ -52,6 +52,9 @@ + + + diff --git a/libnotificationmanager/declarative/notificationmanagerplugin.cpp b/libnotificationmanager/declarative/notificationmanagerplugin.cpp --- a/libnotificationmanager/declarative/notificationmanagerplugin.cpp +++ b/libnotificationmanager/declarative/notificationmanagerplugin.cpp @@ -21,6 +21,7 @@ #include "notificationmanagerplugin.h" #include "notifications.h" +#include "notificationwatcher.h" #include "job.h" #include "server.h" #include "serverinfo.h" @@ -42,4 +43,5 @@ return &Server::self(); }); qmlRegisterUncreatableType(uri, 1, 0, "ServerInfo", QStringLiteral("Can only access ServerInfo via Server")); + qmlRegisterType(uri, 1, 1, "NotificationWatcher"); } diff --git a/libnotificationmanager/notificationwatcher.h b/libnotificationmanager/notificationwatcher.h new file mode 100644 --- /dev/null +++ b/libnotificationmanager/notificationwatcher.h @@ -0,0 +1,52 @@ +/* + * Copyright 2020 Bhushan Shah + * + * 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 . + */ + +#ifndef NOTIFICATIONWATCHER_H +#define NOTIFICATIONWATCHER_H + +#include "notificationmanager_export.h" + +#include + +class QDBusServiceWatcher; + +namespace NotificationManager +{ + +class NOTIFICATIONMANAGER_EXPORT NotificationWatcher : public QObject +{ + Q_OBJECT +public: + NotificationWatcher(QObject *parent = nullptr); + ~NotificationWatcher(); + +public Q_SLOTS: + Q_SCRIPTABLE void Notify(uint id, 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); + Q_SCRIPTABLE void CloseNotification(uint id); + +private: + QDBusServiceWatcher *m_serviceWatcher; +}; + +} // namespace NotificationManager + +#endif // NOTIFICATIONWATCHER_H diff --git a/libnotificationmanager/notificationwatcher.cpp b/libnotificationmanager/notificationwatcher.cpp new file mode 100644 --- /dev/null +++ b/libnotificationmanager/notificationwatcher.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2020 Bhushan Shah + * + * 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 . + */ + +#include "notificationwatcher.h" + +#include +#include +#include +#include + +#include + +using namespace NotificationManager; + +NotificationWatcher::NotificationWatcher(QObject *parent) + : QObject(parent) +{ + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/NotificationWatcher", this, QDBusConnection::ExportScriptableSlots); + + qDebug() << dbus.baseService(); + QDBusMessage msg = QDBusMessage::createMethodCall( + QStringLiteral("org.freedesktop.Notifications"), + QStringLiteral("/org/freedesktop/Notifications"), + QStringLiteral("org.freedesktop.Notifications"), + QStringLiteral("RegisterWatcher") + ); + QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); +} + +NotificationWatcher::~NotificationWatcher() +{ + QDBusMessage msg = QDBusMessage::createMethodCall( + QStringLiteral("org.freedesktop.Notifications"), + QStringLiteral("/org/freedesktop/Notifications"), + QStringLiteral("org.freedesktop.Notifications"), + QStringLiteral("UnRegisterWatcher") + ); + QDBusConnection::sessionBus().call(msg, QDBus::NoBlock); +} + +void NotificationWatcher::Notify(uint id, 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) +{ + //TODO: interact with model + qDebug() << "New notification" << id << app_name << body << summary; +} + + +void NotificationManager::NotificationWatcher::CloseNotification(uint id) +{ + qDebug() << id; + //TODO: interact with model +} diff --git a/libnotificationmanager/server_p.h b/libnotificationmanager/server_p.h --- a/libnotificationmanager/server_p.h +++ b/libnotificationmanager/server_p.h @@ -22,6 +22,7 @@ #include #include +#include #include "notification.h" @@ -68,6 +69,10 @@ void UnInhibit(uint cookie); bool inhibited() const; // property getter + // Subscriber for watcher + void RegisterWatcher(); + void UnRegisterWatcher(); + Q_SIGNALS: // DBus void NotificationClosed(uint id, uint reason); @@ -129,6 +134,8 @@ Notification m_lastNotification; + QStringList m_notificationWatchers; + }; } // namespace NotificationManager diff --git a/libnotificationmanager/server_p.cpp b/libnotificationmanager/server_p.cpp --- a/libnotificationmanager/server_p.cpp +++ b/libnotificationmanager/server_p.cpp @@ -223,12 +223,49 @@ emit static_cast(parent())->notificationAdded(notification); } + // currently we dispatch all notification, this is ugly + // TODO: come up with proper authentication/user selection + for (QString bus: m_notificationWatchers) { + qDebug() << "Dispatching notification to " << bus; + QDBusMessage msg = QDBusMessage::createMethodCall( + bus, + QStringLiteral("/NotificationWatcher"), + QStringLiteral(""), + QStringLiteral("Notify") + ); + msg.setArguments({ + notificationId, + notification.applicationName(), + replaces_id, + notification.applicationIconName(), + notification.summary(), + notification.body(), + notification.actionNames(), + hints, + notification.timeout() + }); + QDBusConnection::sessionBus().call(msg); + } + return notificationId; } void ServerPrivate::CloseNotification(uint id) { // spec says "If the notification no longer exists, an empty D-BUS Error message is sent back." + for (QString bus: m_notificationWatchers) { + qDebug() << "Dispatching notification to " << bus; + QDBusMessage msg = QDBusMessage::createMethodCall( + bus, + QStringLiteral("/NotificationWatcher"), + QStringLiteral(""), + QStringLiteral("CloseNotification") + ); + msg.setArguments({ + id + }); + QDBusConnection::sessionBus().call(msg); + } static_cast(parent())->closeNotification(id, Server::CloseReason::Revoked); } @@ -482,3 +519,16 @@ emit externalInhibitedChanged(); emit externalInhibitionsChanged(); } + +void ServerPrivate::RegisterWatcher() +{ + qDebug() << message().service(); + m_notificationWatchers << message().service(); + //TODO: add a dbus service watcher which automatically unregisters watcher + // when service disappears +} + +void ServerPrivate::UnRegisterWatcher() +{ + m_notificationWatchers.removeOne(message().service()); +}