add ClockApplet with locale-aware calendar grid, refactor ClockModule with hover+pin
This commit is contained in:
parent
0e9c1723f2
commit
472b4e62ab
3 changed files with 198 additions and 4 deletions
148
shell/applets/ClockApplet.qml
Normal file
148
shell/applets/ClockApplet.qml
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
import QtQuick
|
||||
import "../services" as S
|
||||
|
||||
Column {
|
||||
id: root
|
||||
|
||||
required property color accentColor
|
||||
required property date currentDate
|
||||
|
||||
readonly property var _locale: Qt.locale()
|
||||
readonly property int _year: currentDate.getFullYear()
|
||||
readonly property int _month: currentDate.getMonth()
|
||||
readonly property int _day: currentDate.getDate()
|
||||
readonly property int _firstDayOfWeek: _locale.firstDayOfWeek
|
||||
|
||||
// Week number (ISO 8601)
|
||||
function _weekNumber(d) {
|
||||
const tmp = new Date(d.getTime());
|
||||
tmp.setHours(0, 0, 0, 0);
|
||||
tmp.setDate(tmp.getDate() + 3 - (tmp.getDay() + 6) % 7);
|
||||
const jan4 = new Date(tmp.getFullYear(), 0, 4);
|
||||
return 1 + Math.round(((tmp.getTime() - jan4.getTime()) / 86400000 - 3 + (jan4.getDay() + 6) % 7) / 7);
|
||||
}
|
||||
|
||||
// Build 6x7 grid of day numbers for the current month view
|
||||
readonly property var _calendarDays: {
|
||||
const first = new Date(_year, _month, 1);
|
||||
const firstDow = first.getDay();
|
||||
// Offset: how many days from previous month to show
|
||||
let offset = (firstDow - _firstDayOfWeek + 7) % 7;
|
||||
const startDate = new Date(_year, _month, 1 - offset);
|
||||
const days = [];
|
||||
for (let i = 0; i < 42; i++) {
|
||||
const d = new Date(startDate.getTime() + i * 86400000);
|
||||
days.push({
|
||||
day: d.getDate(),
|
||||
month: d.getMonth(),
|
||||
year: d.getFullYear(),
|
||||
isCurrentMonth: d.getMonth() === _month,
|
||||
isToday: d.getDate() === _day && d.getMonth() === _month && d.getFullYear() === _year
|
||||
});
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
// Weekday header names (short, locale-aware)
|
||||
readonly property var _dayNames: {
|
||||
const names = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const idx = (_firstDayOfWeek + i) % 7;
|
||||
names.push(_locale.dayName(idx, Locale.NarrowFormat));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
// Date header
|
||||
Item {
|
||||
width: parent.width
|
||||
height: 28
|
||||
|
||||
Text {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: root._locale.standaloneMonthName(root._month, Locale.LongFormat) + " " + root._year
|
||||
color: root.accentColor
|
||||
font.pixelSize: S.Theme.fontSize
|
||||
font.family: S.Theme.fontFamily
|
||||
font.bold: true
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "W" + root._weekNumber(root.currentDate)
|
||||
color: S.Theme.base04
|
||||
font.pixelSize: S.Theme.fontSize - 2
|
||||
font.family: S.Theme.fontFamily
|
||||
}
|
||||
}
|
||||
|
||||
// Day-of-week headers
|
||||
Row {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
Repeater {
|
||||
model: root._dayNames
|
||||
Text {
|
||||
required property string modelData
|
||||
width: Math.floor((root.width - 24) / 7)
|
||||
height: 18
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: modelData
|
||||
color: S.Theme.base04
|
||||
font.pixelSize: S.Theme.fontSize - 3
|
||||
font.family: S.Theme.fontFamily
|
||||
font.bold: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calendar grid (6 rows x 7 cols)
|
||||
Grid {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
columns: 7
|
||||
Repeater {
|
||||
model: root._calendarDays
|
||||
Item {
|
||||
required property var modelData
|
||||
width: Math.floor((root.width - 24) / 7)
|
||||
height: Math.floor((root.width - 24) / 7)
|
||||
|
||||
Rectangle {
|
||||
anchors.centerIn: parent
|
||||
width: Math.min(parent.width, parent.height) - 4
|
||||
height: width
|
||||
radius: width / 2
|
||||
color: modelData.isToday ? root.accentColor : "transparent"
|
||||
}
|
||||
|
||||
Text {
|
||||
anchors.centerIn: parent
|
||||
text: modelData.day
|
||||
color: modelData.isToday ? S.Theme.base00 : modelData.isCurrentMonth ? S.Theme.base05 : S.Theme.base03
|
||||
font.pixelSize: S.Theme.fontSize - 1
|
||||
font.family: S.Theme.fontFamily
|
||||
font.bold: modelData.isToday
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Full date line
|
||||
Text {
|
||||
width: parent.width - 24
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: root.currentDate.toLocaleDateString(root._locale, Locale.LongFormat)
|
||||
color: S.Theme.base04
|
||||
font.pixelSize: S.Theme.fontSize - 2
|
||||
font.family: S.Theme.fontFamily
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 1
|
||||
height: 4
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ module applets
|
|||
# keep-sorted start
|
||||
BacklightApplet 1.0 BacklightApplet.qml
|
||||
BatteryApplet 1.0 BatteryApplet.qml
|
||||
ClockApplet 1.0 ClockApplet.qml
|
||||
CpuApplet 1.0 CpuApplet.qml
|
||||
DiskApplet 1.0 DiskApplet.qml
|
||||
GpuApplet 1.0 GpuApplet.qml
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue