quickshell/modules/bar/popouts/Calendar.qml
2025-06-10 16:58:12 +02:00

178 lines
No EOL
6.3 KiB
QML

import "root:/widgets"
import "root:/services"
import "root:/config"
import QtQuick
Column {
id: root
spacing: Appearance.spacing.normal
width: 250
property date currentDate: new Date()
property bool isCurrentMonth: true
// Time and Date header
Column {
anchors.horizontalCenter: parent.horizontalCenter
spacing: Appearance.spacing.small
StyledText {
anchors.horizontalCenter: parent.horizontalCenter
text: Qt.formatDateTime(new Date(), "HH:mm:ss")
font.pointSize: Appearance.font.size.larger
font.family: Appearance.font.family.mono
}
Row {
anchors.horizontalCenter: parent.horizontalCenter
spacing: Appearance.spacing.small
StyledText {
text: Qt.formatDateTime(root.currentDate, "yyyy")
font.pointSize: Appearance.font.size.large
font.weight: 700
}
Row {
spacing: Appearance.spacing.small
MaterialIcon {
text: "chevron_left"
color: Colours.palette.m3onSurfaceVariant
MouseArea {
anchors.fill: parent
onClicked: {
monthView.decrementCurrentIndex()
}
}
}
StyledText {
text: Qt.formatDateTime(root.currentDate, "MMMM")
font.pointSize: Appearance.font.size.large
font.weight: 400
color: Colours.palette.m3onSurfaceVariant
}
MaterialIcon {
text: "chevron_right"
color: Colours.palette.m3onSurfaceVariant
MouseArea {
anchors.fill: parent
onClicked: {
monthView.incrementCurrentIndex()
}
}
}
}
}
}
// Calendar grid
Item {
width: 250
height: 200
anchors.horizontalCenter: parent.horizontalCenter
clip: true
ListView {
id: monthView
anchors.fill: parent
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
highlightRangeMode: ListView.StrictlyEnforceRange
highlightMoveDuration: Appearance.anim.durations.normal
highlightMoveVelocity: -1
highlightResizeDuration: Appearance.anim.durations.normal
highlightResizeVelocity: -1
model: 12 // Show all months
currentIndex: new Date().getMonth()
delegate: Grid {
width: monthView.width
height: monthView.height
columns: 7
spacing: Appearance.spacing.small
// Day headers
Repeater {
model: ["Mo", "Tu", "We", "Th", "Fr", "Sa", "Su"]
StyledText {
width: 30
horizontalAlignment: Text.AlignHCenter
text: modelData
font.pointSize: Appearance.font.size.small
color: Colours.palette.m3onSurfaceVariant
}
}
// Calendar days
Repeater {
model: {
const firstDay = new Date(new Date().getFullYear(), monthView.currentIndex, 1);
const lastDay = new Date(new Date().getFullYear(), monthView.currentIndex + 1, 0);
const daysInMonth = lastDay.getDate();
const firstDayOfWeek = firstDay.getDay() || 7; // Convert Sunday (0) to 7
const today = new Date();
let days = [];
// Add empty cells for days before the first of the month
for (let i = 1; i < firstDayOfWeek; i++) {
days.push({ day: "", isCurrentMonth: false });
}
// Add days of the current month
for (let i = 1; i <= daysInMonth; i++) {
const isToday = i === today.getDate() &&
monthView.currentIndex === today.getMonth() &&
new Date().getFullYear() === today.getFullYear();
days.push({
day: i,
isCurrentMonth: true,
isToday: isToday
});
}
return days;
}
Rectangle {
width: 30
height: 30
radius: Appearance.rounding.full
color: modelData.isToday ? Colours.palette.m3primary : "transparent"
StyledText {
anchors.centerIn: parent
text: modelData.day
font.pointSize: Appearance.font.size.small
color: modelData.isToday ?
Colours.palette.m3onPrimary :
modelData.isCurrentMonth ?
Colours.palette.m3onSurface :
Colours.palette.m3outline
}
}
}
}
onCurrentIndexChanged: {
root.currentDate = new Date(new Date().getFullYear(), currentIndex, 1)
root.isCurrentMonth = currentIndex === new Date().getMonth()
}
}
}
// Reset to current month when popout closes
Connections {
target: root.parent
function onVisibleChanged() {
if (!root.parent.visible) {
monthView.currentIndex = new Date().getMonth()
root.currentDate = new Date()
root.isCurrentMonth = true
}
}
}
}