diff --git a/shell/contents/configuration/AppletConfiguration.qml b/shell/contents/configuration/AppletConfiguration.qml new file mode 100644 index 00000000..ca33184d --- /dev/null +++ b/shell/contents/configuration/AppletConfiguration.qml @@ -0,0 +1,382 @@ +/* + * SPDX-FileCopyrightText: 2013 Marco Martin + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import QtQuick 2.6 +import QtQuick.Controls 2.3 as QtControls +import QtQuick.Layouts 1.0 +import QtQuick.Window 2.2 + +import org.kde.kirigami 2.5 as Kirigami +import org.kde.plasma.core 2.1 as PlasmaCore +import org.kde.plasma.configuration 2.0 + + +//TODO: all of this will be done with desktop components +Rectangle { + id: root + // Layout.minimumWidth: plasmoid.availableScreenRect.width + // Layout.minimumHeight: plasmoid.availableScreenRect.height + + + LayoutMirroring.enabled: Qt.application.layoutDirection === Qt.RightToLeft + LayoutMirroring.childrenInherit: true + + color: "transparent" + +//BEGIN properties + property bool isContainment: false + property alias internalDialog: dialogContents +//END properties + +//BEGIN model + property ConfigModel globalConfigModel: globalAppletConfigModel + + ConfigModel { + id: globalAppletConfigModel + } + + Connections { + target: root.Window.window + function onVisibleChanged() { + if (root.Window.window.visible) { + root.Window.window.showMaximized(); + } + } + } + + PlasmaCore.SortFilterModel { + id: configDialogFilterModel + sourceModel: configDialog.configModel + filterRole: "visible" + filterCallback: function(source_row, value) { return value; } + } +//END model + +//BEGIN functions + function saveConfig() { + if (pageStack.currentItem.saveConfig) { + pageStack.currentItem.saveConfig() + } + for (var key in plasmoid.configuration) { + if (pageStack.currentItem["cfg_"+key] !== undefined) { + plasmoid.configuration[key] = pageStack.currentItem["cfg_"+key] + } + } + } + + function configurationHasChanged() { + for (var key in plasmoid.configuration) { + if (pageStack.currentItem["cfg_"+key] !== undefined) { + //for objects == doesn't work + if (typeof plasmoid.configuration[key] == 'object') { + for (var i in plasmoid.configuration[key]) { + if (plasmoid.configuration[key][i] != pageStack.currentItem["cfg_"+key][i]) { + return true; + } + } + return false; + } else if (pageStack.currentItem["cfg_"+key] != plasmoid.configuration[key]) { + return true; + } + } + } + return false; + } + + + function settingValueChanged() { + if (pageStack.currentItem.saveConfig !== undefined) { + pageStack.currentItem.saveConfig(); + } else { + root.saveConfig(); + } + } +//END functions + + +//BEGIN connections + Component.onCompleted: { + if (!isContainment && configDialog.configModel && configDialog.configModel.count > 0) { + if (configDialog.configModel.get(0).source) { + pageStack.sourceFile = configDialog.configModel.get(0).source + } else if (configDialog.configModel.get(0).kcm) { + pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml"); + pageStack.currentItem.kcm = configDialog.configModel.get(0).kcm; + } else { + pageStack.sourceFile = ""; + } + pageStack.title = configDialog.configModel.get(0).name + } else { + pageStack.sourceFile = globalConfigModel.get(0).source + pageStack.title = globalConfigModel.get(0).name + } +// root.width = dialogRootItem.implicitWidth +// root.height = dialogRootItem.implicitHeight + } + onVisibleChanged: { + if (visible) { + dialogContents.visible = true; + } + } +//END connections + +//BEGIN UI components + + Rectangle { + id: dialogContents + visible: true + anchors.fill: parent + color: Kirigami.Theme.backgroundColor + + ColumnLayout { + id: dialogRootItem + anchors.fill: parent + + spacing: 0 + implicitWidth: scroll.implicitWidth + + QtControls.ScrollView { + id: scroll + + activeFocusOnTab: false + + Layout.fillWidth: true + Layout.fillHeight: true + + implicitWidth: pageColumn.implicitWidth + implicitHeight: pageColumn.implicitHeight + + property Item flickableItem: pageFlickable + // this horrible code below ensures the control with active focus stays visible in the window + // by scrolling the view up or down as needed when tabbing through the window + Window.onActiveFocusItemChanged: { + var flickable = scroll.flickableItem; + + var item = Window.activeFocusItem; + if (!item) { + return; + } + + // when an item within ScrollView has active focus the ScrollView, + // as FocusScope, also has it, so we only scroll in this case + if (!scroll.activeFocus) { + return; + } + + var padding = PlasmaCore.Units.gridUnit * 2 // some padding to the top/bottom when we scroll + + var yPos = item.mapToItem(scroll.contentItem, 0, 0).y; + if (yPos < flickable.contentY) { + flickable.contentY = Math.max(0, yPos - padding); + + // The "Math.min(padding, item.height)" ensures that we only scroll the item into view + // when it's barely visible. The logic was mostly meant for keyboard navigating through + // a list of CheckBoxes, so this check keeps us from trying to scroll an inner ScrollView + // into view when it implicitly gains focus (like plasma-pa config dialog has). + } else if (yPos + Math.min(padding, item.height) > flickable.contentY + flickable.height) { + flickable.contentY = Math.min(flickable.contentHeight - flickable.height, + yPos - flickable.height + item.height + padding); + } + } + Flickable { + id: pageFlickable + anchors { + fill: parent + margins: PlasmaCore.Units.smallSpacing + } + contentHeight: pageColumn.height + contentWidth: width + ColumnLayout { + id: pageColumn + spacing: PlasmaCore.Units.largeSpacing / 2 + width: pageFlickable.width + height: Math.max(implicitHeight, pageFlickable.height) + + Kirigami.Heading { + id: pageTitle + Layout.fillWidth: true + level: 1 + text: pageStack.title + } + + QtControls.StackView { + id: pageStack + property string title: "" + property bool invertAnimations: false + + Layout.fillWidth: true + Layout.fillHeight: true + implicitWidth: Math.max(currentItem ? Math.max(currentItem.Layout.minimumWidth, currentItem.Layout.preferredWidth, currentItem.implicitWidth) : 0, PlasmaCore.Units.gridUnit * 15) + implicitHeight: Math.max(currentItem ? Math.max(currentItem.Layout.minimumHeight, currentItem.Layout.preferredHeight, currentItem.implicitHeight) : 0, PlasmaCore.Units.gridUnit * 15) + + property string sourceFile + + onSourceFileChanged: { + if (!sourceFile) { + return; + } + + //in a StackView pages need to be initialized with stackviews size, or have none + var props = {"width": width, "height": height} + + var plasmoidConfig = plasmoid.configuration + for (var key in plasmoidConfig) { + props["cfg_" + key] = plasmoid.configuration[key] + } + + var newItem = replace(Qt.resolvedUrl(sourceFile), props) + + for (var key in plasmoidConfig) { + var changedSignal = newItem["cfg_" + key + "Changed"] + if (changedSignal) { + changedSignal.connect(root.settingValueChanged) + } + } + + var configurationChangedSignal = newItem.configurationChanged + if (configurationChangedSignal) { + configurationChangedSignal.connect(root.settingValueChanged) + } + + scroll.flickableItem.contentY = 0 + + /* + for (var prop in currentItem) { + if (prop.indexOf("cfg_") === 0) { + currentItem[prop+"Changed"].connect(root.pageChanged) + } + }*/ + } + + replaceEnter: Transition { + ParallelAnimation { + //OpacityAnimator when starting from 0 is buggy (it shows one frame with opacity 1) + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + XAnimator { + from: pageStack.invertAnimations ? -scroll.width/3: scroll.width/3 + to: 0 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + replaceExit: Transition { + ParallelAnimation { + OpacityAnimator { + from: 1 + to: 0 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + XAnimator { + from: 0 + to: pageStack.invertAnimations ? scroll.width/3 : -scroll.width/3 + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + } + } + } + } + + Rectangle { + id: separator + Layout.fillWidth: true + Layout.preferredHeight: 1 + color: Kirigami.Theme.highlightColor + visible: categoriesScroll.visible + Behavior on color { + ColorAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + QtControls.ScrollView { + id: categoriesScroll + + Layout.fillWidth: true + Layout.preferredHeight: categories.implicitHeight + + visible: (configDialog.configModel ? configDialog.configModel.count : 0) + globalConfigModel.count > 1 + + Keys.onLeftPressed: { + var buttons = categories.children + + var foundPrevious = false + for (var i = buttons.length - 1; i >= 0; --i) { + var button = buttons[i]; + if (!button.hasOwnProperty("current")) { + // not a ConfigCategoryDelegate + continue; + } + + if (foundPrevious) { + button.openCategory() + return + } else if (button.current) { + foundPrevious = true + } + } + } + + Keys.onRightPressed: { + var buttons = categories.children + + var foundNext = false + for (var i = 0, length = buttons.length; i < length; ++i) { + var button = buttons[i]; + console.log(button) + if (!button.hasOwnProperty("current")) { + continue; + } + + if (foundNext) { + button.openCategory() + return + } else if (button.current) { + foundNext = true + } + } + } + + RowLayout { + id: categories + spacing: 0 + width: categoriesScroll.width + height: implicitHeight + + property Item currentItem: children[1] + + Repeater { + model: root.isContainment ? globalConfigModel : undefined + delegate: ConfigCategoryDelegate {} + } + Repeater { + model: configDialogFilterModel + delegate: ConfigCategoryDelegate {} + } + Repeater { + model: !root.isContainment ? globalConfigModel : undefined + delegate: ConfigCategoryDelegate {} + } + } + } + + } + } +//END UI components +} + diff --git a/shell/contents/configuration/ConfigCategoryDelegate.qml b/shell/contents/configuration/ConfigCategoryDelegate.qml new file mode 100644 index 00000000..8f940178 --- /dev/null +++ b/shell/contents/configuration/ConfigCategoryDelegate.qml @@ -0,0 +1,131 @@ +/* + * SPDX-FileCopyrightText: 2013 Marco Martin + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import QtQuick 2.0 +import QtQuick.Layouts 1.1 +import QtQuick.Controls 2.3 as QtControls +import QtQuick.Window 2.2 + +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.kquickcontrolsaddons 2.0 +import org.kde.kirigami 2.5 as Kirigami + +MouseArea { + id: delegate + +//BEGIN properties + implicitWidth: delegateContents.implicitWidth + 4 * PlasmaCore.Units.smallSpacing + implicitHeight: delegateContents.height + PlasmaCore.Units.smallSpacing * 4 + Layout.fillWidth: true + hoverEnabled: true + + property bool current: (model.kcm && pageStack.currentItem.kcm && model.kcm == pageStack.currentItem.kcm) || (model.source == pageStack.sourceFile) +//END properties + +//BEGIN functions + function openCategory() { + if (current) { + return; + } + if (typeof(categories.currentItem) !== "undefined") { + pageStack.invertAnimations = (categories.currentItem.x > delegate.x); + categories.currentItem = delegate; + } + + if (model.source) { + pageStack.sourceFile = model.source; + } else if (model.kcm) { + pageStack.sourceFile = ""; + pageStack.sourceFile = Qt.resolvedUrl("ConfigurationKcmPage.qml"); + pageStack.currentItem.kcm = model.kcm; + } else { + pageStack.sourceFile = ""; + } + pageStack.title = model.name + } +//END functions + +//BEGIN connections + onPressed: { + categoriesScroll.forceActiveFocus() + + if (current) { + return; + } + + openCategory(); + } + onCurrentChanged: { + if (current) { + categories.currentItem = delegate; + } + } +//END connections + +//BEGIN UI components + Rectangle { + anchors.fill: parent + color: Kirigami.Theme.highlightColor + opacity: { // try to match Breeze style hover handling + var active = categoriesScroll.activeFocus && Window.active + if (current) { + if (active) { + return 1 + } else if (delegate.containsMouse) { + return 0.6 + } else { + return 0.3 + } + } else if (delegate.containsMouse) { + if (active) { + return 0.3 + } else { + return 0.1 + } + } + return 0 + } + Behavior on opacity { + NumberAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + + ColumnLayout { + id: delegateContents + spacing: PlasmaCore.Units.smallSpacing + width: parent.width + anchors.verticalCenter: parent.verticalCenter + + QIconItem { + id: iconItem + Layout.alignment: Qt.AlignHCenter + width: PlasmaCore.Units.iconSizes.medium + height: width + icon: model.icon + state: current && categoriesScroll.activeFocus ? QIconItem.SelectedState : QIconItem.DefaultState + } + + QtControls.Label { + id: nameLabel + Layout.fillWidth: true + text: model.name + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + color: current && categoriesScroll.activeFocus ? Kirigami.Theme.highlightedTextColor : Kirigami.Theme.textColor + Behavior on color { + ColorAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + } +//END UI components +} + diff --git a/shell/contents/configuration/ConfigurationContainmentAppearance.qml b/shell/contents/configuration/ConfigurationContainmentAppearance.qml new file mode 100644 index 00000000..4457bac7 --- /dev/null +++ b/shell/contents/configuration/ConfigurationContainmentAppearance.qml @@ -0,0 +1,191 @@ +/* + * SPDX-FileCopyrightText: 2013 Marco Martin + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import QtQuick 2.15 +import org.kde.plasma.configuration 2.0 +import QtQuick.Controls 2.3 as QQC2 +import QtQuick.Layouts 1.1 + +import org.kde.newstuff 1.62 as NewStuff +import org.kde.kirigami 2.5 as Kirigami +import org.kde.plasma.core 2.0 as PlasmaCore + +ColumnLayout { + id: root + + property int formAlignment: wallpaperComboBox.Kirigami.ScenePosition.x - root.Kirigami.ScenePosition.x + (PlasmaCore.Units.largeSpacing/2) + property string currentWallpaper: "" + property string containmentPlugin: "" + signal configurationChanged + +//BEGIN functions + function saveConfig() { + if (main.currentItem.saveConfig) { + main.currentItem.saveConfig() + } + for (var key in configDialog.wallpaperConfiguration) { + if (main.currentItem["cfg_"+key] !== undefined) { + configDialog.wallpaperConfiguration[key] = main.currentItem["cfg_"+key] + } + } + configDialog.currentWallpaper = root.currentWallpaper; + configDialog.applyWallpaper() + configDialog.containmentPlugin = root.containmentPlugin + } +//END functions + + Component.onCompleted: { + for (var i = 0; i < configDialog.wallpaperConfigModel.count; ++i) { + var data = configDialog.wallpaperConfigModel.get(i); + if (configDialog.currentWallpaper == data.pluginName) { + wallpaperComboBox.currentIndex = i + wallpaperComboBox.activated(i); + break; + } + } + } + + Kirigami.InlineMessage { + visible: plasmoid.immutable || animating + text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout changes have been restricted by the system administrator") + showCloseButton: true + Layout.fillWidth: true + Layout.leftMargin: Kirigami.Units.smallSpacing + Layout.rightMargin: Kirigami.Units.smallSpacing + Layout.bottomMargin: Kirigami.Units.smallSpacing * 2 // we need this because ColumnLayout's spacing is 0 + } + + Kirigami.FormLayout { + Layout.fillWidth: true + + Component.onCompleted: { + for (var i = 0; i < configDialog.containmentPluginsConfigModel.count; ++i) { + var data = configDialog.containmentPluginsConfigModel.get(i); + if (configDialog.containmentPlugin === data.pluginName) { + pluginComboBox.currentIndex = i + pluginComboBox.activated(i); + break; + } + } + + for (var i = 0; i < configDialog.wallpaperConfigModel.count; ++i) { + var data = configDialog.wallpaperConfigModel.get(i); + if (configDialog.currentWallpaper === data.pluginName) { + wallpaperComboBox.currentIndex = i + wallpaperComboBox.activated(i); + break; + } + } + } + + QQC2.ComboBox { + id: pluginComboBox + Layout.preferredWidth: Math.max(implicitWidth, wallpaperComboBox.implicitWidth) + Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout:") + enabled: !plasmoid.immutable + model: configDialog.containmentPluginsConfigModel + textRole: "name" + visible: count > 1 // only show if there are multiple plugins + onActivated: { + var model = configDialog.containmentPluginsConfigModel.get(currentIndex) + root.containmentPlugin = model.pluginName + root.settingValueChanged() + } + } + + RowLayout { + Layout.fillWidth: true + Kirigami.FormData.label: i18nd("plasma_shell_org.kde.plasma.desktop", "Wallpaper Type:") + QQC2.ComboBox { + id: wallpaperComboBox + Layout.preferredWidth: Math.max(implicitWidth, pluginComboBox.implicitWidth) + model: configDialog.wallpaperConfigModel + width: PlasmaCore.Theme.mSize(PlasmaCore.Theme.defaultFont).width * 24 + textRole: "name" + onActivated: { + var model = configDialog.wallpaperConfigModel.get(currentIndex) + root.currentWallpaper = model.pluginName + configDialog.currentWallpaper = model.pluginName + main.sourceFile = model.source + root.configurationChanged() + } + } + NewStuff.Button { + configFile: "wallpaperplugin.knsrc" + text: i18nd("plasma_shell_org.kde.plasma.desktop", "Get New Plugins…") + Layout.preferredHeight: wallpaperComboBox.height + } + } + } + + ColumnLayout { + id: switchContainmentWarning + Layout.fillWidth: true + visible: configDialog.containmentPlugin !== root.containmentPlugin + QQC2.Label { + Layout.fillWidth: true + text: i18nd("plasma_shell_org.kde.plasma.desktop", "Layout changes must be applied before other changes can be made") + wrapMode: Text.Wrap + horizontalAlignment: Text.AlignHCenter + } + QQC2.Button { + Layout.alignment: Qt.AlignHCenter + text: i18nd("plasma_shell_org.kde.plasma.desktop", "Apply now") + onClicked: saveConfig() + } + + Binding { + target: categoriesScroll //from parent scope AppletConfiguration + property: "enabled" + value: !switchContainmentWarning.visible + } + } + + Item { + Layout.fillHeight: true + visible: switchContainmentWarning.visible + } + + Item { + id: emptyConfig + } + + QQC2.StackView { + id: main + + Layout.fillHeight: true; + Layout.fillWidth: true; + + visible: !switchContainmentWarning.visible + + // 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 initially + property string sourceFile: "tbd" + onSourceFileChanged: { + if (sourceFile) { + var props = {} + + var wallpaperConfig = configDialog.wallpaperConfiguration + for (var key in wallpaperConfig) { + props["cfg_" + key] = wallpaperConfig[key] + } + + var newItem = replace(Qt.resolvedUrl(sourceFile), props) + + for (var key in wallpaperConfig) { + var changedSignal = newItem["cfg_" + key + "Changed"] + if (changedSignal) { + changedSignal.connect(root.configurationChanged) + } + } + } else { + replace(emptyConfig) + } + } + } +} + diff --git a/shell/contents/configuration/ContainmentConfiguration.qml b/shell/contents/configuration/ContainmentConfiguration.qml new file mode 100644 index 00000000..217cbd2c --- /dev/null +++ b/shell/contents/configuration/ContainmentConfiguration.qml @@ -0,0 +1,168 @@ +/* + * SPDX-FileCopyrightText: 2013 Marco Martin + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +import QtQuick 2.12 +import QtQuick.Layouts 1.0 +import QtQuick.Window 2.2 +import QtQuick.Controls 2.3 as Controls +import org.kde.plasma.extras 2.0 as PlasmaExtras +import org.kde.plasma.core 2.0 as PlasmaCore +import org.kde.plasma.configuration 2.0 + +//for the "simple mode" +import org.kde.plasma.wallpapers.image 2.0 as Wallpaper +import org.kde.kquickcontrolsaddons 2.0 as Addons +import org.kde.kcm 1.1 as KCM + +AppletConfiguration { + id: root + isContainment: true + + internalDialog.visible: false + internalDialog.width: root.width < root.height ? root.width : Math.min(root.width, Math.max(internalDialog.implicitWidth, PlasmaCore.Units.gridUnit * 45)) + internalDialog.height: Math.min(root.height, Math.max(internalDialog.implicitHeight, PlasmaCore.Units.gridUnit * 29)) + + readonly property bool horizontal: root.width > root.height + +//BEGIN model + globalConfigModel: globalContainmentConfigModel + + ConfigModel { + id: globalContainmentConfigModel + ConfigCategory { + name: i18nd("plasma_shell_org.kde.plasma.desktop", "Wallpaper") + icon: "preferences-desktop-wallpaper" + source: "ConfigurationContainmentAppearance.qml" + } + } +//END model + + Controls.Drawer { + id: imageWallpaperDrawer + edge: root.horizontal ? Qt.LeftEdge : Qt.BottomEdge + visible: true + dragMargin: 0 + + onClosed: { + if (!root.internalDialog.visible) { + configDialog.close() + } + } + onOpened: { + wallpapersView.forceActiveFocus() + } + implicitWidth: PlasmaCore.Units.gridUnit * 10 + implicitHeight: PlasmaCore.Units.gridUnit * 8 + width: root.horizontal ? implicitWidth : root.width + height: root.horizontal ? root.height : implicitHeight + Wallpaper.ImageBackend { + id: imageWallpaper + } + background: null + + ListView { + id: wallpapersView + anchors.fill: parent + orientation: root.horizontal ? ListView.Vertical : ListView.Horizontal + keyNavigationEnabled: true + highlightFollowsCurrentItem: true + snapMode: ListView.SnapToItem + model: imageWallpaper.wallpaperModel + onCountChanged: currentIndex = Math.min(model.indexOf(configDialog.wallpaperConfiguration["Image"]), model.rowCount()-1) + footer: Controls.Control { + z: 999 + width: root.horizontal ? parent.width : implicitWidth + height: root.horizontal ? implicitHeight : parent.height + leftPadding: PlasmaCore.Units.gridUnit + topPadding: PlasmaCore.Units.gridUnit + rightPadding: PlasmaCore.Units.gridUnit + bottomPadding: PlasmaCore.Units.gridUnit + + contentItem: ColumnLayout { + Controls.Button { + icon.name: "configure" + text: i18nd("plasma_shell_org.kde.plasma.desktop", "Customize...") + onClicked: { + print(wallpapersView.currentIndex) + internalDialog.visible = true; + imageWallpaperDrawer.close() + } + } + } + background: Rectangle { + color: Qt.rgba (0, 0, 0, 0.3) + } + } + headerPositioning: ListView.PullBackHeader + delegate: Controls.ItemDelegate { + width: root.horizontal ? parent.width : height * (root.Screen.width / root.Screen.height) + height: root.horizontal ? width / (root.Screen.width / root.Screen.height) : parent.height + padding: wallpapersView.currentIndex === index ? PlasmaCore.Units.gridUnit / 4 : PlasmaCore.Units.gridUnit / 2 + leftPadding: padding + topPadding: padding + rightPadding: padding + bottomPadding: padding + Behavior on padding { + NumberAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + + property bool isCurrent: configDialog.wallpaperConfiguration["Image"] == model.path + onIsCurrentChanged: { + if (isCurrent) { + wallpapersView.currentIndex = index; + } + } + + z: wallpapersView.currentIndex === index ? 2 : 0 + contentItem: Item { + Addons.QIconItem { + anchors.centerIn: parent + width: PlasmaCore.Units.iconSizes.large + height: width + icon: "view-preview" + visible: !walliePreview.visible + } + + Addons.QPixmapItem { + id: walliePreview + anchors.fill: parent + visible: model.screenshot != null + smooth: true + pixmap: model.screenshot + fillMode: Image.PreserveAspectCrop + + } + } + onClicked: { + configDialog.currentWallpaper = "org.kde.image"; + configDialog.wallpaperConfiguration["Image"] = model.path; + configDialog.applyWallpaper() + } + Keys.onReturnPressed: { + clicked(); + } + background: Item { + Rectangle { + anchors { + fill: parent + margins: wallpapersView.currentIndex === index ? 0 : PlasmaCore.Units.gridUnit / 4 + Behavior on margins { + NumberAnimation { + duration: PlasmaCore.Units.longDuration + easing.type: Easing.InOutQuad + } + } + } + radius: PlasmaCore.Units.gridUnit / 4 + } + } + } + } + } +}