185 lines
7.0 KiB
C++
185 lines
7.0 KiB
C++
//
|
|
// Created by zpf on 23-2-2.
|
|
//
|
|
|
|
#include "notification-client.h"
|
|
#include "notification-client-private.h"
|
|
#include <QDBusConnection>
|
|
#include "notificationclientadaptor.h"
|
|
|
|
using namespace UkuiNotification;
|
|
|
|
NotificationClientPrivate::NotificationClientPrivate(NotificationClient *q, QObject *parent) : QObject(parent), q(q)
|
|
{
|
|
}
|
|
|
|
NotificationClientPrivate::~NotificationClientPrivate()
|
|
{
|
|
if(m_notificationsInterface) {
|
|
m_notificationsInterface->call(QDBus::NoBlock, QStringLiteral("UnRegisterClient"));
|
|
delete m_notificationsInterface;
|
|
m_notificationsInterface = nullptr;
|
|
}
|
|
}
|
|
|
|
bool NotificationClientPrivate::init()
|
|
{
|
|
new NotificationClientAdaptor(this);
|
|
QDBusConnection conn = QDBusConnection::sessionBus();
|
|
|
|
if(!conn.registerObject(clientServicePath(), clientServiceInterface(), this)) {
|
|
qWarning() << "Failed to register NotificationClient DBus object!" << conn.lastError();
|
|
return false;
|
|
}
|
|
auto *watcher = new QDBusServiceWatcher(QStringLiteral("org.freedesktop.Notifications"),
|
|
conn,
|
|
QDBusServiceWatcher::WatchForOwnerChange,
|
|
this);
|
|
connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, [](const QString &service, const QString &oldOwner, const QString &newOwner){
|
|
qDebug() << "serviceOwnerChanged" << service << oldOwner << newOwner;
|
|
});
|
|
|
|
return registerClient();
|
|
}
|
|
|
|
bool NotificationClientPrivate::registerClient()
|
|
{
|
|
QDBusConnection conn = QDBusConnection::sessionBus();
|
|
m_notificationsInterface = new OrgFreedesktopNotificationsInterface(QStringLiteral("org.freedesktop.Notifications"),
|
|
QStringLiteral("/org/freedesktop/Notifications"),
|
|
conn);
|
|
if(!m_notificationsInterface->isValid()) {
|
|
qWarning() << "Failed to creat dbus interface for notification server!" << conn.lastError();
|
|
return false;
|
|
}
|
|
connect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
|
|
this, &NotificationClientPrivate::notificationClosed);
|
|
if(!m_serverInterface) {
|
|
m_serverInterface = new QDBusInterface(QStringLiteral("org.freedesktop.Notifications"),
|
|
QStringLiteral("/org/freedesktop/Notifications"),
|
|
QStringLiteral("org.ukui.NotificationServer"),
|
|
conn,
|
|
this);
|
|
if(!m_serverInterface->isValid()) {
|
|
qWarning() << "Failed to create notification server interface! " << conn.lastError();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QDBusMessage reply = m_serverInterface->call(QStringLiteral("RegisterClient"));
|
|
if (reply.type() == QDBusMessage::ErrorMessage || reply.type() == QDBusMessage::InvalidMessage) {
|
|
qWarning() << "Failed to call RegisterClient!" << conn.lastError() << reply.type();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void NotificationClientPrivate::unRegisterClient()
|
|
{
|
|
disconnect(m_notificationsInterface, &OrgFreedesktopNotificationsInterface::NotificationClosed,
|
|
this, &NotificationClientPrivate::notificationClosed);
|
|
if(m_notificationsInterface) {
|
|
delete m_notificationsInterface;
|
|
m_notificationsInterface = nullptr;
|
|
}
|
|
}
|
|
|
|
QString NotificationClientPrivate::clientServicePath()
|
|
{
|
|
return QStringLiteral("/NotificationClient");
|
|
}
|
|
|
|
QString NotificationClientPrivate::clientServiceInterface()
|
|
{
|
|
return QStringLiteral("org.ukui.NotificationClient");
|
|
}
|
|
|
|
void NotificationClientPrivate::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)
|
|
{
|
|
PopupNotification notification(replaces_id);
|
|
notification.setSummary(summary);
|
|
notification.setBody(body);
|
|
notification.setApplicationName(app_name);
|
|
notification.setAplicationIconName(app_icon);
|
|
notification.setActions(actions);
|
|
notification.setTimeout(timeout);
|
|
notification.setHints(hints);
|
|
Q_EMIT q->newNotification(notification);
|
|
}
|
|
|
|
void NotificationClientPrivate::notificationClosed(uint id, uint reason)
|
|
{
|
|
NotificationClient::CloseReason closeReason = NotificationClient::Undefined;
|
|
switch (reason) {
|
|
case 1:
|
|
closeReason = NotificationClient::Expired;
|
|
break;
|
|
case 2:
|
|
closeReason = NotificationClient::DismissedByUser;
|
|
break;
|
|
case 3:
|
|
closeReason = NotificationClient::Revoked;
|
|
break;
|
|
}
|
|
Q_EMIT q->notificationClosed(id, closeReason);
|
|
}
|
|
|
|
void NotificationClientPrivate::closeNotification(uint id, NotificationClient::CloseReason reason)
|
|
{
|
|
if(!m_notificationsInterface) {
|
|
return;
|
|
}
|
|
QDBusMessage reply = m_notificationsInterface->callWithArgumentList(QDBus::NoBlock, QStringLiteral("CloseNotification"), {id, reason});
|
|
if (reply.type() == QDBusMessage::ErrorMessage) {
|
|
qWarning() << "Failed to call CloseNotification!" << QDBusConnection::sessionBus().lastError();
|
|
}
|
|
}
|
|
|
|
void NotificationClientPrivate::serviceChange(const QString &service, const QString &oldOwner, const QString &newOwner)
|
|
{
|
|
qDebug() << "Notification Service" << service << "status change, old owner:" << oldOwner << "new:" << newOwner;
|
|
if(newOwner.isEmpty()) {
|
|
unRegisterClient();
|
|
} else if (oldOwner.isEmpty()) {
|
|
registerClient();
|
|
}
|
|
}
|
|
|
|
void NotificationClientPrivate::invokeAction(uint id, const QString &action_key, const QString &action,
|
|
const QString &display)
|
|
{
|
|
if(!m_notificationsInterface) {
|
|
return;
|
|
}
|
|
QDBusMessage reply = m_notificationsInterface->callWithArgumentList(QDBus::NoBlock,
|
|
QStringLiteral("InvokedAction"),
|
|
{id, action_key, action, display});
|
|
if (reply.type() == QDBusMessage::ErrorMessage) {
|
|
qWarning() << "Failed to call InvokedAction!" << QDBusConnection::sessionBus().lastError();
|
|
}
|
|
}
|
|
|
|
NotificationClient::NotificationClient(QObject *parent) : QObject(parent), d(new NotificationClientPrivate(this))
|
|
{
|
|
qRegisterMetaType<PopupNotification>("PopupNotification");
|
|
}
|
|
|
|
NotificationClient::~NotificationClient() = default;
|
|
|
|
bool NotificationClient::registerClient()
|
|
{
|
|
return d->init();
|
|
}
|
|
|
|
void NotificationClient::closeNotification(uint id, NotificationClient::CloseReason reason)
|
|
{
|
|
d->closeNotification(id, reason);
|
|
}
|
|
|
|
void NotificationClient::invokeAction(uint id, const QString &action_key, const QString &action, const QString &display)
|
|
{
|
|
d->invokeAction(id, action_key, action, display);
|
|
}
|