/*SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>SPDX-License-Identifier: GPL-2.0-or-later*/import QtQuickimport QtQuick.Controls as QQC2import QtQuick.Layoutsimport QtQmlimport org.kde.newstuff as NewStuffimport org.kde.kirigami as Kirigamiimport org.kde.kcmutilsimport org.kde.plasma.plasmoidimport org.kde.plasma.configurationSimpleKCM {id: appearanceRootsignal configurationChangedleftPadding: 0 // let wallpaper config touch the edges in case there's a List/GridView'rightPadding: 0bottomPadding: 0property int formAlignment: wallpaperComboBox.Kirigami.ScenePosition.x - appearanceRoot.Kirigami.ScenePosition.x + Kirigami.Units.smallSpacingproperty string originalWallpaper: ""property alias parentLayout: parentLayoutproperty bool unsavedChanges: falsefunction saveConfig() {if (main.currentItem.saveConfig) {main.currentItem.saveConfig()}configDialog.currentWallpaper = wallpaperComboBox.currentValueappearanceRoot.originalWallpaper = wallpaperComboBox.currentValueconfigDialog.wallpaperConfiguration.keys().forEach(key => {if (main.currentItem["cfg_"+key] !== undefined) {configDialog.wallpaperConfiguration[key] = main.currentItem["cfg_"+key]}})configDialog.applyWallpaper()configDialog.containmentPlugin = pluginComboBox.currentValueappearanceRoot.closeContainmentWarning()appearanceRoot.unsavedChanges = false}function checkUnsavedChanges() {const wallpaperConfig = configDialog.wallpaperConfigurationappearanceRoot.unsavedChanges = configDialog.currentWallpaper != appearanceRoot.originalWallpaper ||configDialog.containmentPlugin != pluginComboBox.currentValue ||wallpaperConfig.keys().some(key => {const cfgKey = "cfg_" + keyif (!(cfgKey in main.currentItem) || key.startsWith("PreviewImage") || key.endsWith("Default")) {return false}return main.currentItem[cfgKey] != wallpaperConfig[key] &&main.currentItem[cfgKey].toString() != wallpaperConfig[key].toString()})}function closeContainmentWarning() {if (main.currentItem?.objectName === "switchContainmentWarningItem") {main.pop();categoriesScroll.enabled = true;}}ColumnLayout {width: appearanceRoot.availableWidthheight: Math.max(implicitHeight, appearanceRoot.availableHeight)spacing: 0 // unless it's 0 there will be an additional gap between two FormLayoutsKirigami.InlineMessage {visible: Plasmoid.immutable || animatingtext: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info:status inlinemessage", "Layout changes have been restricted by the system administrator")showCloseButton: trueLayout.fillWidth: trueLayout.leftMargin: Kirigami.Units.smallSpacingLayout.rightMargin: Kirigami.Units.smallSpacingLayout.bottomMargin: Kirigami.Units.smallSpacing * 2 // we need this because ColumnLayout's spacing is 0}Kirigami.FormLayout {id: parentLayout // needed for twinFormLayouts to work in wallpaper pluginstwinFormLayouts: main.currentItem.formLayout || []Layout.fillWidth: trueQQC2.ComboBox {id: pluginComboBoxLayout.preferredWidth: Math.max(implicitWidth, wallpaperComboBox.implicitWidth)Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:listbox", "Layout:")enabled: !Plasmoid.immutablemodel: configDialog.containmentPluginsConfigModeltextRole: "name"valueRole: "pluginName"onActivated: {if (configDialog.containmentPlugin !== pluginComboBox.currentValue) {main.push(switchContainmentWarning);categoriesScroll.enabled = false;} else {closeContainmentWarning()}appearanceRoot.checkUnsavedChanges()}Component.onCompleted: {currentIndex = indexOfValue(configDialog.containmentPlugin)activated(currentIndex)}}RowLayout {Layout.fillWidth: trueenabled: main.currentItem.objectName !== "switchContainmentWarningItem"Kirigami.FormData.label: i18ndc("plasma_shell_org.kde.plasma.desktop", "@label:listbox", "Wallpaper type:")Kirigami.FormData.buddyFor: wallpaperComboBoxQQC2.ComboBox {id: wallpaperComboBoxfunction selectCurrentWallpaperPlugin() {currentIndex = indexOfValue(configDialog.currentWallpaper)appearanceRoot.originalWallpaper = currentValueactivated(currentIndex)}Layout.preferredWidth: Math.max(implicitWidth, pluginComboBox.implicitWidth)model: configDialog.wallpaperConfigModeltextRole: "name"valueRole: "pluginName"onActivated: {var idx = configDialog.wallpaperConfigModel.index(currentIndex, 0)if (configDialog.currentWallpaper === currentValue && main.sourceFile !== "tbd") {return;}configDialog.currentWallpaper = currentValuemain.sourceFile = idx.data(ConfigModel.SourceRole)appearanceRoot.checkUnsavedChanges()}Component.onCompleted: {selectCurrentWallpaperPlugin();}Connections {enabled: truetarget: configDialog.wallpaperConfigModelfunction onWallpaperPluginsChanged() {wallpaperComboBox.selectCurrentWallpaperPlugin();}}}NewStuff.Button {configFile: "wallpaperplugin.knsrc"text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Get New Pluginsβ¦")visibleWhenDisabled: true // don't hide on disabledLayout.preferredHeight: wallpaperComboBox.height}}}Item {id: emptyConfig}QQC2.StackView {id: mainimplicitHeight: main.empty ? 0 : currentItem.implicitHeightLayout.fillHeight: true;Layout.fillWidth: true;// Bug 360862: if wallpaper has no config, sourceFile will be ""// so we wouldn't load emptyConfig and break all over the place// hence set it to some random value initiallyproperty string sourceFile: "tbd"onSourceFileChanged: loadSourceFile()function loadSourceFile() {const wallpaperConfig = configDialog.wallpaperConfiguration// BUG 407619: wallpaperConfig can be null before calling `ContainmentItem::loadWallpaper()`if (wallpaperConfig && sourceFile) {var props = {"configDialog": configDialog,"wallpaperConfiguration": Qt.binding(() => Plasmoid.wallpaperGraphicsObject.configuration)}// Some third-party wallpaper plugins need the config keys to be set initially.// We should not break them within one Plasma major version, but setting everything// will lead to an error message for every unused property (and some, like KConfigXT// default values, are used by almost no plugin configuration). We load the config// page in a temp variable first, then use that to figure out which ones we need to// set initially.// TODO Plasma 7: consider whether we can drop this workaroundconst temp = Qt.createComponent(Qt.resolvedUrl(sourceFile)).createObject(appearanceRoot, props)wallpaperConfig.keys().forEach(key => {const cfgKey = "cfg_" + key;if (cfgKey in temp) {props[cfgKey] = wallpaperConfig[key]}})temp.destroy()var newItem = replace(Qt.resolvedUrl(sourceFile), props)wallpaperConfig.keys().forEach(key => {const cfgKey = "cfg_" + key;if (cfgKey in newItem) {let changedSignal = main.currentItem[cfgKey + "Changed"]if (changedSignal) {changedSignal.connect(appearanceRoot.checkUnsavedChanges)}}});const configurationChangedSignal = newItem.configurationChangedif (configurationChangedSignal) {configurationChangedSignal.connect(appearanceRoot.configurationChanged)}} else {replace(emptyConfig)}}}Kirigami.Separator {Layout.fillWidth: true}}Component {id: switchContainmentWarningItem {objectName: "switchContainmentWarningItem"Kirigami.PlaceholderMessage {id: messagewidth: parent.width - Kirigami.Units.largeSpacing * 8anchors.centerIn: parenticon.name: "documentinfo"text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@info", "Layout changes must be applied before other changes can be made")helpfulAction: QQC2.Action {icon.name: "dialog-ok-apply"text: i18ndc("plasma_shell_org.kde.plasma.desktop", "@action:button", "Apply Now")onTriggered: appearanceRoot.saveConfig()}}}}}