From ae9a80c1f012686c1f65fce7ce76fdd1b77b0b71 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Wed, 23 Sep 2026 21:08:35 +0200 Subject: ... --- accounts/gkleen@skadhi/shell/quickshell/Clock.qml | 295 ++++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 accounts/gkleen@skadhi/shell/quickshell/Clock.qml (limited to 'accounts/gkleen@skadhi/shell/quickshell/Clock.qml') diff --git a/accounts/gkleen@skadhi/shell/quickshell/Clock.qml b/accounts/gkleen@skadhi/shell/quickshell/Clock.qml new file mode 100644 index 00000000..58a80b8b --- /dev/null +++ b/accounts/gkleen@skadhi/shell/quickshell/Clock.qml @@ -0,0 +1,295 @@ +import QtQml +import QtQuick +import Quickshell +import Custom as Custom +import QtQuick.Controls +import QtQuick.Layouts +import Quickshell.Widgets + +Item { + id: clockItem + + property bool calendarPopup: true + + width: clock.contentWidth + height: parent.height + anchors.verticalCenter: parent.verticalCenter + + WrapperMouseArea { + id: clockMouseArea + + anchors.fill: parent + hoverEnabled: true + enabled: clockItem.calendarPopup + + Item { + anchors.fill: parent + + Text { + id: clock + color: "white" + + anchors.verticalCenter: parent.verticalCenter + + Custom.Chrono { + id: chrono + + onDateChanged: clock.text = format("W{0:%V-%u} {0:%F} {0:%H:%M:%S%Ez}") + } + + font.pointSize: 10 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + } + } + } + + Loader { + id: tooltipLoader + + active: false + + Connections { + target: clockMouseArea + function onContainsMouseChanged() { + if (clockMouseArea.containsMouse) + tooltipLoader.active = true; + } + } + + sourceComponent: PopupWindow { + id: tooltip + + property bool nextVisible: clockMouseArea.containsMouse || tooltipMouseArea.containsMouse + + anchor { + item: clockMouseArea + edges: Edges.Bottom | Edges.Left + } + visible: false + + onNextVisibleChanged: hangTimer.restart() + + Timer { + id: hangTimer + interval: 100 + onTriggered: { + tooltip.visible = tooltip.nextVisible; + if (!tooltip.visible) + tooltipLoader.active = false; + } + } + + implicitWidth: tooltipLayout.childrenRect.width + 16 + implicitHeight: tooltipLayout.childrenRect.height + 16 + color: "black" + + onVisibleChanged: { + yearCalendar.year = chrono.date.getFullYear(); + yearCalendar.angleRem = 0; + } + + WrapperMouseArea { + id: tooltipMouseArea + + hoverEnabled: true + enabled: true + + onWheel: event => yearCalendar.scrollYear(event) + + anchors.fill: parent + + Item { + id: clockTooltipContent + + anchors.fill: parent + + ColumnLayout { + id: tooltipLayout + + anchors { + left: parent.left + top: parent.top + leftMargin: 8 + topMargin: 8 + } + + Text { + id: yearLabel + + horizontalAlignment: Text.AlignHCenter + + font.pointSize: 14 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + color: "white" + + text: yearCalendar.year + + Layout.fillWidth: true + Layout.bottomMargin: 8 + } + + GridLayout { + property int year: chrono.date.getFullYear() + + id: yearCalendar + + columns: 3 + columnSpacing: 16 + rowSpacing: 16 + + Layout.alignment: Qt.AlignHCenter + Layout.fillWidth: false + + property real angleRem: 0 + property real sensitivity: 1 / 120 + + function scrollYear(event) { + angleRem += event.angleDelta.y; + const d = Math.round(angleRem * sensitivity); + yearCalendar.year -= d; + angleRem -= d / sensitivity; + } + + Connections { + target: clockMouseArea + function onWheel(event) { yearCalendar.scrollYear(event); } + } + + Repeater { + model: 12 + + GridLayout { + columns: 2 + + required property int index + property int month: index + + id: monthCalendar + + Layout.alignment: Qt.AlignTop | Qt.AlignRight + Layout.fillWidth: false + + Text { + Layout.column: 1 + Layout.fillWidth: true + + horizontalAlignment: Text.AlignHCenter + + font.pointSize: 10 + font.family: "Fira Sans" + + text: new Date(yearCalendar.year, monthCalendar.month, 1).toLocaleString(Qt.locale("en_DK"), "MMMM") + + color: "#ffead3" + } + + DayOfWeekRow { + locale: grid.locale + + Layout.row: 1 + Layout.column: 1 + Layout.fillWidth: true + + delegate: WrapperItem { + required property string shortName + + width: dowLabel.contentWidth + 6 + + Text { + id: dowLabel + + anchors.fill: parent + + font.pointSize: 10 + font.family: "Fira Sans" + + text: parent.shortName + color: "#ffcc66" + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + } + } + + WeekNumberColumn { + month: grid.month + year: grid.year + locale: grid.locale + + Layout.fillHeight: true + + delegate: Text { + required property int weekNumber + + opacity: { + const simple = new Date(weekNumber == 1 && monthCalendar.month == 12 ? yearCalendar.year + 1 : yearCalendar.year, 0, 1 + (weekNumber - 1) * 7); + const dayOfWeek = simple.getDay(); + const isoWeekStart = simple; + + isoWeekStart.setDate(simple.getDate() - dayOfWeek + 1); + if (dayOfWeek > 4) { + isoWeekStart.setDate(isoWeekStart.getDate() + 7); + } + + for (let i = 0; i < 7; i++) { + const dayInWeek = new Date(isoWeekStart); + dayInWeek.setDate(dayInWeek.getDate() + i); + if (dayInWeek.getMonth() == monthCalendar.month) + return 1; + } + + return 0; + } + + font.pointSize: 10 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + + text: weekNumber + color: "#99ffdd" + + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + } + } + + MonthGrid { + id: grid + + year: yearCalendar.year + month: monthCalendar.month + locale: Qt.locale("en_DK") + + Layout.fillWidth: true + Layout.fillHeight: true + + delegate: Text { + required property var model + + opacity: model.month === monthCalendar.month ? 1 : 0 + + font.pointSize: 10 + font.family: "Fira Sans" + font.features: { "tnum": 1 } + + property bool today: chrono.date.getFullYear() == model.year && chrono.date.getMonth() == model.month && chrono.date.getDate() == model.day + + text: model.day + color: today ? "#ff6699" : "white" + + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + } + } + } + } + } + } + } + } + } + } +} -- cgit v1.2.3