diff --git a/ClockWidget.qml b/ClockWidget.qml index 0df7469..c5c80f2 100644 --- a/ClockWidget.qml +++ b/ClockWidget.qml @@ -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: { diff --git a/Common/CalendarComponent.qml b/Common/CalendarComponent.qml new file mode 100644 index 0000000..60863df --- /dev/null +++ b/Common/CalendarComponent.qml @@ -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; + } + } + } + } + } +} diff --git a/Services/PopUpHover.qml b/Services/PopUpHover.qml index 33a0e2d..c29e4ff 100644 --- a/Services/PopUpHover.qml +++ b/Services/PopUpHover.qml @@ -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 { } } } - } }