1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-05-12 23:32:50 -04:00
Files
DankMaterialShell/.agents/skills/dms-plugin-dev/references/desktop-plugin-guide.md
T

6.1 KiB

Desktop Plugin Guide

Desktop plugins are widgets that appear on the desktop background layer. They support drag-and-drop positioning and resize via corner handles.

Base Component

Desktop widgets use a plain Item with injected properties:

import QtQuick
import qs.Common

Item {
    id: root

    property var pluginService: null
    property string pluginId: ""
    property bool editMode: false
    property real widgetWidth: 200
    property real widgetHeight: 200
    property real minWidth: 150
    property real minHeight: 150

    Rectangle {
        anchors.fill: parent
        radius: Theme.cornerRadius
        color: Theme.surfaceContainer
        opacity: 0.85

        // Your content here
    }
}

Injected Properties

These are set automatically by the DesktopPluginWrapper:

Property Type Description
pluginService object PluginService reference for data persistence
pluginId string Plugin's unique identifier
editMode bool true when user is dragging/resizing
widgetWidth real Current widget container width
widgetHeight real Current widget container height

Optional Properties

Define these on your root item to customize behavior:

Property Type Default Description
minWidth real 100 Minimum allowed width during resize
minHeight real 100 Minimum allowed height during resize

Position and Size Persistence

Position (desktopX, desktopY) and size (desktopWidth, desktopHeight) are automatically managed by the DesktopPluginWrapper. You do not need to handle persistence for positioning.

Edit Mode

When editMode is true, the user is repositioning or resizing. Use this to:

  • Show visual indicators (borders, handles)
  • Disable interactive elements to prevent accidental actions
  • Display additional controls
Rectangle {
    anchors.fill: parent
    border.color: root.editMode ? Theme.primary : "transparent"
    border.width: root.editMode ? 2 : 0

    MouseArea {
        anchors.fill: parent
        enabled: !root.editMode
        onClicked: doSomething()
    }
}

Loading and Saving Data

Use the injected pluginService for data persistence:

property string displayMode: {
    if (!pluginService) return "default"
    return pluginService.loadPluginData(pluginId, "displayMode", "default")
}

Connections {
    target: pluginService
    function onPluginDataChanged(changedId) {
        if (changedId !== pluginId) return
        root.displayMode = pluginService.loadPluginData(pluginId, "displayMode", "default")
    }
}

function saveMode(mode) {
    pluginService?.savePluginData(pluginId, "displayMode", mode)
}

Settings Component

Desktop plugin settings use the same PluginSettings wrapper as other types:

import QtQuick
import qs.Common
import qs.Widgets
import qs.Modules.Plugins

PluginSettings {
    pluginId: "myDesktopWidget"

    SliderSetting {
        settingKey: "opacity"
        label: "Opacity"
        description: "Widget background opacity"
        defaultValue: 85
        minimum: 10
        maximum: 100
        unit: "%"
    }

    SelectionSetting {
        settingKey: "style"
        label: "Display Style"
        options: [
            { label: "Compact", value: "compact" },
            { label: "Expanded", value: "expanded" }
        ]
        defaultValue: "compact"
    }
}

User Interaction

Desktop widgets support:

  1. Drag - click and drag anywhere (in edit mode)
  2. Resize - drag bottom-right corner handle (in edit mode)
  3. Edit mode toggle - via the desktop edit button

Complete Example

Based on the ExampleDesktopClock pattern:

import QtQuick
import qs.Common

Item {
    id: root

    property var pluginService: null
    property string pluginId: ""
    property bool editMode: false
    property real widgetWidth: 250
    property real widgetHeight: 250
    property real minWidth: 150
    property real minHeight: 150

    property string clockStyle: {
        if (!pluginService) return "digital"
        return pluginService.loadPluginData(pluginId, "clockStyle", "digital")
    }

    property real bgOpacity: {
        if (!pluginService) return 0.85
        var val = pluginService.loadPluginData(pluginId, "opacity", 85)
        return val / 100
    }

    Connections {
        target: pluginService
        function onPluginDataChanged(changedId) {
            if (changedId !== pluginId) return
            clockStyle = pluginService.loadPluginData(pluginId, "clockStyle", "digital")
            var val = pluginService.loadPluginData(pluginId, "opacity", 85)
            bgOpacity = val / 100
        }
    }

    Rectangle {
        anchors.fill: parent
        radius: Theme.cornerRadius
        color: Theme.surfaceContainer
        opacity: root.bgOpacity
        border.color: root.editMode ? Theme.primary : "transparent"
        border.width: root.editMode ? 2 : 0

        Column {
            anchors.centerIn: parent
            spacing: Theme.spacingS

            Text {
                anchors.horizontalCenter: parent.horizontalCenter
                text: Qt.formatTime(new Date(), "hh:mm:ss")
                color: Theme.surfaceText
                font.pixelSize: root.widgetWidth * 0.15
                font.weight: Font.Bold
            }

            Text {
                anchors.horizontalCenter: parent.horizontalCenter
                text: Qt.formatDate(new Date(), "ddd, MMM d")
                color: Theme.onSurfaceVariant
                font.pixelSize: Theme.fontSizeMedium
            }
        }
    }

    Timer {
        interval: 1000
        running: true
        repeat: true
        onTriggered: root.widgetWidth = root.widgetWidth // force update
    }
}

Manifest Example

{
    "id": "myDesktopClock",
    "name": "Desktop Clock",
    "description": "Analog and digital clock for the desktop",
    "version": "1.0.0",
    "author": "Developer",
    "type": "desktop",
    "capabilities": ["desktop-widget"],
    "component": "./ClockWidget.qml",
    "icon": "schedule",
    "settings": "./Settings.qml",
    "permissions": ["settings_read", "settings_write"]
}