Share one calendar with day selection and a month picker

This commit is contained in:
SirBlob committed 2026-09-24 12:37:27 -04:00
1 parent d59725f193
commit 3164e50b36
10 files changed
+773 -543

No files matched your search

@@ -1,115 +1,42 @@
import QtQuick
import Quickshell.Io
import qs.Commons
import qs.Ui
Item {
id: root
property int monthOffset: 0
property string monthName: ""
property string monthGrid: ""
property bool polling: false
implicitHeight: layout.implicitHeight
implicitHeight: calendar.implicitHeight
function loadMonth() {
if (monthProbe.running) return
monthProbe.running = true
function refreshToday() {
var now = new Date()
if (CalendarModel.keyForDate(now) === CalendarModel.keyForDate(calendar.today)) return
var followToday = calendar.selectionIsToday
calendar.today = now
if (followToday) calendar.goToToday()
}
function shiftMonth(delta) {
root.monthOffset += delta
root.loadMonth()
}
function resetMonth() {
root.monthOffset = 0
root.loadMonth()
}
Process {
id: monthProbe
command: ["bash", "-c",
'first="$(date +%Y-%m-01) ' + root.monthOffset + ' months"; ' +
'date -d "$first" "+%B %Y"; cal $(date -d "$first" "+%m %Y") | sed "1d"']
stdout: StdioCollector {
onStreamFinished: {
var lines = String(text).replace(/\s+$/, "").split("\n")
root.monthName = (lines[0] || "").trim()
root.monthGrid = lines.slice(1).join("\n")
}
}
onPollingChanged: {
if (!polling) return
calendar.today = new Date()
calendar.goToToday()
}
Timer {
interval: 3600000
interval: 60000
running: root.polling
repeat: true
onTriggered: if (root.monthOffset === 0) root.loadMonth()
onTriggered: root.refreshToday()
}
Component.onCompleted: root.loadMonth()
WheelHandler {
onWheel: function(event) {
root.shiftMonth(event.angleDelta.y > 0 ? -1 : 1)
}
}
Column {
id: layout
CalendarView {
id: calendar
width: parent.width
spacing: Style.spaceReal(6)
Item {
width: parent.width
implicitHeight: Math.max(monthLabel.implicitHeight, navigation.implicitHeight)
Text {
id: monthLabel
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: root.monthName
textFormat: Text.PlainText
color: Color.foreground
font.family: Style.font.family
font.pixelSize: Style.font.body
font.bold: true
}
Row {
id: navigation
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: Style.spaceReal(4)
CardIconButton {
icon: "<"
onActivated: root.shiftMonth(-1)
}
CardIconButton {
icon: "Today"
visible: root.monthOffset !== 0
implicitWidth: Style.spaceReal(44)
onActivated: root.resetMonth()
}
CardIconButton {
icon: ">"
onActivated: root.shiftMonth(1)
}
}
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
text: root.monthGrid
textFormat: Text.PlainText
color: Util.alpha(Color.foreground, 0.85)
font.family: Style.font.family
font.pixelSize: Style.font.bodySmall
}
foreground: Color.foreground
fontFamily: Style.font.family
cellSpacing: Style.space(2)
cellWidth: Math.floor((width - cellSpacing * 6) / 7)
cellHeight: Style.space(24)
}
}