From fe23017a97faec7d5cf44b4f65d64bd67c71fb0e Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Mon, 18 Aug 2025 18:25:23 +0700 Subject: [PATCH] WallpaperOverview: remove unnecessary Variants and Item --- .../wallpaperOverview/WallpaperOverview.qml | 752 +++++++++--------- 1 file changed, 370 insertions(+), 382 deletions(-) diff --git a/.config/quickshell/ii/modules/wallpaperOverview/WallpaperOverview.qml b/.config/quickshell/ii/modules/wallpaperOverview/WallpaperOverview.qml index ef1fa2d0..7ca666b1 100644 --- a/.config/quickshell/ii/modules/wallpaperOverview/WallpaperOverview.qml +++ b/.config/quickshell/ii/modules/wallpaperOverview/WallpaperOverview.qml @@ -14,408 +14,396 @@ import Quickshell.Hyprland Scope { id: scope - Variants { - id: variants - model: Quickshell.screens + PanelWindow { + id: root + readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen) + property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id) + visible: GlobalStates.wallpaperOverviewOpen + property var filteredWallpapers: Wallpapers.wallpapers - PanelWindow { - id: root - required property var modelData - readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen) - property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id) - screen: modelData - visible: GlobalStates.wallpaperOverviewOpen && monitorIsFocused - property var filteredWallpapers: Wallpapers.wallpapers + WlrLayershell.namespace: "quickshell:wallpaper-overview" + WlrLayershell.layer: WlrLayer.Overlay + WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand + color: "transparent" - WlrLayershell.namespace: "quickshell:wallpaper-overview" - WlrLayershell.layer: WlrLayer.Overlay - WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand - color: "transparent" + anchors { + top: true + bottom: true + left: true + right: true + } - anchors { - top: true - bottom: true - left: true - right: true - } + ColumnLayout { + id: layout + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + spacing: 8 - ColumnLayout { - id: layout - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - spacing: 8 - - Item { - width: 1 - height: 1 - } - - TextField { - id: filterField - Layout.preferredWidth: bg.implicitWidth - Layout.alignment: Qt.AlignHcenter - implicitHeight: 40 - padding: 10 - placeholderText: "Search wallpapers..." - placeholderTextColor: Appearance.colors.colSubtext - color: Appearance.colors.colPrimary - background: Rectangle { - color: Appearance.colors.colLayer0 - border.color: Appearance.colors.colLayer0Border - border.width: 1 - radius: Appearance.rounding.small - } - font.family: Appearance.font.family.main - font.pixelSize: Appearance.font.pixelSize.normal - - onTextChanged: { - let newModel = []; - if (text.length > 0) { - for (let i = 0; i < Wallpapers.wallpapers.length; ++i) { - let wallpaperPath = Wallpapers.wallpapers[i]; - if (wallpaperPath.toLowerCase().includes(text.toLowerCase())) { - newModel.push(wallpaperPath); - } - } - root.filteredWallpapers = newModel; - } else { - root.filteredWallpapers = Wallpapers.wallpapers; - } - } - - Keys.onPressed: event => { - if (text.length === 0) { - if (event.key === Qt.Key_Down || event.key === Qt.Key_Left || event.key === Qt.Key_Right) { - bg.forceActiveFocus(); - if (event.key === Qt.Key_Down) - grid.moveSelection(grid.columns); - else if (event.key === Qt.Key_Left) - grid.moveSelection(-1); - else if (event.key === Qt.Key_Right) - grid.moveSelection(1); - event.accepted = true; - } - } else { - if (event.key === Qt.Key_Down) { - grid.moveSelection(grid.columns); - event.accepted = true; - bg.forceActiveFocus(); - } - } - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - grid.activateCurrent(); - event.accepted = true; - } else if (event.key === Qt.Key_Escape) { - if (filterField.text.length > 0) { - filterField.text = ""; - } else { - GlobalStates.wallpaperOverviewOpen = false; - } - event.accepted = true; - } - } - } - - Rectangle { - id: bg - focus: true + TextField { + id: filterField + Layout.preferredWidth: bg.implicitWidth + Layout.alignment: Qt.AlignHcenter + implicitHeight: 40 + padding: 10 + placeholderText: "Search wallpapers..." + placeholderTextColor: Appearance.colors.colSubtext + color: Appearance.colors.colPrimary + background: Rectangle { color: Appearance.colors.colLayer0 - border.width: 1 border.color: Appearance.colors.colLayer0Border - radius: Appearance.rounding.screenRounding + border.width: 1 + radius: Appearance.rounding.small + } + font.family: Appearance.font.family.main + font.pixelSize: Appearance.font.pixelSize.normal - property int calculatedRows: Math.ceil(grid.count / grid.columns) - - implicitWidth: { - if (root.filteredWallpapers.length === 0) { - return 300; - } else if (root.filteredWallpapers.length < grid.columns) { - return root.filteredWallpapers.length * grid.cellWidth + 16; - } else { - return Math.min(root.width * 0.7, 900); - } - } - - implicitHeight: { - if (root.filteredWallpapers.length === 0) { - return 100; - } else { - return Math.min(root.height * 0.6, Math.min(calculatedRows, 3) * grid.cellHeight + 16); - } - } - - Behavior on implicitWidth { - SpringAnimation { - spring: 3 - damping: 0.2 - } - } - - Behavior on implicitHeight { - SpringAnimation { - spring: 3 - damping: 0.2 - } - } - - Keys.onPressed: event => { - if (event.key === Qt.Key_Escape) { - GlobalStates.wallpaperOverviewOpen = false; - event.accepted = true; - } else if (event.key === Qt.Key_Left) { - grid.moveSelection(-1); - event.accepted = true; - } else if (event.key === Qt.Key_Right) { - grid.moveSelection(1); - event.accepted = true; - } else if (event.key === Qt.Key_Up) { - if (grid.currentIndex < grid.columns) { - filterField.forceActiveFocus(); - } else { - grid.moveSelection(-grid.columns); + onTextChanged: { + let newModel = []; + if (text.length > 0) { + for (let i = 0; i < Wallpapers.wallpapers.length; ++i) { + let wallpaperPath = Wallpapers.wallpapers[i]; + if (wallpaperPath.toLowerCase().includes(text.toLowerCase())) { + newModel.push(wallpaperPath); } + } + root.filteredWallpapers = newModel; + } else { + root.filteredWallpapers = Wallpapers.wallpapers; + } + } + + Keys.onPressed: event => { + if (text.length === 0) { + if (event.key === Qt.Key_Down || event.key === Qt.Key_Left || event.key === Qt.Key_Right) { + bg.forceActiveFocus(); + if (event.key === Qt.Key_Down) + grid.moveSelection(grid.columns); + else if (event.key === Qt.Key_Left) + grid.moveSelection(-1); + else if (event.key === Qt.Key_Right) + grid.moveSelection(1); event.accepted = true; - } else if (event.key === Qt.Key_Down) { + } + } else { + if (event.key === Qt.Key_Down) { grid.moveSelection(grid.columns); event.accepted = true; - } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - grid.activateCurrent(); - event.accepted = true; - } else if (event.key === Qt.Key_Backspace) { - if (filterField.text.length > 0) { - filterField.text = filterField.text.substring(0, filterField.text.length - 1); - } - filterField.forceActiveFocus(); - event.accepted = true; - } else { - filterField.forceActiveFocus(); - if (event.text.length > 0) { - filterField.text += event.text; - filterField.cursorPosition = filterField.text.length; - } - event.accepted = true; + bg.forceActiveFocus(); } } - - ColumnLayout { - anchors.fill: parent - anchors.margins: 8 - spacing: 8 - - GridView { - id: grid - visible: root.filteredWallpapers.length > 0 - - readonly property int columns: 4 - property int currentIndex: 0 - readonly property int rows: Math.max(1, Math.ceil(count / columns)) - - Layout.preferredWidth: columns * cellWidth - Layout.alignment: Qt.AlignHcenter - Layout.fillHeight: true - cellWidth: 220 - cellHeight: 140 - clip: true - interactive: true - keyNavigationWraps: true - boundsBehavior: Flickable.StopAtBounds - - cacheBuffer: cellHeight * 2 - ScrollBar.horizontal: ScrollBar { - policy: ScrollBar.AsNeeded - visible: false - } - ScrollBar.vertical: ScrollBar { - policy: ScrollBar.AsNeeded - visible: false - } - - model: root.filteredWallpapers - onModelChanged: currentIndex = 0 - - function moveSelection(delta) { - for (let i = 0; i < count; i++) { - const item = itemAtIndex(i); - if (item) { - item.isHovered = false; - } - } - currentIndex = Math.max(0, Math.min(count - 1, currentIndex + delta)); - positionViewAtIndex(currentIndex, GridView.Contain); - } - function activateCurrent() { - const path = model[currentIndex]; - if (!path) - return; - GlobalStates.wallpaperOverviewOpen = false; - filterField.text = ""; - Wallpapers.apply(path); - } - - delegate: Item { - width: grid.cellWidth - height: grid.cellHeight - property bool isHovered: false - - Behavior on width { - NumberAnimation { - duration: animationCurves.expressiveDefaultSpatialDuration - easing.bezierCurve: animationCurves.expressiveDefaultSpatial - } - } - - Behavior on height { - NumberAnimation { - duration: animationCurves.expressiveDefaultSpatialDuration - easing.bezierCurve: animationCurves.expressiveDefaultSpatial - } - } - - Rectangle { - anchors.fill: parent - radius: Appearance.rounding.windowRounding - color: Appearance.colors.colLayer1 - border.width: (index === grid.currentIndex || parent.isHovered) ? 3 : 0 - border.color: Appearance.colors.colSecondary - } - - Rectangle { - anchors.fill: parent - anchors.margins: 8 - color: Appearance.colors.colLayer2 - radius: Appearance.rounding.elementRounding - - Rectangle { - anchors.centerIn: parent - width: Math.min(parent.width * 0.4, 32) - height: Math.min(parent.height * 0.4, 32) - radius: Appearance.rounding.elementRounding - color: Appearance.colors.colLayer3 - visible: thumbnailImage.status !== Image.Ready - - opacity: 0.3 - SequentialAnimation on opacity { - running: parent.visible - loops: Animation.Infinite - NumberAnimation { - to: 1.0 - duration: 800 - easing.type: Easing.InOutSine - } - NumberAnimation { - to: 0.3 - duration: 800 - easing.type: Easing.InOutSine - } - } - } - - Image { - id: thumbnailImage - anchors.fill: parent - source: `file://${modelData}` - fillMode: Image.PreserveAspectCrop - asynchronous: true - cache: false - smooth: true - - sourceSize.width: Math.min(128, grid.cellWidth - 16) - sourceSize.height: Math.min(96, grid.cellHeight - 16) - - mipmap: false - - opacity: status === Image.Ready ? 1 : 0 - Behavior on opacity { - NumberAnimation { - duration: 200 - easing.type: Easing.OutCubic - } - } - } - } - - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: { - for (let i = 0; i < grid.count; i++) { - const item = grid.itemAtIndex(i); - if (item && item !== parent) { - item.isHovered = false; - } - } - parent.isHovered = true; - grid.currentIndex = index; - } - onExited: { - parent.isHovered = false; - } - onClicked: { - GlobalStates.wallpaperOverviewOpen = false; - filterField.text = ""; - Wallpapers.apply(modelData); - } - } - } - - add: Transition { - from: "*" - to: "*" - ParallelAnimation { - PropertyAnimation { - property: "x" - from: grid.contentX + (grid.width / 2) - width / 2 - } - PropertyAnimation { - property: "y" - from: grid.contentY + (grid.height / 2) - height / 2 - } - NumberAnimation { - property: "scale" - from: 0.0 - to: 1.0 - duration: animationCurves.expressiveDefaultSpatialDuration - easing.bezierCurve: animationCurves.expressiveDefaultSpatial - } - NumberAnimation { - property: "opacity" - from: 0.0 - to: 1.0 - duration: animationCurves.expressiveDefaultSpatialDuration - easing.bezierCurve: animationCurves.expressiveDefaultSpatial - } - } - } - } - // show when no wallpaper found - ColumnLayout { - id: noWallpapersFoundLayout - visible: root.filteredWallpapers.length === 0 - anchors.centerIn: parent - - implicitHeight: noWallpapersFoundLabel.implicitHeight - implicitWidth: noWallpapersFoundLabel.implicitWidth - - Label { - id: noWallpapersFoundLabel - text: "No wallpapers found" - font.family: Appearance.font.family.main - font.pixelSize: Appearance.font.pixelSize.normal - color: Appearance.colors.colSubtext - Layout.alignment: Qt.AlignHcenter | Qt.AlignVCenter - } + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + grid.activateCurrent(); + event.accepted = true; + } else if (event.key === Qt.Key_Escape) { + if (filterField.text.length > 0) { + filterField.text = ""; + } else { + GlobalStates.wallpaperOverviewOpen = false; } + event.accepted = true; } } } - Connections { - target: GlobalStates - function onWallpaperOverviewOpenChanged() { - if (GlobalStates.wallpaperOverviewOpen && monitorIsFocused) { - filterField.forceActiveFocus(); + Rectangle { + id: bg + focus: true + color: Appearance.colors.colLayer0 + border.width: 1 + border.color: Appearance.colors.colLayer0Border + radius: Appearance.rounding.screenRounding + + property int calculatedRows: Math.ceil(grid.count / grid.columns) + + implicitWidth: { + if (root.filteredWallpapers.length === 0) { + return 300; + } else if (root.filteredWallpapers.length < grid.columns) { + return root.filteredWallpapers.length * grid.cellWidth + 16; + } else { + return Math.min(root.width * 0.7, 900); } } + + implicitHeight: { + if (root.filteredWallpapers.length === 0) { + return 100; + } else { + return Math.min(root.height * 0.6, Math.min(calculatedRows, 3) * grid.cellHeight + 16); + } + } + + Behavior on implicitWidth { + SpringAnimation { + spring: 3 + damping: 0.2 + } + } + + Behavior on implicitHeight { + SpringAnimation { + spring: 3 + damping: 0.2 + } + } + + Keys.onPressed: event => { + if (event.key === Qt.Key_Escape) { + GlobalStates.wallpaperOverviewOpen = false; + event.accepted = true; + } else if (event.key === Qt.Key_Left) { + grid.moveSelection(-1); + event.accepted = true; + } else if (event.key === Qt.Key_Right) { + grid.moveSelection(1); + event.accepted = true; + } else if (event.key === Qt.Key_Up) { + if (grid.currentIndex < grid.columns) { + filterField.forceActiveFocus(); + } else { + grid.moveSelection(-grid.columns); + } + event.accepted = true; + } else if (event.key === Qt.Key_Down) { + grid.moveSelection(grid.columns); + event.accepted = true; + } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + grid.activateCurrent(); + event.accepted = true; + } else if (event.key === Qt.Key_Backspace) { + if (filterField.text.length > 0) { + filterField.text = filterField.text.substring(0, filterField.text.length - 1); + } + filterField.forceActiveFocus(); + event.accepted = true; + } else { + filterField.forceActiveFocus(); + if (event.text.length > 0) { + filterField.text += event.text; + filterField.cursorPosition = filterField.text.length; + } + event.accepted = true; + } + } + + ColumnLayout { + anchors.fill: parent + anchors.margins: 8 + spacing: 8 + + GridView { + id: grid + visible: root.filteredWallpapers.length > 0 + + readonly property int columns: 4 + property int currentIndex: 0 + readonly property int rows: Math.max(1, Math.ceil(count / columns)) + + Layout.preferredWidth: columns * cellWidth + Layout.alignment: Qt.AlignHcenter + Layout.fillHeight: true + cellWidth: 220 + cellHeight: 140 + clip: true + interactive: true + keyNavigationWraps: true + boundsBehavior: Flickable.StopAtBounds + + cacheBuffer: cellHeight * 2 + ScrollBar.horizontal: ScrollBar { + policy: ScrollBar.AsNeeded + visible: false + } + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AsNeeded + visible: false + } + + model: root.filteredWallpapers + onModelChanged: currentIndex = 0 + + function moveSelection(delta) { + for (let i = 0; i < count; i++) { + const item = itemAtIndex(i); + if (item) { + item.isHovered = false; + } + } + currentIndex = Math.max(0, Math.min(count - 1, currentIndex + delta)); + positionViewAtIndex(currentIndex, GridView.Contain); + } + function activateCurrent() { + const path = model[currentIndex]; + if (!path) + return; + GlobalStates.wallpaperOverviewOpen = false; + filterField.text = ""; + Wallpapers.apply(path); + } + + delegate: Item { + width: grid.cellWidth + height: grid.cellHeight + property bool isHovered: false + + Behavior on width { + NumberAnimation { + duration: animationCurves.expressiveDefaultSpatialDuration + easing.bezierCurve: animationCurves.expressiveDefaultSpatial + } + } + + Behavior on height { + NumberAnimation { + duration: animationCurves.expressiveDefaultSpatialDuration + easing.bezierCurve: animationCurves.expressiveDefaultSpatial + } + } + + Rectangle { + anchors.fill: parent + radius: Appearance.rounding.windowRounding + color: Appearance.colors.colLayer1 + border.width: (index === grid.currentIndex || parent.isHovered) ? 3 : 0 + border.color: Appearance.colors.colSecondary + } + + Rectangle { + anchors.fill: parent + anchors.margins: 8 + color: Appearance.colors.colLayer2 + radius: Appearance.rounding.elementRounding + + Rectangle { + anchors.centerIn: parent + width: Math.min(parent.width * 0.4, 32) + height: Math.min(parent.height * 0.4, 32) + radius: Appearance.rounding.elementRounding + color: Appearance.colors.colLayer3 + visible: thumbnailImage.status !== Image.Ready + + opacity: 0.3 + SequentialAnimation on opacity { + running: parent.visible + loops: Animation.Infinite + NumberAnimation { + to: 1.0 + duration: 800 + easing.type: Easing.InOutSine + } + NumberAnimation { + to: 0.3 + duration: 800 + easing.type: Easing.InOutSine + } + } + } + + Image { + id: thumbnailImage + anchors.fill: parent + source: `file://${modelData}` + fillMode: Image.PreserveAspectCrop + asynchronous: true + cache: false + smooth: true + + sourceSize.width: Math.min(128, grid.cellWidth - 16) + sourceSize.height: Math.min(96, grid.cellHeight - 16) + + mipmap: false + + opacity: status === Image.Ready ? 1 : 0 + Behavior on opacity { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + } + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: { + for (let i = 0; i < grid.count; i++) { + const item = grid.itemAtIndex(i); + if (item && item !== parent) { + item.isHovered = false; + } + } + parent.isHovered = true; + grid.currentIndex = index; + } + onExited: { + parent.isHovered = false; + } + onClicked: { + GlobalStates.wallpaperOverviewOpen = false; + filterField.text = ""; + Wallpapers.apply(modelData); + } + } + } + + add: Transition { + from: "*" + to: "*" + ParallelAnimation { + PropertyAnimation { + property: "x" + from: grid.contentX + (grid.width / 2) - width / 2 + } + PropertyAnimation { + property: "y" + from: grid.contentY + (grid.height / 2) - height / 2 + } + NumberAnimation { + property: "scale" + from: 0.0 + to: 1.0 + duration: animationCurves.expressiveDefaultSpatialDuration + easing.bezierCurve: animationCurves.expressiveDefaultSpatial + } + NumberAnimation { + property: "opacity" + from: 0.0 + to: 1.0 + duration: animationCurves.expressiveDefaultSpatialDuration + easing.bezierCurve: animationCurves.expressiveDefaultSpatial + } + } + } + } + // show when no wallpaper found + ColumnLayout { + id: noWallpapersFoundLayout + visible: root.filteredWallpapers.length === 0 + anchors.centerIn: parent + + implicitHeight: noWallpapersFoundLabel.implicitHeight + implicitWidth: noWallpapersFoundLabel.implicitWidth + + Label { + id: noWallpapersFoundLabel + text: "No wallpapers found" + font.family: Appearance.font.family.main + font.pixelSize: Appearance.font.pixelSize.normal + color: Appearance.colors.colSubtext + Layout.alignment: Qt.AlignHcenter | Qt.AlignVCenter + } + } + } + } + } + + Connections { + target: GlobalStates + function onWallpaperOverviewOpenChanged() { + if (GlobalStates.wallpaperOverviewOpen && monitorIsFocused) { + filterField.forceActiveFocus(); + } } } }