Skip to content

Commit d87215b

Browse files
authored
Events patch (#48)
* added events display in day detail and monthly events below calendar. now event data is dummy for testing only * some core logic fixed in javascript. added some of real events for test * adhik mas calculation improved. testing lunar month. # added lunar month in debug. # lunar month is considered to starts from new moon. # lunar adhik and kshaya month calculation improved # resized day day detail modal hight to full if content is more like while opening debug information. * moved fixed events to lunar based events. need more test for lunar based events. if accuracy is identical for available festival data or concisely tithi data then lunar based events works, no need to add fixed events every year. still need to refine events for adhik and kshaya lunar months. * added back fallback calculation with lunar month logic change. * added back bikram fixed events parsing. handling events for holiday too. * changed border for holiday to visible color * debug day difference fix between data driven and computed
1 parent 8a001a2 commit d87215b

File tree

10 files changed

+1480
-394
lines changed

10 files changed

+1480
-394
lines changed

qml/CalendarGrid.qml

Lines changed: 108 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,127 @@ import QtQuick.Controls 2.15
44
import "qrc:/qml/"
55

66
// CalendarGrid.qml
7-
GridLayout {
8-
id: calendarGrid
9-
columns: 7
10-
rowSpacing: 0
11-
columnSpacing: 0
7+
ColumnLayout {
8+
id: calendarGridRoot
129
Layout.fillWidth: true
13-
Layout.fillHeight: true
14-
Layout.margins: 20
15-
Layout.topMargin: 10
1610

11+
// Properties
1712
property alias calendarModel: repeater.model
13+
property alias eventListModel: eventLabel.eventModel
1814
property var theme
1915

16+
// Signals
2017
signal dayClicked(var panchanga)
2118

22-
Repeater {
23-
id: repeater
24-
delegate: Item {
25-
Layout.fillWidth: true
26-
Layout.fillHeight: modelData.type === "day" || modelData.type === "empty"
27-
Layout.preferredHeight: modelData.type === "header" ? 35 : -1
19+
// Components
2820

29-
Loader {
30-
id: delegateLoader
31-
anchors.fill: parent
21+
// Calendar grid layout
22+
GridLayout {
23+
id: calendarGrid
24+
columns: 7
25+
rowSpacing: 0
26+
columnSpacing: 0
27+
Layout.fillWidth: true
28+
Layout.preferredHeight: parent.width
29+
Layout.margins: 10
30+
Layout.topMargin: 10
31+
32+
Repeater {
33+
id: repeater
34+
delegate: Item {
35+
Layout.fillWidth: true
36+
Layout.fillHeight: modelData.type === "day" || modelData.type === "empty"
37+
Layout.preferredHeight: modelData.type === "header" ? 35 : -1
38+
39+
Loader {
40+
id: delegateLoader
41+
anchors.fill: parent
42+
43+
sourceComponent: {
44+
if (modelData.type === "header") {
45+
return headerComponent;
46+
} else if (modelData.type === "day") {
47+
return dayComponent;
48+
} else {
49+
return emptyComponent;
50+
}
51+
}
52+
53+
onLoaded: {
54+
if (modelData.type === "day") {
55+
item.bsDay = modelData.bsDay;
56+
item.adDay = modelData.adDay;
57+
item.tithi = modelData.tithi;
58+
item.isToday = modelData.isToday;
59+
item.isSaturday = modelData.isSaturday;
60+
item.hasEvent = modelData.hasEvent;
61+
item.theme = calendarGridRoot.theme;
62+
63+
var isHoliday = false;
64+
if (modelData.panchanga && modelData.panchanga.events) {
65+
for (var i = 0; i < modelData.panchanga.events.length; i++) {
66+
if (modelData.panchanga.events[i].holiday) {
67+
isHoliday = true;
68+
break;
69+
}
70+
}
71+
}
72+
item.isHoliday = isHoliday;
3273

33-
sourceComponent: {
34-
if (modelData.type === "header") {
35-
return headerComponent;
36-
} else if (modelData.type === "day") {
37-
return dayComponent;
38-
} else { // for "empty" type
39-
return emptyComponent;
74+
item.clicked.connect(function() {
75+
calendarGridRoot.dayClicked(modelData.panchanga)
76+
});
77+
} else if (modelData.type === "header") {
78+
item.text = modelData.text;
79+
item.theme = calendarGridRoot.theme;
80+
item.cellIndex = index;
81+
}
4082
}
4183
}
84+
}
85+
}
86+
}
87+
88+
// Event List Footer
89+
Rectangle {
90+
id: eventFooter
91+
Layout.fillWidth: true
92+
implicitHeight: eventLabel.paintedHeight + 20
93+
color: theme.secondaryBg
94+
radius: 6
95+
visible: eventLabel.eventModel && eventLabel.eventModel.length > 0
96+
97+
Label {
98+
id: eventLabel
99+
anchors.fill: parent
100+
anchors.margins: 10
101+
102+
property var eventModel: [] // Model reference
42103

43-
onLoaded: {
44-
if (modelData.type === "day") {
45-
item.bsDay = modelData.bsDay;
46-
item.adDay = modelData.adDay;
47-
item.tithi = modelData.tithi;
48-
item.isToday = modelData.isToday;
49-
item.isSaturday = modelData.isSaturday;
50-
item.theme = calendarGrid.theme;
51-
item.clicked.connect(function() {
52-
calendarGrid.dayClicked(modelData.panchanga)
53-
});
54-
} else if (modelData.type === "header") {
55-
item.text = modelData.text;
56-
item.theme = calendarGrid.theme;
57-
item.cellIndex = index;
104+
text: {
105+
var str = "";
106+
if (eventModel) {
107+
for (var i = 0; i < eventModel.length; i++) {
108+
var item = eventModel[i];
109+
str += item.bsDay + " :\u00A0" + item.eventName;
110+
if (i < eventModel.length - 1) {
111+
str += "  •  ";
112+
}
58113
}
59114
}
115+
return str;
60116
}
117+
118+
font.pixelSize: 12
119+
color: theme ? theme.secondaryText : "black"
120+
wrapMode: Text.WordWrap
121+
horizontalAlignment: Text.AlignHCenter
122+
verticalAlignment: Text.AlignVCenter
61123
}
62124
}
63125

64126

127+
// Component Definitions
65128
Component {
66129
id: headerComponent
67130
Item {
@@ -78,56 +141,15 @@ GridLayout {
78141
border.color: theme.borderColor
79142
}
80143

81-
Rectangle {
82-
visible: cellIndex === 0
83-
width: headerBackground.radius
84-
height: headerBackground.radius
85-
color: headerBackground.color
86-
anchors.top: parent.top
87-
anchors.right: parent.right
88-
}
89-
Rectangle {
90-
visible: cellIndex === 0
91-
width: headerBackground.radius
92-
height: headerBackground.radius
93-
color: headerBackground.color
94-
anchors.bottom: parent.bottom
95-
anchors.left: parent.left
96-
}
97-
Rectangle {
98-
visible: cellIndex === 6
99-
width: headerBackground.radius
100-
height: headerBackground.radius
101-
color: headerBackground.color
102-
anchors.top: parent.top
103-
anchors.left: parent.left
104-
}
105-
Rectangle {
106-
visible: cellIndex === 6
107-
width: headerBackground.radius
108-
height: headerBackground.radius
109-
color: headerBackground.color
110-
anchors.bottom: parent.bottom
111-
anchors.left: parent.left
112-
}
113-
Rectangle {
114-
visible: cellIndex === 0 || cellIndex === 6
115-
width: headerBackground.radius
116-
height: headerBackground.radius
117-
color: headerBackground.color
118-
anchors.bottom: parent.bottom
119-
anchors.right: parent.right
120-
}
144+
Rectangle { visible: cellIndex === 0; width: headerBackground.radius; height: headerBackground.radius; color: headerBackground.color; anchors.top: parent.top; anchors.right: parent.right }
145+
Rectangle { visible: cellIndex === 0; width: headerBackground.radius; height: headerBackground.radius; color: headerBackground.color; anchors.bottom: parent.bottom; anchors.left: parent.left }
146+
Rectangle { visible: cellIndex === 6; width: headerBackground.radius; height: headerBackground.radius; color: headerBackground.color; anchors.top: parent.top; anchors.left: parent.left }
147+
Rectangle { visible: cellIndex === 6; width: headerBackground.radius; height: headerBackground.radius; color: headerBackground.color; anchors.bottom: parent.bottom; anchors.left: parent.left }
148+
Rectangle { visible: cellIndex === 0 || cellIndex === 6; width: headerBackground.radius; height: headerBackground.radius; color: headerBackground.color; anchors.bottom: parent.bottom; anchors.right: parent.right }
121149

122150
Label {
123151
text: headerItemContainer.text
124-
color: {
125-
if (cellIndex === 6) {
126-
return "#E4080A"
127-
} else {
128-
return theme.accentText;
129-
}
130-
}
152+
color: (cellIndex === 6) ? "#E4080A" : theme.accentText
131153
font.bold: true
132154
font.pixelSize: 14
133155
anchors.centerIn: parent

qml/CalendarLogic.qml

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ QtObject {
1414
property int currentBsYear: 2081
1515
property int currentBsMonthIndex: 1
1616
property var calendarModel: []
17+
property var currentMonthEvents: [] // Holds events for the current month
1718
property string currentBsLabelStr: ""
1819
property string currentAdLabelStr: ""
1920
property string prevMonthName: ""
@@ -59,7 +60,9 @@ QtObject {
5960
}
6061

6162
function renderCalendarByBs(year, monthIndex, preserveAdState = false) {
62-
calendarModel = [];
63+
var newCalendarModel = [];
64+
var eventsByDay = {}; // Use an object to group events by day
65+
6366
currentBsYear = year;
6467
currentBsMonthIndex = monthIndex;
6568
var info = Panchanga.getBikramMonthInfo(year, monthIndex);
@@ -69,23 +72,18 @@ QtObject {
6972
}
7073

7174
if (!preserveAdState) {
72-
// LOGIC to determine the representative AD month
7375
var bsMonthStartDate = Panchanga.fromBikramSambat(year, monthIndex, 1);
7476
var startAdYear = bsMonthStartDate.getUTCFullYear();
7577
var startAdMonth = bsMonthStartDate.getUTCMonth();
76-
7778
var nextAdMonth = (startAdMonth + 1) % 12;
7879
var nextAdYear = (startAdMonth === 11) ? startAdYear + 1 : startAdYear;
7980
var firstOfNextAdMonth = new Date(Date.UTC(nextAdYear, nextAdMonth, 1));
80-
8181
var bsMonthEndDate = Panchanga.fromBikramSambat(year, monthIndex, info.totalDays);
8282

8383
if (firstOfNextAdMonth <= bsMonthEndDate) {
84-
// Prefer the later AD month if its first day is in the BS month.
8584
currentAdYear = nextAdYear;
8685
currentAdMonth = nextAdMonth;
8786
} else {
88-
// Otherwise, use the starting AD month.
8987
currentAdYear = startAdYear;
9088
currentAdMonth = startAdMonth;
9189
}
@@ -98,13 +96,12 @@ QtObject {
9896

9997
var daysInMonth = info.totalDays;
10098
var startDay = info.startDayOfWeek;
101-
var model = [];
10299
var weekdaysNe = ["आइतबार", "सोमबार", "मङ्गलबार", "बुधबार", "बिहीबार", "शुक्रबार", "शनिबार"];
103100
for (var i = 0; i < 7; ++i) {
104-
model.push({ type: "header", text: weekdaysNe[i] });
101+
newCalendarModel.push({ type: "header", text: weekdaysNe[i] });
105102
}
106103
for (i = 0; i < startDay; ++i) {
107-
model.push({ type: "empty" });
104+
newCalendarModel.push({ type: "empty" });
108105
}
109106
for (var day = 1; day <= daysInMonth; ++day) {
110107
var adDate = Panchanga.fromBikramSambat(year, monthIndex, day);
@@ -114,14 +111,45 @@ QtObject {
114111
}
115112
var isToday = adDate.toDateString() === new Date().toDateString();
116113
var isSaturday = (startDay + day - 1) % 7 === 6;
114+
var hasEventForDay = result.events && result.events.length > 0;
115+
116+
if (hasEventForDay) {
117+
var devanagariDay = toDevanagari(day);
118+
if (!eventsByDay[devanagariDay]) {
119+
eventsByDay[devanagariDay] = []; // Initialize array if it doesn't exist
120+
}
121+
for (var j = 0; j < result.events.length; j++) {
122+
eventsByDay[devanagariDay].push(result.events[j].name);
123+
}
124+
}
125+
117126
result.monthName = info.monthName;
118-
model.push({
127+
newCalendarModel.push({
119128
type: "day", bsDay: day, adDay: adDate.getDate(),
120129
tithi: result.tithi, isToday: isToday, isSaturday: isSaturday,
130+
hasEvent: hasEventForDay,
121131
gregorianDate: result.gregorianDate, panchanga: result
122132
});
123133
}
124-
calendarModel = model;
134+
135+
// Process the grouped events
136+
var newMonthEvents = [];
137+
// Sort the days to ensure events are listed in chronological order
138+
var sortedDays = Object.keys(eventsByDay).sort(function(a, b) {
139+
return parseInt(fromDevanagari(a)) - parseInt(fromDevanagari(b));
140+
});
141+
142+
for (i = 0; i < sortedDays.length; i++) {
143+
var bsDay = sortedDays[i];
144+
newMonthEvents.push({
145+
bsDay: bsDay,
146+
eventName: eventsByDay[bsDay].join(", ")
147+
});
148+
}
149+
150+
calendarModel = newCalendarModel;
151+
currentMonthEvents = newMonthEvents;
152+
125153
currentBsLabelStr = toDevanagari(year) + " " + info.monthName;
126154
currentAdLabelStr = getGregorianRange(year, monthIndex);
127155
var prevMonthIndex = monthIndex - 1;
@@ -143,10 +171,8 @@ QtObject {
143171
function renderCalendarByAd(year, monthIndex) {
144172
currentAdYear = year;
145173
currentAdMonth = monthIndex;
146-
147174
var date = new Date(Date.UTC(year, monthIndex, 1));
148175
var bsInfo = Panchanga.calculate(date);
149-
150176
renderCalendarByBs(bsInfo.bsYear, bsInfo.bsMonthIndex, true);
151177
}
152178

0 commit comments

Comments
 (0)