103 lines
2.8 KiB
QML
103 lines
2.8 KiB
QML
// CalendarComponent.qml (For one month)
|
|
import QtQuick
|
|
import QtQuick.Controls
|
|
import qs.Common
|
|
import qs.Common.Styled
|
|
|
|
Item {
|
|
id: root
|
|
property int targetYear: new Date().getFullYear()
|
|
property int targetMonth: new Date().getMonth() // 0-11
|
|
property date currentDate: new Date()
|
|
|
|
function getLocalizedDayHeaders() {
|
|
const locale = Qt.locale();
|
|
const headers = [];
|
|
|
|
const firstDay = locale.firstDayOfWeek;
|
|
|
|
for (let i = 0; i < 7; i++) {
|
|
const dayIndex = (firstDay + i) % 7;
|
|
|
|
const dayDate = new Date(1970, 0, 4 + dayIndex);
|
|
headers.push(dayDate.toLocaleString(locale, "ddd").substring(0, 1));
|
|
}
|
|
return headers;
|
|
}
|
|
function getMonthLayout(year, month) {
|
|
let date = new Date(year, month, 1);
|
|
let firstDayOfWeek = date.getDay();
|
|
|
|
let daysInMonth = new Date(year, month + 1, 0).getDate();
|
|
let days = [];
|
|
|
|
for (let i = 0; i < firstDayOfWeek; i++) {
|
|
days.push("");
|
|
}
|
|
|
|
for (let i = 1; i <= daysInMonth; i++) {
|
|
days.push(i);
|
|
}
|
|
|
|
while (days.length % 7 !== 0) {
|
|
days.push("");
|
|
}
|
|
|
|
return {
|
|
monthName: date.toLocaleString(Qt.locale(), "MMMM yyyy"),
|
|
days: days
|
|
};
|
|
}
|
|
|
|
readonly property var layoutData: getMonthLayout(targetYear, targetMonth)
|
|
|
|
implicitWidth: childrenRect.width
|
|
implicitHeight: childrenRect.height
|
|
|
|
Column {
|
|
spacing: 5
|
|
|
|
// Month Title
|
|
StyledText {
|
|
text: root.layoutData.monthName
|
|
font.bold: true
|
|
horizontalAlignment: Text.AlignHCenter
|
|
width: parent.width
|
|
font.family: Theme.fontFamilyMono
|
|
}
|
|
|
|
Grid {
|
|
columns: 7
|
|
rowSpacing: 2
|
|
columnSpacing: 5
|
|
|
|
Repeater {
|
|
model: root.getLocalizedDayHeaders()
|
|
StyledText {
|
|
text: modelData
|
|
horizontalAlignment: Text.AlignHCenter
|
|
width: 18
|
|
font.family: Theme.fontFamilyMono
|
|
}
|
|
}
|
|
|
|
Repeater {
|
|
model: root.layoutData.days
|
|
StyledText {
|
|
text: modelData
|
|
horizontalAlignment: Text.AlignHCenter
|
|
width: 18
|
|
font.family: Theme.fontFamilyMono
|
|
|
|
color: {
|
|
let isCurrentMonth = root.targetYear === root.currentDate.getFullYear() && root.targetMonth === root.currentDate.getMonth();
|
|
let isCurrentDay = isCurrentMonth && modelData === root.currentDate.getDate();
|
|
|
|
return isCurrentDay ? Theme.color6Bright : Theme.textColor;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|