Files
dotfiles/shell/Ui/CalendarView.qml
T

252 lines
7.4 KiB
QML

import QtQuick
import qs.Commons
import "CalendarModel.js" as CalendarModel
Column {
id: root
property date today: new Date()
property int weekStart: CalendarModel.normalizedWeekStart(null, Qt.locale().firstDayOfWeek)
property color foreground: Color.foreground
property string fontFamily: Style.font.family
property bool showWeekNumbers: false
property bool navigationAtBottom: false
property string weekHeaderTooltip: ""
property real cellWidth: Style.space(36)
property real cellHeight: Style.space(28)
property real cellSpacing: Style.space(2)
property real weekColumnWidth: Style.space(32)
property real gutterWidth: Style.space(14)
property int viewYear: today.getFullYear()
property int viewMonth: today.getMonth()
property int selectedYear: today.getFullYear()
property int selectedMonth: today.getMonth()
property int selectedDay: today.getDate()
property bool pickingMonth: false
property int pickerYear: viewYear
property int pickerMonth: viewMonth
readonly property string todayKey: CalendarModel.keyForDate(today)
readonly property string selectedKey: CalendarModel.dateKey(selectedYear, selectedMonth, selectedDay)
readonly property bool selectionIsToday: selectedKey === todayKey
readonly property bool viewingCurrentMonth: viewYear === today.getFullYear() && viewMonth === today.getMonth()
readonly property date viewDate: new Date(viewYear, viewMonth, 1)
readonly property date selectedDate: new Date(selectedYear, selectedMonth, selectedDay)
readonly property int selectedOffset: CalendarModel.daysBetween(
today.getFullYear(), today.getMonth(), today.getDate(), selectedYear, selectedMonth, selectedDay)
readonly property var labelLocale: Qt.locale("en_US")
readonly property real gridWidth: body.width
readonly property color mutedForeground: Qt.darker(foreground, 1.5)
signal weekHeaderClicked()
spacing: Style.space(8)
function weekdayLabel(weekday) {
return String(labelLocale.dayName(weekday, Locale.ShortFormat)).toUpperCase()
}
function monthLabel(month) {
return String(labelLocale.monthName(month, Locale.ShortFormat)).toUpperCase()
}
function selectDay(year, month, day) {
selectedYear = year
selectedMonth = month
selectedDay = day
viewYear = year
viewMonth = month
pickingMonth = false
}
function goToToday() {
selectDay(today.getFullYear(), today.getMonth(), today.getDate())
}
function moveMonth(delta) {
var next = CalendarModel.stepMonth(viewYear, viewMonth, delta)
selectDay(next.year, next.month, CalendarModel.clampDay(next.year, next.month, selectedDay))
}
function moveYear(delta) {
if (pickingMonth) pickerYear += delta
else moveMonth(delta * 12)
}
function moveSelection(days) {
var next = CalendarModel.stepDay(selectedYear, selectedMonth, selectedDay, days)
selectDay(next.year, next.month, next.day)
}
function movePickerCursor(months) {
var next = CalendarModel.stepMonth(pickerYear, pickerMonth, months)
pickerYear = next.year
pickerMonth = next.month
}
function handleMove(dx, dy) {
if (pickingMonth) movePickerCursor(dx + dy * 4)
else moveSelection(dx + dy * 7)
}
function openPicker() {
pickerYear = viewYear
pickerMonth = viewMonth
pickingMonth = true
}
function togglePicker() {
if (pickingMonth) pickingMonth = false
else openPicker()
}
function choosePickerMonth(year, month) {
selectDay(year, month, CalendarModel.clampDay(year, month, selectedDay))
}
function activate() {
if (pickingMonth) choosePickerMonth(pickerYear, pickerMonth)
else goToToday()
}
function dismissPicker() {
if (!pickingMonth) return false
pickingMonth = false
return true
}
function selectedSummary() {
var format = selectedYear === today.getFullYear() ? "dddd, MMMM d" : "dddd, MMMM d, yyyy"
return Qt.formatDate(selectedDate, format)
+ " · Day " + CalendarModel.dayOfYear(selectedYear, selectedMonth, selectedDay)
+ " · " + CalendarModel.relativeDayLabel(selectedOffset)
}
MonthNavigation {
visible: !root.navigationAtBottom
}
Item {
width: root.width
height: body.height
Item {
id: body
anchors.horizontalCenter: parent.horizontalCenter
width: days.width
height: days.height
CalendarDays {
id: days
calendar: root
visible: !root.pickingMonth
}
CalendarMonthPicker {
anchors.fill: parent
calendar: root
visible: root.pickingMonth
}
WheelHandler {
onWheel: function(event) {
if (event.angleDelta.y === 0) return
var step = event.angleDelta.y > 0 ? -1 : 1
if (root.pickingMonth) root.pickerYear += step
else root.moveMonth(step)
}
}
}
}
Text {
width: root.width
horizontalAlignment: Text.AlignHCenter
textFormat: Text.PlainText
elide: Text.ElideRight
text: root.selectedSummary()
color: root.mutedForeground
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
}
MonthNavigation {
visible: root.navigationAtBottom
}
component MonthNavigation: Item {
width: root.width
height: visible ? navigationLabel.implicitHeight + Style.space(10) : 0
Item {
anchors.horizontalCenter: parent.horizontalCenter
width: body.width
height: parent.height
Rectangle {
anchors.centerIn: navigationLabel
width: navigationLabel.width
height: navigationLabel.implicitHeight + Style.space(6)
radius: Style.cornerRadius
color: navigationMouse.containsMouse ? Style.hoverFillFor(root.foreground, Color.accent) : "transparent"
}
Text {
id: navigationLabel
anchors.centerIn: parent
width: Style.space(150)
horizontalAlignment: Text.AlignHCenter
textFormat: Text.PlainText
text: root.pickingMonth
? String(root.pickerYear)
: Qt.formatDate(root.viewDate, "MMMM yyyy").toUpperCase()
color: navigationMouse.containsMouse
? Style.hoverStateColor(root.foreground, Color.accent)
: Qt.darker(root.foreground, 1.4)
font.family: root.fontFamily
font.pixelSize: Style.font.body
font.letterSpacing: 1
}
MouseArea {
id: navigationMouse
anchors.fill: navigationLabel
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: root.togglePicker()
PanelToolTip {
visible: navigationMouse.containsMouse
text: root.pickingMonth ? "Back to the days" : "Pick a month"
fontFamily: root.fontFamily
}
}
PanelActionButton {
anchors.left: parent.left
anchors.leftMargin: -Style.space(8)
anchors.verticalCenter: parent.verticalCenter
iconText: "󰅁"
tooltipText: root.pickingMonth ? "Previous year" : "Previous month"
foreground: root.foreground
fontFamily: root.fontFamily
onClicked: root.pickingMonth ? root.moveYear(-1) : root.moveMonth(-1)
}
PanelActionButton {
anchors.right: parent.right
anchors.rightMargin: -Style.space(8)
anchors.verticalCenter: parent.verticalCenter
iconText: "󰅂"
tooltipText: root.pickingMonth ? "Next year" : "Next month"
foreground: root.foreground
fontFamily: root.fontFamily
onClicked: root.pickingMonth ? root.moveYear(1) : root.moveMonth(1)
}
}
}
}