ukui-notification/notification-server/server.cpp

223 lines
8.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (C) 2023, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: iaom <zhangpengfei@kylinos.cn>
*/
#include <QDBusServiceWatcher>
#include <QDBusConnection>
#include "server.h"
#include "server-private.h"
#include "notificationsadaptor.h"
#include "notificationserveradaptor.h"
#include "notification-server-config.h"
#include "utils.h"
#include "notification-close-reason.h"
#include "notification-settings/settings-manager.h"
using namespace NotificationServer;
ServerPrivate::ServerPrivate(QObject *parent) : QObject(parent), m_notificationWatchers(new QDBusServiceWatcher(this))
{
m_notificationWatchers->setConnection(QDBusConnection::sessionBus());
m_notificationWatchers->setWatchMode(QDBusServiceWatcher::WatchForUnregistration);
connect(m_notificationWatchers, &QDBusServiceWatcher::serviceUnregistered,
m_notificationWatchers, &QDBusServiceWatcher::removeWatchedService);
}
ServerPrivate::~ServerPrivate() = default;
QStringList ServerPrivate::GetCapabilities() const
{
return QStringList();
}
uint ServerPrivate::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)
{
uint id = 0;
if(replaces_id > 0) {
id = replaces_id;
} else {
id = m_increasedNotificationId++;
}
QVariantMap newHints = hints;
newHints.insert(QStringLiteral("x-ukui-createdTime"), QDateTime::currentDateTime().toString());
uint pid = 0;
QDBusReply<uint> pidReply = connection().interface()->servicePid(message().service());
if(pidReply.isValid()) {
pid = pidReply.value();
}
if(newHints.value(QStringLiteral("x-ukui-display")).toString().isEmpty() && pid > 0) {
newHints.insert(QStringLiteral("x-ukui-display"), UkuiNotification::Utils::displayFromPid(pid));
}
//如果desktop-entry只有文件名需要获取全路径
QString desktopEntry = newHints.value(QStringLiteral("desktop-entry")).toString();
if(!desktopEntry.isEmpty()) {
desktopEntry = UkuiNotification::Utils::desktopEntryFromName(desktopEntry);
}
if(desktopEntry.isEmpty() && pid > 0) {
desktopEntry = UkuiNotification::Utils::desktopEntryFromPid(pid);
}
newHints.insert(QStringLiteral("desktop-entry"), desktopEntry);
qDebug() << "New message received:" << app_name << id << app_icon << summary << body
<< actions << hints << timeout << "new hints" << newHints;
if(m_notificationWatchers->watchedServices().isEmpty()) {
Notification notification;
notification.m_appName = app_name;
notification.m_id = id;
notification.m_appIcon = app_icon;
notification.m_summary = summary;
notification.m_body = body;
notification.m_actions = actions;
notification.m_hints = newHints;
m_notificationsCache.insert(id, notification);
return id;
}
for(const QString &service : m_notificationWatchers->watchedServices()) {
QDBusMessage msg = QDBusMessage::createMethodCall(service,
QStringLiteral("/NotificationClient"),
QStringLiteral("org.ukui.NotificationClient"),
QStringLiteral("Notify"));
msg.setArguments({app_name, id, app_icon, summary, body, actions, newHints, timeout});
QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
}
return id;
}
QString ServerPrivate::GetServerInformation(QString &vendor, QString &version, QString &spec_version) const
{
vendor = QStringLiteral("Kylin");
version = QLatin1String(NOTIFICATION_SERVER_VERSION);
spec_version = QStringLiteral("1.2");
return QStringLiteral("UKUI");
}
void ServerPrivate::CloseNotification(uint id)
{
for(const QString &service : m_notificationWatchers->watchedServices()) {
QDBusMessage msg = QDBusMessage::createMethodCall(service,
QStringLiteral("/NotificationClient"),
QStringLiteral("org.ukui.NotificationClient"),
QStringLiteral("CloseNotification"));
msg.setArguments({id, UkuiNotification::NotificationCloseReason::Revoked});
QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
}
}
bool ServerPrivate::init()
{
new NotificationsAdaptor(this);
new NotificationServerAdaptor(this);
QDBusConnection conn = QDBusConnection::sessionBus();
auto registration = conn.interface()->registerService(notificationServiceName(),
QDBusConnectionInterface::ReplaceExistingService,
QDBusConnectionInterface::DontAllowReplacement);
if (registration.value() != QDBusConnectionInterface::ServiceRegistered) {
qWarning() << "Failed to register Notification service on DBus!";
return false;
}
if(!conn.registerObject(notificationServicePath(), this)) {
qWarning() << "Failed to register Notification DBus object!" << conn.lastError().message();
return false;
}
UkuiNotification::SettingsManager::self();
return true;
}
QString ServerPrivate::notificationServiceName()
{
return QStringLiteral("org.freedesktop.Notifications");
}
QString ServerPrivate::notificationServicePath()
{
return QStringLiteral("/org/freedesktop/Notifications");
}
QString ServerPrivate::notificationServiceInterface()
{
return QStringLiteral("org.freedesktop.Notifications");;
}
void ServerPrivate::RegisterClient()
{
m_notificationWatchers->addWatchedService(message().service());
qDebug() << "Watched services:" << m_notificationWatchers->watchedServices();
sendCache();
}
void ServerPrivate::UnRegisterClient()
{
m_notificationWatchers->removeWatchedService(message().service());
}
void ServerPrivate::CloseNotification(uint id, uint reason)
{
if(m_notificationsCache.contains(id)) {
m_notificationsCache.remove(id);
}
Q_EMIT NotificationClosed(id, reason);
}
void ServerPrivate::InvokeAction(uint id, const QString &action_key)
{
qDebug() << "InvokeAction" << id << action_key;
Q_EMIT ActionInvoked(id, action_key);
}
void ServerPrivate::sendCache()
{
for(const uint &id : m_notificationsCache.keys()) {
auto notification = m_notificationsCache.take(id);
for(const QString &service : m_notificationWatchers->watchedServices()) {
QDBusMessage msg = QDBusMessage::createMethodCall(service,
QStringLiteral("/NotificationClient"),
QStringLiteral("org.ukui.NotificationClient"),
QStringLiteral("Notify"));
msg.setArguments({notification.m_appName, notification.m_id, notification.m_appIcon, notification.m_summary,
notification.m_body, notification.m_actions, notification.m_hints, notification.m_timeout});
QDBusConnection::sessionBus().call(msg, QDBus::NoBlock);
}
}
}
void ServerPrivate::UpdateUnreadMessagesNumber(const QString &desktopEntry, uint number)
{
Q_EMIT UnreadMessageNumberUpdated(desktopEntry, number);
}
Server::Server(QObject *parent): QObject(parent), d(new ServerPrivate(this))
{
}
Server &Server::self()
{
static Server self;
return self;
}
bool Server::init()
{
return d->init();
}
Server::~Server() = default;