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

241 lines
6.1 KiB
Markdown

# 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:
```qml
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
```qml
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:
```qml
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:
```qml
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:
```qml
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
```json
{
"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"]
}
```