Refactor calendar component

This commit is contained in:
2025-10-10 16:20:31 -03:00
parent dfe55f34af
commit 92a3907b8f
3 changed files with 138 additions and 21 deletions

View File

@@ -1,6 +1,5 @@
import QtQuick
import Quickshell.Widgets
import Quickshell.Io
import qs.Services
import qs.Common
import qs.Common.Styled
@@ -19,8 +18,6 @@ Item {
implicitWidth: clockText.implicitWidth * 1.6
implicitHeight: Theme.heightGaps
property string calendar: ""
StyledText {
id: clockText
@@ -28,22 +25,10 @@ Item {
text: Time.time
}
Process {
id: cal
running: true
command: ["cal", "-S3"]
stdout: StdioCollector {
onStreamFinished: {
clock.calendar = this.text;
}
}
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
onEntered: {
cal.running = true;
PopUpHover.start(clock, "time");
}
onExited: {

View File

@@ -0,0 +1,102 @@
// 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;
}
}
}
}
}
}

View File

@@ -75,13 +75,42 @@ Singleton {
Component {
id: time
StyledText {
property string calendar: (HoverMediator.component.calendar) ? HoverMediator.component.calendar : ""
text: calendar
RowLayout{
id: rowlayoutCalendar
textFormat: Text.AutoText
font.family: Theme.fontFamilyMono
readonly property date now: new Date()
readonly property int prevMonth: now.getMonth() - 1
readonly property int currentMonth: now.getMonth()
readonly property int nextMonth: now.getMonth() + 1
implicitWidth: childrenRect.width
implicitHeight: childrenRect.height
spacing: 20
CalendarComponent {
Layout.fillHeight: true
Layout.fillWidth: true
targetYear: parent.prevMonth < 0 ? parent.now.getFullYear() - 1 : parent.now.getFullYear()
targetMonth: parent.prevMonth < 0 ? 11 : parent.prevMonth
currentDate: parent.now
}
CalendarComponent {
Layout.fillHeight: true
Layout.fillWidth: true
targetYear: parent.now.getFullYear()
targetMonth: parent.currentMonth
currentDate: parent.now
}
CalendarComponent {
Layout.fillHeight: true
Layout.fillWidth: true
targetYear: parent.nextMonth > 11 ? parent.now.getFullYear() + 1 : parent.now.getFullYear()
targetMonth: parent.nextMonth > 11 ? 0 : parent.nextMonth
currentDate: parent.now
}
}
}
@@ -127,9 +156,11 @@ Singleton {
topMargin: Theme.gaps
bottomMargin: Theme.gaps
}
color: Theme.backgroudColor
radius: 25
opacity: 1
Behavior on opacity {
NumberAnimation {
property: "opacity"
@@ -154,6 +185,5 @@ Singleton {
}
}
}
}
}