Back to skills
extension
Category: Development & EngineeringNo API key required

kde-plasma-widget-dev

This skill should be used when developing, debugging, or fixing KDE Plasma 6 widgets (plasmoids). Triggers on QML widget issues, compactRepresentation not showing, system tray integration, Kirigami.Icon usage, plasmoidviewer testing, and Plasma 6 widget development. Covers common issues like emoji not rendering, widget not appearing in panel, and proper imports for Plasma 6.

personAuthor: jakexiaohubgithub

KDE Plasma 6 Widget Development

Comprehensive skill for developing and debugging KDE Plasma 6 widgets (plasmoids).

When to Use

  • Developing new KDE Plasma 6 widgets
  • Debugging widget display issues (empty space, no icon, not rendering)
  • System tray integration problems
  • QML syntax and import errors for Plasma 6
  • Widget not appearing in panel or "Add Widgets" menu
  • Emoji/text not rendering in compactRepresentation

Plasma 6 Required Structure

File Structure

widget-name/
├── metadata.json           # Widget metadata (REQUIRED)
└── contents/
    ├── ui/
    │   ├── main.qml       # Main widget (REQUIRED)
    │   └── configGeneral.qml  # Settings UI (optional)
    └── config/
        ├── main.xml       # Config schema (optional)
        └── config.qml     # Config categories (optional)

metadata.json (REQUIRED)

{
    "KPlugin": {
        "Authors": [{"Email": "dev@example.com", "Name": "Developer"}],
        "Category": "Utilities",
        "Description": "Widget description",
        "EnabledByDefault": true,
        "Icon": "chronometer",
        "Id": "com.example.widget",
        "Name": "Widget Name",
        "Version": "1.0.0"
    },
    "X-Plasma-API-Minimum-Version": "6.0",
    "KPackageStructure": "Plasma/Applet"
}

For System Tray Placement (optional)

Add these to metadata.json to appear in system tray area:

{
    "X-Plasma-NotificationArea": "true",
    "X-Plasma-NotificationAreaCategory": "ApplicationStatus"
}

Categories: ApplicationStatus, Communications, Hardware, SystemServices

Plasma 6 Imports (CRITICAL)

import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami

Import Changes from Plasma 5 to 6

| Plasma 5 | Plasma 6 | |----------|----------| | org.kde.plasma.core 2.0 | org.kde.plasma.core | | org.kde.plasma.plasmoid 2.0 | org.kde.plasma.plasmoid | | PlasmaCore.Theme | Kirigami.Theme | | PlasmaCore.Units | Kirigami.Units | | PlasmaCore.IconItem | Kirigami.Icon | | Item (root) | PlasmoidItem (root) |

Basic Widget Template

import QtQuick
import QtQuick.Layouts
import org.kde.plasma.plasmoid
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.components as PlasmaComponents
import org.kde.kirigami as Kirigami

PlasmoidItem {
    id: root

    // Compact view (panel/taskbar)
    compactRepresentation: MouseArea {
        Layout.minimumWidth: row.implicitWidth + Kirigami.Units.smallSpacing * 2
        Layout.minimumHeight: Kirigami.Units.iconSizes.medium

        implicitWidth: Layout.minimumWidth
        implicitHeight: Layout.minimumHeight

        hoverEnabled: true
        property bool wasExpanded: false
        onPressed: wasExpanded = root.expanded
        onClicked: root.expanded = !wasExpanded

        RowLayout {
            id: row
            anchors.centerIn: parent
            spacing: Kirigami.Units.smallSpacing

            Kirigami.Icon {
                source: "chronometer"
                Layout.preferredWidth: Kirigami.Units.iconSizes.small
                Layout.preferredHeight: Kirigami.Units.iconSizes.small
            }

            PlasmaComponents.Label {
                text: "25:00"
                font.family: "monospace"
            }
        }
    }

    // Popup view
    fullRepresentation: Item {
        Layout.preferredWidth: 300
        Layout.preferredHeight: 400

        // Popup content here
    }
}

Common Issues & Solutions

Issue 1: Widget Shows Empty Space (No Icon/Text)

Cause: Emoji characters don't render in Plasma widgets.

Solution: Use Kirigami.Icon with system icon names instead of emoji:

// WRONG - emoji won't render
PlasmaComponents.Label {
    text: "🍅"  // Will show blank
}

// CORRECT - use system icons
Kirigami.Icon {
    source: "chronometer"           // Timer icon
    source: "appointment-soon"      // Clock/appointment
    source: "preferences-desktop-screensaver"  // Break/rest
    Layout.preferredWidth: Kirigami.Units.iconSizes.small
    Layout.preferredHeight: Kirigami.Units.iconSizes.small
}

Issue 2: Widget Not Appearing in Panel

Causes:

  1. Missing Layout.minimumWidth/Layout.minimumHeight
  2. Missing implicitWidth/implicitHeight
  3. Root element not PlasmoidItem

Solution:

compactRepresentation: MouseArea {
    // REQUIRED for panel display
    Layout.minimumWidth: content.implicitWidth + Kirigami.Units.smallSpacing * 2
    Layout.minimumHeight: Kirigami.Units.iconSizes.medium

    implicitWidth: Layout.minimumWidth
    implicitHeight: Layout.minimumHeight

    // ... content
}

Issue 3: Widget Not in "Add Widgets" Menu

Solutions:

  1. Verify metadata.json has "X-Plasma-API-Minimum-Version": "6.0"
  2. Refresh KDE cache: kbuildsycoca6
  3. Restart Plasma: plasmashell --replace &
  4. Check widget is installed at: ~/.local/share/plasma/plasmoids/com.widget.id/

Issue 4: Click Doesn't Open Popup

Cause: Missing or incorrect MouseArea setup.

Solution: Follow KDE's official pattern:

compactRepresentation: MouseArea {
    hoverEnabled: true
    property bool wasExpanded: false
    onPressed: wasExpanded = root.expanded
    onClicked: root.expanded = !wasExpanded

    // Content inside...
}

Issue 5: Colors Don't Match Theme

Solution: Use Kirigami.Theme colors:

PlasmaComponents.Label {
    color: Kirigami.Theme.textColor        // Normal text
    color: Kirigami.Theme.highlightColor   // Accent
    color: Kirigami.Theme.disabledTextColor // Muted
}

Testing Commands

Test with plasmoidviewer

cd widget-directory
plasmoidviewer -a package

Install widget

mkdir -p ~/.local/share/plasma/plasmoids
cp -r package ~/.local/share/plasma/plasmoids/com.widget.id

Refresh KDE cache

kbuildsycoca6

Restart Plasma

plasmashell --replace &

Check for QML errors

timeout 5 plasmoidviewer -a package 2>&1 | grep -i "error\|qml"

Common Icon Names

| Purpose | Icon Name | |---------|-----------| | Timer/Clock | chronometer, appointment-soon | | Play | media-playback-start | | Pause | media-playback-pause | | Stop | media-playback-stop | | Skip | media-skip-forward | | Refresh | view-refresh | | Settings | configure | | Check/Done | checkmark, dialog-ok | | Error | dialog-error | | Warning | dialog-warning | | Info | dialog-information |

Panel Form Factor Handling

compactRepresentation: Item {
    readonly property bool isVertical: Plasmoid.formFactor === PlasmaCore.Types.Vertical

    Layout.minimumWidth: isVertical ? 0 : content.implicitWidth
    Layout.minimumHeight: isVertical ? content.implicitHeight : 0

    // Adapt layout based on orientation
}

Configuration Integration

config/main.xml

<?xml version="1.0" encoding="UTF-8"?>
<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0">
    <kcfgfile name=""/>
    <group name="General">
        <entry name="myOption" type="Int">
            <default>25</default>
        </entry>
    </group>
</kcfg>

Access in QML

PlasmoidItem {
    readonly property int myValue: plasmoid.configuration.myOption
}

HTTP Requests in QML

function fetchData() {
    var xhr = new XMLHttpRequest()
    xhr.open("GET", "https://api.example.com/data", true)
    xhr.setRequestHeader("Content-Type", "application/json")

    xhr.onreadystatechange = function() {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            if (xhr.status === 200) {
                var data = JSON.parse(xhr.responseText)
                // Handle data
            } else {
                console.error("Request failed:", xhr.status)
            }
        }
    }
    xhr.send()
}

Sources