13 Commits

15 changed files with 434 additions and 161 deletions
+1
View File
@@ -242,6 +242,7 @@ Singleton {
recolorLogo: lock.recolorLogo, recolorLogo: lock.recolorLogo,
enableFprint: lock.enableFprint, enableFprint: lock.enableFprint,
showNotifContent: lock.showNotifContent, showNotifContent: lock.showNotifContent,
showNotifIcon: lock.showNotifIcon,
maxFprintTries: lock.maxFprintTries, maxFprintTries: lock.maxFprintTries,
blurAmount: lock.blurAmount, blurAmount: lock.blurAmount,
sizes: { sizes: {
+1
View File
@@ -6,6 +6,7 @@ JsonObject {
property int maxFprintTries: 3 property int maxFprintTries: 3
property bool recolorLogo: false property bool recolorLogo: false
property bool showNotifContent: false property bool showNotifContent: false
property bool showNotifIcon: true
property Sizes sizes: Sizes { property Sizes sizes: Sizes {
} }
+20 -20
View File
@@ -16,27 +16,14 @@ Scope {
property bool launching: false property bool launching: false
property string promptMessage: "" property string promptMessage: ""
readonly property var selectedSession: sessionIndex >= 0 ? sessions[sessionIndex] : null readonly property var selectedSession: sessionIndex >= 0 ? sessions[sessionIndex] : null
readonly property var selectedUser: Users.selectedUser
property int sessionIndex: sessions.length > 0 ? 0 : -1 property int sessionIndex: sessions.length > 0 ? 0 : -1
property var sessions: [] property var sessions: []
readonly property string userFace: selectedUser ? selectedUser.face : ""
readonly property string username: Users.selectedUsername
// User handling - now uses the Users singleton // User handling - now uses the Users singleton
readonly property var users: Users.users readonly property var users: Users.users
readonly property var selectedUser: Users.selectedUser
readonly property string username: Users.selectedUsername
readonly property string userFace: selectedUser ? selectedUser.face : ""
// User selection functions (delegate to Users singleton)
function selectUser(username: string): bool {
return Users.selectUser(username);
}
function selectNextUser(): void {
Users.selectNext();
}
function selectPreviousUser(): void {
Users.selectPrevious();
}
signal flashMsg signal flashMsg
@@ -58,11 +45,11 @@ Scope {
event.accepted = true; event.accepted = true;
return; return;
} } else if (event.key === Qt.Key_Escape) {
buffer = "";
if (event.text && !/[\r\n]/.test(event.text)) { } else if (" abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?".includes(event.text.toLowerCase())) {
// No illegal characters (you are insane if you use unicode in your password)
buffer += event.text; buffer += event.text;
event.accepted = true;
} }
} }
@@ -81,6 +68,19 @@ Scope {
Greetd.launch(selectedSession.command, [], true); Greetd.launch(selectedSession.command, [], true);
} }
function selectNextUser(): void {
Users.selectNext();
}
function selectPreviousUser(): void {
Users.selectPrevious();
}
// User selection functions (delegate to Users singleton)
function selectUser(username: string): bool {
return Users.selectUser(username);
}
function submit(): void { function submit(): void {
errorMessage = ""; errorMessage = "";
+14
View File
@@ -6,7 +6,21 @@ import Quickshell.Services.UPower
Singleton { Singleton {
id: root id: root
readonly property real batteryPercent: UPower.displayDevice.percentage
readonly property list<UPowerDevice> devices: UPower.devices.values readonly property list<UPowerDevice> devices: UPower.devices.values
readonly property UPowerDevice displayDevice: UPower.displayDevice readonly property UPowerDevice displayDevice: UPower.displayDevice
readonly property bool onBattery: UPower.onBattery readonly property bool onBattery: UPower.onBattery
// property bool toastShown
//
// Connections {
// target: UPower
//
// function onPercentageChanged(): {
// if (root.batteryPercent >= 0.2 && toastShown)
// return;
//
// root.toastShown = true;
// Toaster.toast(qsTr("Battery "))
// }
// }
} }
+50
View File
@@ -1,7 +1,9 @@
pragma Singleton pragma Singleton
pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Io import Quickshell.Io
import QtQuick
import ZShell.Models import ZShell.Models
import qs.Config import qs.Config
import qs.Modules import qs.Modules
@@ -12,11 +14,17 @@ Searcher {
id: root id: root
property string actualCurrent: WallpaperPath.currentWallpaperPath property string actualCurrent: WallpaperPath.currentWallpaperPath
property alias crops: adapter.monitorCrops
readonly property string current: showPreview ? previewPath : actualCurrent readonly property string current: showPreview ? previewPath : actualCurrent
property alias monitorCrops: monitorCrops
property string previewPath property string previewPath
property bool recentlyChanged property bool recentlyChanged
property bool showPreview: false property bool showPreview: false
function getCrop(screen: string): var {
return root.crops[screen];
}
function preview(path: string): void { function preview(path: string): void {
previewPath = path; previewPath = path;
if (Config.general.color.schemeGeneration) if (Config.general.color.schemeGeneration)
@@ -24,9 +32,35 @@ Searcher {
showPreview = true; showPreview = true;
} }
function setCrop(screen: string, rect: rect, scaledRect: rect, zoom: real): void {
let updated = Object.assign({}, root.crops);
if (zoom <= 0)
zoom = 1.0;
else if (zoom > 5.0)
zoom = 5.0;
updated[screen] = {
x: rect.x,
y: rect.y,
width: rect.width,
height: rect.height,
scaledX: scaledRect.x,
scaledY: scaledRect.y,
scaledWidth: scaledRect.width,
scaledHeight: scaledRect.height,
zoom: zoom
};
root.crops = updated;
monitorCrops.writeAdapter();
monitorCrops.reload();
}
function setWallpaper(path: string): void { function setWallpaper(path: string): void {
actualCurrent = path; actualCurrent = path;
WallpaperPath.currentWallpaperPath = path; WallpaperPath.currentWallpaperPath = path;
Quickshell.screens.forEach(n => setCrop(n.name, Qt.rect(0, 0, 0, 0), Qt.rect(0, 0, 0, 0), 1.0));
Quickshell.execDetached(["zshell-cli", "wallpaper", "lockscreen", "--input-image", `${root.actualCurrent}`, "--output-path", `${Paths.state}/lockscreen_bg.png`, "--blur-amount", `${Config.lock.blurAmount}`]); Quickshell.execDetached(["zshell-cli", "wallpaper", "lockscreen", "--input-image", `${root.actualCurrent}`, "--output-path", `${Paths.state}/lockscreen_bg.png`, "--blur-amount", `${Config.lock.blurAmount}`]);
if (Config.general.color.schemeGeneration) if (Config.general.color.schemeGeneration)
Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]); Quickshell.execDetached(["zshell-cli", "scheme", "generate", "--image-path", `${root.actualCurrent}`, "--scheme", `${Config.colors.schemeType}`, "--mode", `${Config.general.color.mode}`]);
@@ -53,6 +87,22 @@ Searcher {
target: "wallpaper" target: "wallpaper"
} }
FileView {
id: monitorCrops
path: `${Paths.state}/wallpaper-crops.json`
watchChanges: true
onAdapterUpdated: writeAdapter()
onFileChanged: reload()
JsonAdapter {
id: adapter
property var monitorCrops: ({})
}
}
FileSystemModel { FileSystemModel {
id: wallpapers id: wallpapers
+1
View File
@@ -58,6 +58,7 @@ CustomRect {
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
height: Config.notifs.sizes.image height: Config.notifs.sizes.image
source: Qt.resolvedUrl(root.image) source: Qt.resolvedUrl(root.image)
visible: Config.lock.showNotifIcon
width: Config.notifs.sizes.image width: Config.notifs.sizes.image
} }
} }
+2
View File
@@ -30,6 +30,8 @@ Scope {
} else { } else {
buffer = buffer.slice(0, -1); buffer = buffer.slice(0, -1);
} }
} else if (event.key === Qt.Key_Escape) {
buffer = "";
} else if (" abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?".includes(event.text.toLowerCase())) { } else if (" abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()-_=+[{]}\\|;:'\",<.>/?".includes(event.text.toLowerCase())) {
// No illegal characters (you are insane if you use unicode in your password) // No illegal characters (you are insane if you use unicode in your password)
buffer += event.text; buffer += event.text;
+3 -2
View File
@@ -1,3 +1,4 @@
import Quickshell
import QtQuick.Layouts import QtQuick.Layouts
import qs.Modules.Settings.Controls import qs.Modules.Settings.Controls
import qs.Config import qs.Config
@@ -5,6 +6,8 @@ import qs.Config
SettingsPage { SettingsPage {
id: root id: root
required property ShellScreen screen
SettingsSection { SettingsSection {
sectionId: "Wallpaper" sectionId: "Wallpaper"
@@ -33,8 +36,6 @@ SettingsPage {
} }
WallpaperCropper { WallpaperCropper {
Layout.fillWidth: true
Layout.preferredHeight: 600
} }
} }
@@ -50,6 +50,15 @@ SettingsPage {
Separator { Separator {
} }
SettingSwitch {
name: "Show notification icon"
object: Config.lock
setting: "showNotifIcon"
}
Separator {
}
SettingSpinBox { SettingSpinBox {
min: 0 min: 0
name: "Blur amount" name: "Blur amount"
+3 -1
View File
@@ -1,3 +1,5 @@
pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Widgets import Quickshell.Widgets
import QtQuick import QtQuick
@@ -20,7 +22,6 @@ Item {
required property PersistentProperties visibilities required property PersistentProperties visibilities
function scrollToSetting(section: string, settingName: string) { function scrollToSetting(section: string, settingName: string) {
// Wait for the StackView transition to complete, then scroll
root.pendingSection = section; root.pendingSection = section;
root.pendingSetting = settingName; root.pendingSetting = settingName;
scrollTimer.restart(); scrollTimer.restart();
@@ -157,6 +158,7 @@ Item {
id: background id: background
Cat.Background { Cat.Background {
screen: root.screen
} }
} }
+206 -59
View File
@@ -1,73 +1,236 @@
pragma ComponentBehavior: Bound
import QtQuick import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick.Controls
import Quickshell import Quickshell
import Quickshell.Hyprland
import ZShell.Internal
import qs.Config import qs.Config
import qs.Components import qs.Components
import qs.Helpers import qs.Helpers
Item { Item {
id: wrapper
property bool changesMade: false
signal requestCrop
Layout.fillWidth: true
Layout.preferredHeight: 400
IconButton {
anchors.margins: Appearance.padding.normal
anchors.right: parent.right
anchors.top: parent.top
icon: "check"
opacity: wrapper.changesMade ? 1 : 0
scale: wrapper.changesMade ? 1 : 0
z: 2
Behavior on opacity {
Anim {
}
}
Behavior on scale {
Anim {
}
}
onClicked: {
wrapper.requestCrop();
wrapper.changesMade = false;
}
}
RowLayout {
id: root id: root
Image {
id: imageView
property real displayH: paintedHeight
property real displayW: paintedWidth
property real displayX: (width - paintedWidth) * 0.5
property real displayY: (height - paintedHeight) * 0.5
property real scaleX: sourceW / displayW
property real scaleY: sourceH / displayH
property real sourceH: Quickshell.screens[0].height
property real sourceW: Quickshell.screens[0].width
anchors.fill: parent anchors.fill: parent
fillMode: Image.PreserveAspectFit spacing: Appearance.spacing.normal
smooth: true
source: Wallpapers.current Repeater {
model: ScriptModel {
values: [...Quickshell.screens].sort((a, b) => {
return a.x - b.x;
})
} }
Item { Item {
id: overlay id: delegate
clip: true required property ShellScreen modelData
height: imageView.displayH
width: imageView.displayW function applyCrop(): void {
x: imageView.displayX const croprect = cropRect.mapToItem(scaledImg, 0, 0, cropRect.width, cropRect.height);
y: imageView.displayY const upscaledRect = Qt.rect((croprect.x - cropRect.imageX) / scaledImg.paintedWidth, (croprect.y - cropRect.imageY) / scaledImg.paintedHeight, croprect.width / scaledImg.paintedWidth, croprect.height / scaledImg.paintedHeight);
Wallpapers.setCrop(delegate.modelData.name, upscaledRect, croprect, cropRect.zoom);
}
function zoomClipRect(zoom: real): void {
let oldCenterX = cropRect.x + cropRect.width * 0.5;
let oldCenterY = cropRect.y + cropRect.height * 0.5;
cropRect.zoom = zoom;
cropRect.x = oldCenterX - cropRect.width * 0.5;
cropRect.y = oldCenterY - cropRect.height * 0.5;
cropRect.clampToBounds();
}
Layout.fillHeight: true
Layout.fillWidth: true
Connections {
function onRequestCrop(): void {
delegate.applyCrop();
}
target: wrapper
}
RowLayout {
id: sliderLayout
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: parent.right
implicitHeight: 30
spacing: Appearance.spacing.large
CustomText {
text: qsTr("Crop scale")
}
CustomSlider {
id: zoomSlider
Layout.fillWidth: true
Layout.preferredHeight: 10
from: 1.0
to: 5.0
value: cropRect.zoom
onMoved: {
delegate.zoomClipRect(value);
wrapper.changesMade = true;
}
}
}
CachingImage {
id: scaledImg
property var displayData
property real monitorScale: 1.0
anchors.bottom: sliderLayout.top
anchors.bottomMargin: Appearance.spacing.normal
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
asynchronous: true
fillMode: Image.PreserveAspectFit
// retainWhileLoading: true
source: Wallpapers.current
sourceSize.height: parent.height
sourceSize.width: parent.width
onPaintedWidthChanged: {
if (paintedWidth > 0) {
scaledImg.displayData = Wallpapers.getCrop(delegate.modelData.name);
cropRect.zoom = Wallpapers.getCrop(delegate.modelData.name).zoom;
cropRect.restoreFromData();
}
}
onSourceChanged: cropRect.clampToBounds()
onStatusChanged: if (scaledImg.status == Image.Ready)
cropRect.clampToBounds()
CustomText {
id: monitorId
anchors.centerIn: parent
color: Qt.alpha(DynamicColors.palette.m3surface, 0.85)
font.pointSize: Appearance.font.size.large * 4
style: Text.Outline
styleColor: DynamicColors.palette.m3onSurface
text: delegate.modelData.name
}
CustomRect { CustomRect {
id: cropRect id: cropRect
property real aspectRatio: Quickshell.screens[0].width / Quickshell.screens[0].height property real aspectRatio: delegate.modelData.width / delegate.modelData.height
readonly property rect sourceRect: Qt.rect(x * imageView.scaleX, y * imageView.scaleY, width * imageView.scaleX, height * imageView.scaleY) readonly property real baseHeight: baseWidth / aspectRatio
property real zoom: Config.background.zoom readonly property real baseWidth: {
let fittedHeight = scaledImg.paintedHeight;
let fittedWidth = fittedHeight * aspectRatio;
if (fittedWidth > scaledImg.paintedWidth) {
fittedWidth = scaledImg.paintedWidth;
fittedHeight = fittedWidth / aspectRatio;
}
return fittedWidth;
}
readonly property real imageX: (scaledImg.width - scaledImg.paintedWidth) / 2
readonly property real imageY: (scaledImg.height - scaledImg.paintedHeight) / 2
property real imgAspectRatio: scaledImg.paintedWidth / scaledImg.paintedHeight
property real zoom: scaledImg.displayData.zoom
function centerInImage() {
x = imageX + (scaledImg.paintedWidth - width) / 2;
y = imageY + (scaledImg.paintedHeight - height) / 2;
}
function clampToBounds() { function clampToBounds() {
x = Math.max(0, Math.min(x, overlay.width - width)); x = Math.max(imageX, Math.min(x, imageX + scaledImg.paintedWidth - width));
y = Math.max(0, Math.min(y, overlay.height - height)); y = Math.max(imageY, Math.min(y, imageY + scaledImg.paintedHeight - height));
}
function restoreFromData() {
let data = scaledImg.displayData;
if (data && data.scaledX !== 0 || data.scaledY !== 0 || data.scaledWidth !== 0 || data.scaledHeight !== 0) {
x = data.scaledX;
y = data.scaledY;
clampToBounds();
} else {
zoom = 1.0;
centerInImage();
}
} }
border.color: DynamicColors.palette.m3primary border.color: DynamicColors.palette.m3primary
border.width: 2 border.width: 2
color: DynamicColors.tPalette.m3primary height: baseHeight / zoom
height: width / aspectRatio opacity: 1
radius: Appearance.rounding.small width: baseWidth / zoom
visible: imageView.status === Image.Ready
width: Math.min(overlay.width / zoom, overlay.height * aspectRatio / zoom) Behavior on opacity {
x: Config.background.sourceClipX / imageView.scaleX Anim {
y: Config.background.sourceClipY / imageView.scaleY }
}
Component.onCompleted: clampToBounds()
onHeightChanged: clampToBounds()
onWidthChanged: clampToBounds()
} }
MouseArea { MouseArea {
id: mouse
function updateCrop(mouseX, mouseY) { function updateCrop(mouseX, mouseY) {
let nx = mouseX - cropRect.width * 0.5; let nx = mouseX - cropRect.width * 0.5;
let ny = mouseY - cropRect.height * 0.5; let ny = mouseY - cropRect.height * 0.5;
nx = Math.max(0, Math.min(nx, overlay.width - cropRect.width)); nx = Math.max(cropRect.imageX, Math.min(nx, cropRect.imageX + scaledImg.paintedWidth - cropRect.width));
ny = Math.max(0, Math.min(ny, overlay.height - cropRect.height)); ny = Math.max(cropRect.imageY, Math.min(ny, cropRect.imageY + scaledImg.paintedHeight - cropRect.height));
cropRect.x = nx; cropRect.x = nx;
cropRect.y = ny; cropRect.y = ny;
@@ -78,36 +241,20 @@ Item {
preventStealing: true preventStealing: true
onPositionChanged: mouse => { onPositionChanged: mouse => {
if (pressed) if (pressed) {
updateCrop(mouse.x, mouse.y); updateCrop(mouse.x, mouse.y);
wrapper.changesMade = true;
}
} }
onPressed: mouse => { onPressed: mouse => {
updateCrop(mouse.x, mouse.y); updateCrop(mouse.x, mouse.y);
wrapper.changesMade = true;
} }
onReleased: { onReleased: {
Wallpapers.recentlyChanged = false; wrapper.changesMade = true;
Config.background.sourceClipX = cropRect.sourceRect.x; }
Config.background.sourceClipY = cropRect.sourceRect.y; }
Config.background.sourceClipW = cropRect.sourceRect.width;
Config.background.sourceClipH = cropRect.sourceRect.height;
Config.save();
} }
onWheel: wheel => {
let oldCenterX = cropRect.x + cropRect.width * 0.5;
let oldCenterY = cropRect.y + cropRect.height * 0.5;
if (wheel.angleDelta.y > 0)
cropRect.zoom *= 1.1;
else
cropRect.zoom /= 1.1;
cropRect.zoom = Math.max(1.0, Math.min(cropRect.zoom, 10.0));
Config.background.zoom = cropRect.zoom;
cropRect.x = oldCenterX - cropRect.width * 0.5;
cropRect.y = oldCenterY - cropRect.height * 0.5;
cropRect.clampToBounds();
} }
} }
} }
+28 -34
View File
@@ -23,26 +23,13 @@ GridView {
delegate: Item { delegate: Item {
required property int index required property int index
readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent readonly property bool isCurrent: modelData && modelData.path === Wallpapers.actualCurrent
readonly property real itemMargin: Appearance.spacing.normal / 2 readonly property real itemMargin: Appearance.spacing.normal
readonly property real itemRadius: Appearance.rounding.normal readonly property real itemRadius: Appearance.rounding.small
required property var modelData required property var modelData
height: root.cellHeight height: root.cellHeight
width: root.cellWidth width: root.cellWidth
StateLayer {
function onClicked(): void {
Wallpapers.setWallpaper(modelData.path);
}
anchors.bottomMargin: itemMargin
anchors.fill: parent
anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin
radius: itemRadius
}
CustomClippingRect { CustomClippingRect {
id: image id: image
@@ -53,8 +40,6 @@ GridView {
anchors.topMargin: itemMargin anchors.topMargin: itemMargin
antialiasing: true antialiasing: true
color: DynamicColors.tPalette.m3surfaceContainer color: DynamicColors.tPalette.m3surfaceContainer
layer.enabled: true
layer.smooth: true
radius: itemRadius radius: itemRadius
CachingImage { CachingImage {
@@ -100,29 +85,13 @@ GridView {
} }
} }
Timer {
id: fallbackTimer
property bool triggered: false
interval: 800
running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null
onTriggered: triggered = true
}
}
Rectangle { Rectangle {
anchors.bottomMargin: itemMargin
anchors.fill: parent anchors.fill: parent
anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin
antialiasing: true antialiasing: true
border.color: DynamicColors.palette.m3primary border.color: DynamicColors.palette.m3primary
border.width: isCurrent ? 2 : 0 border.width: isCurrent ? 2 : 0
color: "transparent" color: "transparent"
radius: itemRadius - border.width radius: itemRadius + 2
smooth: true smooth: true
Behavior on border.width { Behavior on border.width {
@@ -142,5 +111,30 @@ GridView {
visible: isCurrent visible: isCurrent
} }
} }
Timer {
id: fallbackTimer
property bool triggered: false
interval: 800
running: cachingImage.status === Image.Loading || cachingImage.status === Image.Null
onTriggered: triggered = true
}
}
StateLayer {
function onClicked(): void {
Wallpapers.setWallpaper(modelData.path);
}
anchors.bottomMargin: itemMargin
anchors.fill: parent
anchors.leftMargin: itemMargin
anchors.rightMargin: itemMargin
anchors.topMargin: itemMargin
radius: itemRadius
}
} }
} }
+1
View File
@@ -1,5 +1,6 @@
import QtQuick.Layouts import QtQuick.Layouts
import QtQuick import QtQuick
import QtQuick.VectorImage
import Quickshell import Quickshell
import Quickshell.Services.SystemTray import Quickshell.Services.SystemTray
import qs.Modules import qs.Modules
+56 -13
View File
@@ -1,6 +1,7 @@
pragma ComponentBehavior: Bound pragma ComponentBehavior: Bound
import Quickshell import Quickshell
import Quickshell.Hyprland
import QtQuick import QtQuick
import qs.Components import qs.Components
import qs.Helpers import qs.Helpers
@@ -12,31 +13,73 @@ Item {
required property ShellScreen screen required property ShellScreen screen
property string source: Wallpapers.current property string source: Wallpapers.current
function refreshData(): void {
Hyprland.refreshMonitors();
const scale = Hyprland.monitorFor(root.screen).scale;
if (scale > 0 && img.resScale !== scale) {
img.resScale = scale;
img.sourceSize.width = root.screen.width * scale;
}
const displayData = Wallpapers.getCrop(root.screen.name);
const displayRect = Qt.rect(img.sourceSize.width * displayData.x, img.implicitHeight * displayData.y, img.sourceSize.width * displayData.width, img.implicitHeight * displayData.height);
img.anchors.fill = null;
img.zoom = displayData.zoom;
img.x = -(displayRect.x * displayData.zoom / img.resScale);
img.y = -(displayRect.y * displayData.zoom / img.resScale);
}
anchors.fill: parent anchors.fill: parent
Image { Image {
id: img id: img
anchors.fill: parent property int displayH
property int displayW
property real resScale
property real zoom: 1.0
asynchronous: true asynchronous: true
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
height: implicitHeight * zoom / resScale
opacity: 1 opacity: 1
retainWhileLoading: true retainWhileLoading: true
source: root.source source: root.source
sourceClipRect: Wallpapers.recentlyChanged ? null : Qt.rect(Config.background.sourceClipX, Config.background.sourceClipY, Config.background.sourceClipW, Config.background.sourceClipH) sourceSize.width: root.screen.width * resScale
sourceSize.height: root.screen.height width: implicitWidth * zoom / resScale
sourceSize.width: root.screen.width
onSourceChanged: { Behavior on height {
if (Wallpapers.recentlyChanged) { Anim {
Config.background.sourceClipH = 0;
Config.background.sourceClipW = 0;
Config.background.sourceClipY = 0;
Config.background.sourceClipX = 0;
Config.background.zoom = 1.0;
Config.save();
} }
Wallpapers.recentlyChanged = true; }
Behavior on width {
Anim {
}
}
Behavior on x {
Anim {
}
}
Behavior on y {
Anim {
}
}
onStatusChanged: {
if (img.status == Image.Ready) {
root.refreshData();
}
}
Connections {
function onAdapterUpdated(): void {
root.refreshData();
}
function onLoaded(): void {
root.refreshData();
}
target: Wallpapers.monitorCrops
} }
} }
} }
+7
View File
@@ -311,6 +311,13 @@ export const settingsIndex = [
section: "Lockscreen", section: "Lockscreen",
keywords: ["notification", "hide", "privacy"], keywords: ["notification", "hide", "privacy"],
}, },
{
name: "Show notification icon",
category: "lockscreen",
categoryName: "Lockscreen",
section: "Lockscreen",
keywords: ["notification", "hide", "icon"],
},
{ {
name: "Blur amount", name: "Blur amount",
category: "lockscreen", category: "lockscreen",