Plasma-workspace

notificationsmodel.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Shah Bhushan <bshah@kde.org>
3 SPDX-FileCopyrightText: 2018-2019 Kai Uwe Broulik <kde@privat.broulik.de>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "notificationsmodel.h"
9#include "notification_p.h"
10#include "server.h"
11
12#include "debug.h"
13
14#include <QProcess>
15
16#include <KShell>
17
18using namespace NotificationManager;
19
20NotificationsModel::Ptr NotificationsModel::createNotificationsModel()
21{
22 static std::weak_ptr<NotificationsModel> s_instance;
23 if (s_instance.expired()) {
24 std::shared_ptr<NotificationsModel> ptr(new NotificationsModel());
25 s_instance = ptr;
26 return ptr;
27 }
28 return s_instance.lock();
29}
30
31NotificationsModel::NotificationsModel()
32{
33 connect(&Server::self(), &Server::notificationAdded, this, [this](const Notification &notification) {
34 onNotificationAdded(notification);
35 });
36 connect(&Server::self(), &Server::notificationReplaced, this, [this](uint replacedId, const Notification &notification) {
37 onNotificationReplaced(replacedId, notification);
38 });
39 connect(&Server::self(), &Server::notificationRemoved, this, [this](uint removedId, Server::CloseReason reason) {
40 onNotificationRemoved(removedId, reason);
41 });
42 connect(&Server::self(), &Server::serviceOwnershipLost, this, [this] {
43 // Expire all notifications as we're defunct now
44 const auto notificationList = notifications();
45 for (const Notification &notification : notificationList) {
46 if (!notification.expired()) {
47 onNotificationRemoved(notification.id(), Server::CloseReason::Expired);
48 }
49 }
50 });
51 Server::self().init();
52}
53
54void NotificationsModel::expire(uint notificationId)
55{
56 if (rowOfNotification(notificationId) > -1) {
57 Server::self().closeNotification(notificationId, Server::CloseReason::Expired);
58 }
59}
60
61void NotificationsModel::close(uint notificationId)
62{
63 if (rowOfNotification(notificationId) > -1) {
64 Server::self().closeNotification(notificationId, Server::CloseReason::DismissedByUser);
65 }
66}
67
68void NotificationsModel::invokeDefaultAction(uint notificationId, Notifications::InvokeBehavior behavior)
69{
70 const int row = rowOfNotification(notificationId);
71 if (row == -1) {
72 return;
73 }
74
75 const Notification &notification = notifications().at(row);
76 if (!notification.hasDefaultAction()) {
77 qCWarning(NOTIFICATIONMANAGER) << "Trying to invoke default action on notification" << notificationId << "which doesn't have one";
78 return;
79 }
80
81 Server::self().invokeAction(notificationId,
82 QStringLiteral("default"), // FIXME make a static Notification::defaultActionName() or something
83 notification.d->xdgTokenAppId,
84 behavior,
85 window());
86}
87
88void NotificationsModel::invokeAction(uint notificationId, const QString &actionName, Notifications::InvokeBehavior behavior)
89{
90 const int row = rowOfNotification(notificationId);
91 if (row == -1) {
92 return;
93 }
94
95 const Notification &notification = notifications().at(row);
96 if (!notification.actionNames().contains(actionName)) {
97 qCWarning(NOTIFICATIONMANAGER) << "Trying to invoke action" << actionName << "on notification" << notificationId << "which it doesn't have";
98 return;
99 }
100
101 Server::self().invokeAction(notificationId, actionName, notification.d->xdgTokenAppId, behavior, window());
102}
103
104void NotificationsModel::reply(uint notificationId, const QString &text, Notifications::InvokeBehavior behavior)
105{
106 const int row = rowOfNotification(notificationId);
107 if (row == -1) {
108 return;
109 }
110
111 const Notification &notification = notifications().at(row);
112 if (!notification.hasReplyAction()) {
113 qCWarning(NOTIFICATIONMANAGER) << "Trying to reply to a notification which doesn't have a reply action";
114 return;
115 }
116
117 Server::self().reply(notification.dBusService(), notificationId, text, behavior);
118}
119
120void NotificationsModel::configure(uint notificationId)
121{
122 const int row = rowOfNotification(notificationId);
123 if (row == -1) {
124 return;
125 }
126
127 const Notification &notification = notifications().at(row);
128
129 if (notification.d->hasConfigureAction) {
130 Server::self().invokeAction(notificationId,
131 QStringLiteral("settings"),
132 notification.d->xdgTokenAppId,
133 Notifications::None, // FIXME make a static Notification::configureActionName() or something
134 window());
135 return;
136 }
137
138 if (!notification.desktopEntry().isEmpty() || !notification.notifyRcName().isEmpty()) {
139 configure(notification.desktopEntry(), notification.notifyRcName(), notification.eventId());
140 return;
141 }
142
143 qCWarning(NOTIFICATIONMANAGER) << "Trying to configure notification" << notificationId << "which isn't configurable";
144}
145
146void NotificationsModel::configure(const QString &desktopEntry, const QString &notifyRcName, const QString &eventId)
147{
148 // TODO would be nice to just have a signal but since NotificationsModel is shared,
149 // if we connect to this from Notifications you would get a signal in every instance
150 // and potentially open the config dialog multiple times.
151
152 QStringList args;
153 if (!desktopEntry.isEmpty()) {
154 args.append(QStringLiteral("--desktop-entry"));
155 args.append(desktopEntry);
156 }
157 if (!notifyRcName.isEmpty()) {
158 args.append(QStringLiteral("--notifyrc"));
159 args.append(notifyRcName);
160 }
161 if (!eventId.isEmpty()) {
162 args.append(QStringLiteral("--event-id"));
163 args.append(eventId);
164 }
165
166 QProcess::startDetached(QStringLiteral("kcmshell6"), {QStringLiteral("notifications"), QStringLiteral("--args"), KShell::joinArgs(args)});
167}
Represents a single notification.
CloseReason
The reason a notification was closed.
Definition server.h:69
@ Expired
The notification timed out.
@ DismissedByUser
The user explicitly closed or acknowledged the notification.
void notificationReplaced(uint replacedId, const Notification &notification)
Emitted when a notification is supposed to be updated This is emitted regardless of any filtering rul...
void serviceOwnershipLost()
Emitted when the ownership of the Notification DBus Service is lost.
void notificationRemoved(uint id, CloseReason reason)
Emitted when a notification got removed (closed)
void notificationAdded(const Notification &notification)
Emitted when a notification was added.
KCOREADDONS_EXPORT QString joinArgs(const QStringList &args)
void append(QList< T > &&value)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
bool isEmpty() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:17:42 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.