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-2015 Martin Klapetek <mklapetek@kde.org>
5
6 SPDX-License-Identifier: LGPL-2.0-or-later
7*/
8
9#ifndef KNOTIFICATION_H
10#define KNOTIFICATION_H
11
12#include <knotifications_export.h>
13
14#include <QList>
15#include <QObject>
16#include <QPair>
17#include <QPixmap>
18#include <QUrl>
19#include <QVariant>
20#include <QWindow>
21
22#include <memory>
23
24class KNotificationReplyAction;
25class KNotificationAction;
26
27class KNotificationActionPrivate;
28
29/*!
30 * \class KNotificationAction
31 * \inheaderfile KNotification
32 * \inmodule KNotifications
33 *
34 * \brief This class represents an action in a notification.
35 *
36 * This can be a button on the notification popup,
37 * or triggered by clicking the notification popup itself.
38 *
39 * \since 6.0
40 */
41class KNOTIFICATIONS_EXPORT KNotificationAction : public QObject
42{
43 Q_OBJECT
44 /*!
45 * \property KNotificationAction::label
46 */
47 Q_PROPERTY(QString label READ label WRITE setLabel NOTIFY labelChanged)
48
49public:
50 explicit KNotificationAction(QObject *parent = nullptr);
51
52 /*!
53 * Creates an action with given label
54 *
55 * \a label The label for the action
56 */
57 explicit KNotificationAction(const QString &label);
58
59 ~KNotificationAction() override;
60
61 /*!
62 * The user-facing label for the action
63 */
64 QString label() const;
65
66 /*!
67 * Set the user-facing label for the action
68 */
69 void setLabel(const QString &label);
70
71Q_SIGNALS:
72 /*!
73 * Emitted when the user activates the action
74 */
75 void activated();
76
77 /*!
78 * Emitted when \a label changed.
79 */
80 void labelChanged(const QString &label);
81
82private:
83 friend class KNotification;
84 friend class NotifyByPortalPrivate;
85 friend class NotifyByPopup;
86 friend class NotifyBySnore;
87 friend class NotifyByAndroid;
88
89 void setId(const QString &id);
90 QString id() const;
91
92 std::unique_ptr<KNotificationActionPrivate> const d;
93};
94
95/*!
96 * \class KNotification
97 * \inmodule KNotifications
98 *
99 * \brief KNotification is the main class for creating notifications.
100 */
101class KNOTIFICATIONS_EXPORT KNotification : public QObject
102{
103 Q_OBJECT
104 /*!
105 * \property KNotification::eventId
106 * \since 5.88
107 */
108 Q_PROPERTY(QString eventId READ eventId WRITE setEventId NOTIFY eventIdChanged)
109 /*!
110 * \property KNotification::title
111 * \since 5.88
112 */
113 Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
114 /*!
115 * \property KNotification::text
116 * \since 5.88
117 */
118 Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
119 /*!
120 * \property KNotification::iconName
121 * \since 5.88
122 */
123 Q_PROPERTY(QString iconName READ iconName WRITE setIconName NOTIFY iconNameChanged)
124 /*!
125 * \property KNotification::flags
126 * \since 5.88
127 */
128 Q_PROPERTY(NotificationFlags flags READ flags WRITE setFlags NOTIFY flagsChanged)
129 /*!
130 * \property KNotification::componentName
131 * \since 5.88
132 */
133 Q_PROPERTY(QString componentName READ componentName WRITE setComponentName NOTIFY componentNameChanged)
134 /*!
135 * \property KNotification::urls
136 * \since 5.88
137 */
138 Q_PROPERTY(QList<QUrl> urls READ urls WRITE setUrls NOTIFY urlsChanged)
139 /*!
140 * \property KNotification::urgency
141 * \since 5.88
142 */
143 Q_PROPERTY(Urgency urgency READ urgency WRITE setUrgency NOTIFY urgencyChanged)
144 /*!
145 * \property KNotification::autoDelete
146 * \since 5.88
147 */
148 Q_PROPERTY(bool autoDelete READ isAutoDelete WRITE setAutoDelete NOTIFY autoDeleteChanged)
149 /*!
150 * \property KNotification::xdgActivationToken
151 * \since 5.90
152 */
153 Q_PROPERTY(QString xdgActivationToken READ xdgActivationToken NOTIFY xdgActivationTokenChanged)
154 /*!
155 * \property KNotification::hints
156 * \since 5.101
157 */
158 Q_PROPERTY(QVariantMap hints READ hints WRITE setHints NOTIFY hintsChanged)
159
160public:
161 /*!
162 *
163 * \value CloseOnTimeout The notification will be automatically closed after a timeout. (this is the default)
164 * \value Persistent The notification will NOT be automatically closed after a timeout. You will have to track the notification, and close it with the close
165 * function manually when the event is done, otherwise there will be a memory leak.
166 * \value LoopSound The audio plugin will loop the sound until the notification is closed.
167 * \value [since 5.18] SkipGrouping Sends a hint to Plasma to skip grouping for this notification.
168 * \value [since 6.0] CloseWhenWindowActivated The notification will be automatically closed if the window() becomes activated. You need to set a window
169 * using setWindow().
170 * \value DefaultEvent The event is a standard kde event, and not an event of the application.
171 */
172 enum NotificationFlag {
173 CloseOnTimeout = 0x00,
174 Persistent = 0x02,
175 LoopSound = 0x08,
176 SkipGrouping = 0x10,
177 CloseWhenWindowActivated = 0x20,
178 DefaultEvent = 0xF000,
179 };
180 Q_DECLARE_FLAGS(NotificationFlags, NotificationFlag)
181 Q_FLAG(NotificationFlags)
182
183 /*!
184 * Default events you can use in the event function
185 *
186 * \value Notification
187 * \value Warning
188 * \value Error
189 * \value Catastrophe
190 */
191 enum StandardEvent {
192 Notification,
193 Warning,
194 Error,
195 Catastrophe,
196 };
197
198 /*!
199 * The urgency of a notification.
200 *
201 * \since 5.58
202 * \sa setUrgency
203 *
204 * \value DefaultUrgency
205 * \value LowUrgency
206 * \value NormalUrgency
207 * \value HighUrgency
208 * \value CriticalUrgency
209 */
210 enum Urgency {
211 DefaultUrgency = -1,
212 LowUrgency = 10,
213 NormalUrgency = 50,
214 HighUrgency = 70,
215 CriticalUrgency = 90,
216 };
217 Q_ENUM(Urgency)
218
219 /*!
220 * Create a new notification.
221 *
222 * You have to use sendEvent to show the notification.
223 *
224 * The pointer is automatically deleted when the event is closed.
225 *
226 * \since 4.4
227 *
228 * \a eventId is the name of the event
229 *
230 * \a flags is a bitmask of NotificationFlag
231 *
232 * \a parent parent object
233 */
234 explicit KNotification(const QString &eventId, NotificationFlags flags = CloseOnTimeout, QObject *parent = nullptr);
235
236 ~KNotification() override;
237
238 /*!
239 * Returns the name of the event
240 */
241 QString eventId() const;
242 /*!
243 * Set the event id, if not already passed to the constructor.
244 * \since 5.88
245 */
246 void setEventId(const QString &eventId);
247
248 /*!
249 * Returns the notification title
250 * \sa setTitle
251 * \since 4.3
252 */
253 QString title() const;
254
255 /*!
256 * Set the title of the notification popup.
257 * If no title is set, the application name will be used.
258 *
259 * \a title The title of the notification
260 * \since 4.3
261 */
262 void setTitle(const QString &title);
263
264 /*!
265 * Returns the notification text
266 * \sa setText
267 */
268 QString text() const;
269
270 /*!
271 * Set the notification text that will appear in the popup.
272 *
273 * In Plasma workspace, the text is shown in a QML label which uses Text.StyledText,
274 * ie. it supports a small subset of HTML entities (mostly just formatting tags)
275 *
276 * If the notifications server does not advertise "body-markup" capability,
277 * all HTML tags are stripped before sending it to the server
278 *
279 * \a text The text to display in the notification popup
280 */
281 void setText(const QString &text);
282
283 /*!
284 * Returns the icon shown in the popup
285 * \sa setIconName
286 * \since 5.4
287 */
288 QString iconName() const;
289
290 /*!
291 * Set the icon that will be shown in the popup.
292 *
293 * \a icon the icon
294 *
295 * \since 5.4
296 */
297 void setIconName(const QString &icon);
298
299 /*!
300 * Returns the pixmap shown in the popup
301 * \sa setPixmap
302 */
303 QPixmap pixmap() const;
304 /*!
305 * Set the pixmap that will be shown in the popup. If you want to use an icon from the icon theme use setIconName instead.
306 *
307 * \a pix the pixmap
308 */
309 void setPixmap(const QPixmap &pix);
310
311 /*!
312 * Returns the default action, or nullptr if none is set
313 * \since 6.0
314 */
315 KNotificationAction *defaultAction() const;
316
317 /*!
318 * Add a default action that will be triggered when the notification is
319 * activated (typically, by clicking on the notification popup). The default
320 * action typically raises a window belonging to the application that sent it.
321 *
322 * The string will be used as a label for the action, so ideally it should
323 * be wrapped in i18n() or tr() calls.
324 *
325 * The visual representation of actions depends on the notification server.
326 * In Plasma and Gnome desktops, the actions are performed by clicking on
327 * the notification popup, and the label is not presented to the user.
328 *
329 * Calling this overrides the current default action
330 *
331 * \since 6.0
332 */
333 [[nodiscard]] KNotificationAction *addDefaultAction(const QString &label);
334
335 /*!
336 * Add an action to the notification.
337 *
338 * The visual representation of actions depends
339 * on the notification server.
340 *
341 * \a label the user-visible label of the action
342 *
343 * \sa KNotificationAction
344 *
345 * \since 6.0
346 */
347 [[nodiscard]] KNotificationAction *addAction(const QString &label);
348
349 /*!
350 * Removes all actions previously added by addAction()
351 * from the notification.
352 *
353 * \sa addAction
354 *
355 * \since 6.0
356 */
357 void clearActions();
358
359 /*!
360 * Returns the inline reply action.
361 * \since 5.81
362 */
363 KNotificationReplyAction *replyAction() const;
364
365 /*!
366 * Add an inline reply action to the notification.
367 *
368 * On supported platforms this lets the user type a reply to a notification,
369 * such as replying to a chat message, from the notification popup, for example:
370 *
371 * \code
372 * KNotification *notification = new KNotification(QStringLiteral("notification"));
373 * ...
374 * auto replyAction = std::make_unique<KNotificationReplyAction>(i18nc("@action:button", "Reply"));
375 * replyAction->setPlaceholderText(i18nc("@info:placeholder", "Reply to Dave..."));
376 * QObject::connect(replyAction.get(), &KNotificationReplyAction::replied, [](const QString &text) {
377 * qDebug() << "you replied with" << text;
378 * });
379 * notification->setReplyAction(std::move(replyAction));
380 * \endcode
381 *
382 * \a replyAction the reply action to set
383 *
384 * \since 5.81
385 */
386 void setReplyAction(std::unique_ptr<KNotificationReplyAction> replyAction);
387
388 /*!
389 * Returns the notification flags.
390 */
391 NotificationFlags flags() const;
392
393 /*!
394 * Set the notification flags.
395 *
396 * These must be set before calling sendEvent()
397 */
398 void setFlags(const NotificationFlags &flags);
399
400 /*!
401 * Returns the component name used to determine the location of the configuration file.
402 * \since 5.88
403 */
404 QString componentName() const;
405 /*!
406 * The componentData is used to determine the location of the config file.
407 *
408 * If no componentName is set, the app name is used by default
409 *
410 * \a componentName the new component name
411 */
412 void setComponentName(const QString &componentName);
413
414 /*!
415 * URLs associated with this notification
416 * \since 5.29
417 */
418 QList<QUrl> urls() const;
419
420 /*!
421 * Sets URLs associated with this notification
422 *
423 * For example, a screenshot application might want to provide the
424 * URL to the file that was just taken so the notification service
425 * can show a preview.
426 *
427 * \note This feature might not be supported by the user's notification service
428 *
429 * \a urls A list of URLs
430 *
431 * \since 5.29
432 */
433 void setUrls(const QList<QUrl> &urls);
434
435 /*!
436 * The urgency of the notification.
437 * \since 5.58
438 */
439 Urgency urgency() const;
440
441 /*!
442 * Sets the urgency of the notification.
443 *
444 * This defines the importance of the notification. For example,
445 * a track change in a media player would be a low urgency.
446 * "You have new mail" would be normal urgency. "Your battery level
447 * is low" would be a critical urgency.
448 *
449 * Use critical notifications with care as they might be shown even
450 * when giving a presentation or when notifications are turned off.
451 *
452 * \a urgency The urgency.
453 *
454 * \since 5.58
455 */
456 void setUrgency(Urgency urgency);
457
458 /*!
459 * Sets the window associated with this notification.
460 * This is relevant when using the CloseWhenWindowActivated flag.
461 *
462 * \since 6.0
463 */
464 void setWindow(QWindow *window);
465
466 /*!
467 * The window associated with this notification. nullptr by default.
468 * Returns the window set by setWindow()
469 *
470 * \since 6.0
471 */
472 QWindow *window() const;
473
474 /*!
475 * \internal
476 * appname used for the D-Bus object
477 */
478 QString appName() const;
479
480 /*!
481 * Returns whether this notification object will be automatically deleted after closing.
482 * \since 5.88
483 */
484 bool isAutoDelete() const;
485 /*!
486 * Sets whether this notification object will be automatically deleted after closing.
487 * This is on by default for C++, and off by default for QML.
488 * \since 5.88
489 */
490 void setAutoDelete(bool autoDelete);
491
492 /*!
493 * Returns the activation token to use to activate a window.
494 * \since 5.90
495 */
496 QString xdgActivationToken() const;
497
498Q_SIGNALS:
499 /*!
500 * Emitted when the notification is closed.
501 *
502 * Can be closed either by the user clicking the close button,
503 * the timeout running out or when an action was triggered.
504 */
505 void closed();
506
507 /*!
508 * The notification has been ignored
509 */
510 void ignored();
511
512 /*!
513 * Emitted when eventId changed.
514 * \since 5.88
515 */
516 void eventIdChanged();
517 /*!
518 * Emitted when title changed.
519 * \since 5.88
520 */
521 void titleChanged();
522 /*!
523 * Emitted when text changed.
524 * \since 5.88
525 */
526 void textChanged();
527 /*!
528 * Emitted when iconName changed.
529 * \since 5.88
530 */
531 void iconNameChanged();
532 /*!
533 * Emitted when defaultAction changed.
534 * \since 5.88
535 */
536 void defaultActionChanged();
537 /*!
538 * Emitted when actions changed.
539 * \since 5.88
540 */
541 void actionsChanged();
542 /*!
543 * Emitted when flags changed.
544 * \since 5.88
545 */
546 void flagsChanged();
547 /*!
548 * Emitted when componentName changed.
549 * \since 5.88
550 */
551 void componentNameChanged();
552 /*!
553 * Emitted when urls changed.
554 * \since 5.88
555 */
556 void urlsChanged();
557 /*!
558 * Emitted when urgency changed.
559 * \since 5.88
560 */
561 void urgencyChanged();
562 /*!
563 * Emitted when autoDelete changed.
564 * \since 5.88
565 */
566 void autoDeleteChanged();
567 /*!
568 * Emitted when xdgActivationToken changes.
569 * \since 5.90
570 */
571 void xdgActivationTokenChanged();
572 /*!
573 * Emitted when hints changes.
574 * \since 5.101
575 */
576 void hintsChanged();
577
578public Q_SLOTS:
579 /*!
580 * Close the notification without activating it.
581 *
582 * This will delete the notification.
583 */
584 void close();
585
586 /*!
587 * Send the notification to the server.
588 *
589 * This will cause all the configured plugins to execute their actions on this notification
590 * (eg. a sound will play, a popup will show, a command will be executed etc).
591 */
592 void sendEvent();
593
594 /*!
595 * \since 5.57
596 * Adds a custom hint to the notification. Those are key-value pairs that can be interpreted by the respective notification backend to trigger additional,
597 * non-standard features.
598 *
599 * \a hint the hint's key
600 *
601 * \a value the hint's value
602 */
603 Q_INVOKABLE void setHint(const QString &hint, const QVariant &value);
604
605 /*!
606 * \since 5.57
607 * Returns the custom hints set by setHint()
608 */
609 QVariantMap hints() const;
610
611 /*!
612 * \since 5.101
613 * Set custom hints on the notification.
614 * \sa setHint
615 */
616 void setHints(const QVariantMap &hints);
617
618private:
619 friend class KNotificationManager;
620 friend class NotificationWrapper;
621 friend class NotifyByPopup;
622 friend class NotifyByPortal;
623 friend class NotifyByPortalPrivate;
624 friend class NotifyByExecute;
625 friend class NotifyBySnore;
626 friend class NotifyByAndroid;
627 friend class NotifyByMacOSNotificationCenter;
628 struct Private;
629
630 KNOTIFICATIONS_NO_EXPORT void slotWindowActiveChanged();
631
632 /*!
633 * \internal
634 * Activate the action specified action
635 * If the action is zero, then the default action is activated
636 */
637 KNOTIFICATIONS_NO_EXPORT void activate(const QString &action);
638
639 /*!
640 * \internal
641 * the id given by the notification manager
642 */
643 KNOTIFICATIONS_NO_EXPORT int id();
644
645 /*!
646 * \internal
647 * update the texts, the icon, and the actions of one existing notification
648 */
649 KNOTIFICATIONS_NO_EXPORT void update();
650
651 /*!
652 * \internal
653 * The notification will automatically be closed if all presentations are finished.
654 * if you want to show your own presentation in your application, you should use this
655 * function, so it will not be automatically closed when there is nothing to show.
656 *
657 * Don't forgot to deref, or the notification may be never closed if there is no timeout.
658 *
659 * \sa deref
660 */
661 KNOTIFICATIONS_NO_EXPORT void ref();
662
663 /*!
664 * \internal
665 * Remove a reference made with ref(). If the ref counter hits zero,
666 * the notification will be closed and deleted.
667 *
668 * \sa ref
669 */
670 KNOTIFICATIONS_NO_EXPORT void deref();
671
672 // Like setActions, but doesn't take ownership
673 void setActionsQml(QList<KNotificationAction *> actions);
674 void setDefaultActionQml(KNotificationAction *action);
675 QList<KNotificationAction *> actions() const;
676
677 static QString standardEventToEventId(StandardEvent event);
678 static QString standardEventToIconName(StandardEvent event);
679
680 std::unique_ptr<Private> const d;
681
682public:
683 /*!
684 * Emit an event
685 *
686 * This method creates the KNotification, setting every parameter, and fire the event.
687 * You don't need to call sendEvent
688 *
689 * A popup may be displayed or a sound may be played, depending the config.
690 *
691 * Returns a KNotification . You may use that pointer to connect some signals or slot.
692 * the pointer is automatically deleted when the event is closed.
693 *
694 * \a eventId is the name of the event
695 *
696 * \a title is title of the notification to show in the popup.
697 *
698 * \a text is the text of the notification to show in the popup.
699 *
700 * \a pixmap is a picture which may be shown in the popup.
701 *
702 * \a flags is a bitmask of NotificationFlag
703 *
704 * \a componentName used to determine the location of the config file. by default, appname is used
705 * \since 4.4
706 */
707 static KNotification *event(const QString &eventId,
708 const QString &title,
709 const QString &text,
710 const QPixmap &pixmap = QPixmap(),
711 const NotificationFlags &flags = CloseOnTimeout,
712 const QString &componentName = QString());
713
714 /*!
715 * Emit a standard event
716 *
717 * \overload
718 *
719 * This will emit a standard event
720 *
721 * \a eventId is the name of the event
722 *
723 * \a text is the text of the notification to show in the popup.
724 *
725 * \a pixmap is a picture which may be shown in the popup.
726 *
727 * \a flags is a bitmask of NotificationFlag
728 *
729 * \a componentName used to determine the location of the config file. by default, plasma_workspace is used
730 */
731 static KNotification *event(const QString &eventId,
732 const QString &text = QString(),
733 const QPixmap &pixmap = QPixmap(),
734 const NotificationFlags &flags = CloseOnTimeout,
735 const QString &componentName = QString());
736
737 /*!
738 * Emit a standard event
739 *
740 * \overload
741 *
742 * This will emit a standard event
743 *
744 * \a eventId is the name of the event
745 *
746 * \a text is the text of the notification to show in the popup
747 *
748 * \a pixmap is a picture which may be shown in the popup
749 *
750 * \a flags is a bitmask of NotificationFlag
751 */
752 static KNotification *
753 event(StandardEvent eventId, const QString &text = QString(), const QPixmap &pixmap = QPixmap(), const NotificationFlags &flags = CloseOnTimeout);
754
755 /*!
756 * Emit a standard event
757 *
758 * \overload
759 *
760 * This will emit a standard event
761 *
762 * \a eventId is the name of the event
763 *
764 * \a title is title of the notification to show in the popup.
765 *
766 * \a text is the text of the notification to show in the popup
767 *
768 * \a pixmap is a picture which may be shown in the popup
769 *
770 * \a flags is a bitmask of NotificationFlag
771 *
772 * \since 4.4
773 */
774 static KNotification *
775 event(StandardEvent eventId, const QString &title, const QString &text, const QPixmap &pixmap, const NotificationFlags &flags = CloseOnTimeout);
776
777 /*!
778 * Emit a standard event with the possibility of setting an icon by icon name
779 *
780 * \overload
781 *
782 * This will emit a standard event
783 *
784 * \a eventId is the name of the event
785 *
786 * \a title is title of the notification to show in the popup.
787 *
788 * \a text is the text of the notification to show in the popup
789 *
790 * \a iconName a Freedesktop compatible icon name to be shown in the popup
791 *
792 * \a flags is a bitmask of NotificationFlag
793 *
794 * \a componentName used to determine the location of the config file. by default, plasma_workspace is used
795 *
796 * \since 5.4
797 */
798 static KNotification *event(const QString &eventId,
799 const QString &title,
800 const QString &text,
801 const QString &iconName,
802 const NotificationFlags &flags = CloseOnTimeout,
803 const QString &componentName = QString());
804
805 /*!
806 * Emit a standard event with the possibility of setting an icon by icon name
807 *
808 * \overload
809 *
810 * This will emit a standard event with a custom icon
811 *
812 * \a eventId the type of the standard (not app-defined) event
813 *
814 * \a title is title of the notification to show in the popup.
815 *
816 * \a text is the text of the notification to show in the popup
817 *
818 * \a iconName a Freedesktop compatible icon name to be shown in the popup
819 *
820 * \a flags is a bitmask of NotificationFlag
821 *
822 * \since 5.9
823 */
824 static KNotification *
825 event(StandardEvent eventId, const QString &title, const QString &text, const QString &iconName, const NotificationFlags &flags = CloseOnTimeout);
826
827 /*!
828 * Emit a standard event
829 *
830 * \overload
831 *
832 * This will emit a standard event with its standard icon
833 *
834 * \a eventId the type of the standard (not app-defined) event
835 *
836 * \a title is title of the notification to show in the popup.
837 *
838 * \a text is the text of the notification to show in the popup
839 *
840 * \a flags is a bitmask of NotificationFlag
841 *
842 * \since 5.9
843 */
844 static KNotification *event(StandardEvent eventId, const QString &title, const QString &text, const NotificationFlags &flags = CloseOnTimeout);
845
846 /*!
847 * This is a simple substitution for QApplication::beep()
848 *
849 * \a reason a short text explaining what has happened (may be empty)
850 */
851 static void beep(const QString &reason = QString());
852
853 // prevent warning
854 using QObject::event;
855};
856
857Q_DECLARE_OPERATORS_FOR_FLAGS(KNotification::NotificationFlags)
858
859#endif
860

source code of knotifications/src/knotification.h