[frameworks/knotifications] /: Add API for showing the platform's notification configuration
Volker Krause <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 9c81f069b085e4f05c9f8b20fd4ad3886588f30c by Volker Krause.
Committed on 01/08/2026 at 09:00.
Pushed by vkrause into branch 'master'.
Add API for showing the platform's notification configuration
This is particularly relevant for sandboxed applications, as those cannot
change how the system presents their notifications themselves.
For the sandboxed case this works for Flatpak on Plasma >= 6.7 and on
Android. For the non-sandboxed case there's also a fallback to kcmshell,
which should make this work in most cases. Applications can also query
via API whether this is going to work, to only show the corresponding
action in that case.
This is based on similar code in Itinerary.
M +5 -0 examples/notificationtester.qml
M +2 -0 src/CMakeLists.txt
A +26 -0 src/android/org/kde/knotifications/KNotificationConfiguration.java
A +87 -0 src/knotificationconfiguration.cpp [License: LGPL(v2.0+)]
A +54 -0 src/knotificationconfiguration.h [License: LGPL(v2.0+)]
M +1 -1 src/qml/CMakeLists.txt
M +23 -0 src/qml/knotificationqmlplugin.cpp
M +6 -0 src/qml/knotificationqmlplugin.h
https://invent.kde.org/frameworks/knotifications/-/commit/9c81f069b085e4f05c9f8b20fd4ad3886588f30c
diff --git a/examples/notificationtester.qml b/examples/notificationtester.qml
index 00118623..e5a6dab4 100644
--- a/examples/notificationtester.qml
+++ b/examples/notificationtester.qml
@@ -159,6 +159,11 @@ ApplicationWindow {
text: "Request Permission"
onClicked: NotificationPermission.requestPermission(success => { log.append("Permission request succeeded: " + success); })
}
+ Button {
+ text: "Show Configuration"
+ enabled: NotificationConfiguration.isAvailable
+ onClicked: NotificationConfiguration.show()
+ }
ScrollView {
Layout.fillWidth: true
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5000809f..37253cb4 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -14,6 +14,7 @@ target_sources(KF6Notifications PRIVATE
knotificationreplyaction.cpp
knotificationmanager.cpp
knotificationpermission.cpp
+ knotificationconfiguration.cpp
knotifyconfig.cpp
knotificationplugin.cpp
@@ -105,6 +106,7 @@ endif()
ecm_generate_headers(KNotifications_HEADERS
HEADER_NAMES
KNotification
+ KNotificationConfiguration
KNotificationPermission
KNotificationReplyAction
KNotifyConfig
diff --git a/src/android/org/kde/knotifications/KNotificationConfiguration.java b/src/android/org/kde/knotifications/KNotificationConfiguration.java
new file mode 100644
index 00000000..b56d9858
--- /dev/null
+++ b/src/android/org/kde/knotifications/KNotificationConfiguration.java
@@ -0,0 +1,26 @@
+/*
+ SPDX-FileCopyrightText: 2020-2026 Volker Krause <[email protected]>
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+package org.kde.knotifications;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.provider.Settings;
+
+public class KNotificationConfiguration
+{
+ public static void show(Context context)
+ {
+ Intent intent = new Intent();
+ intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS);
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName());
+
+ Activity activity = (Activity)context;
+ if (activity != null) {
+ activity.startActivity(intent);
+ }
+ }
+}
diff --git a/src/knotificationconfiguration.cpp b/src/knotificationconfiguration.cpp
new file mode 100644
index 00000000..2365c0f9
--- /dev/null
+++ b/src/knotificationconfiguration.cpp
@@ -0,0 +1,87 @@
+/*
+ SPDX-FileCopyrightText: 2020-2026 Volker Krause <[email protected]>
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "knotificationconfiguration.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+#include <QDesktopServices>
+#include <QFileInfo>
+#include <QProcess>
+#include <QStandardPaths>
+#include <QUrl>
+
+#ifdef Q_OS_ANDROID
+#include <QJniObject>
+#endif
+
+using namespace Qt::Literals;
+
+#ifndef Q_OS_ANDROID
+struct {
+ bool initialized : 1 = false;
+ bool hasSystemSettingsUri : 1 = false;
+ bool hasKcm : 1 = false;
+} static s_capabilities;
+
+static void detectCapabilities()
+{
+ if (s_capabilities.initialized) {
+ return;
+ }
+ s_capabilities.initialized = true;
+
+ if (QFileInfo::exists(u"/.flatpak-info"_s)) {
+ // technically only for Plasma >= 6.7, but we have no way to detect that
+ s_capabilities.hasSystemSettingsUri = qgetenv("XDG_CURRENT_DESKTOP") == "KDE";
+ return;
+ }
+
+ s_capabilities.hasSystemSettingsUri = !QStandardPaths::findExecutable(u"systemsettings"_s).isEmpty();
+
+ if (!s_capabilities.hasSystemSettingsUri) {
+ QProcess proc;
+ proc.start(u"kcmshell6"_s, {u"--list"_s});
+ proc.waitForFinished();
+ s_capabilities.hasKcm = proc.readAllStandardOutput().contains("\nkcm_notifications "_L1);
+ }
+}
+#endif
+
+bool KNotificationConfiguration::isAvailable()
+{
+#ifdef Q_OS_ANDROID
+ return true;
+#else
+ detectCapabilities();
+ return s_capabilities.hasSystemSettingsUri || s_capabilities.hasKcm;
+#endif
+}
+
+void KNotificationConfiguration::show()
+{
+#ifdef Q_OS_ANDROID
+ QJniObject::callStaticMethod<void>("org/kde/knotifications/KNotificationConfiguration", "show", QNativeInterface::QAndroidApplication::context());
+#else
+ detectCapabilities();
+ if (s_capabilities.hasSystemSettingsUri) {
+ QUrl url;
+ url.setScheme(u"systemsettings"_s);
+ url.setHost(u"kcm_notifications"_s);
+ url.setPath("/--notifyrc "_L1 + QCoreApplication::applicationName());
+ QDesktopServices::openUrl(url);
+ return;
+ }
+
+ if (s_capabilities.hasKcm) {
+ QProcess proc;
+ proc.setProgram(u"kcmshell6"_s);
+ proc.setArguments({u"--args"_s, "--notifyrc %1"_L1.arg(QCoreApplication::applicationName()), u"notifications"_s});
+ proc.startDetached();
+ }
+#endif
+}
+
+#include "moc_knotificationconfiguration.cpp"
diff --git a/src/knotificationconfiguration.h b/src/knotificationconfiguration.h
new file mode 100644
index 00000000..7412befb
--- /dev/null
+++ b/src/knotificationconfiguration.h
@@ -0,0 +1,54 @@
+/*
+ SPDX-FileCopyrightText: 2020-2026 Volker Krause <[email protected]>
+ SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KNOTIFICATIONCONFIGURATION_H
+#define KNOTIFICATIONCONFIGURATION_H
+
+#include <knotifications_export.h>
+
+#include <qobjectdefs.h>
+
+class KNotificationConfigurationPrivate;
+
+/*!
+ * \class KNotificationConfiguration
+ * \inheaderfile KNotificationConfiguration
+ * \inmodule KNotifications
+ *
+ * \brief Configure notifications using the means of the platform.
+ *
+ * This provides ways to interact with platform-specific means of
+ * configuring notifications of the current application.
+ *
+ * This is particularly relevant for sandboxed applications (Flatpak, APK, etc)
+ * where the host platform ultimately decides if/how notifications are shown.
+ *
+ * \since 6.28
+ */
+class KNOTIFICATIONS_EXPORT KNotificationConfiguration
+{
+ Q_GADGET
+ /*!
+ * \property KNotificationConfiguration::isAvailable
+ */
+ Q_PROPERTY(bool isAvailable READ isAvailable)
+
+public:
+ /*!
+ * Returns \c true if notifications can be configured on the current platform.
+ */
+ [[nodiscard]] static bool isAvailable();
+
+ /*!
+ * Opens a platform-specific UI for configuring the notifications of the current
+ * application.
+ */
+ Q_INVOKABLE static void show();
+
+private:
+ KNotificationConfigurationPrivate *d;
+};
+
+#endif
diff --git a/src/qml/CMakeLists.txt b/src/qml/CMakeLists.txt
index a9ea2765..5079368f 100644
--- a/src/qml/CMakeLists.txt
+++ b/src/qml/CMakeLists.txt
@@ -1,7 +1,7 @@
# SPDX-FileCopyrightText: 2021 Volker Krause <[email protected]>
# SPDX-License-Identifier: BSD-3-Clause
-ecm_add_qml_module(knotificationqmlplugin URI org.kde.notification VERSION 1.0 GENERATE_PLUGIN_SOURCE)
+ecm_add_qml_module(knotificationqmlplugin URI org.kde.notification VERSION 1.0 CLASS_NAME KNotificationsQmlPlugin)
target_sources(knotificationqmlplugin PRIVATE
knotificationqmlplugin.cpp
diff --git a/src/qml/knotificationqmlplugin.cpp b/src/qml/knotificationqmlplugin.cpp
index 72e9dcb7..542a2dd1 100644
--- a/src/qml/knotificationqmlplugin.cpp
+++ b/src/qml/knotificationqmlplugin.cpp
@@ -6,6 +6,11 @@
#include "knotificationqmlplugin.h"
+#include <KNotificationConfiguration>
+
+#include <QQmlEngine>
+#include <QQmlExtensionPlugin>
+
NotificationWrapper::NotificationWrapper(QObject *parent)
: KNotification(QString(), KNotification::CloseOnTimeout, parent)
{
@@ -66,4 +71,22 @@ void NotificationWrapper::clearActions(QQmlListProperty<KNotificationAction> *li
notification->clearActions();
}
+
+class KNotificationsQmlPlugin : public QQmlExtensionPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid)
+
+public:
+ void registerTypes(const char *uri) override;
+};
+
+void KNotificationsQmlPlugin::registerTypes(const char *uri)
+{
+ qmlRegisterSingletonType(uri, 1, 0, "NotificationConfiguration", [](QQmlEngine *, QJSEngine *jsEngine) -> QJSValue {
+ return jsEngine->toScriptValue(KNotificationConfiguration());
+ });
+}
+
+#include "knotificationqmlplugin.moc"
#include "moc_knotificationqmlplugin.cpp"
diff --git a/src/qml/knotificationqmlplugin.h b/src/qml/knotificationqmlplugin.h
index 7619bda6..0b5d9065 100644
--- a/src/qml/knotificationqmlplugin.h
+++ b/src/qml/knotificationqmlplugin.h
@@ -119,4 +119,10 @@ public:
}
};
+/*!
+ * \qmltype NotificationConfiguration
+ * \inqmlmodule org.kde.notifications
+ * \nativetype KNotificationConfiguration
+ */
+
#endif // KNOTIFICATIONQMLPLUGIN_H