import QtQuick import qs.Common import qs.Services import qs.Widgets Item { id: root required property string pluginId property var pluginService: null default property list content signal settingChanged() property var variants: [] property alias variantsModel: variantsListModel implicitHeight: hasPermission ? settingsColumn.implicitHeight : errorText.implicitHeight height: implicitHeight 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 } }