Split clocks out into multiple files

This commit is contained in:
Corey Woodworth
2025-10-29 21:00:15 -04:00
parent 3db3226b6f
commit 04d89905cf
4 changed files with 238 additions and 193 deletions
+135
View File
@@ -0,0 +1,135 @@
import QtQuick
import qs.Commons
import Quickshell
Item {
property var now
anchors.fill: parent
Canvas {
id: clockCanvas
anchors.fill: parent
property int hours: now.getHours()
property int minutes: now.getMinutes()
property int seconds: now.getSeconds()
property real markAlpha: 0.7
property color secondHandColor: {
var defaultColor = Color.mError
var backgroundL = Color.mPrimary.hslLightness
var hourMarkL = (Color.mOnPrimary.hslLightness * markAlpha) + (backgroundL *(1.0-markAlpha))
var bestWorstContrast = -1
var bestColor = defaultColor
var candidates = [
Color.mSecondary,
Color.mTertiary,
Color.mError,
]
for (var i = 0; i < candidates.length; i++) {
var candidateColor = candidates[i]
var candidateL = candidateColor.hslLightness
var diffBackground = Math.abs(backgroundL - candidateL)
var diffHourMark = Math.abs(hourMarkL - candidateL)
var currentWorstContrast = Math.min(diffBackground, diffHourMark)
if (currentWorstContrast > bestWorstContrast) {
bestWorstContrast = currentWorstContrast
bestColor = candidateColor
}
}
return bestColor
}
onPaint: {
var ctx = getContext("2d")
ctx.reset()
ctx.translate(width / 2, height / 2)
var radius = Math.min(width, height) / 2
// Hour marks
ctx.strokeStyle = Qt.alpha(Color.mOnPrimary, markAlpha)
ctx.lineWidth = 2 * Style.uiScaleRatio
var scaleFactor = 0.7
for (var i = 0; i < 12; i++) {
var scaleFactor = 0.8
if (i % 3 === 0) {
scaleFactor = 0.65
}
ctx.save()
ctx.rotate(i * Math.PI / 6)
ctx.beginPath()
ctx.moveTo(0, -radius * scaleFactor)
ctx.lineTo(0, -radius)
ctx.stroke()
ctx.restore()
}
// Hour hand
ctx.save()
var hourAngle = (hours % 12 + minutes / 60) * Math.PI / 6
ctx.rotate(hourAngle)
ctx.strokeStyle = Color.mOnPrimary
ctx.lineWidth = 3 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius * 0.6)
ctx.stroke()
ctx.restore()
// Minute hand
ctx.save()
var minuteAngle = (minutes + seconds / 60) * Math.PI / 30
ctx.rotate(minuteAngle)
ctx.strokeStyle = Color.mOnPrimary
ctx.lineWidth = 2 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius * 0.9)
ctx.stroke()
ctx.restore()
// Second hand
ctx.save()
var secondAngle = seconds * Math.PI / 30
ctx.rotate(secondAngle)
ctx.strokeStyle = secondHandColor
ctx.lineWidth = 1.6 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius)
ctx.stroke()
ctx.restore()
// Center dot
ctx.beginPath()
ctx.arc(0, 0, 3 * Style.uiScaleRatio, 0, 2 * Math.PI)
ctx.fillStyle = Color.mOnPrimary
ctx.fill()
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: {
clockCanvas.hours = now.getHours()
clockCanvas.minutes = now.getMinutes()
clockCanvas.seconds = now.getSeconds()
clockCanvas.requestPaint()
}
}
Component.onCompleted: requestPaint()
}
}
+2 -193
View File
@@ -215,204 +215,13 @@ NPanel {
}
// Analog clock
Item {
id: clockItem
ClockLoader {
anchors.right: parent.right
anchors.rightMargin: Style.marginM
anchors.verticalCenter: parent.verticalCenter
Layout.alignment: Qt.AlignVCenter
height: Math.round((Style.fontSizeXXXL * 1.9) / 2 * Style.uiScaleRatio) * 2
width: clockItem.height
Canvas {
id: clockCanvas
visible: Settings.data.location.analogClockInCalendar
anchors.fill: parent
property int hours: now.getHours()
property int minutes: now.getMinutes()
property int seconds: now.getSeconds()
property real markAlpha: 0.7
property color secondHandColor: {
var defaultColor = Color.mError
var backgroundL = Color.mPrimary.hslLightness
var hourMarkL = (Color.mOnPrimary.hslLightness * markAlpha) + (backgroundL * (1.0 - markAlpha))
var bestWorstContrast = -1
var bestColor = defaultColor
var candidates = [Color.mSecondary, Color.mTertiary, Color.mError]
for (var i = 0; i < candidates.length; i++) {
var candidateColor = candidates[i]
var candidateL = candidateColor.hslLightness
var diffBackground = Math.abs(backgroundL - candidateL)
var diffHourMark = Math.abs(hourMarkL - candidateL)
var currentWorstContrast = Math.min(diffBackground, diffHourMark)
if (currentWorstContrast > bestWorstContrast) {
bestWorstContrast = currentWorstContrast
bestColor = candidateColor
}
}
return bestColor
}
onPaint: {
var ctx = getContext("2d")
ctx.reset()
ctx.translate(width / 2, height / 2)
var radius = Math.min(width, height) / 2
// Hour marks
ctx.strokeStyle = Qt.alpha(Color.mOnPrimary, markAlpha)
ctx.lineWidth = 2 * Style.uiScaleRatio
var scaleFactor = 0.7
for (var i = 0; i < 12; i++) {
var scaleFactor = 0.8
if (i % 3 === 0) {
scaleFactor = 0.65
}
ctx.save()
ctx.rotate(i * Math.PI / 6)
ctx.beginPath()
ctx.moveTo(0, -radius * scaleFactor)
ctx.lineTo(0, -radius)
ctx.stroke()
ctx.restore()
}
// Hour hand
ctx.save()
var hourAngle = (hours % 12 + minutes / 60) * Math.PI / 6
ctx.rotate(hourAngle)
ctx.strokeStyle = Color.mOnPrimary
ctx.lineWidth = 3 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius * 0.6)
ctx.stroke()
ctx.restore()
// Minute hand
ctx.save()
var minuteAngle = (minutes + seconds / 60) * Math.PI / 30
ctx.rotate(minuteAngle)
ctx.strokeStyle = Color.mOnPrimary
ctx.lineWidth = 2 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius * 0.9)
ctx.stroke()
ctx.restore()
// Second hand
ctx.save()
var secondAngle = seconds * Math.PI / 30
ctx.rotate(secondAngle)
ctx.strokeStyle = secondHandColor
ctx.lineWidth = 1.6 * Style.uiScaleRatio
ctx.lineCap = "round"
ctx.beginPath()
ctx.moveTo(0, 0)
ctx.lineTo(0, -radius)
ctx.stroke()
ctx.restore()
// Center dot
ctx.beginPath()
ctx.arc(0, 0, 3 * Style.uiScaleRatio, 0, 2 * Math.PI)
ctx.fillStyle = Color.mOnPrimary
ctx.fill()
}
Timer {
interval: 1000
running: true
repeat: true
onTriggered: {
clockCanvas.hours = now.getHours()
clockCanvas.minutes = now.getMinutes()
clockCanvas.seconds = now.getSeconds()
clockCanvas.requestPaint()
}
}
Component.onCompleted: requestPaint()
}
// Digital clock's seconds circular progress
Canvas {
id: secondsProgress
visible: !Settings.data.location.analogClockInCalendar
anchors.fill: parent
property real progress: now.getSeconds() / 60
onProgressChanged: requestPaint()
Connections {
target: Time
function onDateChanged() {
const total = now.getSeconds() * 1000 + now.getMilliseconds()
secondsProgress.progress = total / 60000
}
}
onPaint: {
var ctx = getContext("2d")
var centerX = width / 2
var centerY = height / 2
var radius = Math.min(width, height) / 2 - 3
ctx.reset()
// Background circle
ctx.beginPath()
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI)
ctx.lineWidth = 2.5
ctx.strokeStyle = Qt.alpha(Color.mOnPrimary, 0.15)
ctx.stroke()
// Progress arc
ctx.beginPath()
ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + progress * 2 * Math.PI)
ctx.lineWidth = 2.5
ctx.strokeStyle = Color.mOnPrimary
ctx.lineCap = "round"
ctx.stroke()
}
}
// Digital clock
ColumnLayout {
visible: !Settings.data.location.analogClockInCalendar
anchors.centerIn: parent
spacing: -Style.marginXXS
NText {
text: {
var t = Settings.data.location.use12hourFormat ? Qt.locale().toString(now, "hh AP") : Qt.locale().toString(now, "HH")
return t.split(" ")[0]
}
pointSize: Style.fontSizeXS
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
family: Settings.data.ui.fontFixed
Layout.alignment: Qt.AlignHCenter
}
NText {
text: Qt.formatTime(now, "mm")
pointSize: Style.fontSizeXXS
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
family: Settings.data.ui.fontFixed
Layout.alignment: Qt.AlignHCenter
}
}
now: root.now
}
}
+25
View File
@@ -0,0 +1,25 @@
import QtQuick
import qs.Commons
import qs.Services
import Quickshell
Item {
id: clockRoot
property var now
height: Math.round((Style.fontSizeXXXL * 1.9) / 2 * Style.uiScaleRatio) * 2
width: clockRoot.height
Loader {
id: clockLoader
anchors.fill: parent
source: Settings.data.location.analogClockInCalendar ? "AnalogClock.qml" : "DigitalClock.qml"
onLoaded: {
// Bind the loaded item's 'now' property to *this* component's 'now' property
item.now = Qt.binding(function() { return clockRoot.now })
}
}
}
+76
View File
@@ -0,0 +1,76 @@
import QtQuick
import qs.Commons
import Quickshell
Item {
property var now
anchors.fill: parent
// Digital clock's seconds circular progress
Canvas {
id: secondsProgress
visible: !Settings.data.location.analogClockInCalendar
anchors.fill: parent
property real progress: now.getSeconds() / 60
onProgressChanged: requestPaint()
Connections {
target: Time
function onDateChanged() {
const total = now.getSeconds() * 1000 + now.getMilliseconds()
secondsProgress.progress = total / 60000
}
}
onPaint: {
var ctx = getContext("2d")
var centerX = width / 2
var centerY = height / 2
var radius = Math.min(width, height) / 2 - 3
ctx.reset()
// Background circle
ctx.beginPath()
ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI)
ctx.lineWidth = 2.5
ctx.strokeStyle = Qt.alpha(Color.mOnPrimary, 0.15)
ctx.stroke()
// Progress arc
ctx.beginPath()
ctx.arc(centerX, centerY, radius, -Math.PI / 2, -Math.PI / 2 + progress * 2 * Math.PI)
ctx.lineWidth = 2.5
ctx.strokeStyle = Color.mOnPrimary
ctx.lineCap = "round"
ctx.stroke()
}
}
// Digital clock
ColumnLayout {
visible: !Settings.data.location.analogClockInCalendar
anchors.centerIn: parent
spacing: -Style.marginXXS
NText {
text: {
var t = Settings.data.location.use12hourFormat ? Qt.locale().toString(now, "hh AP") : Qt.locale().toString(now, "HH")
return t.split(" ")[0]
}
pointSize: Style.fontSizeXS
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
family: Settings.data.ui.fontFixed
Layout.alignment: Qt.AlignHCenter
}
NText {
text: Qt.formatTime(now, "mm")
pointSize: Style.fontSizeXXS
font.weight: Style.fontWeightBold
color: Color.mOnPrimary
family: Settings.data.ui.fontFixed
Layout.alignment: Qt.AlignHCenter
}
}
}