forked from Shinonome/dots-hyprland
Rearrange for tidier structure (#2212)
This commit is contained in:
@@ -0,0 +1,480 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions as CF
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell
|
||||
import Quickshell.Io
|
||||
import Quickshell.Wayland
|
||||
import Quickshell.Hyprland
|
||||
|
||||
import "./cookieClock"
|
||||
|
||||
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: Math.max(0, Math.min(1, Config.options.background.parallax.clockFactor)) // 0 = full parallax, 1 = no parallax
|
||||
model: Quickshell.screens
|
||||
|
||||
PanelWindow {
|
||||
id: bgRoot
|
||||
|
||||
required property var modelData
|
||||
|
||||
// Hide when fullscreen
|
||||
property list<HyprlandWorkspace> workspacesForMonitor: Hyprland.workspaces.values.filter(workspace => workspace.monitor && workspace.monitor.name == monitor.name)
|
||||
property var activeWorkspaceWithFullscreen: workspacesForMonitor.filter(workspace => ((workspace.toplevels.values.filter(window => window.wayland?.fullscreen)[0] != undefined) && workspace.active))[0]
|
||||
visible: GlobalStates.screenLocked || (!(activeWorkspaceWithFullscreen != undefined)) || !Config?.options.background.hideWhenFullscreen
|
||||
|
||||
// Workspaces
|
||||
property HyprlandMonitor monitor: Hyprland.monitorFor(modelData)
|
||||
property list<var> relevantWindows: HyprlandData.windowList.filter(win => win.monitor == monitor?.id && win.workspace.id >= 0).sort((a, b) => a.workspace.id - b.workspace.id)
|
||||
property int firstWorkspaceId: relevantWindows[0]?.workspace.id || 1
|
||||
property int lastWorkspaceId: relevantWindows[relevantWindows.length - 1]?.workspace.id || 10
|
||||
// Wallpaper
|
||||
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))
|
||||
return enabled && sensitiveWallpaper && sensitiveNetwork;
|
||||
}
|
||||
property real wallpaperToScreenRatio: Math.min(wallpaperWidth / screen.width, wallpaperHeight / screen.height)
|
||||
property real preferredWallpaperScale: Config.options.background.parallax.workspaceZoom
|
||||
property real effectiveWallpaperScale: 1 // Some reasonable init value, to be updated
|
||||
property int wallpaperWidth: modelData.width // Some reasonable init value, to be updated
|
||||
property int wallpaperHeight: modelData.height // Some reasonable init value, to be updated
|
||||
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
|
||||
property bool dominantColorIsDark: dominantColor.hslLightness < 0.5
|
||||
property color colText: {
|
||||
if (wallpaperSafetyTriggered)
|
||||
return CF.ColorUtils.mix(Appearance.colors.colOnLayer0, Appearance.colors.colPrimary, 0.75);
|
||||
return (GlobalStates.screenLocked && shouldBlur) ? Appearance.colors.colOnLayer0 : CF.ColorUtils.colorWithLightness(Appearance.colors.colPrimary, (dominantColorIsDark ? 0.8 : 0.12));
|
||||
}
|
||||
Behavior on colText {
|
||||
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||
}
|
||||
|
||||
// Layer props
|
||||
screen: modelData
|
||||
exclusionMode: ExclusionMode.Ignore
|
||||
WlrLayershell.layer: (GlobalStates.screenLocked && !scaleAnim.running) ? WlrLayer.Overlay : WlrLayer.Bottom
|
||||
// WlrLayershell.layer: WlrLayer.Bottom
|
||||
WlrLayershell.namespace: "quickshell:background"
|
||||
anchors {
|
||||
top: true
|
||||
bottom: true
|
||||
left: true
|
||||
right: true
|
||||
}
|
||||
color: CF.ColorUtils.transparentize(CF.ColorUtils.mix(Appearance.colors.colLayer0, Appearance.colors.colPrimary, 0.75), (bgRoot.wallpaperIsVideo ? 1 : 0))
|
||||
Behavior on color {
|
||||
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
|
||||
}
|
||||
|
||||
onWallpaperPathChanged: {
|
||||
bgRoot.updateZoomScale();
|
||||
// Clock position gets updated after zoom scale is updated
|
||||
}
|
||||
|
||||
// Wallpaper zoom scale
|
||||
function updateZoomScale() {
|
||||
getWallpaperSizeProc.path = bgRoot.wallpaperPath;
|
||||
getWallpaperSizeProc.running = true;
|
||||
}
|
||||
Process {
|
||||
id: getWallpaperSizeProc
|
||||
property string path: bgRoot.wallpaperPath
|
||||
command: ["magick", "identify", "-format", "%w %h", path]
|
||||
stdout: StdioCollector {
|
||||
id: wallpaperSizeOutputCollector
|
||||
onStreamFinished: {
|
||||
const output = wallpaperSizeOutputCollector.text;
|
||||
const [width, height] = output.split(" ").map(Number);
|
||||
const [screenWidth, screenHeight] = [bgRoot.screen.width, bgRoot.screen.height];
|
||||
bgRoot.wallpaperWidth = width;
|
||||
bgRoot.wallpaperHeight = height;
|
||||
|
||||
if (width <= screenWidth || height <= screenHeight) {
|
||||
// Undersized/perfectly sized wallpapers
|
||||
bgRoot.effectiveWallpaperScale = Math.max(screenWidth / width, screenHeight / height);
|
||||
} else {
|
||||
// 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
|
||||
|
||||
StyledImage {
|
||||
id: wallpaper
|
||||
visible: opacity > 0 && !blurLoader.active
|
||||
opacity: (status === Image.Ready && !bgRoot.wallpaperIsVideo) ? 1 : 0
|
||||
cache: false
|
||||
smooth: false
|
||||
// Range = groups that workspaces span on
|
||||
property int chunkSize: Config?.options.bar.workspaces.shown ?? 10
|
||||
property int lower: Math.floor(bgRoot.firstWorkspaceId / chunkSize) * chunkSize
|
||||
property int upper: Math.ceil(bgRoot.lastWorkspaceId / chunkSize) * chunkSize
|
||||
property int range: upper - lower
|
||||
property real valueX: {
|
||||
let result = 0.5;
|
||||
if (Config.options.background.parallax.enableWorkspace && !bgRoot.verticalParallax) {
|
||||
result = ((bgRoot.monitor.activeWorkspace?.id - lower) / range);
|
||||
}
|
||||
if (Config.options.background.parallax.enableSidebar) {
|
||||
result += (0.15 * GlobalStates.sidebarRightOpen - 0.15 * GlobalStates.sidebarLeftOpen);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
property real valueY: {
|
||||
let result = 0.5;
|
||||
if (Config.options.background.parallax.enableWorkspace && bgRoot.verticalParallax) {
|
||||
result = ((bgRoot.monitor.activeWorkspace?.id - lower) / range);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
property real effectiveValueX: Math.max(0, Math.min(1, valueX))
|
||||
property real effectiveValueY: Math.max(0, Math.min(1, valueY))
|
||||
x: -(bgRoot.movableXSpace) - (effectiveValueX - 0.5) * 2 * bgRoot.movableXSpace
|
||||
y: -(bgRoot.movableYSpace) - (effectiveValueY - 0.5) * 2 * bgRoot.movableYSpace
|
||||
source: bgRoot.wallpaperSafetyTriggered ? "" : bgRoot.wallpaperPath
|
||||
fillMode: Image.PreserveAspectCrop
|
||||
Behavior on x {
|
||||
NumberAnimation {
|
||||
duration: 600
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
Behavior on y {
|
||||
NumberAnimation {
|
||||
duration: 600
|
||||
easing.type: Easing.OutCubic
|
||||
}
|
||||
}
|
||||
sourceSize {
|
||||
width: bgRoot.screen.width * bgRoot.effectiveWallpaperScale * bgRoot.monitor.scale
|
||||
height: bgRoot.screen.height * bgRoot.effectiveWallpaperScale * bgRoot.monitor.scale
|
||||
}
|
||||
width: bgRoot.wallpaperWidth / bgRoot.wallpaperToScreenRatio * bgRoot.effectiveWallpaperScale
|
||||
height: bgRoot.wallpaperHeight / bgRoot.wallpaperToScreenRatio * bgRoot.effectiveWallpaperScale
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: blurLoader
|
||||
active: Config.options.lock.blur.enable && (GlobalStates.screenLocked || scaleAnim.running)
|
||||
anchors.fill: wallpaper
|
||||
scale: GlobalStates.screenLocked ? Config.options.lock.blur.extraZoom : 1
|
||||
Behavior on scale {
|
||||
NumberAnimation {
|
||||
id: scaleAnim
|
||||
duration: 400
|
||||
easing.type: Easing.BezierSpline
|
||||
easing.bezierCurve: Appearance.animationCurves.expressiveDefaultSpatial
|
||||
}
|
||||
}
|
||||
sourceComponent: GaussianBlur {
|
||||
source: wallpaper
|
||||
radius: GlobalStates.screenLocked ? Config.options.lock.blur.radius : 0
|
||||
samples: radius * 2 + 1
|
||||
|
||||
Rectangle {
|
||||
opacity: GlobalStates.screenLocked ? 1 : 0
|
||||
anchors.fill: parent
|
||||
color: CF.ColorUtils.transparentize(Appearance.colors.colLayer0, 0.7)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The clock
|
||||
Loader {
|
||||
id: clockLoader
|
||||
scale: Config.options.background.clock.scale
|
||||
active: Config.options.background.clock.show
|
||||
anchors {
|
||||
left: wallpaper.left
|
||||
top: wallpaper.top
|
||||
horizontalCenter: undefined
|
||||
verticalCenter: undefined
|
||||
leftMargin: {
|
||||
const clockXOnWallpaper = bgRoot.movableXSpace + ((root.fixedClockPosition ? root.fixedClockX : bgRoot.clockX * bgRoot.effectiveWallpaperScale) - implicitWidth / 2)
|
||||
const moveBack = (wallpaper.effectiveValueX * 2 * bgRoot.movableXSpace) * (1 - root.clockParallaxFactor);
|
||||
return clockXOnWallpaper + moveBack;
|
||||
}
|
||||
topMargin: {
|
||||
const clockYOnWallpaper = bgRoot.movableYSpace + ((root.fixedClockPosition ? root.fixedClockY : bgRoot.clockY * bgRoot.effectiveWallpaperScale) - implicitHeight / 2)
|
||||
const moveBack = (wallpaper.effectiveValueY * 2 * bgRoot.movableYSpace) * (1 - root.clockParallaxFactor);
|
||||
return clockYOnWallpaper + moveBack;
|
||||
}
|
||||
Behavior on leftMargin {
|
||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on topMargin {
|
||||
animation: Appearance.animation.elementMove.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
states: State {
|
||||
name: "centered"
|
||||
when: (GlobalStates.screenLocked && Config.options.lock.centerClock) || bgRoot.wallpaperSafetyTriggered
|
||||
AnchorChanges {
|
||||
target: clockLoader
|
||||
anchors {
|
||||
left: undefined
|
||||
right: undefined
|
||||
top: undefined
|
||||
verticalCenter: parent.verticalCenter
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
transitions: Transition {
|
||||
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 {
|
||||
family: Appearance.font.family.main
|
||||
pixelSize: Appearance.font.pixelSize.normal
|
||||
weight: 350
|
||||
italic: true
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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: true
|
||||
}
|
||||
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 {
|
||||
family: Appearance.font.family.main
|
||||
pixelSize: Appearance.font.pixelSize.large
|
||||
weight: Font.Normal
|
||||
}
|
||||
style: Text.Raised
|
||||
styleColor: Appearance.colors.colShadow
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import QtQuick
|
||||
import QtQuick.Layouts
|
||||
import Qt5Compat.GraphicalEffects
|
||||
import Quickshell.Io
|
||||
|
||||
import "./dateIndicator"
|
||||
import "./minuteMarks"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
readonly property string clockStyle: Config.options.background.clock.style
|
||||
|
||||
property real implicitSize: 230
|
||||
|
||||
property color colShadow: Appearance.colors.colShadow
|
||||
property color colBackground: Appearance.colors.colSecondaryContainer
|
||||
property color colOnBackground: ColorUtils.mix(Appearance.colors.colSecondary, Appearance.colors.colSecondaryContainer, 0.15)
|
||||
property color colBackgroundInfo: ColorUtils.mix(Appearance.colors.colPrimary, Appearance.colors.colSecondaryContainer, 0.55)
|
||||
property color colHourHand: Appearance.colors.colPrimary
|
||||
property color colMinuteHand: Appearance.colors.colSecondary
|
||||
property color colSecondHand: Appearance.colors.colTertiary
|
||||
|
||||
readonly property list<string> clockNumbers: DateTime.time.split(/[: ]/)
|
||||
readonly property int clockHour: parseInt(clockNumbers[0]) % 12
|
||||
readonly property int clockMinute: DateTime.clock.minutes
|
||||
readonly property int clockSecond: DateTime.clock.seconds
|
||||
|
||||
implicitWidth: implicitSize
|
||||
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
|
||||
}
|
||||
|
||||
function setClockPreset(category) {
|
||||
if (!Config.options.background.clock.cookie.aiStyling) return;
|
||||
if (category === "") return;
|
||||
print("[Cookie clock] Setting clock preset for category: " + category)
|
||||
// "abstract", "anime", "city", "minimalist", "landscape", "plants", "person", "space"
|
||||
if (category == "abstract") {
|
||||
applyStyle(10, "dots", "fill", "medium", "dot", "bubble")
|
||||
} else if (category == "anime") {
|
||||
applyStyle(12, "dots", "fill", "bold", "dot", "bubble")
|
||||
} else if (category == "city" || category == "space") {
|
||||
applyStyle(23, "full", "hollow", "thin", "classic", "bubble")
|
||||
} else if (category == "minimalist") {
|
||||
applyStyle(6, "none", "fill", "bold", "dot", "hide")
|
||||
} else if (category == "landscape") {
|
||||
applyStyle(14, "full", "hollow", "medium", "classic", "bubble")
|
||||
} else if (category == "plants") {
|
||||
applyStyle(9, "dots", "fill", "bold", "dot", "border")
|
||||
} else if (category == "person") {
|
||||
applyStyle(14, "full", "classic", "classic", "classic", "rect")
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: Config
|
||||
function onReadyChanged() {
|
||||
categoryFileView.path = Directories.generatedWallpaperCategoryPath
|
||||
}
|
||||
}
|
||||
|
||||
FileView {
|
||||
id: categoryFileView
|
||||
path: ""
|
||||
watchChanges: true
|
||||
onFileChanged: reload()
|
||||
onLoaded: {
|
||||
root.setClockPreset(categoryFileView.text().trim())
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow {
|
||||
source: cookie
|
||||
anchors.fill: source
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 1
|
||||
radius: 8
|
||||
samples: radius * 2 + 1
|
||||
color: root.colShadow
|
||||
transparentBorder: true
|
||||
}
|
||||
|
||||
MaterialCookie {
|
||||
id: cookie
|
||||
z: 0
|
||||
implicitSize: root.implicitSize
|
||||
amplitude: implicitSize / 70
|
||||
sides: Config.options.background.clock.cookie.sides
|
||||
color: root.colBackground
|
||||
constantlyRotate: Config.options.background.clock.cookie.constantlyRotate
|
||||
|
||||
// Hour/minutes numbers/dots/lines
|
||||
MinuteMarks {
|
||||
anchors.fill: parent
|
||||
color: root.colOnBackground
|
||||
}
|
||||
|
||||
// Stupid extra hour marks in the middle
|
||||
FadeLoader {
|
||||
id: hourMarksLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.hourMarks
|
||||
sourceComponent: HourMarks {
|
||||
implicitSize: 135 * (1.75 - 0.75 * hourMarksLoader.opacity)
|
||||
color: root.colOnBackground
|
||||
colOnBackground: ColorUtils.mix(root.colBackgroundInfo, root.colOnBackground, 0.5)
|
||||
}
|
||||
}
|
||||
|
||||
// Number column in the middle
|
||||
FadeLoader {
|
||||
id: timeColumnLoader
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.timeIndicators
|
||||
scale: 1.4 - 0.4 * timeColumnLoader.shown
|
||||
Behavior on scale {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
sourceComponent: TimeColumn {
|
||||
color: root.colBackgroundInfo
|
||||
}
|
||||
}
|
||||
|
||||
// Hour hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 1
|
||||
shown: Config.options.background.clock.cookie.hourHandStyle !== "hide"
|
||||
sourceComponent: HourHand {
|
||||
clockHour: root.clockHour
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.hourHandStyle
|
||||
color: root.colHourHand
|
||||
}
|
||||
}
|
||||
|
||||
// Minute hand
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
z: 2
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "hide"
|
||||
sourceComponent: MinuteHand {
|
||||
anchors.fill: parent
|
||||
clockMinute: root.clockMinute
|
||||
style: Config.options.background.clock.cookie.minuteHandStyle
|
||||
color: root.colMinuteHand
|
||||
}
|
||||
}
|
||||
|
||||
// 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"
|
||||
anchors.fill: parent
|
||||
sourceComponent: SecondHand {
|
||||
id: secondHand
|
||||
clockSecond: root.clockSecond
|
||||
style: Config.options.background.clock.cookie.secondHandStyle
|
||||
color: root.colSecondHand
|
||||
}
|
||||
}
|
||||
|
||||
// Center dot
|
||||
FadeLoader {
|
||||
z: 4
|
||||
anchors.centerIn: parent
|
||||
shown: Config.options.background.clock.cookie.minuteHandStyle !== "bold"
|
||||
sourceComponent: Rectangle {
|
||||
color: Config.options.background.clock.cookie.minuteHandStyle === "medium" ? root.colBackground : root.colMinuteHand
|
||||
implicitWidth: 6
|
||||
implicitHeight: implicitWidth
|
||||
radius: width / 2
|
||||
}
|
||||
}
|
||||
|
||||
// Date
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
shown: Config.options.background.clock.cookie.dateStyle !== "hide"
|
||||
|
||||
sourceComponent: DateIndicator {
|
||||
color: root.colBackgroundInfo
|
||||
style: Config.options.background.clock.cookie.dateStyle
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
import Qt5Compat.GraphicalEffects
|
||||
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
readonly property string quoteText: Config.options.background.quote
|
||||
|
||||
implicitWidth: quoteBox.implicitWidth
|
||||
implicitHeight: quoteBox.implicitHeight
|
||||
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -24
|
||||
|
||||
DropShadow {
|
||||
source: quoteBox
|
||||
anchors.fill: quoteBox
|
||||
horizontalOffset: 0
|
||||
verticalOffset: 2
|
||||
radius: 12
|
||||
samples: radius * 2 + 1
|
||||
color: Appearance.colors.colShadow
|
||||
transparentBorder: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: quoteBox
|
||||
|
||||
implicitWidth: quoteStyledText.width + quoteIcon.width + 16 // for spacing on both sides
|
||||
implicitHeight: quoteStyledText.height + 8
|
||||
radius: Appearance.rounding.small
|
||||
color: Appearance.colors.colSecondaryContainer
|
||||
|
||||
Row {
|
||||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
MaterialSymbol {
|
||||
id: quoteIcon
|
||||
anchors.top: parent.top
|
||||
iconSize: Appearance.font.pixelSize.huge
|
||||
text: "format_quote"
|
||||
color: Appearance.colors.colOnSecondaryContainer
|
||||
}
|
||||
StyledText {
|
||||
id: quoteStyledText
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
text: Config.options.background.quote
|
||||
color: Appearance.colors.colOnSecondaryContainer
|
||||
font {
|
||||
family: Appearance.font.family.reading
|
||||
pixelSize: Appearance.font.pixelSize.large
|
||||
weight: Font.Normal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
required property int clockHour
|
||||
required property int clockMinute
|
||||
property real handLength: 72
|
||||
property real handWidth: 18
|
||||
property string style: "fill"
|
||||
property color color: Appearance.colors.colPrimary
|
||||
|
||||
property real fillColorAlpha: root.style === "hollow" ? 0 : 1
|
||||
Behavior on fillColorAlpha {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
rotation: -90 + (360 / 12) * (root.clockHour + root.clockMinute / 60)
|
||||
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: (parent.width - root.handWidth) / 2 - 15 * (root.style === "classic")
|
||||
width: root.handLength
|
||||
height: root.style === "classic" ? 8 : root.handWidth
|
||||
radius: root.style === "classic" ? 2 : root.handWidth / 2
|
||||
color : Qt.rgba(root.color.r, root.color.g, root.color.b, root.fillColorAlpha)
|
||||
border.color: root.color
|
||||
border.width: 4
|
||||
|
||||
Behavior on x {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property real implicitSize: 135
|
||||
property real markLength: 12
|
||||
property real markWidth: 4
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
property color colOnBackground: Appearance.colors.colSecondaryContainer
|
||||
property real padding: 8
|
||||
|
||||
Rectangle {
|
||||
color: root.color
|
||||
anchors.centerIn: parent
|
||||
implicitWidth: root.implicitSize
|
||||
implicitHeight: root.implicitSize
|
||||
radius: width / 2
|
||||
|
||||
// Hour mark lines
|
||||
Repeater {
|
||||
model: 12
|
||||
|
||||
Item {
|
||||
required property int index
|
||||
anchors.fill: parent
|
||||
rotation: 360 / 12 * index
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: root.padding
|
||||
}
|
||||
implicitWidth: root.markLength
|
||||
implicitHeight: root.markWidth
|
||||
|
||||
radius: width / 2
|
||||
color: root.colOnBackground
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
|
||||
required property int clockMinute
|
||||
property string style: "medium"
|
||||
property real handLength: 95
|
||||
property real handWidth: style === "bold" ? 18 : style === "medium" ? 12 : 5
|
||||
property color color: Appearance.colors.colSecondary
|
||||
|
||||
rotation: -90 + (360 / 60) * root.clockMinute
|
||||
|
||||
Behavior on rotation {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
x: {
|
||||
let position = parent.width / 2 - root.handWidth / 2;
|
||||
if (root.style === "classic") position -= 15;
|
||||
return position;
|
||||
}
|
||||
width: root.handLength
|
||||
height: root.handWidth
|
||||
|
||||
radius: root.style === "classic" ? 2 : root.handWidth / 2
|
||||
color: Appearance.colors.colSecondary
|
||||
|
||||
Behavior on height {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
anchors.fill: parent
|
||||
|
||||
required property int clockSecond
|
||||
property real handWidth: 2
|
||||
property real handLength: 100
|
||||
property real dotSize: 20
|
||||
property string style: "hide"
|
||||
property color color: Appearance.colors.colSecondary
|
||||
|
||||
rotation: (360 / 60 * clockSecond) + 90
|
||||
|
||||
Behavior on rotation {
|
||||
enabled: Config.options.background.clock.cookie.constantlyRotate // Animating every second is expensive...
|
||||
animation: NumberAnimation {
|
||||
duration: 1000 // 1 second
|
||||
easing.type: Easing.InOutQuad
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: 10
|
||||
}
|
||||
implicitWidth: root.style === "dot" ? root.dotSize : root.handLength
|
||||
implicitHeight: root.style === "dot" ? root.dotSize : root.handWidth
|
||||
radius: Math.min(width, height) / 2
|
||||
color: root.color
|
||||
Behavior on implicitHeight {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
Behavior on implicitWidth {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
|
||||
// Classic style dot in the middle of the hand
|
||||
FadeLoader {
|
||||
id: classicDotLoader
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
}
|
||||
shown: root.style === "classic"
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: 40
|
||||
}
|
||||
implicitWidth: root.style === "classic" ? 14 : 0
|
||||
implicitHeight: implicitWidth
|
||||
color: root.color
|
||||
radius: Appearance.rounding.small
|
||||
|
||||
Behavior on implicitWidth {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Column {
|
||||
id: root
|
||||
property list<string> clockNumbers: DateTime.time.split(/[: ]/)
|
||||
property bool isEnabled: Config.options.background.clock.cookie.timeIndicators
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
|
||||
property bool hourMarksEnabled: Config.options.background.clock.cookie.hourMarks
|
||||
spacing: -16
|
||||
|
||||
Repeater {
|
||||
model: root.clockNumbers
|
||||
|
||||
delegate: StyledText {
|
||||
required property string modelData
|
||||
text: modelData.padStart(2, "0")
|
||||
property bool isAmPm: !text.match(/\d{2}/i)
|
||||
property real numberSizeWithoutGlow: isAmPm ? 26 : 68
|
||||
property real numberSizeWithGlow: isAmPm ? 20 : 40
|
||||
property real numberSize: root.hourMarksEnabled ? numberSizeWithGlow : numberSizeWithoutGlow
|
||||
|
||||
anchors.horizontalCenter: root.horizontalCenter
|
||||
color: root.color
|
||||
font {
|
||||
family: Appearance.font.family.expressive
|
||||
weight: Font.Bold
|
||||
pixelSize: numberSize
|
||||
}
|
||||
|
||||
Behavior on numberSize {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property bool isMonth: false
|
||||
property real targetSize: 0
|
||||
property alias text: bubbleText.text
|
||||
|
||||
text: Qt.locale().toString(DateTime.clock.date, root.isMonth ? "MM" : "d")
|
||||
|
||||
MaterialCookie {
|
||||
z: 5
|
||||
sides: root.isMonth ? 1 : 4
|
||||
anchors.centerIn: parent
|
||||
color: root.isMonth ? Appearance.colors.colPrimaryContainer : Appearance.colors.colTertiaryContainer
|
||||
implicitSize: targetSize
|
||||
constantlyRotate: Config.options.background.clock.cookie.constantlyRotate
|
||||
}
|
||||
|
||||
StyledText {
|
||||
id: bubbleText
|
||||
z: 6
|
||||
anchors.centerIn: parent
|
||||
color: root.isMonth ? Appearance.colors.colPrimary : Appearance.colors.colTertiary
|
||||
font {
|
||||
family: Appearance.font.family.expressive
|
||||
pixelSize: 30
|
||||
weight: Font.Black
|
||||
}
|
||||
}
|
||||
}
|
||||
+76
@@ -0,0 +1,76 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import qs.modules.common.functions
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property string style: "bubble"
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
property real dateSquareSize: 64
|
||||
|
||||
// Rotating date
|
||||
FadeLoader {
|
||||
anchors.fill: parent
|
||||
shown: Config.options.background.clock.cookie.dateStyle === "border"
|
||||
sourceComponent: RotatingDate {
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
|
||||
// Rectangle date (only today's number) in right side of the clock
|
||||
FadeLoader {
|
||||
id: rectLoader
|
||||
shown: root.style === "rect"
|
||||
anchors {
|
||||
verticalCenter: parent.verticalCenter
|
||||
right: parent.right
|
||||
rightMargin: 40 - rectLoader.opacity * 30
|
||||
}
|
||||
|
||||
sourceComponent: RectangleDate {
|
||||
color: ColorUtils.mix(root.color, Appearance.colors.colSecondaryContainerHover, 0.5)
|
||||
radius: Appearance.rounding.small
|
||||
implicitWidth: 45 * rectLoader.opacity
|
||||
implicitHeight: 30 * rectLoader.opacity
|
||||
}
|
||||
}
|
||||
|
||||
// Bubble style: day of month
|
||||
FadeLoader {
|
||||
id: dayBubbleLoader
|
||||
shown: root.style === "bubble"
|
||||
property real targetSize: root.dateSquareSize * opacity
|
||||
anchors {
|
||||
left: parent.left
|
||||
top: parent.top
|
||||
}
|
||||
|
||||
sourceComponent: BubbleDate {
|
||||
implicitWidth: dayBubbleLoader.targetSize
|
||||
implicitHeight: dayBubbleLoader.targetSize
|
||||
isMonth: false
|
||||
targetSize: dayBubbleLoader.targetSize
|
||||
}
|
||||
}
|
||||
|
||||
// Bubble style: month
|
||||
FadeLoader {
|
||||
id: monthBubbleLoader
|
||||
shown: root.style === "bubble"
|
||||
property real targetSize: root.dateSquareSize * opacity
|
||||
anchors {
|
||||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
|
||||
sourceComponent: BubbleDate {
|
||||
implicitWidth: monthBubbleLoader.targetSize
|
||||
implicitHeight: monthBubbleLoader.targetSize
|
||||
isMonth: true
|
||||
targetSize: monthBubbleLoader.targetSize
|
||||
}
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Rectangle {
|
||||
id: rect
|
||||
readonly property string dialStyle: Config.options.background.clock.cookie.dialNumberStyle
|
||||
|
||||
StyledText {
|
||||
anchors.centerIn: parent
|
||||
color: Appearance.colors.colSecondaryHover
|
||||
text: Qt.locale().toString(DateTime.clock.date, "dd")
|
||||
font {
|
||||
family: Appearance.font.family.expressive
|
||||
pixelSize: 20
|
||||
weight: 1000
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.services
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property string style: Config.options.background.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
|
||||
|
||||
property real radius: style === "border" ? 90 : 0
|
||||
Behavior on radius {
|
||||
animation: Appearance.animation.elementResize.numberAnimation.createObject(this)
|
||||
}
|
||||
|
||||
rotation: {
|
||||
if (!Config.options.time.secondPrecision) return 0
|
||||
else return (360 / 60 * clockSecond) + 180 - (angleStep / Math.PI * 180 * dateText.length) / 2
|
||||
}
|
||||
|
||||
Repeater {
|
||||
model: root.dateText.length
|
||||
|
||||
delegate: Text {
|
||||
required property int index
|
||||
property real angle: index * root.angleStep - Math.PI / 2
|
||||
x: root.width / 2 + root.radius * Math.cos(angle) - width / 2
|
||||
y: root.height / 2 + root.radius * Math.sin(angle) - height / 2
|
||||
rotation: angle * 180 / Math.PI + 90
|
||||
|
||||
color: root.color
|
||||
font {
|
||||
family: Appearance.font.family.title
|
||||
pixelSize: 30
|
||||
weight: Font.DemiBold
|
||||
}
|
||||
|
||||
text: root.dateText.charAt(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property real numberSize: 80
|
||||
property real margins: 10
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
|
||||
property int hours: 12
|
||||
property int numbers: 4
|
||||
property int fontSize: 80
|
||||
|
||||
Repeater {
|
||||
model: root.numbers
|
||||
|
||||
Item {
|
||||
id: numberItem
|
||||
required property int index
|
||||
rotation: 360 / root.numbers * (index + 1)
|
||||
anchors.fill: parent
|
||||
|
||||
Item {
|
||||
implicitWidth: root.numberSize
|
||||
implicitHeight: implicitWidth
|
||||
anchors {
|
||||
top: parent.top
|
||||
horizontalCenter: parent.horizontalCenter
|
||||
topMargin: root.margins
|
||||
}
|
||||
StyledText {
|
||||
color: root.color
|
||||
anchors.centerIn: parent
|
||||
text: root.hours / root.numbers * (numberItem.index + 1)
|
||||
rotation: -numberItem.rotation
|
||||
|
||||
font {
|
||||
family: Appearance.font.family.reading
|
||||
pixelSize: root.fontSize
|
||||
weight: Font.Black
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property real implicitSize: 12
|
||||
property real margins: 10
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
|
||||
Repeater {
|
||||
model: 12
|
||||
|
||||
Item {
|
||||
required property int index
|
||||
anchors.fill: parent // Ensures rotation works properly
|
||||
rotation: 360 / 12 * index
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: root.margins
|
||||
}
|
||||
implicitWidth: root.implicitSize
|
||||
implicitHeight: implicitWidth
|
||||
radius: implicitWidth / 2
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property real numberSize: 80
|
||||
property real margins: 10
|
||||
property color color: Appearance.colors.colOnSecondaryContainer
|
||||
|
||||
property real hourLineSize: 4
|
||||
property real minuteLineSize: 2
|
||||
property real hourLineLength: 18
|
||||
property real minuteLineLength: 7
|
||||
|
||||
property int hours: 12
|
||||
property int minutes: 60
|
||||
|
||||
// Full dial style hour lines
|
||||
Repeater {
|
||||
model: root.hours
|
||||
|
||||
Item {
|
||||
required property int index
|
||||
rotation: 360 / root.hours * index
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: root.margins
|
||||
}
|
||||
implicitWidth: root.hourLineLength
|
||||
implicitHeight: root.hourLineSize
|
||||
radius: implicitWidth / 2
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Minute lines
|
||||
Repeater {
|
||||
model: root.minutes
|
||||
|
||||
Item {
|
||||
required property int index
|
||||
rotation: 360 / root.minutes * index
|
||||
anchors.fill: parent
|
||||
|
||||
Rectangle {
|
||||
anchors {
|
||||
left: parent.left
|
||||
verticalCenter: parent.verticalCenter
|
||||
leftMargin: root.margins
|
||||
}
|
||||
implicitWidth: root.minuteLineLength
|
||||
implicitHeight: root.minuteLineSize
|
||||
radius: implicitWidth / 2
|
||||
color: root.color
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
pragma ComponentBehavior: Bound
|
||||
|
||||
import qs.modules.common
|
||||
import qs.modules.common.widgets
|
||||
import QtQuick
|
||||
|
||||
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
|
||||
|
||||
// 12 Dots
|
||||
FadeLoader {
|
||||
id: dotsLoader
|
||||
anchors.fill: parent
|
||||
shown: root.style === "dots"
|
||||
sourceComponent: Dots {
|
||||
color: root.color
|
||||
margins: 46 - dotsLoader.opacity * 34
|
||||
}
|
||||
}
|
||||
|
||||
// 3-6-9-12 hour numbers (pls don't realize you can have more than 4 numbers)
|
||||
FadeLoader {
|
||||
id: bigHourNumbersLoader
|
||||
anchors.fill: parent
|
||||
shown: root.style === "numbers"
|
||||
sourceComponent: BigHourNumbers {
|
||||
numberSize: 80
|
||||
color: root.color
|
||||
margins: 20 - 10 * bigHourNumbersLoader.opacity
|
||||
}
|
||||
}
|
||||
|
||||
// Lines
|
||||
FadeLoader {
|
||||
id: linesLoader
|
||||
anchors.fill: parent
|
||||
shown: root.style === "full"
|
||||
sourceComponent: Lines {
|
||||
color: root.color
|
||||
margins: 46 - linesLoader.opacity * 34
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user