1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-25 05:52:50 -05:00
Files
DankMaterialShell/quickshell/Modules/Plugins/PluginSettings.qml
bbedward 0034926df7 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
2025-12-17 12:08:03 -05:00

283 lines
9.2 KiB
QML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import QtQuick
import Quickshell
import qs.Common
import qs.Widgets
Item {
id: root
required property string pluginId
property var pluginService: null
default property list<QtObject> content
signal settingChanged
property var variants: []
property alias variantsModel: variantsListModel
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;
}
Component.onCompleted: {
loadVariants();
}
onPluginServiceChanged: {
if (pluginService) {
loadVariants();
for (let i = 0; i < content.length; i++) {
const child = content[i];
if (child.loadValue) {
child.loadValue();
}
}
}
}
onContentChanged: {
for (let i = 0; i < content.length; i++) {
const item = content[i];
if (item instanceof Item) {
item.parent = settingsColumn;
}
}
}
Connections {
target: pluginService
function onPluginDataChanged(changedPluginId) {
if (changedPluginId === pluginId) {
loadVariants();
}
}
}
function loadVariants() {
if (!pluginService || !pluginId) {
variants = [];
return;
}
variants = pluginService.getPluginVariants(pluginId);
syncVariantsToModel();
}
function syncVariantsToModel() {
variantsListModel.clear();
for (let i = 0; i < variants.length; i++) {
variantsListModel.append(variants[i]);
}
}
onVariantsChanged: {
syncVariantsToModel();
}
ListModel {
id: variantsListModel
}
function createVariant(variantName, variantConfig) {
if (!pluginService || !pluginId) {
return null;
}
return pluginService.createPluginVariant(pluginId, variantName, variantConfig);
}
function removeVariant(variantId) {
if (!pluginService || !pluginId) {
return;
}
pluginService.removePluginVariant(pluginId, variantId);
}
function updateVariant(variantId, variantConfig) {
if (!pluginService || !pluginId) {
return;
}
pluginService.updatePluginVariant(pluginId, variantId, variantConfig);
}
function saveValue(key, value) {
if (!pluginService) {
return;
}
if (!hasPermission) {
console.warn("PluginSettings: Plugin", pluginId, "does not have settings_write permission");
return;
}
if (pluginService.savePluginData) {
pluginService.savePluginData(pluginId, key, value);
settingChanged();
}
}
function loadValue(key, defaultValue) {
if (pluginService && pluginService.loadPluginData) {
return pluginService.loadPluginData(pluginId, key, defaultValue);
}
return defaultValue;
}
function findFlickable(item) {
var current = item?.parent;
while (current) {
if (current.contentY !== undefined && current.contentHeight !== undefined) {
return current;
}
current = current.parent;
}
return null;
}
function ensureItemVisible(item) {
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 itemRelativeY = itemGlobalY - flickableGlobalY;
var viewportTop = 0;
var viewportBottom = viewportHeight;
if (itemRelativeY < viewportTop) {
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);
}
}
StyledText {
id: errorText
visible: pluginService && !root.hasPermission
anchors.fill: parent
text: I18n.tr("This plugin does not have 'settings_write' permission.\n\nAdd \"permissions\": [\"settings_read\", \"settings_write\"] to plugin.json")
color: Theme.error
font.pixelSize: Theme.fontSizeMedium
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
}
Column {
id: settingsColumn
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);
}
}
}
}
}
}
}
}