Rearrange for tidier structure (#2212)

This commit is contained in:
clsty
2025-10-16 07:19:55 +08:00
parent 13065d7e5a
commit 8b493e091d
529 changed files with 165 additions and 138 deletions
@@ -0,0 +1,34 @@
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
import QtQuick.Layouts
RippleButton {
id: button
property string day
property int isToday
property bool bold
Layout.fillWidth: false
Layout.fillHeight: false
implicitWidth: 38;
implicitHeight: 38;
toggled: (isToday == 1)
buttonRadius: Appearance.rounding.small
contentItem: StyledText {
anchors.fill: parent
text: day
horizontalAlignment: Text.AlignHCenter
font.weight: bold ? Font.DemiBold : Font.Normal
color: (isToday == 1) ? Appearance.m3colors.m3onPrimary :
(isToday == 0) ? Appearance.colors.colOnLayer1 :
Appearance.colors.colOutlineVariant
Behavior on color {
animation: Appearance.animation.elementMoveFast.colorAnimation.createObject(this)
}
}
}
@@ -0,0 +1,36 @@
import qs.modules.common
import qs.modules.common.widgets
import QtQuick
RippleButton {
id: button
property string buttonText: ""
property string tooltipText: ""
property bool forceCircle: false
implicitHeight: 30
implicitWidth: forceCircle ? implicitHeight : (contentItem.implicitWidth + 10 * 2)
Behavior on implicitWidth {
SmoothedAnimation {
velocity: Appearance.animation.elementMove.velocity
}
}
background.anchors.fill: button
buttonRadius: Appearance.rounding.full
colBackground: Appearance.colors.colLayer2
colBackgroundHover: Appearance.colors.colLayer2Hover
colRipple: Appearance.colors.colLayer2Active
contentItem: StyledText {
text: buttonText
horizontalAlignment: Text.AlignHCenter
font.pixelSize: Appearance.font.pixelSize.larger
color: Appearance.colors.colOnLayer1
}
StyledToolTip {
text: tooltipText
extraVisibleCondition: tooltipText.length > 0
}
}
@@ -0,0 +1,122 @@
import qs.services
import qs.modules.common
import qs.modules.common.widgets
import "./calendar_layout.js" as CalendarLayout
import QtQuick
import QtQuick.Layouts
Item {
// Layout.topMargin: 10
anchors.topMargin: 10
property int monthShift: 0
property var viewingDate: CalendarLayout.getDateInXMonthsTime(monthShift)
property var calendarLayout: CalendarLayout.getCalendarLayout(viewingDate, monthShift === 0)
width: calendarColumn.width
implicitHeight: calendarColumn.height + 10 * 2
Keys.onPressed: (event) => {
if ((event.key === Qt.Key_PageDown || event.key === Qt.Key_PageUp)
&& event.modifiers === Qt.NoModifier) {
if (event.key === Qt.Key_PageDown) {
monthShift++;
} else if (event.key === Qt.Key_PageUp) {
monthShift--;
}
event.accepted = true;
}
}
MouseArea {
anchors.fill: parent
onWheel: (event) => {
if (event.angleDelta.y > 0) {
monthShift--;
} else if (event.angleDelta.y < 0) {
monthShift++;
}
}
}
ColumnLayout {
id: calendarColumn
anchors.centerIn: parent
spacing: 5
// Calendar header
RowLayout {
Layout.fillWidth: true
spacing: 5
CalendarHeaderButton {
clip: true
buttonText: `${monthShift != 0 ? "• " : ""}${viewingDate.toLocaleDateString(Qt.locale(), "MMMM yyyy")}`
tooltipText: (monthShift === 0) ? "" : Translation.tr("Jump to current month")
downAction: () => {
monthShift = 0;
}
}
Item {
Layout.fillWidth: true
Layout.fillHeight: false
}
CalendarHeaderButton {
forceCircle: true
downAction: () => {
monthShift--;
}
contentItem: MaterialSymbol {
text: "chevron_left"
iconSize: Appearance.font.pixelSize.larger
horizontalAlignment: Text.AlignHCenter
color: Appearance.colors.colOnLayer1
}
}
CalendarHeaderButton {
forceCircle: true
downAction: () => {
monthShift++;
}
contentItem: MaterialSymbol {
text: "chevron_right"
iconSize: Appearance.font.pixelSize.larger
horizontalAlignment: Text.AlignHCenter
color: Appearance.colors.colOnLayer1
}
}
}
// Week days row
RowLayout {
id: weekDaysRow
Layout.alignment: Qt.AlignHCenter
Layout.fillHeight: false
spacing: 5
Repeater {
model: CalendarLayout.weekDays
delegate: CalendarDayButton {
day: Translation.tr(modelData.day)
isToday: modelData.today
bold: true
enabled: false
}
}
}
// Real week rows
Repeater {
id: calendarRows
// model: calendarLayout
model: 6
delegate: RowLayout {
Layout.alignment: Qt.AlignHCenter
Layout.fillHeight: false
spacing: 5
Repeater {
model: Array(7).fill(modelData)
delegate: CalendarDayButton {
day: calendarLayout[modelData][index].day
isToday: calendarLayout[modelData][index].today
}
}
}
}
}
}
@@ -0,0 +1,115 @@
const weekDays = [ // MONDAY IS THE FIRST DAY OF THE WEEK :HESRIGHTYOUKNOW:
{ day: 'Mo', today: 0 },
{ day: 'Tu', today: 0 },
{ day: 'We', today: 0 },
{ day: 'Th', today: 0 },
{ day: 'Fr', today: 0 },
{ day: 'Sa', today: 0 },
{ day: 'Su', today: 0 },
]
function checkLeapYear(year) {
return (
year % 400 == 0 ||
(year % 4 == 0 && year % 100 != 0));
}
function getMonthDays(month, year) {
const leapYear = checkLeapYear(year);
if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 31;
if (month == 2 && leapYear) return 29;
if (month == 2 && !leapYear) return 28;
return 30;
}
function getNextMonthDays(month, year) {
const leapYear = checkLeapYear(year);
if (month == 1 && leapYear) return 29;
if (month == 1 && !leapYear) return 28;
if (month == 12) return 31;
if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30;
return 31;
}
function getPrevMonthDays(month, year) {
const leapYear = checkLeapYear(year);
if (month == 3 && leapYear) return 29;
if (month == 3 && !leapYear) return 28;
if (month == 1) return 31;
if ((month <= 7 && month % 2 == 1) || (month >= 8 && month % 2 == 0)) return 30;
return 31;
}
function getDateInXMonthsTime(x) {
var currentDate = new Date(); // Get the current date
if (x == 0) return currentDate; // If x is 0, return the current date
var targetMonth = currentDate.getMonth() + x; // Calculate the target month
var targetYear = currentDate.getFullYear(); // Get the current year
// Adjust the year and month if necessary
targetYear += Math.floor(targetMonth / 12);
targetMonth = (targetMonth % 12 + 12) % 12;
// Create a new date object with the target year and month
var targetDate = new Date(targetYear, targetMonth, 1);
// Set the day to the last day of the month to get the desired date
// targetDate.setDate(0);
return targetDate;
}
function getCalendarLayout(dateObject, highlight) {
if (!dateObject) dateObject = new Date();
const weekday = (dateObject.getDay() + 6) % 7; // MONDAY IS THE FIRST DAY OF THE WEEK
const day = dateObject.getDate();
const month = dateObject.getMonth() + 1;
const year = dateObject.getFullYear();
const weekdayOfMonthFirst = (weekday + 35 - (day - 1)) % 7;
const daysInMonth = getMonthDays(month, year);
const daysInNextMonth = getNextMonthDays(month, year);
const daysInPrevMonth = getPrevMonthDays(month, year);
// Fill
var monthDiff = (weekdayOfMonthFirst == 0 ? 0 : -1);
var toFill, dim;
if(weekdayOfMonthFirst == 0) {
toFill = 1;
dim = daysInMonth;
}
else {
toFill = (daysInPrevMonth - (weekdayOfMonthFirst - 1));
dim = daysInPrevMonth;
}
var calendar = [...Array(6)].map(() => Array(7));
var i = 0, j = 0;
while (i < 6 && j < 7) {
calendar[i][j] = {
"day": toFill,
"today": ((toFill == day && monthDiff == 0 && highlight) ? 1 : (
monthDiff == 0 ? 0 :
-1
))
};
// Increment
toFill++;
if (toFill > dim) { // Next month?
monthDiff++;
if (monthDiff == 0)
dim = daysInMonth;
else if (monthDiff == 1)
dim = daysInNextMonth;
toFill = 1;
}
// Next tile
j++;
if (j == 7) {
j = 0;
i++;
}
}
return calendar;
}