calendar
This commit is contained in:
+50
-49
@@ -1,55 +1,56 @@
|
|||||||
import Quickshell.Io
|
import Quickshell.Io
|
||||||
|
|
||||||
JsonObject {
|
JsonObject {
|
||||||
property Popouts popouts: Popouts {}
|
property Popouts popouts: Popouts {}
|
||||||
|
|
||||||
property list<var> entries: [
|
property list<var> entries: [
|
||||||
{
|
{
|
||||||
id: "workspaces",
|
id: "workspaces",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "audio",
|
id: "audio",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "resources",
|
id: "resources",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "updates",
|
id: "updates",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "spacer",
|
id: "spacer",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "activeWindow",
|
id: "activeWindow",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "spacer",
|
id: "spacer",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "tray",
|
id: "tray",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "clock",
|
id: "clock",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "notifBell",
|
id: "notifBell",
|
||||||
enabled: true
|
enabled: true
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
component Popouts: JsonObject {
|
component Popouts: JsonObject {
|
||||||
property bool tray: true
|
property bool tray: true
|
||||||
property bool audio: true
|
property bool audio: true
|
||||||
property bool activeWindow: false
|
property bool activeWindow: false
|
||||||
property bool resources: true
|
property bool resources: true
|
||||||
}
|
property bool clock: true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,99 @@
|
|||||||
|
pragma Singleton
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
Singleton {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
property int displayMonth: new Date().getMonth()
|
||||||
|
property int displayYear: new Date().getFullYear()
|
||||||
|
readonly property int weekStartDay: 1 // 0 = Sunday, 1 = Monday
|
||||||
|
|
||||||
|
function getWeeksForMonth(month: int, year: int): var {
|
||||||
|
const firstDayOfMonth = new Date(year, month, 1);
|
||||||
|
const lastDayOfMonth = new Date(year, month + 1, 0);
|
||||||
|
|
||||||
|
const days = [];
|
||||||
|
let currentDate = new Date(year, month, 1);
|
||||||
|
|
||||||
|
// Back up to the start of the first week (Sunday or Monday based on locale)
|
||||||
|
const dayOfWeek = firstDayOfMonth.getDay();
|
||||||
|
const daysToBackup = (dayOfWeek - root.weekStartDay + 7) % 7;
|
||||||
|
currentDate.setDate(currentDate.getDate() - daysToBackup);
|
||||||
|
|
||||||
|
// Collect all days, including padding from previous/next month to complete the weeks
|
||||||
|
while (true) {
|
||||||
|
days.push({
|
||||||
|
day: currentDate.getDate(),
|
||||||
|
month: currentDate.getMonth(),
|
||||||
|
year: currentDate.getFullYear(),
|
||||||
|
isCurrentMonth: currentDate.getMonth() === month,
|
||||||
|
isToday: isDateToday(currentDate)
|
||||||
|
});
|
||||||
|
|
||||||
|
currentDate.setDate(currentDate.getDate() + 1);
|
||||||
|
|
||||||
|
// Stop after we've completed a full week following the last day of the month
|
||||||
|
if (currentDate > lastDayOfMonth && days.length % 7 === 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return days;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWeekNumbers(month: int, year: int): var {
|
||||||
|
const days = getWeeksForMonth(month, year);
|
||||||
|
const weekNumbers = [];
|
||||||
|
let lastWeekNumber = -1;
|
||||||
|
|
||||||
|
for (let i = 0; i < days.length; i++) {
|
||||||
|
// Only add week numbers for days that belong to the current month
|
||||||
|
if (days[i].isCurrentMonth) {
|
||||||
|
const dayDate = new Date(days[i].year, days[i].month, days[i].day);
|
||||||
|
const weekNumber = getISOWeekNumber(dayDate);
|
||||||
|
|
||||||
|
// Only push if this is a new week
|
||||||
|
if (weekNumber !== lastWeekNumber) {
|
||||||
|
weekNumbers.push(weekNumber);
|
||||||
|
lastWeekNumber = weekNumber;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return weekNumbers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getISOWeekNumber(date: var): int {
|
||||||
|
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
|
||||||
|
const dayNum = d.getUTCDay() || 7;
|
||||||
|
d.setUTCDate(d.getUTCDate() + 4 - dayNum);
|
||||||
|
const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
|
||||||
|
return Math.ceil((((d - yearStart) / 86400000) + 1) / 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDateToday(date: var): bool {
|
||||||
|
const today = new Date();
|
||||||
|
return date.getDate() === today.getDate() &&
|
||||||
|
date.getMonth() === today.getMonth() &&
|
||||||
|
date.getFullYear() === today.getFullYear();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getWeekStartIndex(month: int, year: int): int {
|
||||||
|
const today = new Date();
|
||||||
|
if (today.getMonth() !== month || today.getFullYear() !== year) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const days = getWeeksForMonth(month, year);
|
||||||
|
for (let i = 0; i < days.length; i++) {
|
||||||
|
if (days[i].isToday) {
|
||||||
|
// Return the start index of the week containing today
|
||||||
|
return Math.floor(i / 7) * 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,420 @@
|
|||||||
|
import Quickshell.Io
|
||||||
|
|
||||||
|
JsonObject {
|
||||||
|
property list<var> week_0: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_1: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_2: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_3: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_4: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_5: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_6: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_7: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_8: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_9: [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_10:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_11:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_12:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_13:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_14:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_15:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_16:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_17:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_18:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_19:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_20:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_21:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_22:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_23:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_24:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_25:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_26:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_27:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_28:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_29:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_30:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_31:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_32:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_33:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_34:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_35:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_36:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_37:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_38:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_39:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_40:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_41:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_42:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_43:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_44:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_45:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_46:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_47:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_48:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_49:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_50:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
property list<var> week_51:[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
]
|
||||||
|
}
|
||||||
+134
-128
@@ -9,147 +9,153 @@ import qs.Helpers
|
|||||||
import qs.Daemons
|
import qs.Daemons
|
||||||
|
|
||||||
RowLayout {
|
RowLayout {
|
||||||
id: root
|
id: root
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
readonly property int vPadding: 6
|
readonly property int vPadding: 6
|
||||||
required property Wrapper popouts
|
required property Wrapper popouts
|
||||||
required property PanelWindow bar
|
required property PanelWindow bar
|
||||||
|
|
||||||
function checkPopout(x: real): void {
|
function checkPopout(x: real): void {
|
||||||
const ch = childAt(x, height / 2) as WrappedLoader;
|
const ch = childAt(x, height / 2) as WrappedLoader;
|
||||||
|
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
popouts.hasCurrent = false;
|
popouts.hasCurrent = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const id = ch.id;
|
const id = ch.id;
|
||||||
const top = ch.x;
|
const top = ch.x;
|
||||||
const item = ch.item;
|
const item = ch.item;
|
||||||
const itemWidth = item.implicitWidth;
|
const itemWidth = item.implicitWidth;
|
||||||
|
|
||||||
|
|
||||||
if (id === "audio" && Config.barConfig.popouts.audio) {
|
if (id === "audio" && Config.barConfig.popouts.audio) {
|
||||||
popouts.currentName = "audio";
|
popouts.currentName = "audio";
|
||||||
popouts.currentCenter = Qt.binding( () => item.mapToItem(root, itemWidth / 2, 0 ).x );
|
popouts.currentCenter = Qt.binding( () => item.mapToItem(root, itemWidth / 2, 0 ).x );
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
} else if ( id === "resources" && Config.barConfig.popouts.resources ) {
|
} else if ( id === "resources" && Config.barConfig.popouts.resources ) {
|
||||||
popouts.currentName = "resources";
|
popouts.currentName = "resources";
|
||||||
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
} else if ( id === "tray" && Config.barConfig.popouts.tray ) {
|
} else if ( id === "tray" && Config.barConfig.popouts.tray ) {
|
||||||
const index = Math.floor((( x - top ) / item.implicitWidth ) * item.items.count );
|
const index = Math.floor((( x - top ) / item.implicitWidth ) * item.items.count );
|
||||||
const trayItem = item.items.itemAt( index );
|
const trayItem = item.items.itemAt( index );
|
||||||
if ( trayItem ) {
|
if ( trayItem ) {
|
||||||
popouts.currentName = `traymenu${ index }`;
|
popouts.currentName = `traymenu${ index }`;
|
||||||
popouts.currentCenter = Qt.binding( () => trayItem.mapToItem( root, trayItem.implicitWidth / 2, 0 ).x );
|
popouts.currentCenter = Qt.binding( () => trayItem.mapToItem( root, trayItem.implicitWidth / 2, 0 ).x );
|
||||||
popouts.hasCurrent = true;
|
popouts.hasCurrent = true;
|
||||||
} else {
|
} else {
|
||||||
popouts.hasCurrent = false;
|
popouts.hasCurrent = false;
|
||||||
}
|
}
|
||||||
}
|
} else if ( id === "clock" && Config.barConfig.popouts.clock ) {
|
||||||
}
|
Calendar.displayYear = new Date().getFullYear();
|
||||||
|
Calendar.displayMonth = new Date().getMonth();
|
||||||
|
popouts.currentName = "calendar";
|
||||||
|
popouts.currentCenter = Qt.binding( () => item.mapToItem( root, itemWidth / 2, 0 ).x );
|
||||||
|
popouts.hasCurrent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Repeater {
|
Repeater {
|
||||||
id: repeater
|
id: repeater
|
||||||
model: Config.barConfig.entries
|
model: Config.barConfig.entries
|
||||||
|
|
||||||
DelegateChooser {
|
DelegateChooser {
|
||||||
role: "id"
|
role: "id"
|
||||||
|
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "spacer"
|
roleValue: "spacer"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "workspaces"
|
roleValue: "workspaces"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: Workspaces {
|
sourceComponent: Workspaces {
|
||||||
bar: root.bar
|
bar: root.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "audio"
|
roleValue: "audio"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: AudioWidget {}
|
sourceComponent: AudioWidget {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "tray"
|
roleValue: "tray"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: TrayWidget {
|
sourceComponent: TrayWidget {
|
||||||
bar: root.bar
|
bar: root.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "resources"
|
roleValue: "resources"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: Resources {}
|
sourceComponent: Resources {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "updates"
|
roleValue: "updates"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: UpdatesWidget {}
|
sourceComponent: UpdatesWidget {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "notifBell"
|
roleValue: "notifBell"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: NotifBell {}
|
sourceComponent: NotifBell {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "clock"
|
roleValue: "clock"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: Clock {}
|
sourceComponent: Clock {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DelegateChoice {
|
DelegateChoice {
|
||||||
roleValue: "activeWindow"
|
roleValue: "activeWindow"
|
||||||
delegate: WrappedLoader {
|
delegate: WrappedLoader {
|
||||||
sourceComponent: WindowTitle {}
|
sourceComponent: WindowTitle {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component WrappedLoader: Loader {
|
component WrappedLoader: Loader {
|
||||||
required property bool enabled
|
required property bool enabled
|
||||||
required property string id
|
required property string id
|
||||||
required property int index
|
required property int index
|
||||||
|
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
|
|
||||||
function findFirstEnabled(): Item {
|
function findFirstEnabled(): Item {
|
||||||
const count = repeater.count;
|
const count = repeater.count;
|
||||||
for (let i = 0; i < count; i++) {
|
for (let i = 0; i < count; i++) {
|
||||||
const item = repeater.itemAt(i);
|
const item = repeater.itemAt(i);
|
||||||
if (item?.enabled)
|
if (item?.enabled)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findLastEnabled(): Item {
|
function findLastEnabled(): Item {
|
||||||
for (let i = repeater.count - 1; i >= 0; i--) {
|
for (let i = repeater.count - 1; i >= 0; i--) {
|
||||||
const item = repeater.itemAt(i);
|
const item = repeater.itemAt(i);
|
||||||
if (item?.enabled)
|
if (item?.enabled)
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
|
Layout.leftMargin: findFirstEnabled() === this ? root.vPadding : 0
|
||||||
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
|
Layout.rightMargin: findLastEnabled() === this ? root.vPadding : 0
|
||||||
|
|
||||||
visible: enabled
|
visible: enabled
|
||||||
active: enabled
|
active: enabled
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredWidth: 40
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
color: "transparent"
|
||||||
|
radius: 1000
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: "◀"
|
||||||
|
font.pointSize: 12
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
onClicked: {
|
||||||
|
if (Calendar.displayMonth === 0) {
|
||||||
|
Calendar.displayMonth = 11;
|
||||||
|
Calendar.displayYear -= 1;
|
||||||
|
} else {
|
||||||
|
Calendar.displayMonth -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: new Date(Calendar.displayYear, Calendar.displayMonth, 1).toLocaleDateString(
|
||||||
|
Qt.locale(),
|
||||||
|
"MMMM yyyy"
|
||||||
|
)
|
||||||
|
font.weight: 600
|
||||||
|
font.pointSize: 14
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
Layout.fillWidth: true
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
Layout.preferredWidth: 40
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
color: "transparent"
|
||||||
|
radius: 1000
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
text: "▶"
|
||||||
|
font.pointSize: 12
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
anchors.centerIn: parent
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
onClicked: {
|
||||||
|
if (Calendar.displayMonth === 11) {
|
||||||
|
Calendar.displayMonth = 0;
|
||||||
|
Calendar.displayYear += 1;
|
||||||
|
} else {
|
||||||
|
Calendar.displayMonth += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property Item wrapper
|
||||||
|
|
||||||
|
implicitWidth: layout.childrenRect.width + layout.anchors.margins * 2
|
||||||
|
implicitHeight: layout.childrenRect.height + layout.anchors.margins * 2
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: layout
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors.margins: 16
|
||||||
|
spacing: 16
|
||||||
|
|
||||||
|
// Header with month/year and navigation
|
||||||
|
CalendarHeader {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar grid
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
spacing: 12
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
Layout.preferredWidth: weekNumberColumn.width
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.preferredHeight: dayOfWeekRow.height
|
||||||
|
}
|
||||||
|
|
||||||
|
WeekNumberColumn {
|
||||||
|
id: weekNumberColumn
|
||||||
|
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.preferredHeight: weekNumbers.values.length * 44
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
Layout.alignment: Qt.AlignTop
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
spacing: 8
|
||||||
|
|
||||||
|
DayOfWeekRow {
|
||||||
|
id: dayOfWeekRow
|
||||||
|
locale: Qt.locale()
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 30
|
||||||
|
}
|
||||||
|
|
||||||
|
MonthGrid {
|
||||||
|
locale: Qt.locale()
|
||||||
|
|
||||||
|
wrapper: root.wrapper
|
||||||
|
Layout.preferredWidth: childrenRect.width
|
||||||
|
Layout.preferredHeight: childrenRect.height
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var locale
|
||||||
|
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: 7
|
||||||
|
|
||||||
|
Item {
|
||||||
|
required property int index
|
||||||
|
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 30
|
||||||
|
|
||||||
|
readonly property string dayName: {
|
||||||
|
// Get the day name for this column
|
||||||
|
const dayIndex = (index + Calendar.weekStartDay) % 7;
|
||||||
|
return root.locale.dayName(dayIndex, Locale.ShortFormat);
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
text: parent.dayName
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
opacity: 0.8
|
||||||
|
font.weight: 500
|
||||||
|
font.pointSize: 11
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
GridLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
required property var locale
|
||||||
|
required property Item wrapper
|
||||||
|
|
||||||
|
columns: 7
|
||||||
|
rowSpacing: 4
|
||||||
|
columnSpacing: 4
|
||||||
|
uniformCellWidths: true
|
||||||
|
uniformCellHeights: true
|
||||||
|
|
||||||
|
component Anim: NumberAnimation {
|
||||||
|
target: root
|
||||||
|
duration: MaterialEasing.expressiveEffectsTime
|
||||||
|
easing.bezierCurve: MaterialEasing.expressiveEffects
|
||||||
|
}
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
id: repeater
|
||||||
|
model: ScriptModel {
|
||||||
|
values: Calendar.getWeeksForMonth(Calendar.displayMonth, Calendar.displayYear)
|
||||||
|
|
||||||
|
Behavior on values {
|
||||||
|
SequentialAnimation {
|
||||||
|
id: switchAnim
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
from: 1.0
|
||||||
|
to: 0.0
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
property: "scale"
|
||||||
|
from: 1.0
|
||||||
|
to: 0.8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PropertyAction {}
|
||||||
|
ParallelAnimation {
|
||||||
|
Anim {
|
||||||
|
property: "opacity"
|
||||||
|
from: 0.0
|
||||||
|
to: 1.0
|
||||||
|
}
|
||||||
|
Anim {
|
||||||
|
property: "scale"
|
||||||
|
from: 0.8
|
||||||
|
to: 1.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
|
||||||
|
required property var modelData
|
||||||
|
required property int index
|
||||||
|
|
||||||
|
Layout.preferredWidth: 40
|
||||||
|
Layout.preferredHeight: width
|
||||||
|
|
||||||
|
|
||||||
|
radius: 1000
|
||||||
|
color: {
|
||||||
|
if (modelData.isToday) {
|
||||||
|
console.log(width);
|
||||||
|
return DynamicColors.palette.m3primaryContainer;
|
||||||
|
}
|
||||||
|
return "transparent";
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
text: parent.modelData.day.toString()
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
opacity: parent.modelData.isCurrentMonth ? 1.0 : 0.4
|
||||||
|
color: {
|
||||||
|
if (parent.modelData.isToday) {
|
||||||
|
return DynamicColors.palette.m3onPrimaryContainer;
|
||||||
|
}
|
||||||
|
return DynamicColors.palette.m3onSurface;
|
||||||
|
}
|
||||||
|
|
||||||
|
Behavior on color {
|
||||||
|
ColorAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
Behavior on opacity {
|
||||||
|
NumberAnimation { duration: 200 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StateLayer {
|
||||||
|
color: DynamicColors.palette.m3onSurface
|
||||||
|
onClicked: {
|
||||||
|
console.log(`Selected date: ${parent.modelData.day}/${parent.modelData.month + 1}/${parent.modelData.year}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
|
import Quickshell
|
||||||
|
import QtQuick
|
||||||
|
import QtQuick.Layouts
|
||||||
|
import qs.Components
|
||||||
|
import qs.Config
|
||||||
|
import qs.Helpers
|
||||||
|
|
||||||
|
ColumnLayout {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
spacing: 4
|
||||||
|
|
||||||
|
readonly property var weekNumbers: Calendar.getWeekNumbers(Calendar.displayMonth, Calendar.displayYear)
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: ScriptModel {
|
||||||
|
values: root.weekNumbers
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: weekItem
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
Layout.preferredWidth: 20
|
||||||
|
Layout.alignment: Qt.AlignHCenter
|
||||||
|
|
||||||
|
required property int index
|
||||||
|
required property var modelData
|
||||||
|
|
||||||
|
CustomText {
|
||||||
|
id: weekText
|
||||||
|
|
||||||
|
anchors.centerIn: parent
|
||||||
|
|
||||||
|
text: weekItem.modelData
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
color: DynamicColors.palette.m3onSurfaceVariant
|
||||||
|
opacity: 0.5
|
||||||
|
font.pointSize: 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import Quickshell
|
|||||||
import Quickshell.Services.SystemTray
|
import Quickshell.Services.SystemTray
|
||||||
import QtQuick
|
import QtQuick
|
||||||
import qs.Config
|
import qs.Config
|
||||||
|
import qs.Modules.Calendar
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
id: root
|
id: root
|
||||||
@@ -69,6 +70,13 @@ Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Popout {
|
||||||
|
name: "calendar"
|
||||||
|
sourceComponent: CalendarPopup {
|
||||||
|
wrapper: root.wrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
component Popout: Loader {
|
component Popout: Loader {
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ WlSessionLockSurface {
|
|||||||
onTextChanged: text = ""
|
onTextChanged: text = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ScreencopyView {
|
ScreencopyView {
|
||||||
id: background
|
id: background
|
||||||
|
|
||||||
@@ -84,14 +83,11 @@ WlSessionLockSurface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Image {
|
CachingImage {
|
||||||
id: backgroundImage
|
id: backgroundImage
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
asynchronous: false
|
asynchronous: false
|
||||||
cache: false
|
path: WallpaperPath.currentWallpaperPath
|
||||||
source: WallpaperPath.currentWallpaperPath
|
|
||||||
sourceSize.width: root.screen.width
|
|
||||||
sourceSize.height: root.screen.height
|
|
||||||
visible: Config.lock.useWallpaper
|
visible: Config.lock.useWallpaper
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Calendar cache generator for z-bar-qt
|
||||||
|
Generates a JSON file containing date numbers for all 52 weeks of 3 years (last, current, next)
|
||||||
|
Structure: { "2024": { "week_0": [1,2,3,4,5,6,7], ... }, "2025": {...}, ... }
|
||||||
|
"""
|
||||||
|
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def get_week_start_day():
|
||||||
|
"""Returns the first day of the week (0=Sunday, 1=Monday, etc.) - hardcoded to Monday"""
|
||||||
|
return 1 # Monday
|
||||||
|
|
||||||
|
|
||||||
|
def get_weeks_for_year(year, week_start_day=1):
|
||||||
|
"""
|
||||||
|
Generate week data for a given year.
|
||||||
|
Returns a dict with 52 weeks, each containing 7 date numbers.
|
||||||
|
"""
|
||||||
|
weeks = {}
|
||||||
|
|
||||||
|
# Find the first day of the year
|
||||||
|
jan_1 = datetime(year, 1, 1)
|
||||||
|
|
||||||
|
# Find the first week's start date (adjust based on week_start_day)
|
||||||
|
first_date = jan_1 - timedelta(days=(jan_1.weekday() - week_start_day) % 7)
|
||||||
|
|
||||||
|
# Generate 52 weeks
|
||||||
|
for week_num in range(52):
|
||||||
|
week_dates = []
|
||||||
|
week_start = first_date + timedelta(weeks=week_num)
|
||||||
|
|
||||||
|
for day_offset in range(7):
|
||||||
|
current_date = week_start + timedelta(days=day_offset)
|
||||||
|
week_dates.append(current_date.day)
|
||||||
|
|
||||||
|
weeks[f"week_{week_num}"] = week_dates
|
||||||
|
|
||||||
|
return weeks
|
||||||
|
|
||||||
|
|
||||||
|
def generate_calendar_cache(year=None):
|
||||||
|
"""Generate cache for last year, current year, and next year"""
|
||||||
|
if year is None:
|
||||||
|
year = datetime.now().year
|
||||||
|
|
||||||
|
cache = {}
|
||||||
|
for offset_year in [-1, 0, 1]:
|
||||||
|
target_year = year + offset_year
|
||||||
|
cache[str(target_year)] = get_weeks_for_year(target_year)
|
||||||
|
|
||||||
|
return cache
|
||||||
|
|
||||||
|
|
||||||
|
def write_cache_file(cache_data):
|
||||||
|
"""Write cache to the same location as Paths.cache in QML"""
|
||||||
|
import os
|
||||||
|
|
||||||
|
# Use XDG_CACHE_HOME or ~/.cache, then add /zshell (matching Paths singleton)
|
||||||
|
xdg_cache_home = os.environ.get("XDG_CACHE_HOME")
|
||||||
|
if xdg_cache_home:
|
||||||
|
cache_dir = Path(xdg_cache_home) / "zshell"
|
||||||
|
else:
|
||||||
|
cache_dir = Path.home() / ".cache" / "zshell"
|
||||||
|
|
||||||
|
cache_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
cache_file = cache_dir / "calendar_cache.json"
|
||||||
|
|
||||||
|
with open(cache_file, "w") as f:
|
||||||
|
json.dump(cache_data, f, indent=2)
|
||||||
|
|
||||||
|
print(f"Calendar cache written to: {cache_file}")
|
||||||
|
return cache_file
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
try:
|
||||||
|
# Generate cache for current year and ±1 year
|
||||||
|
cache = generate_calendar_cache()
|
||||||
|
|
||||||
|
# Write to file
|
||||||
|
cache_file = write_cache_file(cache)
|
||||||
|
|
||||||
|
print("Cache structure:")
|
||||||
|
print(" - Keys: year (e.g., '2024', '2025', '2026')")
|
||||||
|
print(" - Values: dict with 52 weeks")
|
||||||
|
print(" - Each week: array of 7 date numbers")
|
||||||
|
print(f"\nExample (first week of 2025):")
|
||||||
|
print(f" {cache['2025']['week_0']}")
|
||||||
|
|
||||||
|
return 0
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Error generating calendar cache: {e}", file=sys.stderr)
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
sys.exit(main())
|
||||||
Reference in New Issue
Block a user