1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-27 15:02:50 -05:00

plugins/desktop-widgets: create a new "desktop" widget plugin type

- Draggable per-monitor background layer widgets
- Add basic dms version checks on plugins
- Clock: built-in clock desktop plugin
- dgop: built-in system monitor desktop plugin
This commit is contained in:
bbedward
2025-12-17 12:08:03 -05:00
parent d082d41ab9
commit 0034926df7
27 changed files with 4135 additions and 62 deletions

View File

@@ -1,6 +1,6 @@
import QtQuick
import Quickshell
import qs.Common
import qs.Services
import qs.Widgets
Item {
@@ -10,7 +10,7 @@ Item {
property var pluginService: null
default property list<QtObject> content
signal settingChanged()
signal settingChanged
property var variants: []
property alias variantsModel: variantsListModel
@@ -18,26 +18,35 @@ Item {
implicitHeight: hasPermission ? settingsColumn.implicitHeight : errorText.implicitHeight
height: implicitHeight
readonly property bool isDesktopPlugin: {
if (!pluginService || !pluginId)
return false;
const plugin = pluginService.availablePlugins[pluginId];
return plugin?.type === "desktop";
}
readonly property bool hasPermission: {
if (!pluginService || !pluginId) return true
const allPlugins = pluginService.availablePlugins
const plugin = allPlugins[pluginId]
if (!plugin) return true
const permissions = Array.isArray(plugin.permissions) ? plugin.permissions : []
return permissions.indexOf("settings_write") !== -1
if (!pluginService || !pluginId)
return true;
const allPlugins = pluginService.availablePlugins;
const plugin = allPlugins[pluginId];
if (!plugin)
return true;
const permissions = Array.isArray(plugin.permissions) ? plugin.permissions : [];
return permissions.indexOf("settings_write") !== -1;
}
Component.onCompleted: {
loadVariants()
loadVariants();
}
onPluginServiceChanged: {
if (pluginService) {
loadVariants()
loadVariants();
for (let i = 0; i < content.length; i++) {
const child = content[i]
const child = content[i];
if (child.loadValue) {
child.loadValue()
child.loadValue();
}
}
}
@@ -45,9 +54,9 @@ Item {
onContentChanged: {
for (let i = 0; i < content.length; i++) {
const item = content[i]
const item = content[i];
if (item instanceof Item) {
item.parent = settingsColumn
item.parent = settingsColumn;
}
}
}
@@ -56,29 +65,29 @@ Item {
target: pluginService
function onPluginDataChanged(changedPluginId) {
if (changedPluginId === pluginId) {
loadVariants()
loadVariants();
}
}
}
function loadVariants() {
if (!pluginService || !pluginId) {
variants = []
return
variants = [];
return;
}
variants = pluginService.getPluginVariants(pluginId)
syncVariantsToModel()
variants = pluginService.getPluginVariants(pluginId);
syncVariantsToModel();
}
function syncVariantsToModel() {
variantsListModel.clear()
variantsListModel.clear();
for (let i = 0; i < variants.length; i++) {
variantsListModel.append(variants[i])
variantsListModel.append(variants[i]);
}
}
onVariantsChanged: {
syncVariantsToModel()
syncVariantsToModel();
}
ListModel {
@@ -87,79 +96,76 @@ Item {
function createVariant(variantName, variantConfig) {
if (!pluginService || !pluginId) {
return null
return null;
}
return pluginService.createPluginVariant(pluginId, variantName, variantConfig)
return pluginService.createPluginVariant(pluginId, variantName, variantConfig);
}
function removeVariant(variantId) {
if (!pluginService || !pluginId) {
return
return;
}
pluginService.removePluginVariant(pluginId, variantId)
pluginService.removePluginVariant(pluginId, variantId);
}
function updateVariant(variantId, variantConfig) {
if (!pluginService || !pluginId) {
return
return;
}
pluginService.updatePluginVariant(pluginId, variantId, variantConfig)
pluginService.updatePluginVariant(pluginId, variantId, variantConfig);
}
function saveValue(key, value) {
if (!pluginService) {
return
return;
}
if (!hasPermission) {
console.warn("PluginSettings: Plugin", pluginId, "does not have settings_write permission")
return
console.warn("PluginSettings: Plugin", pluginId, "does not have settings_write permission");
return;
}
if (pluginService.savePluginData) {
pluginService.savePluginData(pluginId, key, value)
settingChanged()
pluginService.savePluginData(pluginId, key, value);
settingChanged();
}
}
function loadValue(key, defaultValue) {
if (pluginService && pluginService.loadPluginData) {
return pluginService.loadPluginData(pluginId, key, defaultValue)
return pluginService.loadPluginData(pluginId, key, defaultValue);
}
return defaultValue
return defaultValue;
}
function findFlickable(item) {
var current = item?.parent
var current = item?.parent;
while (current) {
if (current.contentY !== undefined && current.contentHeight !== undefined) {
return current
return current;
}
current = current.parent
current = current.parent;
}
return null
return null;
}
function ensureItemVisible(item) {
if (!item) return
if (!item)
return;
var flickable = findFlickable(root);
if (!flickable)
return;
var itemGlobalY = item.mapToItem(null, 0, 0).y;
var itemHeight = item.height;
var flickableGlobalY = flickable.mapToItem(null, 0, 0).y;
var viewportHeight = flickable.height;
var flickable = findFlickable(root)
if (!flickable) return
var itemGlobalY = item.mapToItem(null, 0, 0).y
var itemHeight = item.height
var flickableGlobalY = flickable.mapToItem(null, 0, 0).y
var viewportHeight = flickable.height
var itemRelativeY = itemGlobalY - flickableGlobalY
var viewportTop = 0
var viewportBottom = viewportHeight
var itemRelativeY = itemGlobalY - flickableGlobalY;
var viewportTop = 0;
var viewportBottom = viewportHeight;
if (itemRelativeY < viewportTop) {
flickable.contentY = Math.max(0, flickable.contentY - (viewportTop - itemRelativeY) - Theme.spacingL)
flickable.contentY = Math.max(0, flickable.contentY - (viewportTop - itemRelativeY) - Theme.spacingL);
} else if (itemRelativeY + itemHeight > viewportBottom) {
flickable.contentY = Math.min(
flickable.contentHeight - viewportHeight,
flickable.contentY + (itemRelativeY + itemHeight - viewportBottom) + Theme.spacingL
)
flickable.contentY = Math.min(flickable.contentHeight - viewportHeight, flickable.contentY + (itemRelativeY + itemHeight - viewportBottom) + Theme.spacingL);
}
}
@@ -180,5 +186,97 @@ Item {
visible: root.hasPermission
width: parent.width
spacing: Theme.spacingM
Item {
id: desktopDisplaySettings
visible: root.isDesktopPlugin
width: parent.width
height: visible ? displaySettingsColumn.implicitHeight : 0
Column {
id: displaySettingsColumn
width: parent.width
spacing: Theme.spacingS
Rectangle {
width: parent.width
height: 1
color: Theme.outline
opacity: 0.3
visible: root.content.length > 0
}
StyledText {
text: I18n.tr("Display Settings")
font.pixelSize: Theme.fontSizeMedium
font.weight: Font.Medium
color: Theme.surfaceText
}
StyledText {
text: I18n.tr("Choose which displays show this widget")
font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText
width: parent.width
wrapMode: Text.WordWrap
}
DankToggle {
width: parent.width
text: I18n.tr("All displays")
checked: {
const prefs = root.loadValue("displayPreferences", ["all"]);
return Array.isArray(prefs) && (prefs.includes("all") || prefs.length === 0);
}
onToggled: isChecked => {
if (isChecked) {
root.saveValue("displayPreferences", ["all"]);
} else {
root.saveValue("displayPreferences", []);
}
}
}
Column {
width: parent.width
spacing: Theme.spacingXS
visible: {
const prefs = root.loadValue("displayPreferences", ["all"]);
return !Array.isArray(prefs) || (!prefs.includes("all") && prefs.length >= 0);
}
Repeater {
model: Quickshell.screens
DankToggle {
required property var modelData
width: parent.width
text: SettingsData.getScreenDisplayName(modelData)
description: modelData.width + "×" + modelData.height
checked: {
const prefs = root.loadValue("displayPreferences", ["all"]);
if (!Array.isArray(prefs) || prefs.includes("all"))
return false;
return prefs.some(p => p.name === modelData.name);
}
onToggled: isChecked => {
var prefs = root.loadValue("displayPreferences", ["all"]);
if (!Array.isArray(prefs) || prefs.includes("all")) {
prefs = [];
}
prefs = prefs.filter(p => p.name !== modelData.name);
if (isChecked) {
prefs.push({
name: modelData.name,
model: modelData.model || ""
});
}
root.saveValue("displayPreferences", prefs);
}
}
}
}
}
}
}
}