Skip to content

Commit 4a71792

Browse files
committed
fix(desktop-widget-settings): Second draft
1 parent 8099815 commit 4a71792

1 file changed

Lines changed: 149 additions & 53 deletions

File tree

src/content/docs/development/plugins/desktop-widget-settings.mdx

Lines changed: 149 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ sidebar:
55
order: 41
66
---
77

8-
A Desktop Widget Settings component is a QML file that gives the ability to change the widgetData.
9-
It is used when right clicking on a desktop widget and pressing "widget settings".
10-
It should follow the following structure:
8+
A dedicated configuration interface for their desktop widget.
9+
Unlike the general [Settings UI](/development/plugins/settings-ui/) which configures plugin-wide settings.
10+
Desktop Widget Settings operate on **per-instance widget data**, the position, scale, and custom properties stored for each individual widget on the desktop.
11+
12+
## Basic Structure
13+
14+
A Desktop Widget Settings component is a QML file that receives a `pluginApi` and a `widgetSettings` object:
1115

1216
```qml
1317
import QtQuick
@@ -17,82 +21,79 @@ import qs.Widgets
1721
1822
ColumnLayout {
1923
id: root
24+
spacing: Style.marginM
2025
21-
// Required: Plugin API
26+
// Plugin API (injected by the settings dialog system)
2227
property var pluginApi: null
23-
property var widgetSettings: null
2428
25-
// Local state for editing
26-
property string editValue: widgetSettings?.data?.myValue ?? ""
29+
// Widget settings object (injected by the settings dialog system)
30+
property var widgetSettings: null
2731
28-
spacing: Style.marginM
32+
// Local state - initialize from widgetSettings.data with metadata fallback
33+
property bool valueShowBackground:
34+
widgetSettings?.data?.showBackground ??
35+
widgetSettings?.metadata?.showBackground ??
36+
true
2937
3038
// Your settings controls here
3139
32-
// Optional: Save function to call when data is changed
40+
NToggle {
41+
Layout.fillWidth: true
42+
label: "Show Background"
43+
description: "Display the widget background container"
44+
checked: root.valueShowBackground
45+
onToggled: checked => {
46+
root.valueShowBackground = checked;
47+
saveSettings();
48+
}
49+
}
50+
3351
function saveSettings() {
34-
widgetSettings.data.value = editValue;
52+
if (!widgetSettings) return;
53+
widgetSettings.data.showBackground = root.valueShowBackground;
3554
widgetSettings.save();
3655
}
3756
}
3857
```
3958

40-
## Required Elements
59+
## How It Works
60+
61+
When a user right-clicks a desktop widget and selects **Widget Settings** (or clicks the gear icon in the Desktop Widgets settings tab), Noctalia loads your `desktopWidgetSettings` component inside a `DesktopWidgetSettingsDialog`. The dialog injects two properties into your component:
4162

4263
### `pluginApi`
43-
Injected by the settings dialog system. Provides access to plugin settings and the save function.
64+
The standard [Plugin API](/development/plugins/api/) object. Use it to access plugin-wide settings, translations, manifest data, and more.
4465

4566
```qml
4667
property var pluginApi: null
4768
```
4869

4970
### `widgetSettings`
50-
Injected by the desktop widget settings dialog system. Provides access to the widget data, metadata and the save function.
71+
An object that provides access to the current widget instance's data:
5172

5273
```qml
5374
property var widgetSettings: null
5475
```
5576

56-
#### `data` field
57-
The data field contains the variables you have saved. Each desktop widget has it's own data.
58-
59-
#### `metadata` field
60-
The metadata is shared between all widgets.
61-
It's the same as the `pluginApi.metadata` field, with the following extra variables: `showBackground` and `roundedCorners`.
62-
63-
The `showBackground` field when enabled shows a background behind the desktop widget.
64-
When the `showBackground` is enabled, the `roundedCorners` variable decides if the desktop widget should have rounded corners.
77+
The `widgetSettings` object contains two variables and one function:
6578

66-
#### `save` function
67-
When the save function is called, the data of the specific widget is updated.
68-
69-
```qml
70-
property var widgetSettings: null
71-
property bool myValue: widgetSettings?.data?.myValue ?? true
79+
#### `data`
80+
- **Type**: `object`
81+
- **Read-only**: no
82+
- **Description**: The current widget instance's stored settings (position, scale, and any custom keys you've added). Modify this object directly.
7283

73-
function saveSettings() {
74-
if(!widgetSettings || !widgetSettings.data) {
75-
Logger.e("MyPlugin", "Error widgetSettings is null");
76-
return;
77-
}
84+
#### `metadata`
85+
- **Type**: object
86+
- **Read-only**: yes
87+
- **Description**: Read-only default metadata registered by the `DesktopWidgetRegistry` for your widget. Use as fallback values.
7888

79-
widgetSettings.data.myValue = myValue;
80-
// Saves the widgetData to the widget.
81-
widgetSettings.save();
82-
}
89+
#### `save()`
90+
- **Type**: function
91+
- **Signature**: `function save(): void`
92+
- **Description**: Call this to persist the current `widgetSettings.data` to disk.
8393

84-
NToggle {
85-
label: "My Toggle"
86-
description: "My very nice and cool toggle!"
87-
checked: myValue
88-
onToggled: checked => {
89-
myValue = checked;
90-
// You can save when you have changed a value.
91-
saveSettings();
92-
}
93-
defaultValue: true
94-
}
95-
```
94+
:::caution
95+
Always call `widgetSettings.save()` after modifying `widgetSettings.data` to persist changes. Unlike the general settings entry point, there is no separate `saveSettings()` function called by the dialog.
96+
:::
9697

9798
## Manifest Entry
9899

@@ -117,6 +118,101 @@ Register the desktop widget settings in your plugin's `manifest.json`:
117118
}
118119
```
119120

121+
:::note
122+
If `desktopWidgetSettings` is not defined but `settings` is, the desktop widget settings menu will load the `settings` component.
123+
:::
124+
125+
:::note
126+
When both `desktopWidgetSettings` and `settings` are defined, the desktop widget settings menu will load `desktopWidgetSettings`. The general `settings` entry point is used for the plugin-wide configuration accessed from **Plugins > Your Plugin > Configure**.
127+
128+
:::
129+
130+
## Local State Pattern
131+
132+
Follows the same local state pattern used in the Settings UI.
133+
Initialize local properties from `widgetSettings.data` with fallbacks to `widgetSettings.metadata`, `pluginApi.pluginSettings` or `pluginApi.manifest.metadata.defaultSettings`:
134+
135+
```qml
136+
ColumnLayout {
137+
id: root
138+
spacing: Style.marginM
139+
140+
property var pluginApi: null
141+
property var widgetSettings: null
142+
143+
// Local state with metadata fallback
144+
property bool valueShowBackground:
145+
widgetSettings?.data?.showBackground ??
146+
widgetSettings?.metadata?.showBackground ??
147+
true
148+
149+
property bool valueRoundedCorners:
150+
widgetSettings?.data?.roundedCorners ??
151+
widgetSettings?.metadata?.roundedCorners ??
152+
true
153+
154+
property string valueLayout:
155+
widgetSettings?.data?.layout ??
156+
pluginApi?.manifest?.metadata?.defaultSettings?.layout ??
157+
"side"
158+
159+
function save() {
160+
if (!widgetSettings) return;
161+
widgetSettings.data.showBackground = root.valueShowBackground;
162+
widgetSettings.data.roundedCorners = root.valueRoundedCorners;
163+
widgetSettings.data.layout = root.valueLayout;
164+
widgetSettings.save();
165+
}
166+
}
167+
```
168+
169+
:::tip
170+
Unlike the general Settings UI where `saveSettings()` is called by the dialog on "Save", Desktop Widget Settings use a **live-save** pattern.
171+
Call `widgetSettings.save()` whenever a value changes.
172+
:::
173+
174+
## `settingsChanged` signal
175+
176+
As an alternative to calling `widgetSettings.save()`, your component can emit a `settingsChanged` signal. The settings dialog listens for this signal and handles persistence automatically:
177+
178+
```qml
179+
ColumnLayout {
180+
id: root
181+
182+
property var pluginApi: null
183+
property var widgetSettings: null
184+
185+
signal settingsChanged(var settings)
186+
187+
property bool valueShowBackground:
188+
widgetSettings?.data?.showBackground ??
189+
widgetSettings?.manifest?.showBackground ??
190+
true
191+
192+
function save() {
193+
var settings = Object.assign({}, widgetSettings?.data || {});
194+
settings.showBackground = root.valueShowBackground;
195+
settingsChanged(settings);
196+
}
197+
198+
NToggle {
199+
Layout.fillWidth: true
200+
label: "Show Background"
201+
checked: root.valueShowBackground
202+
onToggled: checked => {
203+
root.valueShowBackground = checked;
204+
root.save();
205+
}
206+
}
207+
}
208+
209+
210+
```
211+
212+
:::note
213+
This is **not** the recommended way, this is only an alternative way to save the widget state.
214+
:::
215+
120216
## Complete Example
121217

122218
Here's a complete desktop widget settings example:
@@ -308,12 +404,12 @@ ColumnLayout {
308404
```
309405

310406
## Best Practices
311-
312-
1. **Provide fallbacks**: Always have default values for settings and data
313-
2. **Save frequently**: When some property changes, it's recommended to save the data so that the user can see the updated widget.
407+
1. **Use for per-instance options only**: Desktop widget settings should control appearance and behavior of a specific widget instance (background, colors, layout). Plugin-wide settings (API keys, global toggles) belong in the general `settings` entry point.
408+
2. **Provide metadata fallbacks**: Always fall back to `widgetSettings.metadata` values so widgets have sensible defaults before the user configures them.
409+
3. **Save on change**: Use the live-save pattern, call `widgetSettings.save()` immediately when values change. The system debounces writes automatically.
410+
4. **Use Noctalia widgets**: Use `NToggle`, `NDropdown`, `NTextInput`, and other Noctalia components for a consistent look.
314411

315412
## See Also
316-
317413
- [Getting Started](/development/plugins/getting-started/) - Create your first plugin
318414
- [Bar Widget Development](/development/plugins/bar-widget/) - Create bar widgets
319415
- [Desktop Widget Development](/development/plugins/desktop-widget/) - Create desktop widgets

0 commit comments

Comments
 (0)