KNotifications

knotification.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2005-2006 Olivier Goffart <ogoffart at kde.org>
4 SPDX-FileCopyrightText: 2013-2014 Martin Klapetek <mklapetek@kde.org>
5
6 code from KNotify/KNotifyClient
7 SPDX-FileCopyrightText: 1997 Christian Esken <esken@kde.org>
8 SPDX-FileCopyrightText: 2000 Charles Samuels <charles@kde.org>
9 SPDX-FileCopyrightText: 2000 Stefan Schimanski <1Stein@gmx.de>
10 SPDX-FileCopyrightText: 2000 Matthias Ettrich <ettrich@kde.org>
11 SPDX-FileCopyrightText: 2000 Waldo Bastian <bastian@kde.org>
12 SPDX-FileCopyrightText: 2000-2003 Carsten Pfeiffer <pfeiffer@kde.org>
13 SPDX-FileCopyrightText: 2005 Allan Sandfeld Jensen <kde@carewolf.com>
14
15 SPDX-License-Identifier: LGPL-2.0-only
16*/
17
18#include "knotification.h"
19#include "debug_p.h"
20#include "knotification_p.h"
21#include "knotificationmanager_p.h"
22#include "knotificationreplyaction.h"
23
24#include <config-knotifications.h>
25
26#include <QGuiApplication>
27
28#include <QStringList>
29#include <QUrl>
30
31// incremental notification ID
32static int notificationIdCounter = 0;
33
34class KNotificationActionPrivate
35{
36public:
37 QString label;
38 QString id;
39};
40
41KNotificationAction::KNotificationAction(QObject *parent)
42 : QObject(parent)
43 , d(new KNotificationActionPrivate)
44{
45}
46
47KNotificationAction::KNotificationAction(const QString &label)
48 : QObject()
49 , d(new KNotificationActionPrivate)
50{
51 d->label = label;
52}
53
54KNotificationAction::~KNotificationAction()
55{
56}
57
59{
60 return d->label;
61}
62
64{
65 if (d->label != label) {
66 d->label = label;
68 }
69}
70
71QString KNotificationAction::id() const
72{
73 return d->id;
74}
75
76void KNotificationAction::setId(const QString &id)
77{
78 d->id = id;
79}
80
82 : QObject(parent)
83 , d(new Private)
84{
85 d->eventId = eventId;
86 d->flags = flags;
87 connect(&d->updateTimer, &QTimer::timeout, this, &KNotification::update);
88 d->updateTimer.setSingleShot(true);
89 d->updateTimer.setInterval(100);
90 d->id = ++notificationIdCounter;
91}
92
93KNotification::~KNotification()
94{
95 if (d->ownsActions) {
96 qDeleteAll(d->actions);
97 delete d->defaultAction;
98 }
99
100 if (d->id >= 0) {
101 KNotificationManager::self()->close(d->id);
102 }
103}
104
106{
107 return d->eventId;
108}
109
111{
112 if (d->eventId != eventId) {
113 d->eventId = eventId;
115 }
116}
117
119{
120 return d->title;
121}
122
124{
125 return d->text;
126}
127
129{
130 if (title == d->title) {
131 return;
132 }
133
134 d->needUpdate = true;
135 d->title = title;
137 if (d->id >= 0) {
138 d->updateTimer.start();
139 }
140}
141
143{
144 if (text == d->text) {
145 return;
146 }
147
148 d->needUpdate = true;
149 d->text = text;
151 if (d->id >= 0) {
152 d->updateTimer.start();
153 }
154}
155
157{
158 if (icon == d->iconName) {
159 return;
160 }
161
162 d->needUpdate = true;
163 d->iconName = icon;
165 if (d->id >= 0) {
166 d->updateTimer.start();
167 }
168}
169
171{
172 return d->iconName;
173}
174
176{
177 return d->pixmap;
178}
179
181{
182 d->needUpdate = true;
183 d->pixmap = pix;
184 if (d->id >= 0) {
185 d->updateTimer.start();
186 }
187}
188
189QList<KNotificationAction *> KNotification::actions() const
190{
191 return d->actions;
192}
193
195{
196 if (d->ownsActions) {
197 qDeleteAll(d->actions);
198 }
199 d->actions.clear();
200 d->actionIdCounter = 1;
201
202 d->needUpdate = true;
203 if (d->id >= 0) {
204 d->updateTimer.start();
205 }
206}
207
209{
210 d->needUpdate = true;
211
212 KNotificationAction *action = new KNotificationAction(label);
213 action->setId(QString::number(d->actionIdCounter));
214 d->actionIdCounter++;
215
216 d->actions << action;
217 d->ownsActions = true;
219
220 if (d->id >= 0) {
221 d->updateTimer.start();
222 }
223
224 return action;
225}
226
227void KNotification::setActionsQml(QList<KNotificationAction *> actions)
228{
229 if (actions == d->actions) {
230 return;
231 }
232
233 d->actions.clear();
234
235 d->needUpdate = true;
236 d->actions = actions;
237 d->ownsActions = false;
239
240 int idCounter = 1;
241
242 for (KNotificationAction *action : d->actions) {
243 action->setId(QString::number(idCounter));
244 ++idCounter;
245 }
246
247 if (d->id >= 0) {
248 d->updateTimer.start();
249 }
250}
251
253{
254 return d->replyAction.get();
255}
256
257void KNotification::setReplyAction(std::unique_ptr<KNotificationReplyAction> replyAction)
258{
259 if (replyAction == d->replyAction) {
260 return;
261 }
262
263 d->needUpdate = true;
264 d->replyAction = std::move(replyAction);
265 if (d->id >= 0) {
266 d->updateTimer.start();
267 }
268}
269
271{
272 if (d->ownsActions) {
273 delete d->defaultAction;
274 }
275
276 d->needUpdate = true;
277 d->ownsActions = true;
278 d->defaultAction = new KNotificationAction(label);
279
280 d->defaultAction->setId(QStringLiteral("default"));
281
283 if (d->id >= 0) {
284 d->updateTimer.start();
285 }
286
287 return d->defaultAction;
288}
289
290void KNotification::setDefaultActionQml(KNotificationAction *defaultAction)
291{
292 if (defaultAction == d->defaultAction) {
293 return;
294 }
295
296 d->needUpdate = true;
297 d->defaultAction = defaultAction;
298 d->ownsActions = false;
299
300 d->defaultAction->setId(QStringLiteral("default"));
301
303 if (d->id >= 0) {
304 d->updateTimer.start();
305 }
306}
307
309{
310 return d->defaultAction;
311}
312
314{
315 return d->flags;
316}
317
319{
320 if (d->flags == flags) {
321 return;
322 }
323
324 d->needUpdate = true;
325 d->flags = flags;
327 if (d->id >= 0) {
328 d->updateTimer.start();
329 }
330}
331
333{
334 return d->componentName;
335}
336
338{
339 if (d->componentName != c) {
340 d->componentName = c;
342 }
343}
344
346{
347 return QUrl::fromStringList(d->hints[QStringLiteral("x-kde-urls")].toStringList());
348}
349
351{
352 setHint(QStringLiteral("x-kde-urls"), QUrl::toStringList(urls));
354}
355
357{
358 return d->urgency;
359}
360
362{
363 if (d->urgency == urgency) {
364 return;
365 }
366
367 d->needUpdate = true;
368 d->urgency = urgency;
370 if (d->id >= 0) {
371 d->updateTimer.start();
372 }
373}
374
375void KNotification::activate(const QString &actionId)
376{
377 if (d->defaultAction && actionId == QLatin1String("default")) {
378 Q_EMIT d->defaultAction->activated();
379 }
380
381 for (KNotificationAction *action : d->actions) {
382 if (action->id() == actionId) {
383 Q_EMIT action->activated();
384 }
385 }
386}
387
389{
390 if (d->id >= 0) {
391 KNotificationManager::self()->close(d->id);
392 }
393
394 if (d->id == -1) {
395 d->id = -2;
396 Q_EMIT closed();
397 if (d->autoDelete) {
398 deleteLater();
399 } else {
400 // reset for being reused
401 d->isNew = true;
402 d->id = ++notificationIdCounter;
403 }
404 }
405}
406
407static QString defaultComponentName()
408{
409#if defined(Q_OS_ANDROID)
410 return QStringLiteral("android_defaults");
411#else
412 return QStringLiteral("plasma_workspace");
413#endif
414}
415
417 const QString &title,
418 const QString &text,
419 const QPixmap &pixmap,
420 const NotificationFlags &flags,
421 const QString &componentName)
422{
423 KNotification *notify = new KNotification(eventid, flags);
424 notify->setTitle(title);
425 notify->setText(text);
426 notify->setPixmap(pixmap);
427 notify->setComponentName((flags & DefaultEvent) ? defaultComponentName() : componentName);
428
430
431 return notify;
432}
433
435KNotification::event(const QString &eventid, const QString &text, const QPixmap &pixmap, const NotificationFlags &flags, const QString &componentName)
436{
437 return event(eventid, QString(), text, pixmap, flags, componentName);
438}
439
440KNotification *KNotification::event(StandardEvent eventid, const QString &title, const QString &text, const QPixmap &pixmap, const NotificationFlags &flags)
441{
442 return event(standardEventToEventId(eventid), title, text, pixmap, flags | DefaultEvent);
443}
444
445KNotification *KNotification::event(StandardEvent eventid, const QString &text, const QPixmap &pixmap, const NotificationFlags &flags)
446{
447 return event(eventid, QString(), text, pixmap, flags);
448}
449
451 const QString &title,
452 const QString &text,
453 const QString &iconName,
454 const NotificationFlags &flags,
455 const QString &componentName)
456{
457 KNotification *notify = new KNotification(eventid, flags);
458 notify->setTitle(title);
459 notify->setText(text);
460 notify->setIconName(iconName);
461 notify->setComponentName((flags & DefaultEvent) ? defaultComponentName() : componentName);
462
464
465 return notify;
466}
467
468KNotification *KNotification::event(StandardEvent eventid, const QString &title, const QString &text, const QString &iconName, const NotificationFlags &flags)
469{
470 return event(standardEventToEventId(eventid), title, text, iconName, flags | DefaultEvent);
471}
472
473KNotification *KNotification::event(StandardEvent eventid, const QString &title, const QString &text, const NotificationFlags &flags)
474{
475 return event(standardEventToEventId(eventid), title, text, standardEventToIconName(eventid), flags | DefaultEvent);
476}
477
478void KNotification::ref()
479{
480 d->ref++;
481}
482void KNotification::deref()
483{
484 Q_ASSERT(d->ref > 0);
485 d->ref--;
486 if (d->ref == 0) {
487 d->id = -1;
488 close();
489 }
490}
491
492void KNotification::beep(const QString &reason)
493{
494 event(QStringLiteral("beep"), reason, QPixmap(), CloseOnTimeout | DefaultEvent);
495}
496
498{
499 d->needUpdate = false;
500 if (d->isNew) {
501 d->isNew = false;
502 KNotificationManager::self()->notify(this);
503 } else {
504 KNotificationManager::self()->reemit(this);
505 }
506}
507
508int KNotification::id()
509{
510 if (!d) {
511 return -1;
512 }
513 return d->id;
514}
515
517{
518 QString appname;
519
520 if (d->flags & DefaultEvent) {
521 appname = defaultComponentName();
522 } else if (!d->componentName.isEmpty()) {
523 appname = d->componentName;
524 } else {
526 }
527
528 return appname;
529}
530
532{
533 return d->autoDelete;
534}
535
536void KNotification::setAutoDelete(bool autoDelete)
537{
538 if (d->autoDelete != autoDelete) {
539 d->autoDelete = autoDelete;
541 }
542}
543
544void KNotification::update()
545{
546 if (d->needUpdate) {
547 KNotificationManager::self()->update(this);
548 }
549}
550
551QString KNotification::standardEventToEventId(KNotification::StandardEvent event)
552{
554 switch (event) {
555 case Warning:
556 eventId = QStringLiteral("warning");
557 break;
558 case Error:
559 eventId = QStringLiteral("fatalerror");
560 break;
561 case Catastrophe:
562 eventId = QStringLiteral("catastrophe");
563 break;
564 case Notification: // fall through
565 default:
566 eventId = QStringLiteral("notification");
567 break;
568 }
569 return eventId;
570}
571
572QString KNotification::standardEventToIconName(KNotification::StandardEvent event)
573{
575 switch (event) {
576 case Warning:
577 iconName = QStringLiteral("dialog-warning");
578 break;
579 case Error:
580 iconName = QStringLiteral("dialog-error");
581 break;
582 case Catastrophe:
583 iconName = QStringLiteral("dialog-error");
584 break;
585 case Notification: // fall through
586 default:
587 iconName = QStringLiteral("dialog-information");
588 break;
589 }
590 return iconName;
591}
592
593void KNotification::setHint(const QString &hint, const QVariant &value)
594{
595 if (value == d->hints.value(hint)) {
596 return;
597 }
598
599 d->needUpdate = true;
600 d->hints[hint] = value;
601 if (d->id >= 0) {
602 d->updateTimer.start();
603 }
605}
606
607QVariantMap KNotification::hints() const
608{
609 return d->hints;
610}
611
612void KNotification::setHints(const QVariantMap &hints)
613{
614 if (hints == d->hints) {
615 return;
616 }
617
618 d->needUpdate = true;
619 d->hints = hints;
620 if (d->id >= 0) {
621 d->updateTimer.start();
622 }
624}
625
627{
628 return d->xdgActivationToken;
629}
630
632{
633 if (window == d->window) {
634 return;
635 }
636
637 disconnect(d->window, &QWindow::activeChanged, this, &KNotification::slotWindowActiveChanged);
638 d->window = window;
639 connect(d->window, &QWindow::activeChanged, this, &KNotification::slotWindowActiveChanged);
640}
641
642void KNotification::slotWindowActiveChanged()
643{
644 if (d->window->isActive() && (d->flags & CloseWhenWindowActivated)) {
645 close();
646 }
647}
648
650{
651 return d->window;
652}
653
654#include "moc_knotification.cpp"
This class represents a notification.
void labelChanged(const QString &label)
Emitted when label changed.
void setLabel(const QString &label)
Set the user-facing label for the action.
void activated()
Emitted when the user activates the action.
KNotification is the main class for creating notifications.
void defaultActionChanged()
Emitted when defaultAction changed.
void clearActions()
Removes all actions previously added by addAction() from the notification.
void sendEvent()
Send the notification to the server.
QWindow * window() const
The window associated with this notification.
KNotificationReplyAction * replyAction() const
void urgencyChanged()
Emitted when urgency changed.
void eventIdChanged()
Emitted when eventId changed.
QString title
Set the title of the notification popup.
void setTitle(const QString &title)
Set the title of the notification popup.
void setEventId(const QString &eventId)
Set the event id, if not already passed to the constructor.
KNotification(const QString &eventId, NotificationFlags flags=CloseOnTimeout, QObject *parent=nullptr)
Create a new notification.
KNotificationAction * defaultAction() const
void iconNameChanged()
Emitted when iconName changed.
void closed()
Emitted when the notification is closed.
QPixmap pixmap() const
void setAutoDelete(bool autoDelete)
Sets whether this notification object will be automatically deleted after closing.
void actionsChanged()
Emitted when actions changed.
void close()
Close the notification without activating it.
void hintsChanged()
Emitted when hints changes.
QVariantMap hints
static KNotification * event(const QString &eventId, const QString &title, const QString &text, const QPixmap &pixmap=QPixmap(), const NotificationFlags &flags=CloseOnTimeout, const QString &componentName=QString())
emit an event
NotificationFlags flags
Set the notification flags.
Urgency
The urgency of a notification.
static void beep(const QString &reason=QString())
This is a simple substitution for QApplication::beep()
void setFlags(const NotificationFlags &flags)
Set the notification flags.
void titleChanged()
Emitted when title changed.
void setPixmap(const QPixmap &pix)
Set the pixmap that will be shown in the popup.
QString eventId
Set the event id, if not already passed to the constructor.
QString text
Set the notification text that will appear in the popup.
Urgency urgency
Sets the urgency of the notification.
void autoDeleteChanged()
Emitted when autoDelete changed.
Q_INVOKABLE void setHint(const QString &hint, const QVariant &value)
void setIconName(const QString &icon)
Set the icon that will be shown in the popup.
QString appName() const
void setComponentName(const QString &componentName)
The componentData is used to determine the location of the config file.
StandardEvent
default events you can use in the event function
bool isAutoDelete() const
Returns whether this notification object will be automatically deleted after closing.
KNotificationAction * addAction(const QString &label)
Add an action to the notification.
QString iconName
Set the icon that will be shown in the popup.
void textChanged()
Emitted when text changed.
void urlsChanged()
Emitted when urls changed.
bool autoDelete
Sets whether this notification object will be automatically deleted after closing.
void flagsChanged()
Emitted when flags changed.
QList< QUrl > urls
Sets URLs associated with this notification.
void setUrls(const QList< QUrl > &urls)
Sets URLs associated with this notification.
QString xdgActivationToken
void setWindow(QWindow *window)
Sets the window associated with this notification.
@ CloseOnTimeout
The notification will be automatically closed after a timeout.
@ CloseWhenWindowActivated
The notification will be automatically closed if the window() becomes activated.
void componentNameChanged()
Emitted when componentName changed.
void setReplyAction(std::unique_ptr< KNotificationReplyAction > replyAction)
Add an inline reply action to the notification.
QString componentName
The componentData is used to determine the location of the config file.
void setUrgency(Urgency urgency)
Sets the urgency of the notification.
KNotificationAction * addDefaultAction(const QString &label)
Add a default action that will be triggered when the notification is activated (typically,...
void setHints(const QVariantMap &hints)
void setText(const QString &text)
Set the notification text that will appear in the popup.
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void deleteLater()
bool disconnect(const QMetaObject::Connection &connection)
QString number(double n, char format, int precision)
void timeout()
QList< QUrl > fromStringList(const QStringList &urls, ParsingMode mode)
QStringList toStringList(const QList< QUrl > &urls, FormattingOptions options)
void activeChanged()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Oct 11 2024 12:09:43 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.