From 52302057ba8521a893ecec23c62b38ac4c97b219 Mon Sep 17 00:00:00 2001 From: zach Date: Mon, 13 Apr 2026 00:00:51 +0200 Subject: [PATCH] wallpaper cropper start, doesn't work. --- Config/BackgroundConfig.qml | 3 + Config/Config.qml | 5 +- Modules/Settings/Categories/Background.qml | 8 ++ .../Settings/Controls/WallpaperCropper.qml | 102 ++++++++++++++++++ Modules/Wallpaper/WallBackground.qml | 15 ++- 5 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 Modules/Settings/Controls/WallpaperCropper.qml diff --git a/Config/BackgroundConfig.qml b/Config/BackgroundConfig.qml index bcae021..160fa8e 100644 --- a/Config/BackgroundConfig.qml +++ b/Config/BackgroundConfig.qml @@ -4,4 +4,7 @@ import qs.Config JsonObject { property bool enabled: true property int wallFadeDuration: MaterialEasing.standardTime + property real alignX: 0.5 + property real alignY: 0.5 + property real zoom: 1.0 } diff --git a/Config/Config.qml b/Config/Config.qml index c4777dc..c0ca873 100644 --- a/Config/Config.qml +++ b/Config/Config.qml @@ -77,7 +77,10 @@ Singleton { function serializeBackground(): var { return { wallFadeDuration: background.wallFadeDuration, - enabled: background.enabled + enabled: background.enabled, + alignX: background.alignX, + alignY: background.alignY, + zoom: background.zoom }; } diff --git a/Modules/Settings/Categories/Background.qml b/Modules/Settings/Categories/Background.qml index 63c8d65..8933102 100644 --- a/Modules/Settings/Categories/Background.qml +++ b/Modules/Settings/Categories/Background.qml @@ -28,6 +28,14 @@ SettingsPage { setting: "wallFadeDuration" step: 50 } + + // Separator { + // } + // + // WallpaperCropper { + // Layout.fillWidth: true + // Layout.preferredHeight: 300 + // } } SettingsSection { diff --git a/Modules/Settings/Controls/WallpaperCropper.qml b/Modules/Settings/Controls/WallpaperCropper.qml new file mode 100644 index 0000000..ee355a8 --- /dev/null +++ b/Modules/Settings/Controls/WallpaperCropper.qml @@ -0,0 +1,102 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import Quickshell +import qs.Config +import qs.Components +import qs.Helpers + +ColumnLayout { + id: root + + width: Math.min(parent ? parent.width : 600, 600) + spacing: 15 + + Rectangle { + id: previewContainer + Layout.fillWidth: true + Layout.preferredHeight: width * (Quickshell.screens.length > 0 ? (Quickshell.screens[0].height / Math.max(1, Quickshell.screens[0].width)) : 9/16) + clip: true + color: DynamicColors.surfaceContainer + radius: Config.appearance.rounding.scale * 10 + + Image { + id: img + + anchors.fill: parent + asynchronous: true + fillMode: Image.PreserveAspectFit + source: Wallpapers.current + + Rectangle { + id: cropRect + + property real paintedWidth: img.paintedWidth > 0 ? img.paintedWidth : img.width + property real paintedHeight: img.paintedHeight > 0 ? img.paintedHeight : img.height + property real paintedX: (img.width - paintedWidth) / 2 + property real paintedY: (img.height - paintedHeight) / 2 + + property real screenAspect: Quickshell.screens.length > 0 ? (Quickshell.screens[0].width / Math.max(1, Quickshell.screens[0].height)) : 16/9 + property real imageAspect: Math.max(1, paintedWidth) / Math.max(1, paintedHeight) + + property real cropWidth: (imageAspect > screenAspect ? paintedHeight * screenAspect : paintedWidth) / Config.background.zoom + property real cropHeight: (imageAspect > screenAspect ? paintedHeight : paintedWidth / screenAspect) / Config.background.zoom + + border.color: DynamicColors.primary + border.width: 2 + color: DynamicColors.primaryContainer.withAlpha(0.3) + + width: cropWidth + height: cropHeight + + x: paintedX + (paintedWidth - width) * Config.background.alignX + y: paintedY + (paintedHeight - height) * Config.background.alignY + + DragHandler { + target: null + onActiveTranslationChanged: { + if (active) { + let newX = cropRect.x - cropRect.paintedX + translation.x; + let newY = cropRect.y - cropRect.paintedY + translation.y; + + let rangeX = cropRect.paintedWidth - cropRect.width; + let rangeY = cropRect.paintedHeight - cropRect.height; + + if (rangeX > 0) { + let valX = newX / rangeX; + Config.background.alignX = Math.max(0.0, Math.min(1.0, valX)); + } + + if (rangeY > 0) { + let valY = newY / rangeY; + Config.background.alignY = Math.max(0.0, Math.min(1.0, valY)); + } + } + } + } + + PinchHandler { + maximumScale: 5.0 + minimumScale: 1.0 + target: null + + onActiveScaleChanged: { + if (active) { + let newZoom = Config.background.zoom * (1 / (1 + (activeScale - 1) * 0.1)); + Config.background.zoom = Math.max(1.0, Math.min(newZoom, 5.0)); + } + } + } + } + } + } + + SettingSpinBox { + name: "Zoom" + object: Config.background + setting: "zoom" + min: 1.0 + max: 5.0 + step: 0.1 + } +} \ No newline at end of file diff --git a/Modules/Wallpaper/WallBackground.qml b/Modules/Wallpaper/WallBackground.qml index ad0ffc2..a47ca64 100644 --- a/Modules/Wallpaper/WallBackground.qml +++ b/Modules/Wallpaper/WallBackground.qml @@ -48,9 +48,22 @@ Item { } } - anchors.fill: parent + anchors.fill: undefined asynchronous: true opacity: 0 + fillMode: Image.Stretch + + property real windowRatio: root.width / Math.max(1, root.height) + property real imageRatio: Math.max(1, sourceSize.width) / Math.max(1, sourceSize.height) + + property bool isValid: sourceSize.width > 0 && sourceSize.height > 0 && root.width > 0 && root.height > 0 + + width: isValid ? (imageRatio > windowRatio ? root.height * imageRatio : root.width) * Config.background.zoom : root.width + height: isValid ? (imageRatio > windowRatio ? root.height : root.width / imageRatio) * Config.background.zoom : root.height + + x: isValid ? (root.width - width) * Config.background.alignX : 0 + y: isValid ? (root.height - height) * Config.background.alignY : 0 + scale: Wallpapers.showPreview ? 1 : 0.8 states: State {