Branch data Line data Source code
1 : : #include "EventDetailPopup.h"
2 : :
3 : : #include "ui/ThemeManager.h"
4 : :
5 : : #include <QFrame>
6 : : #include <QHBoxLayout>
7 : : #include <QKeyEvent>
8 : : #include <QLabel>
9 : : #include <QMessageBox>
10 : : #include <QPushButton>
11 : : #include <QVBoxLayout>
12 : :
13 : 7 : EventDetailPopup::EventDetailPopup(QWidget *parent)
14 : 7 : : QWidget(parent, Qt::Popup | Qt::FramelessWindowHint) {
15 [ + - ]: 14 : setObjectName(QStringLiteral("eventDetailPopup"));
16 [ + - ]: 7 : setAttribute(Qt::WA_DeleteOnClose, false);
17 [ + - ]: 7 : setAttribute(Qt::WA_StyledBackground, true);
18 [ + - ]: 7 : setMinimumWidth(280);
19 [ + - ]: 7 : setMaximumWidth(400);
20 : :
21 [ + - + - : 7 : auto *layout = new QVBoxLayout(this);
- + - - ]
22 [ + - ]: 7 : layout->setContentsMargins(0, 0, 0, 0);
23 [ + - ]: 7 : layout->setSpacing(0);
24 : :
25 : : // T-532: Color bar at top
26 [ + - + - : 7 : m_colorBar = new QFrame(this);
- + - - ]
27 [ + - ]: 14 : m_colorBar->setObjectName(QStringLiteral("eventPopupColorBar"));
28 [ + - ]: 7 : m_colorBar->setFixedHeight(4);
29 : : // Sprint 69: radius moved to main.qss; only dynamic bg stays inline.
30 [ + - ]: 14 : m_colorBar->setStyleSheet(
31 : 14 : QStringLiteral("background: %1;")
32 [ + - + - ]: 14 : .arg(ThemeManager::calendarPalette().constFirst()));
33 [ + - ]: 7 : layout->addWidget(m_colorBar);
34 : :
35 : : // Content area with padding
36 [ + - + - : 7 : auto *content = new QVBoxLayout();
- + - - ]
37 [ + - ]: 7 : content->setContentsMargins(12, 10, 12, 10);
38 [ + - ]: 7 : content->setSpacing(6);
39 : :
40 : : // Title row with action buttons
41 [ + - + - : 7 : auto *titleRow = new QHBoxLayout();
- + - - ]
42 [ + - + - : 7 : m_titleLabel = new QLabel(this);
- + - - ]
43 [ + - ]: 14 : m_titleLabel->setObjectName(QStringLiteral("eventPopupTitle"));
44 [ + - ]: 7 : m_titleLabel->setTextFormat(Qt::PlainText);
45 [ + - ]: 7 : m_titleLabel->setWordWrap(true);
46 [ + - ]: 7 : QFont titleFont = font();
47 [ + - ]: 7 : titleFont.setPointSize(13);
48 [ + - ]: 7 : titleFont.setBold(true);
49 [ + - ]: 7 : m_titleLabel->setFont(titleFont);
50 [ + - ]: 7 : titleRow->addWidget(m_titleLabel, 1);
51 : :
52 : : // Sprint 39: Compact icon-only buttons
53 [ + - ]: 7 : QFont emojiFont(QStringLiteral("Noto Sans"), 14);
54 [ + - + + : 21 : emojiFont.setFamilies({QStringLiteral("Noto Sans"),
- - ]
55 : 7 : QStringLiteral("Noto Color Emoji")});
56 : :
57 [ + - + - : 14 : m_editBtn = new QPushButton(QStringLiteral("\u270f\ufe0f"), this);
- + - - ]
58 [ + - ]: 14 : m_editBtn->setObjectName(QStringLiteral("eventPopupEditButton"));
59 [ + - + - ]: 7 : m_editBtn->setToolTip(tr("Edit"));
60 [ + - + - ]: 7 : m_editBtn->setCursor(Qt::PointingHandCursor);
61 [ + - ]: 7 : m_editBtn->setFixedSize(28, 28);
62 [ + - ]: 7 : m_editBtn->setFont(emojiFont);
63 [ + - ]: 7 : titleRow->addWidget(m_editBtn);
64 : :
65 [ + - + - : 14 : m_deleteBtn = new QPushButton(QStringLiteral("\U0001f5d1\ufe0f"), this);
- + - - ]
66 [ + - ]: 14 : m_deleteBtn->setObjectName(QStringLiteral("eventPopupDeleteButton"));
67 [ + - + - ]: 7 : m_deleteBtn->setToolTip(tr("Delete"));
68 [ + - + - ]: 7 : m_deleteBtn->setCursor(Qt::PointingHandCursor);
69 [ + - ]: 7 : m_deleteBtn->setFixedSize(28, 28);
70 [ + - ]: 7 : m_deleteBtn->setFont(emojiFont);
71 [ + - ]: 7 : titleRow->addWidget(m_deleteBtn);
72 : :
73 [ + - ]: 7 : content->addLayout(titleRow);
74 : :
75 [ + - + - : 7 : m_timeLabel = new QLabel(this);
- + - - ]
76 [ + - ]: 14 : m_timeLabel->setObjectName(QStringLiteral("eventPopupTime"));
77 [ + - ]: 7 : m_timeLabel->setTextFormat(Qt::PlainText);
78 [ + - ]: 7 : content->addWidget(m_timeLabel);
79 : :
80 [ + - + - : 7 : m_locationLabel = new QLabel(this);
- + - - ]
81 [ + - ]: 14 : m_locationLabel->setObjectName(QStringLiteral("eventPopupLocation"));
82 [ + - ]: 7 : m_locationLabel->setTextFormat(Qt::PlainText);
83 [ + - ]: 7 : m_locationLabel->setWordWrap(true);
84 [ + - ]: 7 : content->addWidget(m_locationLabel);
85 : :
86 [ + - + - : 7 : m_calendarLabel = new QLabel(this);
- + - - ]
87 [ + - ]: 14 : m_calendarLabel->setObjectName(QStringLiteral("eventPopupCalendar"));
88 [ + - ]: 7 : m_calendarLabel->setTextFormat(Qt::RichText);
89 [ + - ]: 7 : content->addWidget(m_calendarLabel);
90 : :
91 [ + - + - : 7 : m_descLabel = new QLabel(this);
- + - - ]
92 [ + - ]: 14 : m_descLabel->setObjectName(QStringLiteral("eventPopupDescription"));
93 [ + - ]: 7 : m_descLabel->setTextFormat(Qt::PlainText);
94 [ + - ]: 7 : m_descLabel->setWordWrap(true);
95 [ + - ]: 7 : m_descLabel->setMaximumHeight(200);
96 [ + - ]: 7 : content->addWidget(m_descLabel);
97 [ + - ]: 7 : m_descLabel->hide();
98 : :
99 [ + - ]: 7 : layout->addLayout(content);
100 : :
101 : : // Connections
102 [ + - ]: 7 : connect(m_editBtn, &QPushButton::clicked, this, [this]() {
103 : 1 : hide();
104 : 1 : emit editRequested(m_currentEvent);
105 : 1 : });
106 [ + - ]: 7 : connect(m_deleteBtn, &QPushButton::clicked, this, [this]() {
107 : 0 : hide();
108 : 0 : emit deleteRequested(m_currentEvent);
109 : 0 : });
110 : :
111 : : // Popup styling lives in main.qss (67.B3): #eventDetailPopup and the
112 : : // eventPopup* object names.
113 : :
114 [ + - ]: 7 : installEventFilter(this);
115 [ + - - - : 28 : }
- - ]
116 : :
117 : 6 : void EventDetailPopup::showEvent(const CalendarEvent &event,
118 : : const QPoint &globalPos) {
119 : 6 : m_currentEvent = event;
120 [ + - ]: 6 : m_titleLabel->setText(event.summary);
121 : :
122 : : // T-532: Color bar
123 : 6 : QColor evColor(event.color.isEmpty()
124 [ + - + + : 10 : ? ThemeManager::calendarPalette().constFirst()
- - ]
125 [ + + ]: 10 : : event.color);
126 : : // Sprint 69: radius moved to main.qss; only dynamic bg stays inline.
127 [ + - ]: 12 : m_colorBar->setStyleSheet(
128 [ + - + - ]: 18 : QStringLiteral("background: %1;").arg(evColor.name()));
129 : :
130 : : // Time
131 [ + - ]: 6 : QLocale loc = QLocale::system();
132 : 6 : QString timeStr;
133 [ + + ]: 6 : if (event.allDay) {
134 [ + - + - : 2 : timeStr = loc.toString(event.dtStart.toLocalTime().date(),
+ - ]
135 : 1 : QLocale::LongFormat);
136 [ + - + - ]: 2 : if (event.dtEnd.isValid() &&
137 [ + - + - : 2 : event.dtEnd.date() != event.dtStart.date())
- + - + ]
138 : 0 : timeStr += QStringLiteral(" – ") +
139 [ # # # # : 0 : loc.toString(event.dtEnd.toLocalTime().date(),
# # ]
140 [ # # # # ]: 0 : QLocale::LongFormat);
141 [ + - ]: 1 : timeStr += QStringLiteral(" (ganztägig)");
142 : : } else {
143 [ + - + - ]: 10 : timeStr = loc.toString(event.dtStart.toLocalTime(),
144 : 15 : QStringLiteral("dd.MM.yyyy HH:mm"));
145 [ + - + - ]: 5 : if (event.dtEnd.isValid())
146 : 10 : timeStr += QStringLiteral(" – ") +
147 [ + - + - ]: 10 : loc.toString(event.dtEnd.toLocalTime(),
148 [ + - + - ]: 15 : QStringLiteral("HH:mm"));
149 : : }
150 [ + - ]: 6 : m_timeLabel->setText(timeStr);
151 : :
152 : : // Location
153 [ + + ]: 6 : if (event.location.isEmpty()) {
154 [ + - ]: 2 : m_locationLabel->hide();
155 : : } else {
156 [ + - ]: 4 : m_locationLabel->setText(
157 [ + - ]: 12 : QStringLiteral("📍 ") + event.location);
158 [ + - ]: 4 : m_locationLabel->show();
159 : : }
160 : :
161 : : // Calendar name + color
162 [ + - ]: 12 : m_calendarLabel->setText(
163 : 12 : QStringLiteral("<span style='color: %1;'>●</span> %2")
164 [ + - + - : 12 : .arg(evColor.name(), event.calendarPath.toHtmlEscaped()));
+ - ]
165 : :
166 : : // Description
167 [ + + ]: 6 : if (event.description.isEmpty()) {
168 [ + - ]: 4 : m_descLabel->hide();
169 : : } else {
170 [ + - ]: 2 : m_descLabel->setText(event.description);
171 [ + - ]: 2 : m_descLabel->show();
172 : : }
173 : :
174 [ + - ]: 6 : adjustSize();
175 [ + - ]: 6 : move(globalPos);
176 [ + - ]: 6 : show();
177 [ + - ]: 6 : raise();
178 [ + - ]: 6 : setFocus();
179 : 6 : }
180 : :
181 : 193 : bool EventDetailPopup::eventFilter(QObject *obj, QEvent *ev) {
182 [ - + ]: 193 : if (ev->type() == QEvent::MouseButtonPress) {
183 : 0 : auto *me = static_cast<QMouseEvent *>(ev);
184 [ # # # # : 0 : if (!rect().contains(mapFromGlobal(me->globalPosition().toPoint()))) {
# # ]
185 : 0 : hide();
186 : 0 : return true;
187 : : }
188 : : }
189 : 193 : return QWidget::eventFilter(obj, ev);
190 : : }
191 : :
192 : 2 : void EventDetailPopup::keyPressEvent(QKeyEvent *event) {
193 [ + - ]: 2 : if (event->key() == Qt::Key_Escape) {
194 : 2 : hide();
195 : 2 : return;
196 : : }
197 : 0 : QWidget::keyPressEvent(event);
198 : : }
199 : :
200 : : // T-76.B3: Runtime language switching
201 : 2 : void EventDetailPopup::changeEvent(QEvent *event) {
202 [ - + ]: 2 : if (event->type() == QEvent::LanguageChange)
203 : 0 : retranslateUi();
204 : 2 : QWidget::changeEvent(event);
205 : 2 : }
206 : :
207 : 0 : void EventDetailPopup::retranslateUi() {
208 [ # # # # ]: 0 : m_editBtn->setToolTip(tr("Edit"));
209 [ # # # # ]: 0 : m_deleteBtn->setToolTip(tr("Delete"));
210 : 0 : }
|