How to make a simple passive popup for plasmoid? Help

hi,
I’m not a developer (it’s been a week since I started learning to code), I’m trying to understand, it’s hard.

I’m trying to create a plasmoid on/off switch, I managed to make it work but I’ve been trying for more than 4 days to add a simple passive popup like this :
Copie d'écran_20240328_222739

to indicate the change of state of the switch but I achieves nothing.

In a.sh script it’s simple like:
kdialog --passivepopup “Light On” 5

but in .qml I couldn’t do it, I also tried to understand Knotification but barely lost the documentation is so hard to understand, it gives the impression that the KDE devs who wrote their documentation don’t want that the general public understands, the language barrier doesn’t help me either (I’m French)

Could anyone help me? I despair.

This “passive popup” feature you talk about is called “notifications”. The API to implement this in KDE is called KNotifications.

The documentation for KNotifications QML API seems pretty straight forward: import org.kde.notifications; create a Notification object with the properties you need; update its text and/or title fields as needed; call sendEvent() to trigger the notification.

Which of these is giving your problems, what specific errors or unexpected behavior did you encounter and can you show what you did and didn’t work for you?

Hi,

I tried to integrate KNotifications following this same doc to test but I got an error which tells me:

kf.notifications: No event config could be found for event id “led_on” under notifyrc file for app “Switch-Toggle”

I searched on the internet and it says that this file is not found in /root, I did not find it (I am using KDE Neon) and I find it strange to have for plasmoid to touch files in /root for a simple passive notification.

Here is my complete code, sorry it’s very ugly, I’m a beginner:



import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents3
import org.kde.plasma.plasma5support as Plasma5Support
import QtQuick.Controls
import QtQuick.LocalStorage
import org.kde.notification


PlasmoidItem {
    id: root

    property bool isPrimaryCommand: Plasmoid.configuration.switchPosition

    Layout.maximumWidth: Infinity
    Layout.maximumHeight: Infinity

    Layout.minimumWidth: 0
    Layout.minimumHeight: 0

    readonly property bool inVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical
    readonly property string defaultIconName: "new-command-alarm"

    preferredRepresentation: fullRepresentation

    property bool initialExecution: true
    property var settings

    Notification {
        id: myNotification
        componentName: "Switch-Toggle"
        eventId: "led_on"
        title: "Attention!"
        text: "The LEDs are on"
        iconName: "video-display-brightness-symbolic"
        flags: Notification.Persistent
        urgency: Notification.HighUrgency
        onClosed: console.log("Notification closed.")
        actions: [
            NotificationAction {
                label: "Action 1"
                onActivated: log.append("Action 1 activated.")
            }
        ]
    }

    Component.onCompleted: {
        settings = LocalStorage.openDatabaseSync("MySettings", "1.0", "Settings database", 1000000);
        if (!settings) {
            console.error("Failed to open settings database.");
            return;
        }

        toggleSwitch.checked = settings.toggleSwitchChecked === "true";
        executeCommand();
    }

    function executeCommand() {
        if (toggleSwitch.checked) {
            if (!initialExecution) {
                executable.exec(isPrimaryCommand ? plasmoid.configuration.offCommandClic : plasmoid.configuration.onCommandClic);
                myNotification.sendEvent();
            }
        } else {
            if (!initialExecution) {
                executable.exec(isPrimaryCommand ? plasmoid.configuration.onCommandClic : plasmoid.configuration.offCommandClic);
            }
        }
        initialExecution = false;
        settings.toggleSwitchChecked = toggleSwitch.checked.toString();
    }

     function executeCommand2() {
        if (toggleSwitch.checked) {
            executable.exec(isPrimaryCommand ? plasmoid.configuration.offCommandMiddle : plasmoid.configuration.onCommandMiddle);
            myNotification.sendEvent();
        } else {
            executable.exec(isPrimaryCommand ? plasmoid.configuration.onCommandMiddle : plasmoid.configuration.offCommandMiddle);
        }
    }

    function handleWheel(wheel) {
        if (wheel.angleDelta.y > 0) {
            // Molette vers le haut
            executable.exec(isPrimaryCommand ? plasmoid.configuration.offCommandWeels : plasmoid.configuration.onCommandWeels);
            myNotification.sendEvent();
        } else {
            // Molette vers le bas
            executable.exec(isPrimaryCommand ? plasmoid.configuration.onCommandWeels : plasmoid.configuration.offCommandWeels);
        }
    }

    PlasmaComponents3.Switch {
        id: toggleSwitch
        anchors.left: parent.left
        anchors.verticalCenter: parent.verticalCenter
        checked: settings ? settings.toggleSwitchChecked === "true" : false
        onToggled: {
            executeCommand();
        }

        MouseArea {
            anchors.fill: parent
            acceptedButtons: Qt.MiddleButton
            onClicked: {
                executeCommand2();
            }
            onWheel: {
                handleWheel(wheel);
            }
        }
    }

    Plasma5Support.DataSource {
        id: executable
        engine: "executable"
        connectedSources: []
        onNewData: function(source, data) {
            disconnectSource(source)
        }

        function exec(cmd) {
            executable.connectSource(cmd)
        }
    }
}

That does not seem like a good explanation. I’m pretty sure that wherever you read that - it was wrong. The /root directory is the home directory for the administrator, and unless you are running as the administrator account (which you shouldn’t and I’m not even sure that you can in modern operating systems), then that is irrelevant.

Ok, I see where the problem is. The KNotifications QML manual assume that you have read the main KNotifications manual and knows how KNotifications work and just need to get it running in QML. I think its a valid assumption.

If you review the above linked document you’ll see that for KNotifications to work you need to have a file called YOURCOMPONENT.notifyrc installed into the KNotifications state directory. The document describes how to create that file and what should be in it, though it doesn’t say in which directory to put the file in - it says “It needs to be installed to knotifications5/appname.notifyrc in a QStandardPaths::GenericDataLocationdirectory” which may not mean much to new developers, so it may worth it to put some time into explaining directory locations:

The QStandardPaths is a mechanism to help developers put things in directories that make sense according to the Linux Filesystem Heirarchy Standard. The Qt implementation of that offers several categories to match the different places in the FSH that applications are expected to put stuff in - you can see the full list by running qtpaths --types or just looking at the linked reference. The GenericDataLocation is where applications should put their state data, into specific folders per application. KNotifications state data (the .notifyrc files) should go into either ${GenericDataLocation}/knotifications5 if you are using Knotifications for Plasma 5 or ${GenericDataLocation}/knotifications6 if you are using it on Plasma 6.

The user’s GenericDataLocation is normally ~/.local/share(*), so if you are developing your plasma widget locally to install into your user account, you use Plasma 6, and you call your component “Switch-Toggle” then you should create the file in ~/.local/share/knotifications6/Switch-Toggle.notifyrc and put the notifications configuration for it.

*) To see other potential GenericDataLocation paths you have on your system, you can run qtpaths --paths GenericDataLocation - this will list a bunch of directory in “PATH” format, i.e. in one line delimited by a colon (“:”).

1 Like

It works !!! After creating the file: Switch-Toggle.notifyrc in home: .local/share/knotifications6/ in which I put:

[Global]
IconName=folder-appimage
Name=Switch-Toggle
Comment=Switch on/off
DesktopEntry=Switch-Toggle

[Event/led_on]
Name=Switch: Commande activée
Comment=La commande a été exécutée
Sound=Oxygen-Sys-Trash-Emptied.ogg
Action=Popup
Urgency=Low

Copie d'écran_20240330_132556

Do I really have to put this file in: .local/share/knotifications6/?

I mean, isn’t it possible to put the file in the Plasmoid files and make it tell Knotification is located in exemple : .local/share/plasma/plasmoids/Switch-Toggle/contents/ui/?

Because if I want to share the plasmoid I will have to create an installer, that complicates my task, I have never done that.

Thank you so much for your help, I will be sure to mention you if I share it.

The main reason for installing the notifyrc file in the knotifications general data directory, is that you want to allow the user to configure the application notifications (change sounds, control history, enable in d-n-d mode, etc) so you want a way for the Notifications System Settings module to know about all the applications that can show notifications (you can see them by clicking Configure under Application-specific Settings).

There was some discussions about making the notifyrc file optional (for example) but as far as i know nothing came out of it, as of yet.

1 Like