Skip to content

Commit 6fef886

Browse files
committed
Fix: day details on day cell click. improved panchanga calculations.
#39 as per [comment](#39 (comment))
1 parent 37ba006 commit 6fef886

File tree

9 files changed

+572
-372
lines changed

9 files changed

+572
-372
lines changed

DayTithiWidget.h

Lines changed: 186 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -4,102 +4,233 @@
44
#include <QWidget>
55
#include <QLabel>
66
#include <QVBoxLayout>
7+
#include <QHBoxLayout>
78
#include <QIcon>
89
#include <QPixmap>
910
#include <QPainter>
1011
#include <QResizeEvent>
1112
#include <QFont>
1213
#include <QFontDatabase>
13-
#include <QtGlobal>
1414
#include <QMouseEvent>
1515
#include <QMessageBox>
16+
#include <QStyleOption>
17+
#include "panchanga.h"
1618
#include "bikram.h"
1719
#include <QDate>
1820
#include "calendarlogic.h"
19-
#include "panchanga.h"
2021

2122
class DayTithiWidget : public QWidget {
2223
Q_OBJECT
2324

2425
public:
25-
explicit DayTithiWidget(const QString &day, const QString &tithi, const QString &englishDay, QWidget *parent = nullptr)
26+
explicit DayTithiWidget(const QString &day = "", const QString &tithi = "", const QString &englishDay = "", QWidget *parent = nullptr)
2627
: QWidget(parent), dayLabelText(day), tithiLabelText(tithi), englishDayLabelText(englishDay) {
2728

28-
// Day number (centered large text)
29-
dayLabel = new QLabel(day, this);
30-
dayLabel->setObjectName("dayLabel");
31-
dayLabel->setAlignment(Qt::AlignCenter);
32-
dayLabel->setStyleSheet("color: black; background-color: transparent;");
29+
setAttribute(Qt::WA_Hover);
30+
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
31+
setMinimumSize(60, 60);
32+
33+
QVBoxLayout *mainLayout = new QVBoxLayout(this);
34+
mainLayout->setContentsMargins(4, 4, 4, 4);
35+
mainLayout->setSpacing(2);
36+
37+
QHBoxLayout *topLayout = new QHBoxLayout();
38+
topLayout->setContentsMargins(0, 0, 0, 0);
39+
topLayout->setSpacing(0);
3340

34-
// English day number (top-right, small, gray)
3541
englishDayLabel = new QLabel(englishDay, this);
36-
englishDayLabel->setObjectName("englishDayLabel");
37-
englishDayLabel->setAlignment(Qt::AlignRight | Qt::AlignTop);
3842
englishDayLabel->setStyleSheet("color:rgb(74, 32, 240); background-color: transparent;");
39-
englishDayLabel->adjustSize();
43+
englishDayLabel->setAlignment(Qt::AlignRight);
44+
topLayout->addStretch();
45+
topLayout->addWidget(englishDayLabel);
46+
47+
dayLabel = new QLabel(day, this);
48+
dayLabel->setAlignment(Qt::AlignCenter);
49+
dayLabel->setStyleSheet("color: black; background-color: transparent;");
50+
dayLabel->setMinimumSize(1, 1);
4051

41-
// Tithi label (bottom left)
4252
tithiLabel = new QLabel(tithi, this);
43-
tithiLabel->setObjectName("tithiLabel");
4453
tithiLabel->setStyleSheet("color: #2563eb; background-color: transparent;");
45-
tithiLabel->setVisible(true);
46-
tithiLabel->adjustSize();
54+
tithiLabel->setAlignment(Qt::AlignLeft);
55+
56+
mainLayout->addLayout(topLayout);
57+
mainLayout->addStretch();
58+
mainLayout->addWidget(dayLabel);
59+
mainLayout->addStretch();
60+
mainLayout->addWidget(tithiLabel);
4761

48-
// Icon label (bottom right)
4962
iconLabel = new QLabel(this);
50-
iconLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
5163
iconLabel->setStyleSheet("background-color: transparent;");
52-
iconLabel->adjustSize();
64+
iconLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
65+
66+
applyResponsiveLayout();
67+
}
68+
69+
void updateLabels(const QString &day, const QString &tithi, const QString &englishDay) {
70+
dayLabel->setText(day);
71+
tithiLabel->setText(tithi);
72+
englishDayLabel->setText(englishDay);
73+
applyResponsiveLayout();
5374
}
5475

5576
void setTodayStyle() {
5677
QFont font = dayLabel->font();
5778
font.setBold(true);
5879
dayLabel->setFont(font);
59-
dayLabel->adjustSize();
60-
int contentWidth = dayLabel->width();
61-
int contentHeight = dayLabel->height();
62-
int maxDimension = qMax(contentWidth, contentHeight);
63-
int dynamicPadding = maxDimension / 3;
64-
int finalPadding = qBound(10, dynamicPadding, 30);
65-
int circleDiameter = maxDimension + (finalPadding * 2);
66-
if (circleDiameter < 40) circleDiameter = 40;
67-
dayLabel->setFixedSize(circleDiameter, circleDiameter);
80+
6881
QString styleSheet = QString(
6982
"QLabel {"
7083
" background-color:rgb(91, 240, 156);"
7184
" color: white;"
72-
" border-radius: %1px;" // Half of the diameter for a circle
73-
" qproperty-alignment: AlignCenter;" // Center the text within the circular area
85+
" border-radius: 50px;"
86+
" qproperty-alignment: AlignCenter;"
7487
"}"
75-
).arg(circleDiameter / 2);
76-
88+
);
7789
dayLabel->setStyleSheet(styleSheet);
90+
applyResponsiveLayout();
7891
}
7992

80-
8193
void setSaturdayStyle() {
8294
dayLabel->setStyleSheet("color: red;");
95+
applyResponsiveLayout();
96+
}
97+
98+
void setNormalStyle() {
99+
dayLabel->setStyleSheet("color: black; background-color: transparent;");
100+
QFont font = dayLabel->font();
101+
font.setBold(false);
102+
dayLabel->setFont(font);
103+
applyResponsiveLayout();
104+
}
105+
106+
void setIcon(const QIcon &icon, qreal opacity = 1.0) {
107+
storedIcon = icon;
108+
storedIconOpacity = opacity;
109+
adjustIconSize();
110+
}
111+
112+
void setSelected(bool selected) {
113+
isSelected = selected;
114+
update();
115+
}
116+
117+
signals:
118+
void dayCellClicked(DayTithiWidget *cell); // use to manage global selection
119+
120+
protected:
121+
void resizeEvent(QResizeEvent *event) override {
122+
QWidget::resizeEvent(event);
123+
applyResponsiveLayout();
124+
}
125+
126+
void mousePressEvent(QMouseEvent *event) override {
127+
if (event->button() == Qt::LeftButton) {
128+
isSelected = true;
129+
update();
130+
emit dayCellClicked(this);
131+
132+
int day = property("gDay").toInt();
133+
int month = property("month").toInt();
134+
int year = property("year").toInt();
135+
136+
QDate gdate(year, month, day);
137+
Bikram bs;
138+
bs.fromGregorian(year, month, day);
139+
140+
std::tm date = {};
141+
date.tm_year = year - 1900;
142+
date.tm_mon = month - 1;
143+
date.tm_mday = day;
144+
145+
TithiResult tithi = calculateTithi(date);
146+
YogaResult yoga = calculateYoga(date);
147+
KaranResult karan = calculateKaran(date);
148+
NakshatraResult nakshatra = calculateNakshatra(date);
149+
RashiResult rashi = calculateRashi(date);
150+
QString sunrise = QString::fromStdString(calculateSunriseOrSunset(date, true));
151+
QString sunset = QString::fromStdString(calculateSunriseOrSunset(date, false));
152+
153+
QString details = QString(
154+
"Gregorian: %1\n"
155+
"Bikram: %2-%3-%4\n"
156+
"Tithi: %5\n"
157+
"Paksha: %6\n"
158+
"Yoga: %7\n"
159+
"Karana: %8\n"
160+
"Nakshatra: %9\n"
161+
"Rashi: %10\n"
162+
"Sunrise: %11\n"
163+
"Sunset: %12")
164+
.arg(gdate.toString("yyyy-MM-dd"))
165+
.arg(convertToNepaliNumerals(bs.getYear()))
166+
.arg(convertToNepaliNumerals(bs.getMonth()))
167+
.arg(convertToNepaliNumerals(bs.getDay()))
168+
.arg(QString::fromStdString(tithi.tithiName))
169+
.arg(QString::fromStdString(tithi.paksha))
170+
.arg(QString::fromStdString(yoga.yogaName))
171+
.arg(QString::fromStdString(karan.karanName))
172+
.arg(QString::fromStdString(nakshatra.nakshatraName))
173+
.arg(QString::fromStdString(rashi.rashiName))
174+
.arg(sunrise)
175+
.arg(sunset);
176+
177+
QMessageBox::information(this, tr("Day Details"), details);
178+
}
179+
QWidget::mousePressEvent(event);
180+
}
181+
182+
bool event(QEvent *event) override {
183+
if (event->type() == QEvent::Enter) {
184+
isHovered = true;
185+
update();
186+
} else if (event->type() == QEvent::Leave) {
187+
isHovered = false;
188+
update();
189+
}
190+
return QWidget::event(event);
191+
}
192+
193+
void paintEvent(QPaintEvent *event) override {
194+
Q_UNUSED(event);
195+
QPainter painter(this);
196+
QColor bgColor = Qt::white;
197+
198+
if (isSelected) {
199+
bgColor = QColor("#bfdbfe"); // light blue
200+
} else if (isHovered) {
201+
bgColor = QColor("#d1fae5"); // light green
202+
}
203+
204+
painter.fillRect(rect(), bgColor);
205+
206+
QStyleOption opt;
207+
opt.init(this);
208+
style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
83209
}
84210

85211
private:
86212
QLabel *dayLabel;
87213
QLabel *tithiLabel;
88214
QLabel *iconLabel;
89215
QLabel *englishDayLabel;
216+
90217
QString dayLabelText;
91218
QString tithiLabelText;
92219
QString englishDayLabelText;
220+
93221
QSize iconSize = QSize(24, 24);
94222
QIcon storedIcon;
95223
qreal storedIconOpacity = 1.0;
224+
225+
bool isHovered = false;
226+
bool isSelected = false;
227+
96228
void adjustIconSize() {
97229
int minSize = qMin(width(), height()) / 4;
98230
iconSize = QSize(minSize + 18, minSize + 18);
99231
iconLabel->setFixedSize(iconSize);
100232
iconLabel->setScaledContents(true);
101233
iconLabel->move(width() - iconSize.width() - 4, height() - iconSize.height() - 4);
102-
// Always re-render from original icon for sharpness
103234
if (!storedIcon.isNull()) {
104235
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
105236
QPixmap pixmap = storedIcon.pixmap(iconSize);
@@ -115,95 +246,43 @@ class DayTithiWidget : public QWidget {
115246
iconLabel->setPixmap(transparentPixmap);
116247
}
117248
}
118-
public:
119-
void setIcon(const QIcon &icon, qreal opacity = 1.0) {
120-
storedIcon = icon;
121-
storedIconOpacity = opacity;
122-
adjustIconSize();
123-
}
124249

125-
protected:
126-
void resizeEvent(QResizeEvent *event) override {
127-
QWidget::resizeEvent(event);
250+
void applyResponsiveLayout() {
128251
int w = width();
129252
int h = height();
130253
int minDim = qMin(w, h);
254+
131255
int dayFontSize = std::max(12, static_cast<int>(minDim * 0.14));
132256
int tithiFontSize = std::max(8, static_cast<int>(minDim * 0.05));
133257
int englishDayFontSize = std::max(8, static_cast<int>(minDim * 0.05));
134-
QString notoFamily = "Noto Sans Devanagari";
135258

136-
// Register font if it's not available
137-
if (!QFontDatabase().families().contains(notoFamily)) {
138-
QFontDatabase::addApplicationFont(":/resources/NotoSansDevanagari-VariableFont_wdth,wght.ttf");
259+
static QString fontFamily;
260+
if (fontFamily.isEmpty()) {
261+
int fontId = QFontDatabase::addApplicationFont(":/resources/NotoSansDevanagari-VariableFont_wdth,wght.ttf");
262+
fontFamily = QFontDatabase::applicationFontFamilies(fontId).value(0, "Noto Sans");
139263
}
140264

141-
// Set label font
142-
QFont labelFont = dayLabel->font();
143-
labelFont.setPointSize(dayFontSize);
144-
labelFont.setFamily(notoFamily);
145-
labelFont.setBold(false);
146-
dayLabel->setFont(labelFont);
265+
QFont dayFont;
266+
dayFont.setFamily(fontFamily);
267+
dayFont.setPointSize(dayFontSize);
268+
dayFont.setBold(dayLabel->font().bold());
269+
dayLabel->setFont(dayFont);
147270

148-
QFont tithiFont = tithiLabel->font();
271+
QFont tithiFont;
149272
tithiFont.setPointSize(tithiFontSize);
150273
tithiFont.setItalic(true);
151274
tithiLabel->setFont(tithiFont);
152-
QFont englishDayFont = englishDayLabel->font();
153-
englishDayFont.setPointSize(englishDayFontSize);
154-
englishDayLabel->setFont(englishDayFont);
155-
// Position labels without adjustSize/repaint
156-
int dayX = 20;
157-
int dayY = (h / 3) - (dayLabel->height() / 2);
158-
dayLabel->move(dayX, dayY);
159-
englishDayLabel->move(width() - englishDayLabel->width() - 6, 6);
160-
tithiLabel->move(6, h - tithiLabel->height() - 6);
275+
276+
QFont englishFont;
277+
englishFont.setPointSize(englishDayFontSize);
278+
englishDayLabel->setFont(englishFont);
279+
280+
dayLabel->adjustSize();
281+
tithiLabel->adjustSize();
282+
englishDayLabel->adjustSize();
283+
161284
adjustIconSize();
162285
}
163-
void mousePressEvent(QMouseEvent *event) override {
164-
if (event->button() == Qt::LeftButton) {
165-
int day = property("gDay").toInt(); // Use actual Gregorian day
166-
int month = property("month").toInt();
167-
int year = property("year").toInt();
168-
// Gregorian date
169-
QDate gdate(year, month, day);
170-
// Bikram date
171-
Bikram bs;
172-
bs.fromGregorian(year, month, day);
173-
int bsYear = bs.getYear();
174-
int bsMonth = bs.getMonth();
175-
int bsDay = bs.getDay();
176-
// Panchanga details
177-
std::tm date = {};
178-
date.tm_year = year - 1900;
179-
date.tm_mon = month - 1;
180-
date.tm_mday = day;
181-
TithiResult tithi = calculateTithi(date);
182-
YogaResult yoga = calculateYoga(date);
183-
KaranResult karan = calculateKaran(date);
184-
NakshatraResult nakshatra = calculateNakshatra(date);
185-
RashiResult rashi = calculateRashi(date);
186-
QString sunrise = QString::fromStdString(calculateSunriseOrSunset(date, true));
187-
QString sunset = QString::fromStdString(calculateSunriseOrSunset(date, false));
188-
// Show details dialog
189-
QString details = QString(
190-
"Gregorian: %1\nBikram: %2-%3-%4\nTithi: %5\nPaksha: %6\nYoga: %7\nKarana: %8\nNakshatra: %9\nRashi: %10\nSunrise: %11\nSunset: %12")
191-
.arg(QString::number(gdate.year()) + "-" + QString::number(gdate.month()).rightJustified(2, '0') + "-" + QString::number(gdate.day()).rightJustified(2, '0'))
192-
.arg(convertToNepaliNumerals(bsYear)).arg(convertToNepaliNumerals(bsMonth)).arg(convertToNepaliNumerals(bsDay))
193-
.arg(QString::fromStdString(tithi.tithiName))
194-
.arg(QString::fromStdString(tithi.paksha))
195-
.arg(QString::fromStdString(yoga.yogaName))
196-
.arg(QString::fromStdString(karan.karanName))
197-
.arg(QString::fromStdString(nakshatra.nakshatraName))
198-
.arg(QString::fromStdString(rashi.rashiName))
199-
.arg(sunrise)
200-
.arg(sunset);
201-
QWidget *topLevel = this->window();
202-
QMessageBox::information(topLevel, tr("Day Details"), details);
203-
}
204-
QWidget::mousePressEvent(event);
205-
}
206-
207286
};
208287

209288
#endif // DAYTITHIWIDGET_H

0 commit comments

Comments
 (0)