wallpaper selector: remove some useless layout crap

This commit is contained in:
end-4
2025-08-18 21:47:55 +07:00
parent 8124f688da
commit 980533052b
@@ -12,17 +12,20 @@ import Quickshell.Wayland
import Quickshell.Hyprland import Quickshell.Hyprland
Scope { Scope {
id: scope id: root
property int thumbnailWidth: 128
property int thumbnailHeight: 72
Loader { Loader {
active: GlobalStates.wallpaperSelectorOpen active: GlobalStates.wallpaperSelectorOpen
sourceComponent: PanelWindow { sourceComponent: PanelWindow {
id: root id: panelWindow
readonly property HyprlandMonitor monitor: Hyprland.monitorFor(root.screen) readonly property HyprlandMonitor monitor: Hyprland.monitorFor(panelWindow.screen)
property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id) property bool monitorIsFocused: (Hyprland.focusedMonitor?.id == monitor?.id)
property var filteredWallpapers: Wallpapers.wallpapers property var filteredWallpapers: Wallpapers.wallpapers
exclusionMode: ExclusionMode.Ignore
WlrLayershell.namespace: "quickshell:wallpaperSelector" WlrLayershell.namespace: "quickshell:wallpaperSelector"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand WlrLayershell.keyboardFocus: WlrKeyboardFocus.OnDemand
@@ -35,6 +38,10 @@ Scope {
right: true right: true
} }
margins {
top: Appearance.sizes.barHeight + Appearance.sizes.hyprlandGapsOut
}
ColumnLayout { ColumnLayout {
id: layout id: layout
anchors.horizontalCenter: parent.horizontalCenter anchors.horizontalCenter: parent.horizontalCenter
@@ -43,9 +50,9 @@ Scope {
TextField { TextField {
id: filterField id: filterField
Layout.preferredWidth: bg.implicitWidth Layout.alignment: Qt.AlignHCenter
Layout.alignment: Qt.AlignHcenter
implicitHeight: 40 implicitHeight: 40
implicitWidth: Appearance.sizes.searchWidth
padding: 10 padding: 10
placeholderText: "Search wallpapers..." placeholderText: "Search wallpapers..."
placeholderTextColor: Appearance.colors.colSubtext placeholderTextColor: Appearance.colors.colSubtext
@@ -68,9 +75,9 @@ Scope {
newModel.push(wallpaperPath); newModel.push(wallpaperPath);
} }
} }
root.filteredWallpapers = newModel; panelWindow.filteredWallpapers = newModel;
} else { } else {
root.filteredWallpapers = Wallpapers.wallpapers; panelWindow.filteredWallpapers = Wallpapers.wallpapers;
} }
} }
@@ -114,24 +121,25 @@ Scope {
border.width: 1 border.width: 1
border.color: Appearance.colors.colLayer0Border border.color: Appearance.colors.colLayer0Border
radius: Appearance.rounding.screenRounding radius: Appearance.rounding.screenRounding
// Layout.alignment: Qt.AlignHCenter
property int calculatedRows: Math.ceil(grid.count / grid.columns) property int calculatedRows: Math.ceil(grid.count / grid.columns)
implicitWidth: { implicitWidth: {
if (root.filteredWallpapers.length === 0) { if (panelWindow.filteredWallpapers.length === 0) {
return 300; return 300;
} else if (root.filteredWallpapers.length < grid.columns) { } else if (panelWindow.filteredWallpapers.length < grid.columns) {
return root.filteredWallpapers.length * grid.cellWidth + 16; return panelWindow.filteredWallpapers.length * grid.cellWidth + 16;
} else { } else {
return Math.min(root.width * 0.7, 900); return Math.min(panelWindow.width * 0.7, 900);
} }
} }
implicitHeight: { implicitHeight: {
if (root.filteredWallpapers.length === 0) { if (panelWindow.filteredWallpapers.length === 0) {
return 100; return 100;
} else { } else {
return Math.min(root.height * 0.6, Math.min(calculatedRows, 3) * grid.cellHeight + 16); return Math.min(panelWindow.height * 0.6, Math.min(calculatedRows, 3) * grid.cellHeight + 16);
} }
} }
@@ -182,204 +190,186 @@ Scope {
} }
} }
ColumnLayout { GridView {
id: grid
visible: panelWindow.filteredWallpapers.length > 0
readonly property int columns: 7
property int currentIndex: 0
readonly property int rows: Math.max(1, Math.ceil(count / columns))
anchors.fill: parent anchors.fill: parent
anchors.margins: 8 cellWidth: root.thumbnailWidth
spacing: 8 cellHeight: root.thumbnailHeight
clip: true
interactive: true
keyNavigationWraps: true
boundsBehavior: Flickable.StopAtBounds
GridView { cacheBuffer: cellHeight * 2
id: grid ScrollBar.horizontal: ScrollBar {
visible: root.filteredWallpapers.length > 0 policy: ScrollBar.AsNeeded
}
ScrollBar.vertical: ScrollBar {
policy: ScrollBar.AsNeeded
}
readonly property int columns: 4 model: panelWindow.filteredWallpapers
property int currentIndex: 0 onModelChanged: currentIndex = 0
readonly property int rows: Math.max(1, Math.ceil(count / columns))
Layout.preferredWidth: columns * cellWidth function moveSelection(delta) {
Layout.alignment: Qt.AlignHCenter for (let i = 0; i < count; i++) {
Layout.fillHeight: true const item = itemAtIndex(i);
cellWidth: 128 if (item) {
cellHeight: 72 item.isHovered = false;
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() { currentIndex = Math.max(0, Math.min(count - 1, currentIndex + delta));
const path = model[currentIndex]; positionViewAtIndex(currentIndex, GridView.Contain);
if (!path) }
return; function activateCurrent() {
GlobalStates.wallpaperSelectorOpen = false; const path = model[currentIndex];
filterField.text = ""; if (!path)
Wallpapers.apply(path); return;
GlobalStates.wallpaperSelectorOpen = false;
filterField.text = "";
Wallpapers.apply(path);
}
delegate: Item {
width: grid.cellWidth
height: grid.cellHeight
property bool isHovered: false
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
} }
delegate: Item { Rectangle {
width: grid.cellWidth anchors.fill: parent
height: grid.cellHeight anchors.margins: 8
property bool isHovered: false color: Appearance.colors.colLayer2
radius: Appearance.rounding.elementRounding
Rectangle { Rectangle {
anchors.fill: parent anchors.centerIn: parent
radius: Appearance.rounding.windowRounding width: Math.min(parent.width * 0.4, 32)
color: Appearance.colors.colLayer1 height: Math.min(parent.height * 0.4, 32)
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 radius: Appearance.rounding.elementRounding
color: Appearance.colors.colLayer3
visible: thumbnailImage.status !== Image.Ready
Rectangle { opacity: 0.3
anchors.centerIn: parent SequentialAnimation on opacity {
width: Math.min(parent.width * 0.4, 32) running: parent.visible
height: Math.min(parent.height * 0.4, 32) loops: Animation.Infinite
radius: Appearance.rounding.elementRounding NumberAnimation {
color: Appearance.colors.colLayer3 to: 1.0
visible: thumbnailImage.status !== Image.Ready duration: 800
easing.type: Easing.InOutSine
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
}
} }
} NumberAnimation {
to: 0.3
Image { duration: 800
id: thumbnailImage easing.type: Easing.InOutSine
anchors.fill: parent
source: {
const resolvedUrl = Qt.resolvedUrl(modelData);
const md5Hash = Qt.md5(resolvedUrl);
const cacheSize = "normal"
const thumbnailPath = `${Directories.genericCache}/thumbnails/${cacheSize}/${md5Hash}.png`;
return thumbnailPath
}
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 {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
} }
} }
} }
MouseArea { Image {
id: thumbnailImage
anchors.fill: parent anchors.fill: parent
hoverEnabled: true source: {
onEntered: { const resolvedUrl = Qt.resolvedUrl(modelData);
for (let i = 0; i < grid.count; i++) { const md5Hash = Qt.md5(resolvedUrl);
const item = grid.itemAtIndex(i); const cacheSize = "normal"
if (item && item !== parent) { const thumbnailPath = `${Directories.genericCache}/thumbnails/${cacheSize}/${md5Hash}.png`;
item.isHovered = false; return thumbnailPath
} }
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 {
animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this)
}
}
}
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.wallpaperSelectorOpen = false;
filterField.text = "";
Wallpapers.apply(modelData);
} }
parent.isHovered = true;
grid.currentIndex = index;
} }
} onExited: {
parent.isHovered = false;
add: Transition { }
from: "*" onClicked: {
to: "*" GlobalStates.wallpaperSelectorOpen = false;
ParallelAnimation { filterField.text = "";
PropertyAnimation { Wallpapers.apply(modelData);
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 add: Transition {
implicitWidth: noWallpapersFoundLabel.implicitWidth from: "*"
to: "*"
Label { ParallelAnimation {
id: noWallpapersFoundLabel PropertyAnimation {
text: "No wallpapers found" property: "x"
font.family: Appearance.font.family.main from: grid.contentX + (grid.width / 2) - width / 2
font.pixelSize: Appearance.font.pixelSize.normal }
color: Appearance.colors.colSubtext PropertyAnimation {
Layout.alignment: Qt.AlignHcenter | Qt.AlignVCenter 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
}
} }
} }
} }
Label {
id: noWallpapersFoundLabel
visible: panelWindow.filteredWallpapers.length === 0
anchors.centerIn: parent
text: "No wallpapers found"
font.family: Appearance.font.family.main
font.pixelSize: Appearance.font.pixelSize.normal
color: Appearance.colors.colSubtext
}
} }
} }