From 0e7422c335f54ab440ca02a294e32c930d5e3099 Mon Sep 17 00:00:00 2001 From: end-4 <97237370+end-4@users.noreply.github.com> Date: Wed, 5 Nov 2025 00:07:38 +0100 Subject: [PATCH] make bg clock draggable --- .../ii/modules/background/Background.qml | 292 +++--------------- .../widgets/AbstractBackgroundWidget.qml | 97 ++++++ .../background/widgets/clock/ClockWidget.qml | 195 ++++++++++++ .../clock}/CookieClock.qml | 54 ++-- .../clock}/CookieQuote.qml | 0 .../clock}/HourHand.qml | 0 .../clock}/HourMarks.qml | 0 .../clock}/MinuteHand.qml | 0 .../clock}/SecondHand.qml | 2 +- .../clock}/TimeColumn.qml | 4 +- .../clock}/dateIndicator/BubbleDate.qml | 0 .../clock}/dateIndicator/DateIndicator.qml | 2 +- .../clock}/dateIndicator/RectangleDate.qml | 2 +- .../clock}/dateIndicator/RotatingDate.qml | 6 +- .../clock}/minuteMarks/BigHourNumbers.qml | 0 .../clock}/minuteMarks/Dots.qml | 0 .../clock}/minuteMarks/Lines.qml | 0 .../clock}/minuteMarks/MinuteMarks.qml | 4 +- .../quickshell/ii/modules/common/Config.qml | 54 ++-- .../widgets/widgetCanvas/AbstractWidget.qml | 26 ++ .../widgets/widgetCanvas/WidgetCanvas.qml | 7 + .../ii/modules/settings/InterfaceConfig.qml | 113 ++++--- .../ii/scripts/images/least_busy_region.py | 16 +- 23 files changed, 521 insertions(+), 353 deletions(-) create mode 100644 dots/.config/quickshell/ii/modules/background/widgets/AbstractBackgroundWidget.qml create mode 100644 dots/.config/quickshell/ii/modules/background/widgets/clock/ClockWidget.qml rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/CookieClock.qml (73%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/CookieQuote.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/HourHand.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/HourMarks.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/MinuteHand.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/SecondHand.qml (94%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/TimeColumn.qml (86%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/dateIndicator/BubbleDate.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/dateIndicator/DateIndicator.qml (96%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/dateIndicator/RectangleDate.qml (92%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/dateIndicator/RotatingDate.qml (90%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/minuteMarks/BigHourNumbers.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/minuteMarks/Dots.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/minuteMarks/Lines.qml (100%) rename dots/.config/quickshell/ii/modules/background/{cookieClock => widgets/clock}/minuteMarks/MinuteMarks.qml (84%) create mode 100644 dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/AbstractWidget.qml create mode 100644 dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/WidgetCanvas.qml diff --git a/dots/.config/quickshell/ii/modules/background/Background.qml b/dots/.config/quickshell/ii/modules/background/Background.qml index f36cf3590..583c085ea 100644 --- a/dots/.config/quickshell/ii/modules/background/Background.qml +++ b/dots/.config/quickshell/ii/modules/background/Background.qml @@ -4,6 +4,7 @@ import qs import qs.services import qs.modules.common import qs.modules.common.widgets +import qs.modules.common.widgets.widgetCanvas import qs.modules.common.functions as CF import QtQuick import QtQuick.Layouts @@ -13,18 +14,11 @@ import Quickshell.Io import Quickshell.Wayland import Quickshell.Hyprland -import qs.modules.background.cookieClock +import qs.modules.background.widgets +import qs.modules.background.widgets.clock Variants { id: root - readonly property bool fixedClockPosition: Config.options.background.clock.fixedPosition - readonly property real fixedClockX: Config.options.background.clock.x - readonly property real fixedClockY: Config.options.background.clock.y - readonly property real clockSizePadding: 20 - readonly property real screenSizePadding: 50 - readonly property string clockStyle: Config.options.background.clock.style - readonly property bool showCookieQuote: Config.options.background.showQuote && Config.options.background.quote !== "" && !GlobalStates.screenLocked && Config.options.background.clock.style === "cookie" - readonly property real clockParallaxFactor: Config.options.background.parallax.clockFactor // 0 = full parallax, 1 = no parallax model: Quickshell.screens PanelWindow { @@ -46,9 +40,9 @@ Variants { property bool wallpaperIsVideo: Config.options.background.wallpaperPath.endsWith(".mp4") || Config.options.background.wallpaperPath.endsWith(".webm") || Config.options.background.wallpaperPath.endsWith(".mkv") || Config.options.background.wallpaperPath.endsWith(".avi") || Config.options.background.wallpaperPath.endsWith(".mov") property string wallpaperPath: wallpaperIsVideo ? Config.options.background.thumbnailPath : Config.options.background.wallpaperPath property bool wallpaperSafetyTriggered: { - const enabled = Config.options.workSafety.enable.wallpaper - const sensitiveWallpaper = (CF.StringUtils.stringListContainsSubstring(wallpaperPath.toLowerCase(), Config.options.workSafety.triggerCondition.fileKeywords)) - const sensitiveNetwork = (CF.StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords)) + const enabled = Config.options.workSafety.enable.wallpaper; + const sensitiveWallpaper = (CF.StringUtils.stringListContainsSubstring(wallpaperPath.toLowerCase(), Config.options.workSafety.triggerCondition.fileKeywords)); + const sensitiveNetwork = (CF.StringUtils.stringListContainsSubstring(Network.networkName.toLowerCase(), Config.options.workSafety.triggerCondition.networkNameKeywords)); return enabled && sensitiveWallpaper && sensitiveNetwork; } property real wallpaperToScreenRatio: Math.min(wallpaperWidth / screen.width, wallpaperHeight / screen.height) @@ -59,18 +53,6 @@ Variants { property real movableXSpace: ((wallpaperWidth / wallpaperToScreenRatio * effectiveWallpaperScale) - screen.width) / 2 property real movableYSpace: ((wallpaperHeight / wallpaperToScreenRatio * effectiveWallpaperScale) - screen.height) / 2 readonly property bool verticalParallax: (Config.options.background.parallax.autoVertical && wallpaperHeight > wallpaperWidth) || Config.options.background.parallax.vertical - // Position - property real clockX: (modelData.width / 2) - property real clockY: (modelData.height / 2) - property var textHorizontalAlignment: { - if ((Config.options.lock.centerClock && GlobalStates.screenLocked) || wallpaperSafetyTriggered) - return Text.AlignHCenter; - if (clockX < screen.width / 3) - return Text.AlignLeft; - if (clockX > screen.width * 2 / 3) - return Text.AlignRight; - return Text.AlignHCenter; - } // Colors property bool shouldBlur: (GlobalStates.screenLocked && Config.options.lock.blur.enable) property color dominantColor: Appearance.colors.colPrimary // Default, to be changed @@ -97,8 +79,9 @@ Variants { right: true } color: { - if (!bgRoot.wallpaperSafetyTriggered || bgRoot.wallpaperIsVideo) return "transparent"; - return CF.ColorUtils.mix(Appearance.colors.colLayer0, Appearance.colors.colPrimary, 0.75) + if (!bgRoot.wallpaperSafetyTriggered || bgRoot.wallpaperIsVideo) + return "transparent"; + return CF.ColorUtils.mix(Appearance.colors.colLayer0, Appearance.colors.colPrimary, 0.75); } Behavior on color { animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this) @@ -134,53 +117,15 @@ Variants { // Oversized = can be zoomed for parallax, yay bgRoot.effectiveWallpaperScale = Math.min(bgRoot.preferredWallpaperScale, width / screenWidth, height / screenHeight); } - - bgRoot.updateClockPosition(); } } } - // Clock positioning - function updateClockPosition() { - // Somehow all this manual setting is needed to make the proc correctly use the new values - leastBusyRegionProc.path = bgRoot.wallpaperPath; - leastBusyRegionProc.contentWidth = clockLoader.implicitWidth + root.clockSizePadding * 2; - leastBusyRegionProc.contentHeight = clockLoader.implicitHeight + root.clockSizePadding * 2; - leastBusyRegionProc.horizontalPadding = bgRoot.movableXSpace + root.screenSizePadding * 2; - leastBusyRegionProc.verticalPadding = bgRoot.movableYSpace + root.screenSizePadding * 2; - leastBusyRegionProc.running = false; - leastBusyRegionProc.running = true; - } - Process { - id: leastBusyRegionProc - property string path: bgRoot.wallpaperPath - property int contentWidth: 300 - property int contentHeight: 300 - property int horizontalPadding: bgRoot.movableXSpace - property int verticalPadding: bgRoot.movableYSpace - command: [Quickshell.shellPath("scripts/images/least-busy-region-venv.sh"), "--screen-width", Math.round(bgRoot.screen.width / bgRoot.effectiveWallpaperScale), "--screen-height", Math.round(bgRoot.screen.height / bgRoot.effectiveWallpaperScale), "--width", contentWidth, "--height", contentHeight, "--horizontal-padding", horizontalPadding, "--vertical-padding", verticalPadding, path - // "--visual-output", - ,] - stdout: StdioCollector { - id: leastBusyRegionOutputCollector - onStreamFinished: { - const output = leastBusyRegionOutputCollector.text; - // console.log("[Background] Least busy region output:", output) - if (output.length === 0) - return; - const parsedContent = JSON.parse(output); - bgRoot.clockX = parsedContent.center_x * bgRoot.effectiveWallpaperScale; - bgRoot.clockY = parsedContent.center_y * bgRoot.effectiveWallpaperScale; - bgRoot.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary; - } - } - } - - // Wallpaper Item { anchors.fill: parent clip: true + // Wallpaper StyledImage { id: wallpaper visible: opacity > 0 && !blurLoader.active @@ -261,25 +206,23 @@ Variants { } } - // The clock - Loader { - id: clockLoader - scale: Config.options.background.clock.scale - active: Config.options.background.clock.show + WidgetCanvas { + id: widgetCanvas anchors { left: wallpaper.left + right: wallpaper.right top: wallpaper.top - horizontalCenter: undefined - verticalCenter: undefined + bottom: wallpaper.bottom + readonly property real parallaxFactor: Config.options.background.parallax.widgetsFactor leftMargin: { - const clockXOnWallpaper = bgRoot.movableXSpace + ((root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX * bgRoot.effectiveWallpaperScale) - implicitWidth / 2) - const extraMove = (wallpaper.effectiveValueX * 2 * bgRoot.movableXSpace) * (root.clockParallaxFactor - 1); - return clockXOnWallpaper - extraMove; + const xOnWallpaper = bgRoot.movableXSpace; + const extraMove = (wallpaper.effectiveValueX * 2 * bgRoot.movableXSpace) * (parallaxFactor - 1); + return xOnWallpaper - extraMove; } topMargin: { - const clockYOnWallpaper = bgRoot.movableYSpace + ((root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY * bgRoot.effectiveWallpaperScale) - implicitHeight / 2) - const extraMove = (wallpaper.effectiveValueY * 2 * bgRoot.movableYSpace) * (root.clockParallaxFactor - 1); - return clockYOnWallpaper - extraMove; + const yOnWallpaper = bgRoot.movableYSpace; + const extraMove = (wallpaper.effectiveValueY * 2 * bgRoot.movableYSpace) * (parallaxFactor - 1); + return yOnWallpaper - extraMove; } Behavior on leftMargin { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) @@ -288,193 +231,54 @@ Variants { animation: Appearance.animation.elementMove.numberAnimation.createObject(this) } } + width: wallpaper.width + height: wallpaper.height states: State { name: "centered" - when: (GlobalStates.screenLocked && Config.options.lock.centerClock) || bgRoot.wallpaperSafetyTriggered + when: GlobalStates.screenLocked || bgRoot.wallpaperSafetyTriggered + PropertyChanges { + target: widgetCanvas + width: parent.width + height: parent.height + } AnchorChanges { - target: clockLoader + target: widgetCanvas anchors { left: undefined right: undefined top: undefined - verticalCenter: parent.verticalCenter - horizontalCenter: parent.horizontalCenter + bottom: undefined + // horizontalCenter: parent.horizontalCenter + // verticalCenter: parent.verticalCenter } } } transitions: Transition { + PropertyAnimation { + properties: "width,height" + duration: Appearance.animation.elementMove.duration + easing.type: Appearance.animation.elementMove.type + easing.bezierCurve: Appearance.animation.elementMove.bezierCurve + } AnchorAnimation { duration: Appearance.animation.elementMove.duration easing.type: Appearance.animation.elementMove.type easing.bezierCurve: Appearance.animation.elementMove.bezierCurve } } - sourceComponent: Column { - Loader { - id: digitalClockLoader - visible: root.clockStyle === "digital" - active: visible - sourceComponent: ColumnLayout { - id: clockColumn - spacing: 6 - ClockText { - font.pixelSize: 90 - text: DateTime.time - } - ClockText { - Layout.topMargin: -5 - text: DateTime.date - } - StyledText { - // Somehow gets fucked up if made a ClockText??? - visible: Config.options.background.showQuote && Config.options.background.quote.length > 0 - Layout.fillWidth: true - horizontalAlignment: bgRoot.textHorizontalAlignment - font { - pixelSize: Appearance.font.pixelSize.normal - weight: 350 - } - color: bgRoot.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - text: Config.options.background.quote - } - } - } - - Loader { - id: cookieClockLoader - visible: root.clockStyle === "cookie" - active: visible - sourceComponent: CookieClock {} - } - - Loader { - id: cookieQuoteLoader - visible: root.showCookieQuote - active: visible - sourceComponent: CookieQuote {} - anchors.horizontalCenter: cookieClockLoader.horizontalCenter - } - - } - - Item { - anchors { - top: clockLoader.bottom - topMargin: 8 - horizontalCenter: (bgRoot.textHorizontalAlignment === Text.AlignHCenter || root.clockStyle === "cookie") ? clockLoader.horizontalCenter : undefined - left: (bgRoot.textHorizontalAlignment === Text.AlignLeft) ? clockLoader.left : undefined - right: (bgRoot.textHorizontalAlignment === Text.AlignRight) ? clockLoader.right : undefined - leftMargin: -26 - rightMargin: -26 - } - implicitWidth: statusTextBg.implicitWidth - implicitHeight: statusTextBg.implicitHeight - - StyledRectangularShadow { - target: statusTextBg - visible: statusTextBg.visible && root.clockStyle === "cookie" - opacity: statusTextBg.opacity - } - - Rectangle { - id: statusTextBg - anchors.centerIn: parent - clip: true - opacity: (safetyStatusText.shown || lockStatusText.shown) ? 1 : 0 - visible: opacity > 0 - implicitHeight: statusTextRow.implicitHeight + 5 * 2 - implicitWidth: statusTextRow.implicitWidth + 5 * 2 - radius: Appearance.rounding.small - color: CF.ColorUtils.transparentize(Appearance.colors.colSecondaryContainer, root.clockStyle === "cookie" ? 0 : 1) - - Behavior on implicitWidth { - animation: Appearance.animation.elementResize.numberAnimation.createObject(this) - } - Behavior on implicitHeight { - animation: Appearance.animation.elementResize.numberAnimation.createObject(this) - } - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - - RowLayout { - id: statusTextRow - anchors.centerIn: parent - spacing: 14 - Item { - Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignLeft - implicitWidth: 1 - } - ClockStatusText { - id: safetyStatusText - shown: bgRoot.wallpaperSafetyTriggered - statusIcon: "hide_image" - statusText: Translation.tr("Wallpaper safety enforced") - } - ClockStatusText { - id: lockStatusText - shown: GlobalStates.screenLocked && Config.options.lock.showLockedText - statusIcon: "lock" - statusText: Translation.tr("Locked") - } - Item { - Layout.fillWidth: bgRoot.textHorizontalAlignment !== Text.AlignRight - implicitWidth: 1 - } - } + FadeLoader { + shown: Config.options.background.widgets.clock.enable + sourceComponent: ClockWidget { + screenWidth: bgRoot.screen.width + screenHeight: bgRoot.screen.height + scaledScreenWidth: bgRoot.screen.width / bgRoot.effectiveWallpaperScale + scaledScreenHeight: bgRoot.screen.height / bgRoot.effectiveWallpaperScale + wallpaperScale: bgRoot.effectiveWallpaperScale + wallpaperSafetyTriggered: bgRoot.wallpaperSafetyTriggered } } } } } - - // ComponentsCookieClock {} - component ClockText: StyledText { - Layout.fillWidth: true - horizontalAlignment: bgRoot.textHorizontalAlignment - font { - family: Appearance.font.family.expressive - pixelSize: 20 - weight: Font.DemiBold - } - color: bgRoot.colText - style: Text.Raised - styleColor: Appearance.colors.colShadow - animateChange: Config.options.background.clock.digital.animateChange - } - component ClockStatusText: Row { - id: statusTextRow - property alias statusIcon: statusIconWidget.text - property alias statusText: statusTextWidget.text - property bool shown: true - property color textColor: root.clockStyle === "cookie" ? Appearance.colors.colOnSecondaryContainer : bgRoot.colText - opacity: shown ? 1 : 0 - visible: opacity > 0 - Behavior on opacity { - animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) - } - spacing: 4 - MaterialSymbol { - id: statusIconWidget - anchors.verticalCenter: statusTextRow.verticalCenter - iconSize: Appearance.font.pixelSize.huge - color: statusTextRow.textColor - style: Text.Raised - styleColor: Appearance.colors.colShadow - } - ClockText { - id: statusTextWidget - color: statusTextRow.textColor - anchors.verticalCenter: statusTextRow.verticalCenter - font { - pixelSize: Appearance.font.pixelSize.large - weight: Font.Normal - } - style: Text.Raised - styleColor: Appearance.colors.colShadow - } - } } diff --git a/dots/.config/quickshell/ii/modules/background/widgets/AbstractBackgroundWidget.qml b/dots/.config/quickshell/ii/modules/background/widgets/AbstractBackgroundWidget.qml new file mode 100644 index 000000000..93960148d --- /dev/null +++ b/dots/.config/quickshell/ii/modules/background/widgets/AbstractBackgroundWidget.qml @@ -0,0 +1,97 @@ +import QtQuick +import Quickshell +import Quickshell.Io +import qs +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets.widgetCanvas + +AbstractWidget { + id: root + + required property string configEntryName + required property int screenWidth + required property int screenHeight + required property int scaledScreenWidth + required property int scaledScreenHeight + required property real wallpaperScale + property bool visibleWhenLocked: false + property var configEntry: Config.options.background.widgets[configEntryName] + property string placementStrategy: configEntry.placementStrategy + property real targetX: Math.max(0, Math.min(configEntry.x, scaledScreenWidth - width)) + property real targetY : Math.max(0, Math.min(configEntry.y, scaledScreenHeight - height)) + x: targetX + y: targetY + visible: opacity > 0 + opacity: (GlobalStates.screenLocked && !visibleWhenLocked) ? 0 : 1 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + draggable: placementStrategy === "free" + onReleased: { + root.targetX = root.x; + root.targetY = root.y; + configEntry.x = root.targetX; + configEntry.y = root.targetY ; + } + + property bool needsColText: false + property color dominantColor: Appearance.colors.colPrimary + property bool dominantColorIsDark: dominantColor.hslLightness < 0.5 + property color colText: { + const onNormalBackground = (GlobalStates.screenLocked && Config.options.lock.blur.enable) + const adaptiveColor = ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12)) + return onNormalBackground ? Appearance.colors.colOnLayer0 : adaptiveColor; + } + + property bool wallpaperIsVideo: Config.options.background.wallpaperPath.endsWith(".mp4") || Config.options.background.wallpaperPath.endsWith(".webm") || Config.options.background.wallpaperPath.endsWith(".mkv") || Config.options.background.wallpaperPath.endsWith(".avi") || Config.options.background.wallpaperPath.endsWith(".mov") + property string wallpaperPath: wallpaperIsVideo ? Config.options.background.thumbnailPath : Config.options.background.wallpaperPath + + onWallpaperPathChanged: refreshPlacementIfNeeded() + onPlacementStrategyChanged: refreshPlacementIfNeeded() + Connections { + target: Config + function onReadyChanged() { refreshPlacementIfNeeded() } + } + function refreshPlacementIfNeeded() { + if (!Config.ready || (root.placementStrategy === "free" && root.needsColText)) return; + leastBusyRegionProc.wallpaperPath = root.wallpaperPath; + leastBusyRegionProc.running = false; + leastBusyRegionProc.running = true; + } + Process { + id: leastBusyRegionProc + property string wallpaperPath: root.wallpaperPath + // TODO: make these less arbitrary + property int contentWidth: 300 + property int contentHeight: 300 + property int horizontalPadding: 200 + property int verticalPadding: 200 + command: [Quickshell.shellPath("scripts/images/least-busy-region-venv.sh") // Comments to force the formatter to break lines + , "--screen-width", Math.round(root.scaledScreenWidth) // + , "--screen-height", Math.round(root.scaledScreenHeight) // + , "--width", contentWidth // + , "--height", contentHeight // + , "--horizontal-padding", horizontalPadding // + , "--vertical-padding", verticalPadding // + , wallpaperPath // + , ...(root.placementStrategy === "mostBusy" ? ["--busiest"] : []) + // "--visual-output", + ] + stdout: StdioCollector { + id: leastBusyRegionOutputCollector + onStreamFinished: { + const output = leastBusyRegionOutputCollector.text; + // console.log("[Background] Least busy region output:", output) + if (output.length === 0) return; + const parsedContent = JSON.parse(output); + root.dominantColor = parsedContent.dominant_color || Appearance.colors.colPrimary; + if (root.placementStrategy === "free") return; + root.targetX = parsedContent.center_x * root.wallpaperScale - root.width / 2; + root.targetY = parsedContent.center_y * root.wallpaperScale - root.height / 2; + } + } + } +} + diff --git a/dots/.config/quickshell/ii/modules/background/widgets/clock/ClockWidget.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/ClockWidget.qml new file mode 100644 index 000000000..2c3852f4e --- /dev/null +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/ClockWidget.qml @@ -0,0 +1,195 @@ +import QtQuick +import QtQuick.Layouts +import qs +import qs.services +import qs.modules.common +import qs.modules.common.functions +import qs.modules.common.widgets +import qs.modules.common.widgets.widgetCanvas +import qs.modules.background.widgets + +AbstractBackgroundWidget { + id: root + + configEntryName: "clock" + + implicitHeight: contentColumn.implicitHeight + implicitWidth: contentColumn.implicitWidth + + property string clockStyle: Config.options.background.widgets.clock.style + property bool forceCenter: (GlobalStates.screenLocked && Config.options.lock.centerClock) + property bool wallpaperSafetyTriggered: false + needsColText: clockStyle === "digital" + x: forceCenter ? ((root.screenWidth - root.width) / 2) : targetX + y: forceCenter ? ((root.screenHeight - root.height) / 2) : targetY + visibleWhenLocked: true + + property var textHorizontalAlignment: { + if (root.forceCenter) + return Text.AlignHCenter; + if (root.x < root.scaledScreenWidth / 3) + return Text.AlignLeft; + if (root.x > root.scaledScreenWidth * 2 / 3) + return Text.AlignRight; + return Text.AlignHCenter; + } + + Column { + id: contentColumn + anchors.centerIn: parent + spacing: 10 + + FadeLoader { + id: cookieClockLoader + anchors.horizontalCenter: parent.horizontalCenter + shown: root.clockStyle === "cookie" + sourceComponent: Column { + CookieClock { + anchors.horizontalCenter: parent.horizontalCenter + } + FadeLoader { + anchors.horizontalCenter: parent.horizontalCenter + shown: Config.options.background.showQuote && Config.options.background.quote !== "" + sourceComponent: CookieQuote {} + } + } + } + + FadeLoader { + id: digitalClockLoader + anchors.horizontalCenter: parent.horizontalCenter + shown: root.clockStyle === "digital" + sourceComponent: ColumnLayout { + id: clockColumn + spacing: 6 + + ClockText { + font.pixelSize: 90 + text: DateTime.time + } + ClockText { + Layout.topMargin: -5 + text: DateTime.date + } + StyledText { + // Somehow gets fucked up if made a ClockText??? + visible: Config.options.background.showQuote && Config.options.background.quote.length > 0 + Layout.fillWidth: true + horizontalAlignment: root.textHorizontalAlignment + font { + pixelSize: Appearance.font.pixelSize.normal + weight: 350 + } + color: root.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + text: Config.options.background.quote + } + } + } + Item { + id: statusText + anchors.horizontalCenter: parent.horizontalCenter + implicitHeight: statusTextBg.implicitHeight + implicitWidth: statusTextBg.implicitWidth + StyledRectangularShadow { + target: statusTextBg + visible: statusTextBg.visible && root.clockStyle === "cookie" + opacity: statusTextBg.opacity + } + Rectangle { + id: statusTextBg + anchors.centerIn: parent + clip: true + opacity: (safetyStatusText.shown || lockStatusText.shown) ? 1 : 0 + visible: opacity > 0 + implicitHeight: statusTextRow.implicitHeight + 5 * 2 + implicitWidth: statusTextRow.implicitWidth + 5 * 2 + radius: Appearance.rounding.small + color: ColorUtils.transparentize(Appearance.colors.colSecondaryContainer, root.clockStyle === "cookie" ? 0 : 1) + + Behavior on implicitWidth { + animation: Appearance.animation.elementResize.numberAnimation.createObject(this) + } + Behavior on implicitHeight { + animation: Appearance.animation.elementResize.numberAnimation.createObject(this) + } + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + + RowLayout { + id: statusTextRow + anchors.centerIn: parent + spacing: 14 + Item { + Layout.fillWidth: root.textHorizontalAlignment !== Text.AlignLeft + implicitWidth: 1 + } + ClockStatusText { + id: safetyStatusText + shown: root.wallpaperSafetyTriggered + statusIcon: "hide_image" + statusText: Translation.tr("Wallpaper safety enforced") + } + ClockStatusText { + id: lockStatusText + shown: GlobalStates.screenLocked && Config.options.lock.showLockedText + statusIcon: "lock" + statusText: Translation.tr("Locked") + } + Item { + Layout.fillWidth: root.textHorizontalAlignment !== Text.AlignRight + implicitWidth: 1 + } + } + } + } + } + + component ClockText: StyledText { + Layout.fillWidth: true + horizontalAlignment: root.textHorizontalAlignment + font { + family: Appearance.font.family.expressive + pixelSize: 20 + weight: Font.DemiBold + } + color: root.colText + style: Text.Raised + styleColor: Appearance.colors.colShadow + animateChange: Config.options.background.widgets.clock.digital.animateChange + } + component ClockStatusText: Row { + id: statusTextRow + property alias statusIcon: statusIconWidget.text + property alias statusText: statusTextWidget.text + property bool shown: true + property color textColor: root.clockStyle === "cookie" ? Appearance.colors.colOnSecondaryContainer : root.colText + opacity: shown ? 1 : 0 + visible: opacity > 0 + Behavior on opacity { + animation: Appearance.animation.elementMoveFast.numberAnimation.createObject(this) + } + spacing: 4 + MaterialSymbol { + id: statusIconWidget + anchors.verticalCenter: statusTextRow.verticalCenter + iconSize: Appearance.font.pixelSize.huge + color: statusTextRow.textColor + style: Text.Raised + styleColor: Appearance.colors.colShadow + } + ClockText { + id: statusTextWidget + color: statusTextRow.textColor + anchors.verticalCenter: statusTextRow.verticalCenter + font { + pixelSize: Appearance.font.pixelSize.large + weight: Font.Normal + } + style: Text.Raised + styleColor: Appearance.colors.colShadow + } + } +} diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/CookieClock.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/CookieClock.qml similarity index 73% rename from dots/.config/quickshell/ii/modules/background/cookieClock/CookieClock.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/CookieClock.qml index a730535ec..1dbaea8cf 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/CookieClock.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/CookieClock.qml @@ -9,13 +9,13 @@ import QtQuick.Layouts import Qt5Compat.GraphicalEffects import Quickshell.Io -import qs.modules.background.cookieClock.dateIndicator -import qs.modules.background.cookieClock.minuteMarks +import qs.modules.background.widgets.clock.dateIndicator +import qs.modules.background.widgets.clock.minuteMarks Item { id: root - readonly property string clockStyle: Config.options.background.clock.style + readonly property string clockStyle: Config.options.background.widgets.clock.style property real implicitSize: 230 @@ -36,16 +36,16 @@ Item { implicitHeight: implicitSize function applyStyle(sides, dialStyle, hourHandStyle, minuteHandStyle, secondHandStyle, dateStyle) { - Config.options.background.clock.cookie.sides = sides - Config.options.background.clock.cookie.dialNumberStyle = dialStyle - Config.options.background.clock.cookie.hourHandStyle = hourHandStyle - Config.options.background.clock.cookie.minuteHandStyle = minuteHandStyle - Config.options.background.clock.cookie.secondHandStyle = secondHandStyle - Config.options.background.clock.cookie.dateStyle = dateStyle + Config.options.background.widgets.clock.cookie.sides = sides + Config.options.background.widgets.clock.cookie.dialNumberStyle = dialStyle + Config.options.background.widgets.clock.cookie.hourHandStyle = hourHandStyle + Config.options.background.widgets.clock.cookie.minuteHandStyle = minuteHandStyle + Config.options.background.widgets.clock.cookie.secondHandStyle = secondHandStyle + Config.options.background.widgets.clock.cookie.dateStyle = dateStyle } function setClockPreset(category) { - if (!Config.options.background.clock.cookie.aiStyling) return; + if (!Config.options.background.widgets.clock.cookie.aiStyling) return; if (category === "") return; print("[Cookie clock] Setting clock preset for category: " + category) // "abstract", "anime", "city", "minimalist", "landscape", "plants", "person", "space" @@ -83,7 +83,7 @@ Item { } } - property bool useSineCookie: Config.options.background.clock.cookie.useSineCookie + property bool useSineCookie: Config.options.background.widgets.clock.cookie.useSineCookie DropShadow { source: useSineCookie ? sineCookieLoader : roundedPolygonCookieLoader anchors.fill: source @@ -93,7 +93,7 @@ Item { transparentBorder: true RotationAnimation on rotation { - running: Config.options.background.clock.cookie.constantlyRotate + running: Config.options.background.widgets.clock.cookie.constantlyRotate duration: 30000 easing.type: Easing.Linear loops: Animation.Infinite @@ -108,7 +108,7 @@ Item { active: useSineCookie sourceComponent: SineCookie { implicitSize: root.implicitSize - sides: Config.options.background.clock.cookie.sides + sides: Config.options.background.widgets.clock.cookie.sides color: root.colBackground } } @@ -119,7 +119,7 @@ Item { active: !useSineCookie sourceComponent: MaterialCookie { implicitSize: root.implicitSize - sides: Config.options.background.clock.cookie.sides + sides: Config.options.background.widgets.clock.cookie.sides color: root.colBackground } } @@ -134,7 +134,7 @@ Item { FadeLoader { id: hourMarksLoader anchors.centerIn: parent - shown: Config.options.background.clock.cookie.hourMarks + shown: Config.options.background.widgets.clock.cookie.hourMarks sourceComponent: HourMarks { implicitSize: 135 * (1.75 - 0.75 * hourMarksLoader.opacity) color: root.colOnBackground @@ -146,7 +146,7 @@ Item { FadeLoader { id: timeColumnLoader anchors.centerIn: parent - shown: Config.options.background.clock.cookie.timeIndicators + shown: Config.options.background.widgets.clock.cookie.timeIndicators scale: 1.4 - 0.4 * timeColumnLoader.shown Behavior on scale { animation: Appearance.animation.elementResize.numberAnimation.createObject(this) @@ -161,11 +161,11 @@ Item { FadeLoader { anchors.fill: parent z: 1 - shown: Config.options.background.clock.cookie.minuteHandStyle !== "hide" + shown: Config.options.background.widgets.clock.cookie.minuteHandStyle !== "hide" sourceComponent: MinuteHand { anchors.fill: parent clockMinute: root.clockMinute - style: Config.options.background.clock.cookie.minuteHandStyle + style: Config.options.background.widgets.clock.cookie.minuteHandStyle color: root.colMinuteHand } } @@ -174,11 +174,11 @@ Item { FadeLoader { anchors.fill: parent z: item?.style === "hollow" ? 0 : 2 - shown: Config.options.background.clock.cookie.hourHandStyle !== "hide" + shown: Config.options.background.widgets.clock.cookie.hourHandStyle !== "hide" sourceComponent: HourHand { clockHour: root.clockHour clockMinute: root.clockMinute - style: Config.options.background.clock.cookie.hourHandStyle + style: Config.options.background.widgets.clock.cookie.hourHandStyle color: root.colHourHand } } @@ -186,13 +186,13 @@ Item { // Second hand FadeLoader { id: secondHandLoader - z: (Config.options.background.clock.cookie.secondHandStyle === "line") ? 2 : 3 - shown: Config.options.time.secondPrecision && Config.options.background.clock.cookie.secondHandStyle !== "hide" + z: (Config.options.background.widgets.clock.cookie.secondHandStyle === "line") ? 2 : 3 + shown: Config.options.time.secondPrecision && Config.options.background.widgets.clock.cookie.secondHandStyle !== "hide" anchors.fill: parent sourceComponent: SecondHand { id: secondHand clockSecond: root.clockSecond - style: Config.options.background.clock.cookie.secondHandStyle + style: Config.options.background.widgets.clock.cookie.secondHandStyle color: root.colSecondHand } } @@ -201,9 +201,9 @@ Item { FadeLoader { z: 4 anchors.centerIn: parent - shown: Config.options.background.clock.cookie.minuteHandStyle !== "bold" + shown: Config.options.background.widgets.clock.cookie.minuteHandStyle !== "bold" sourceComponent: Rectangle { - color: Config.options.background.clock.cookie.minuteHandStyle === "medium" ? root.colBackground : root.colMinuteHand + color: Config.options.background.widgets.clock.cookie.minuteHandStyle === "medium" ? root.colBackground : root.colMinuteHand implicitWidth: 6 implicitHeight: implicitWidth radius: width / 2 @@ -213,11 +213,11 @@ Item { // Date FadeLoader { anchors.fill: parent - shown: Config.options.background.clock.cookie.dateStyle !== "hide" + shown: Config.options.background.widgets.clock.cookie.dateStyle !== "hide" sourceComponent: DateIndicator { color: root.colBackgroundInfo - style: Config.options.background.clock.cookie.dateStyle + style: Config.options.background.widgets.clock.cookie.dateStyle } } } diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/CookieQuote.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/CookieQuote.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/CookieQuote.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/CookieQuote.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/HourHand.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/HourHand.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/HourHand.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/HourHand.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/HourMarks.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/HourMarks.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/HourMarks.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/HourMarks.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/MinuteHand.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/MinuteHand.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/MinuteHand.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/MinuteHand.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/SecondHand.qml similarity index 94% rename from dots/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/SecondHand.qml index 93ca1cf48..2c436a292 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/SecondHand.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/SecondHand.qml @@ -18,7 +18,7 @@ Item { rotation: (360 / 60 * clockSecond) + 90 Behavior on rotation { - enabled: Config.options.background.clock.cookie.constantlyRotate // Animating every second is expensive... + enabled: Config.options.background.widgets.clock.cookie.constantlyRotate // Animating every second is expensive... animation: RotationAnimation { direction: RotationAnimation.Clockwise duration: 1000 // 1 second diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/TimeColumn.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/TimeColumn.qml similarity index 86% rename from dots/.config/quickshell/ii/modules/background/cookieClock/TimeColumn.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/TimeColumn.qml index e2d00c23c..6b73c851a 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/TimeColumn.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/TimeColumn.qml @@ -8,10 +8,10 @@ import QtQuick Column { id: root property list clockNumbers: DateTime.time.split(/[: ]/) - property bool isEnabled: Config.options.background.clock.cookie.timeIndicators + property bool isEnabled: Config.options.background.widgets.clock.cookie.timeIndicators property color color: Appearance.colors.colOnSecondaryContainer - property bool hourMarksEnabled: Config.options.background.clock.cookie.hourMarks + property bool hourMarksEnabled: Config.options.background.widgets.clock.cookie.hourMarks spacing: -16 Repeater { diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/BubbleDate.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/BubbleDate.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/BubbleDate.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/BubbleDate.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/DateIndicator.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/DateIndicator.qml similarity index 96% rename from dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/DateIndicator.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/DateIndicator.qml index 66b1852ee..820a96dea 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/DateIndicator.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/DateIndicator.qml @@ -14,7 +14,7 @@ Item { // Rotating date FadeLoader { anchors.fill: parent - shown: Config.options.background.clock.cookie.dateStyle === "border" + shown: Config.options.background.widgets.clock.cookie.dateStyle === "border" sourceComponent: RotatingDate { color: root.color } diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RectangleDate.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RectangleDate.qml similarity index 92% rename from dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RectangleDate.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RectangleDate.qml index d8ea9ab2e..0c09db194 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RectangleDate.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RectangleDate.qml @@ -6,7 +6,7 @@ import QtQuick Rectangle { id: rect - readonly property string dialStyle: Config.options.background.clock.cookie.dialNumberStyle + readonly property string dialStyle: Config.options.background.widgets.clock.cookie.dialNumberStyle StyledText { anchors.centerIn: parent diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RotatingDate.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RotatingDate.qml similarity index 90% rename from dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RotatingDate.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RotatingDate.qml index ec25c024f..3c8354d74 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/dateIndicator/RotatingDate.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/dateIndicator/RotatingDate.qml @@ -8,14 +8,14 @@ import QtQuick Item { id: root - property string style: Config.options.background.clock.cookie.dateStyle + property string style: Config.options.background.widgets.clock.cookie.dateStyle property color color: Appearance.colors.colOnSecondaryContainer property real angleStep: 12 * Math.PI / 180 property string dateText: Qt.locale().toString(DateTime.clock.date, "ddd dd") readonly property int clockSecond: DateTime.clock.seconds - readonly property string dialStyle: Config.options.background.clock.cookie.dialNumberStyle - readonly property bool timeIndicators: Config.options.background.clock.cookie.timeIndicators + readonly property string dialStyle: Config.options.background.widgets.clock.cookie.dialNumberStyle + readonly property bool timeIndicators: Config.options.background.widgets.clock.cookie.timeIndicators property real radius: style === "border" ? 90 : 0 Behavior on radius { diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/BigHourNumbers.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/BigHourNumbers.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/BigHourNumbers.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/BigHourNumbers.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/Dots.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/Dots.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/Dots.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/Dots.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/Lines.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/Lines.qml similarity index 100% rename from dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/Lines.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/Lines.qml diff --git a/dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/MinuteMarks.qml b/dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/MinuteMarks.qml similarity index 84% rename from dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/MinuteMarks.qml rename to dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/MinuteMarks.qml index 07cf0dc5e..02d8f2582 100644 --- a/dots/.config/quickshell/ii/modules/background/cookieClock/minuteMarks/MinuteMarks.qml +++ b/dots/.config/quickshell/ii/modules/background/widgets/clock/minuteMarks/MinuteMarks.qml @@ -8,8 +8,8 @@ Item { id: root property color color: Appearance.colors.colOnSecondaryContainer - property string style: Config.options.background.clock.cookie.dialNumberStyle // "dots", "numbers", "full", "hide" - property string dateStyle : Config.options.background.clock.cookie.dateStyle + property string style: Config.options.background.widgets.clock.cookie.dialNumberStyle // "dots", "numbers", "full", "hide" + property string dateStyle : Config.options.background.widgets.clock.cookie.dateStyle // 12 Dots FadeLoader { diff --git a/dots/.config/quickshell/ii/modules/common/Config.qml b/dots/.config/quickshell/ii/modules/common/Config.qml index 4df736237..948f92601 100644 --- a/dots/.config/quickshell/ii/modules/common/Config.qml +++ b/dots/.config/quickshell/ii/modules/common/Config.qml @@ -145,31 +145,33 @@ Singleton { } property JsonObject background: JsonObject { - property JsonObject clock: JsonObject { - property bool fixedPosition: false - property real x: -500 - property real y: -500 - property bool show: true - property string style: "cookie" // Options: "cookie", "digital" - property real scale: 1 - property JsonObject cookie: JsonObject { - property bool aiStyling: false - property int sides: 14 - property string dialNumberStyle: "full" // Options: "dots" , "numbers", "full" , "none" - property string hourHandStyle: "fill" // Options: "classic", "fill", "hollow", "hide" - property string minuteHandStyle: "medium" // Options "classic", "thin", "medium", "bold", "hide" - property string secondHandStyle: "dot" // Options: "dot", "line", "classic", "hide" - property string dateStyle: "bubble" // Options: "border", "rect", "bubble" , "hide" - property bool timeIndicators: true - property bool hourMarks: false - property bool dateInClock: true - property bool constantlyRotate: false - property bool useSineCookie: false + property JsonObject widgets: JsonObject { + property JsonObject clock: JsonObject { + property bool enable: true + property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy" + property real x: 100 + property real y: 100 + property string style: "cookie" // Options: "cookie", "digital" + property real scale: 1 + property JsonObject cookie: JsonObject { + property bool aiStyling: false + property int sides: 14 + property string dialNumberStyle: "full" // Options: "dots" , "numbers", "full" , "none" + property string hourHandStyle: "fill" // Options: "classic", "fill", "hollow", "hide" + property string minuteHandStyle: "medium" // Options "classic", "thin", "medium", "bold", "hide" + property string secondHandStyle: "dot" // Options: "dot", "line", "classic", "hide" + property string dateStyle: "bubble" // Options: "border", "rect", "bubble" , "hide" + property bool timeIndicators: true + property bool hourMarks: false + property bool dateInClock: true + property bool constantlyRotate: false + property bool useSineCookie: false + } + property JsonObject digital: JsonObject { + property bool animateChange: true + } + } - property JsonObject digital: JsonObject { - property bool animateChange: true - } - } property string wallpaperPath: "" property string thumbnailPath: "" @@ -182,7 +184,7 @@ Singleton { property bool enableWorkspace: true property real workspaceZoom: 1.07 // Relative to your screen, not wallpaper size property bool enableSidebar: true - property real clockFactor: 1.2 + property real widgetsFactor: 1.2 } } @@ -318,7 +320,7 @@ Singleton { property bool useHyprlock: false property bool launchOnStartup: false property JsonObject blur: JsonObject { - property bool enable: false + property bool enable: true property real radius: 100 property real extraZoom: 1.1 } diff --git a/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/AbstractWidget.qml b/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/AbstractWidget.qml new file mode 100644 index 000000000..26d8c9547 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/AbstractWidget.qml @@ -0,0 +1,26 @@ +import QtQuick +import Quickshell +import qs.modules.common + +/* + * Widget to be placed on a WidgetCanvas + */ +MouseArea { + id: root + + property bool draggable: true + drag.target: draggable ? root : undefined + cursorShape: drag.active ? Qt.ClosedHandCursor : draggable ? Qt.OpenHandCursor : Qt.ArrowCursor + + function center() { + root.x = (root.parent.width - root.width) / 2 + root.y = (root.parent.height - root.height) / 2 + } + + Behavior on x { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } + Behavior on y { + animation: Appearance.animation.elementMove.numberAnimation.createObject(this) + } +} diff --git a/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/WidgetCanvas.qml b/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/WidgetCanvas.qml new file mode 100644 index 000000000..b40091432 --- /dev/null +++ b/dots/.config/quickshell/ii/modules/common/widgets/widgetCanvas/WidgetCanvas.qml @@ -0,0 +1,7 @@ +import QtQuick + +Item { + id: root + + // uh this is stupid turns out we don't need anything here +} diff --git a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml index 89e202e0c..d1b8030ec 100644 --- a/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml +++ b/dots/.config/quickshell/ii/modules/settings/InterfaceConfig.qml @@ -14,9 +14,9 @@ ContentPage { ConfigSwitch { buttonIcon: "nest_clock_farsight_analog" text: Translation.tr("Show clock") - checked: Config.options.background.clock.show + checked: Config.options.background.widgets.clock.enable onCheckedChanged: { - Config.options.background.clock.show = checked; + Config.options.background.widgets.clock.enable = checked; } } @@ -24,21 +24,48 @@ ContentPage { ConfigSpinBox { icon: "loupe" text: Translation.tr("Scale (%)") - value: Config.options.background.clock.scale * 100 + value: Config.options.background.widgets.clock.scale * 100 from: 1 to: 200 stepSize: 2 onValueChanged: { - Config.options.background.clock.scale = value / 100; + Config.options.background.widgets.clock.scale = value / 100; + } + } + + ContentSubsection { + title: Translation.tr("Clock placement strategy") + ConfigSelectionArray { + currentValue: Config.options.background.widgets.clock.placementStrategy + onSelected: newValue => { + Config.options.background.widgets.clock.placementStrategy = newValue; + } + options: [ + { + displayName: Translation.tr("Draggable"), + icon: "drag_pan", + value: "free" + }, + { + displayName: Translation.tr("Least busy"), + icon: "arrows_output", + value: "leastBusy" + }, + { + displayName: Translation.tr("Most busy"), + icon: "arrows_input", + value: "mostBusy" + }, + ] } } ContentSubsection { title: Translation.tr("Clock style") ConfigSelectionArray { - currentValue: Config.options.background.clock.style + currentValue: Config.options.background.widgets.clock.style onSelected: newValue => { - Config.options.background.clock.style = newValue; + Config.options.background.widgets.clock.style = newValue; } options: [ { @@ -56,29 +83,29 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "digital" + visible: Config.options.background.widgets.clock.style === "digital" title: Translation.tr("Digital clock settings") ConfigSwitch { buttonIcon: "animation" text: Translation.tr("Animate time change") - checked: Config.options.background.clock.digital.animateChange + checked: Config.options.background.widgets.clock.digital.animateChange onCheckedChanged: { - Config.options.background.clock.digital.animateChange = checked; + Config.options.background.widgets.clock.digital.animateChange = checked; } } } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Cookie clock settings") ConfigSwitch { buttonIcon: "wand_stars" text: Translation.tr("Auto styling with Gemini") - checked: Config.options.background.clock.cookie.aiStyling + checked: Config.options.background.widgets.clock.cookie.aiStyling onCheckedChanged: { - Config.options.background.clock.cookie.aiStyling = checked; + Config.options.background.widgets.clock.cookie.aiStyling = checked; } StyledToolTip { text: Translation.tr("Uses Gemini to categorize the wallpaper then picks a preset based on it.\nYou'll need to set Gemini API key on the left sidebar first.\nImages are downscaled for performance, but just to be safe,\ndo not select wallpapers with sensitive information.") @@ -88,9 +115,9 @@ ContentPage { ConfigSwitch { buttonIcon: "airwave" text: Translation.tr("Use old sine wave cookie implementation") - checked: Config.options.background.clock.cookie.useSineCookie + checked: Config.options.background.widgets.clock.cookie.useSineCookie onCheckedChanged: { - Config.options.background.clock.cookie.useSineCookie = checked; + Config.options.background.widgets.clock.cookie.useSineCookie = checked; } StyledToolTip { text: "Looks a bit softer and more consistent with different number of sides,\nbut has less impressive morphing" @@ -100,21 +127,21 @@ ContentPage { ConfigSpinBox { icon: "add_triangle" text: Translation.tr("Sides") - value: Config.options.background.clock.cookie.sides + value: Config.options.background.widgets.clock.cookie.sides from: 0 to: 40 stepSize: 1 onValueChanged: { - Config.options.background.clock.cookie.sides = value; + Config.options.background.widgets.clock.cookie.sides = value; } } ConfigSwitch { buttonIcon: "autoplay" text: Translation.tr("Constantly rotate") - checked: Config.options.background.clock.cookie.constantlyRotate + checked: Config.options.background.widgets.clock.cookie.constantlyRotate onCheckedChanged: { - Config.options.background.clock.cookie.constantlyRotate = checked; + Config.options.background.widgets.clock.cookie.constantlyRotate = checked; } StyledToolTip { text: "Makes the clock always rotate. This is extremely expensive\n(expect 50% usage on Intel UHD Graphics) and thus impractical." @@ -124,15 +151,15 @@ ContentPage { ConfigRow { ConfigSwitch { - enabled: Config.options.background.clock.style === "cookie" && Config.options.background.clock.cookie.dialNumberStyle === "dots" || Config.options.background.clock.cookie.dialNumberStyle === "full" + enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle === "dots" || Config.options.background.widgets.clock.cookie.dialNumberStyle === "full" buttonIcon: "brightness_7" text: Translation.tr("Hour marks") - checked: Config.options.background.clock.cookie.hourMarks + checked: Config.options.background.widgets.clock.cookie.hourMarks onEnabledChanged: { - checked = Config.options.background.clock.cookie.hourMarks; + checked = Config.options.background.widgets.clock.cookie.hourMarks; } onCheckedChanged: { - Config.options.background.clock.cookie.hourMarks = checked; + Config.options.background.widgets.clock.cookie.hourMarks = checked; } StyledToolTip { text: "Can only be turned on using the 'Dots' or 'Full' dial style for aesthetic reasons" @@ -140,15 +167,15 @@ ContentPage { } ConfigSwitch { - enabled: Config.options.background.clock.style === "cookie" && Config.options.background.clock.cookie.dialNumberStyle !== "numbers" + enabled: Config.options.background.widgets.clock.style === "cookie" && Config.options.background.widgets.clock.cookie.dialNumberStyle !== "numbers" buttonIcon: "timer_10" text: Translation.tr("Digits in the middle") - checked: Config.options.background.clock.cookie.timeIndicators + checked: Config.options.background.widgets.clock.cookie.timeIndicators onEnabledChanged: { - checked = Config.options.background.clock.cookie.timeIndicators; + checked = Config.options.background.widgets.clock.cookie.timeIndicators; } onCheckedChanged: { - Config.options.background.clock.cookie.timeIndicators = checked; + Config.options.background.widgets.clock.cookie.timeIndicators = checked; } StyledToolTip { text: "Can't be turned on when using 'Numbers' dial style for aesthetic reasons" @@ -158,17 +185,17 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Dial style") ConfigSelectionArray { - currentValue: Config.options.background.clock.cookie.dialNumberStyle + currentValue: Config.options.background.widgets.clock.cookie.dialNumberStyle onSelected: newValue => { - Config.options.background.clock.cookie.dialNumberStyle = newValue; + Config.options.background.widgets.clock.cookie.dialNumberStyle = newValue; if (newValue !== "dots" && newValue !== "full") { - Config.options.background.clock.cookie.hourMarks = false; + Config.options.background.widgets.clock.cookie.hourMarks = false; } if (newValue === "numbers") { - Config.options.background.clock.cookie.timeIndicators = false; + Config.options.background.widgets.clock.cookie.timeIndicators = false; } } options: [ @@ -197,12 +224,12 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Hour hand") ConfigSelectionArray { - currentValue: Config.options.background.clock.cookie.hourHandStyle + currentValue: Config.options.background.widgets.clock.cookie.hourHandStyle onSelected: newValue => { - Config.options.background.clock.cookie.hourHandStyle = newValue; + Config.options.background.widgets.clock.cookie.hourHandStyle = newValue; } options: [ { @@ -230,13 +257,13 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Minute hand") ConfigSelectionArray { - currentValue: Config.options.background.clock.cookie.minuteHandStyle + currentValue: Config.options.background.widgets.clock.cookie.minuteHandStyle onSelected: newValue => { - Config.options.background.clock.cookie.minuteHandStyle = newValue; + Config.options.background.widgets.clock.cookie.minuteHandStyle = newValue; } options: [ { @@ -269,13 +296,13 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Second hand") ConfigSelectionArray { - currentValue: Config.options.background.clock.cookie.secondHandStyle + currentValue: Config.options.background.widgets.clock.cookie.secondHandStyle onSelected: newValue => { - Config.options.background.clock.cookie.secondHandStyle = newValue; + Config.options.background.widgets.clock.cookie.secondHandStyle = newValue; } options: [ { @@ -303,13 +330,13 @@ ContentPage { } ContentSubsection { - visible: Config.options.background.clock.style === "cookie" + visible: Config.options.background.widgets.clock.style === "cookie" title: Translation.tr("Date style") ConfigSelectionArray { - currentValue: Config.options.background.clock.cookie.dateStyle + currentValue: Config.options.background.widgets.clock.cookie.dateStyle onSelected: newValue => { - Config.options.background.clock.cookie.dateStyle = newValue; + Config.options.background.widgets.clock.cookie.dateStyle = newValue; } options: [ { diff --git a/dots/.config/quickshell/ii/scripts/images/least_busy_region.py b/dots/.config/quickshell/ii/scripts/images/least_busy_region.py index 1d64033c6..b9e1c8963 100755 --- a/dots/.config/quickshell/ii/scripts/images/least_busy_region.py +++ b/dots/.config/quickshell/ii/scripts/images/least_busy_region.py @@ -18,7 +18,7 @@ def center_crop(img, target_w, target_h): y2 = y1 + target_h return img[y1:y2, x1:x2] -def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", horizontal_padding=50, vertical_padding=50): +def find_least_busy_region(image_path, region_width=300, region_height=200, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", horizontal_padding=50, vertical_padding=50, busiest=False): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) if img is None: raise FileNotFoundError(f"Image not found: {image_path}") @@ -77,7 +77,9 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre total += ii[y1-1, x1-1] return total min_var = None + max_var = None min_coords = (horizontal_padding, vertical_padding) + max_coords = (horizontal_padding, vertical_padding) area = region_width * region_height x_start = horizontal_padding y_start = vertical_padding @@ -100,7 +102,13 @@ def find_least_busy_region(image_path, region_width=300, region_height=200, scre if (min_var is None) or (var < min_var): min_var = var min_coords = (x, y) - return min_coords, min_var + if (max_var is None) or (var > max_var): + max_var = var + max_coords = (x, y) + if busiest: + return max_coords, max_var + else: + return min_coords, min_var def find_largest_region(image_path, screen_width=None, screen_height=None, verbose=False, stride=2, screen_mode="fill", threshold=100.0, aspect_ratio=1.0, horizontal_padding=50, vertical_padding=50): img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) @@ -313,6 +321,7 @@ def main(): parser.add_argument("--aspect-ratio", type=float, default=1.78, help="Aspect ratio (width/height) for largest region mode") parser.add_argument("--horizontal-padding", "-hp", type=int, default=50, help="Minimum horizontal distance from region to image edge") parser.add_argument("--vertical-padding", "-vp", type=int, default=50, help="Minimum vertical distance from region to image edge") + parser.add_argument("--busiest", action="store_true", help="Find the busiest region instead of the least busy") args = parser.parse_args() if args.largest_region: @@ -363,7 +372,8 @@ def main(): stride=args.stride, screen_mode=args.screen_mode, horizontal_padding=args.horizontal_padding, - vertical_padding=args.vertical_padding + vertical_padding=args.vertical_padding, + busiest=args.busiest ) if args.visual_output: draw_region(args.image_path, coords, region_width=args.width, region_height=args.height, screen_width=args.screen_width, screen_height=args.screen_height, screen_mode=args.screen_mode)