MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 95.0% 133 / 0 / 140
Functions: 92.9% 13 / 0 / 14
Branches: 75.5% 225 / 0 / 298

presentation/QuickNextUp.cpp
Line Branch Exec Source
1 #include "QuickNextUp.h"
2
3 #include "CalendarEventDetails.h"
4 #include "QuickCalendarModel.h"
5 #include "data/CalendarStore.h"
6
7 #include <QLocale>
8 #include <algorithm>
9 #include <QLoggingCategory>
10 #include <QSettings>
11
12 ✗ Q_LOGGING_CATEGORY(lcNextUp, "mailjd.quick.nextup")
13
14 namespace {
15 const QString kEnabledKey = QStringLiteral("calendar/nextUpInStatusBar");
16
17 497 QString shortTime(const QDateTime &time) { return CalendarLayout::timeText(time); }
18
19 // "15:30 Review" today, "Tomorrow 09:00 Standup", "Fri 09:00 Planning" later.
20 463 QString followingText(const CalendarOccurrence &occurrence, const QDate &today) {
21
2/2
✓ Branch 2 → 3 taken 463 times.
✓ Branch 3 → 4 taken 463 times.
463 const qint64 days = today.daysTo(occurrence.start.date());
22
1/1
✓ Branch 4 → 5 taken 463 times.
463 const QString time = shortTime(occurrence.start);
23
4/4
✓ Branch 5 → 6 taken 20 times.
✓ Branch 5 → 11 taken 443 times.
✓ Branch 6 → 7 taken 20 times.
✓ Branch 7 → 8 taken 20 times.
463 if (days == 0) return QuickNextUp::tr("%1 %2").arg(time, occurrence.summary);
24 443 const QString day = days == 1 ? QuickNextUp::tr("Tomorrow")
25
9/11
✓ Branch 11 → 12 taken 266 times.
✓ Branch 11 → 13 taken 177 times.
✓ Branch 12 → 17 taken 266 times.
✓ Branch 13 → 14 taken 177 times.
✓ Branch 14 → 15 taken 177 times.
✓ Branch 15 → 16 taken 177 times.
✓ Branch 16 → 17 taken 177 times.
✓ Branch 17 → 18 taken 177 times.
✓ Branch 17 → 19 taken 266 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
443 : QLocale().dayName(occurrence.start.date().dayOfWeek(), QLocale::ShortFormat);
26
2/2
✓ Branch 19 → 20 taken 443 times.
✓ Branch 20 → 21 taken 443 times.
443 return QuickNextUp::tr("%1 %2 %3").arg(day, time, occurrence.summary);
27 463 }
28
29 // F95-12: all-day appointments in the hover list ("Today, all day: Holiday").
30 2 QString allDayText(const CalendarOccurrence &occurrence, const QDate &today) {
31 2 const qint64 days = today.daysTo(occurrence.start.date());
32
3/4
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 10 not taken.
✓ Branch 5 → 6 taken 2 times.
✓ Branch 7 → 8 taken 2 times.
4 if (days <= 0) return QuickNextUp::tr("Today, all day: %1").arg(occurrence.summary);
33 ✗ if (days == 1) return QuickNextUp::tr("Tomorrow, all day: %1").arg(occurrence.summary);
34 ✗ return QuickNextUp::tr("%1, all day: %2")
35 ✗ .arg(QLocale().dayName(occurrence.start.date().dayOfWeek(), QLocale::ShortFormat), occurrence.summary);
36 }
37 } // namespace
38
39 796 QuickNextUp::QuickNextUp(QString databasePath, HiddenCalendars hiddenCalendars, QObject *parent)
40 796 : QObject(parent), m_databasePath(std::move(databasePath)),
41
1/1
✓ Branch 9 → 10 taken 796 times.
1592 m_hiddenCalendars(std::move(hiddenCalendars)) {
42 // "in 25 min" counts down; a finished appointment gives way to the next.
43
1/1
✓ Branch 15 → 16 taken 796 times.
796 m_tick.setInterval(30000);
44
1/1
✓ Branch 16 → 17 taken 796 times.
796 connect(&m_tick, &QTimer::timeout, this, &QuickNextUp::refresh);
45
1/1
✓ Branch 18 → 19 taken 796 times.
796 m_tick.start();
46 796 }
47
48 796 QuickNextUp::~QuickNextUp() = default;
49
50
2/2
✓ Branch 3 → 4 taken 30 times.
✓ Branch 3 → 5 taken 1843 times.
1873 QDateTime QuickNextUp::now() const { return m_clock ? m_clock() : QDateTime::currentDateTime(); }
51
52
3/3
✓ Branch 2 → 3 taken 2514 times.
✓ Branch 5 → 6 taken 2514 times.
✓ Branch 6 → 7 taken 2514 times.
2514 bool QuickNextUp::enabled() const { return QSettings().value(kEnabledKey, true).toBool(); }
53
54 6 void QuickNextUp::setEnabled(bool enabled) {
55
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6 times.
6 if (enabled == this->enabled()) return;
56
2/2
✓ Branch 5 → 6 taken 6 times.
✓ Branch 8 → 9 taken 6 times.
6 QSettings().setValue(kEnabledKey, enabled);
57 6 emit changed();
58 }
59
60 937 void QuickNextUp::refresh() {
61 937 QVariantMap chosen;
62 937 QVariantList following;
63 937 int moreToday = 0;
64 937 QString text;
65 937 QString meeting;
66 937 bool ongoing = false;
67
6/7
✓ Branch 2 → 3 taken 937 times.
✓ Branch 3 → 4 taken 935 times.
✓ Branch 3 → 7 taken 2 times.
✓ Branch 5 → 6 taken 935 times.
✗ Branch 5 → 7 not taken.
✓ Branch 8 → 9 taken 935 times.
✓ Branch 8 → 159 taken 2 times.
937 if (enabled() && !m_databasePath.isEmpty()) {
68
2/2
✓ Branch 10 → 11 taken 742 times.
✓ Branch 10 → 29 taken 193 times.
935 if (!m_store) {
69
1/1
✓ Branch 11 → 12 taken 742 times.
742 m_store = std::make_unique<CalendarStore>();
70
2/3
✓ Branch 15 → 16 taken 742 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 29 taken 742 times.
742 if (!m_store->open(m_databasePath)) {
71 ✗ qCWarning(lcNextUp) << "Calendar store unavailable for next-up:" << m_databasePath;
72 ✗ m_store.reset();
73 }
74 }
75
1/2
✓ Branch 30 → 31 taken 935 times.
✗ Branch 30 → 159 not taken.
935 if (m_store) {
76
1/1
✓ Branch 31 → 32 taken 935 times.
935 const QDateTime current = now();
77
1/1
✓ Branch 32 → 33 taken 935 times.
935 const QDate today = current.date();
78 1870 const auto occurrences = calendarOccurrencesFor(*m_store, today, today,
79
3/4
✓ Branch 35 → 36 taken 935 times.
✗ Branch 35 → 37 not taken.
✓ Branch 36 → 38 taken 935 times.
✓ Branch 39 → 40 taken 935 times.
1870 m_hiddenCalendars ? m_hiddenCalendars() : QStringList{});
80 935 const CalendarOccurrence *running = nullptr;
81 935 const CalendarOccurrence *next = nullptr;
82
2/2
✓ Branch 83 → 44 taken 727 times.
✓ Branch 83 → 84 taken 935 times.
1662 for (const auto &occurrence : occurrences) {
83
6/7
✓ Branch 45 → 46 taken 721 times.
✓ Branch 45 → 49 taken 6 times.
✓ Branch 46 → 47 taken 721 times.
✗ Branch 48 → 49 not taken.
✓ Branch 48 → 50 taken 721 times.
✓ Branch 51 → 52 taken 6 times.
✓ Branch 51 → 53 taken 721 times.
727 if (occurrence.allDay || occurrence.start.date() != today) continue;
84
8/8
✓ Branch 53 → 54 taken 721 times.
✓ Branch 55 → 56 taken 305 times.
✓ Branch 55 → 60 taken 416 times.
✓ Branch 56 → 57 taken 305 times.
✓ Branch 58 → 59 taken 10 times.
✓ Branch 58 → 60 taken 295 times.
✓ Branch 61 → 62 taken 10 times.
✓ Branch 61 → 70 taken 711 times.
721 if (occurrence.start <= current && occurrence.end > current) {
85 // The one ending first is what the user is in now.
86
2/7
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 66 taken 10 times.
✗ Branch 63 → 64 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
✓ Branch 68 → 69 taken 10 times.
✗ Branch 68 → 81 not taken.
10 if (!running || occurrence.end < running->end) running = &occurrence;
87
3/3
✓ Branch 70 → 71 taken 711 times.
✓ Branch 72 → 73 taken 416 times.
✓ Branch 72 → 81 taken 295 times.
711 } else if (occurrence.start > current) {
88
6/7
✓ Branch 73 → 74 taken 387 times.
✓ Branch 73 → 77 taken 29 times.
✓ Branch 74 → 75 taken 387 times.
✗ Branch 76 → 77 not taken.
✓ Branch 76 → 78 taken 387 times.
✓ Branch 79 → 80 taken 29 times.
✓ Branch 79 → 81 taken 387 times.
416 if (!next || occurrence.start < next->start) next = &occurrence;
89 }
90 }
91
2/2
✓ Branch 84 → 85 taken 10 times.
✓ Branch 84 → 93 taken 925 times.
935 if (running) {
92 10 ongoing = true;
93
3/3
✓ Branch 85 → 86 taken 10 times.
✓ Branch 86 → 87 taken 10 times.
✓ Branch 87 → 88 taken 10 times.
10 text = tr("Now: %1 until %2").arg(running->summary, shortTime(running->end));
94
2/2
✓ Branch 93 → 94 taken 24 times.
✓ Branch 93 → 111 taken 901 times.
925 } else if (next) {
95
1/1
✓ Branch 94 → 95 taken 24 times.
24 const qint64 minutes = (current.secsTo(next->start) + 59) / 60;
96 const QString when = minutes < 60
97
3/4
✓ Branch 95 → 96 taken 16 times.
✓ Branch 95 → 99 taken 8 times.
✗ Branch 96 → 97 not taken.
✓ Branch 96 → 98 taken 16 times.
24 ? (minutes == 1 ? tr("in 1 min") : tr("in %n min", "", int(minutes)))
98
5/6
✗ Branch 97 → 102 not taken.
✓ Branch 98 → 102 taken 16 times.
✓ Branch 99 → 100 taken 5 times.
✓ Branch 99 → 101 taken 3 times.
✓ Branch 100 → 102 taken 5 times.
✓ Branch 101 → 102 taken 3 times.
24 : (minutes < 120 ? tr("in 1 h") : tr("in %n h", "", int(minutes / 60)));
99
3/3
✓ Branch 102 → 103 taken 24 times.
✓ Branch 103 → 104 taken 24 times.
✓ Branch 104 → 105 taken 24 times.
24 text = tr("%1 %2 · %3").arg(shortTime(next->start), next->summary, when);
100 24 }
101 // F100-34: nothing more today — the next appointment of the coming
102 // week ("Tomorrow 09:00 Standup"), else an all-day one running today or
103 // ahead, so the chip does not vanish in the evening.
104 935 std::optional<CalendarOccurrence> later;
105
4/4
✓ Branch 111 → 112 taken 925 times.
✓ Branch 111 → 127 taken 10 times.
✓ Branch 112 → 113 taken 901 times.
✓ Branch 112 → 127 taken 24 times.
935 if (!running && !next) {
106
1/1
✓ Branch 113 → 114 taken 901 times.
901 later = nextLater(current);
107
4/6
✓ Branch 117 → 118 taken 220 times.
✓ Branch 117 → 127 taken 681 times.
✗ Branch 119 → 120 not taken.
✓ Branch 119 → 122 taken 220 times.
✗ Branch 121 → 124 not taken.
✓ Branch 123 → 124 taken 220 times.
901 if (later) text = later->allDay ? allDayText(*later, today) : followingText(*later, today);
108 }
109
8/8
✓ Branch 127 → 128 taken 925 times.
✓ Branch 127 → 136 taken 10 times.
✓ Branch 128 → 129 taken 901 times.
✓ Branch 128 → 134 taken 24 times.
✓ Branch 130 → 131 taken 220 times.
✓ Branch 130 → 132 taken 681 times.
✓ Branch 137 → 138 taken 254 times.
✓ Branch 137 → 155 taken 681 times.
935 if (const CalendarOccurrence *shown = running ? running : next ? next : later ? &*later : nullptr) {
110
1/1
✓ Branch 138 → 139 taken 254 times.
254 chosen = CalendarLayout::toVariant(*shown);
111
1/1
✓ Branch 142 → 143 taken 254 times.
254 const auto series = m_store->eventSeries(shown->uid, shown->accountId, shown->calendarPath);
112
2/3
✓ Branch 144 → 145 taken 254 times.
✗ Branch 144 → 150 not taken.
✓ Branch 146 → 147 taken 254 times.
254 if (!series.isEmpty()) meeting = CalendarEventDetails::meetingUrl(series.first());
113
1/1
✓ Branch 150 → 151 taken 254 times.
254 following = followingAfter(*shown, current, &moreToday);
114 254 }
115 935 }
116 }
117 // S106-296: `today` is part of the state — a multi-day all-day event
118 // reads the same on both days, yet the chip's day changed at midnight.
119
1/1
✓ Branch 159 → 160 taken 937 times.
937 const QString today = todayIso();
120
5/7
✓ Branch 160 → 161 taken 937 times.
✓ Branch 163 → 164 taken 716 times.
✓ Branch 163 → 173 taken 1 time.
✓ Branch 165 → 166 taken 716 times.
✗ Branch 165 → 173 not taken.
✓ Branch 166 → 167 taken 716 times.
✗ Branch 166 → 173 not taken.
1654 if (chosen == m_occurrence && text == m_text && meeting == m_meetingUrl && ongoing == m_ongoing &&
121
10/11
✓ Branch 161 → 162 taken 717 times.
✓ Branch 161 → 173 taken 220 times.
✓ Branch 167 → 168 taken 716 times.
✓ Branch 168 → 169 taken 704 times.
✓ Branch 168 → 173 taken 12 times.
✓ Branch 169 → 170 taken 704 times.
✗ Branch 169 → 173 not taken.
✓ Branch 171 → 172 taken 151 times.
✓ Branch 171 → 173 taken 553 times.
✓ Branch 174 → 175 taken 151 times.
✓ Branch 174 → 176 taken 786 times.
1654 following == m_following && moreToday == m_moreToday && today == m_today)
122 151 return;
123 786 m_today = today;
124 786 m_occurrence = chosen;
125 786 m_following = following;
126 786 m_moreToday = moreToday;
127 786 m_text = text;
128 786 m_meetingUrl = meeting;
129 786 m_ongoing = ongoing;
130
1/1
✓ Branch 181 → 182 taken 786 times.
786 emit changed();
131 1541 }
132
133 901 std::optional<CalendarOccurrence> QuickNextUp::nextLater(const QDateTime &current) {
134
1/1
✓ Branch 2 → 3 taken 901 times.
901 const QDate today = current.date();
135
1/1
✓ Branch 8 → 9 taken 901 times.
1802 const auto occurrences = calendarOccurrencesFor(*m_store, today, today.addDays(7),
136
3/4
✓ Branch 5 → 6 taken 901 times.
✗ Branch 5 → 7 not taken.
✓ Branch 6 → 8 taken 901 times.
✓ Branch 10 → 11 taken 901 times.
1802 m_hiddenCalendars ? m_hiddenCalendars() : QStringList{});
137 901 const CalendarOccurrence *timed = nullptr;
138 901 const CalendarOccurrence *allDay = nullptr;
139
2/2
✓ Branch 42 → 15 taken 588 times.
✓ Branch 42 → 43 taken 901 times.
1489 for (const auto &occurrence : occurrences) {
140
2/2
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 29 taken 587 times.
588 if (occurrence.allDay) {
141
4/10
✓ Branch 17 → 18 taken 1 time.
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 26 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 25 taken 1 time.
✗ Branch 22 → 23 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
✓ Branch 27 → 28 taken 1 time.
✗ Branch 27 → 40 not taken.
1 if (occurrence.end.date() > today && (!allDay || occurrence.start < allDay->start)) allDay = &occurrence;
142
9/10
✓ Branch 29 → 30 taken 587 times.
✓ Branch 31 → 32 taken 448 times.
✓ Branch 31 → 37 taken 139 times.
✓ Branch 32 → 33 taken 228 times.
✓ Branch 32 → 36 taken 220 times.
✓ Branch 33 → 34 taken 228 times.
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 228 times.
✓ Branch 38 → 39 taken 220 times.
✓ Branch 38 → 40 taken 367 times.
587 } else if (occurrence.start > current && (!timed || occurrence.start < timed->start)) {
143 220 timed = &occurrence;
144 }
145 }
146
2/2
✓ Branch 43 → 44 taken 220 times.
✓ Branch 43 → 45 taken 681 times.
901 if (timed) return *timed;
147
1/2
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 681 times.
681 if (allDay) return *allDay;
148 681 return std::nullopt;
149 901 }
150
151 254 QVariantList QuickNextUp::followingAfter(const CalendarOccurrence &shown, const QDateTime &current, int *moreToday) {
152
1/1
✓ Branch 2 → 3 taken 254 times.
254 const QDate today = current.date();
153
1/1
✓ Branch 8 → 9 taken 254 times.
508 auto occurrences = calendarOccurrencesFor(*m_store, today, today.addDays(7),
154
3/4
✓ Branch 5 → 6 taken 254 times.
✗ Branch 5 → 7 not taken.
✓ Branch 6 → 8 taken 254 times.
✓ Branch 10 → 11 taken 254 times.
508 m_hiddenCalendars ? m_hiddenCalendars() : QStringList{});
155
3/3
✓ Branch 13 → 14 taken 254 times.
✓ Branch 14 → 15 taken 254 times.
✓ Branch 15 → 16 taken 254 times.
254 std::sort(occurrences.begin(), occurrences.end(),
156 22129 [](const CalendarOccurrence &a, const CalendarOccurrence &b) { return a.start < b.start; });
157 245 const auto entry = [](const CalendarOccurrence &occurrence, const QString &text) {
158
1/1
✓ Branch 2 → 3 taken 245 times.
245 const QVariantMap variant = CalendarLayout::toVariant(occurrence);
159 490 return QVariantMap{{QStringLiteral("text"), text},
160
1/1
✓ Branch 14 → 15 taken 245 times.
735 {QStringLiteral("color"), variant.value(QStringLiteral("color"))},
161
2/4
✓ Branch 22 → 23 taken 735 times.
✓ Branch 22 → 24 taken 245 times.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
1470 {QStringLiteral("occurrence"), variant}};
162
1/5
✓ Branch 20 → 21 taken 245 times.
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 75 not taken.
✗ Branch 73 → 74 not taken.
✗ Branch 73 → 75 not taken.
1225 };
163 // F100-17: timed appointments after the shown one first, then all-day
164 // ones (today's running ones before later days) — at most two in all.
165 254 QList<const CalendarOccurrence *> timed, allDay;
166 254 int todayCount = 0;
167
4/4
✓ Branch 16 → 17 taken 254 times.
✓ Branch 17 → 18 taken 254 times.
✓ Branch 65 → 19 taken 2686 times.
✓ Branch 65 → 66 taken 254 times.
2940 for (const auto &occurrence : occurrences) {
168
7/7
✓ Branch 21 → 22 taken 2322 times.
✓ Branch 21 → 25 taken 364 times.
✓ Branch 22 → 23 taken 2322 times.
✓ Branch 23 → 24 taken 254 times.
✓ Branch 23 → 25 taken 2068 times.
✓ Branch 26 → 27 taken 254 times.
✓ Branch 26 → 28 taken 2432 times.
2686 if (occurrence.uid == shown.uid && occurrence.start == shown.start) continue;
169
6/8
✓ Branch 28 → 29 taken 6 times.
✓ Branch 28 → 38 taken 2426 times.
✓ Branch 29 → 30 taken 6 times.
✓ Branch 32 → 33 taken 6 times.
✗ Branch 32 → 38 not taken.
✓ Branch 33 → 34 taken 6 times.
✓ Branch 36 → 37 taken 6 times.
✗ Branch 36 → 38 not taken.
2432 const bool runningToday = occurrence.allDay && occurrence.start.date() <= today && occurrence.end.date() > today;
170
2/2
✓ Branch 39 → 40 taken 6 times.
✓ Branch 39 → 53 taken 2426 times.
2432 if (occurrence.allDay) {
171
3/8
✗ Branch 40 → 41 not taken.
✓ Branch 40 → 45 taken 6 times.
✗ Branch 41 → 42 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
✓ Branch 47 → 48 taken 6 times.
✗ Branch 47 → 49 not taken.
✓ Branch 48 → 49 taken 6 times.
6 if (runningToday || occurrence.start.date() > today) allDay.append(&occurrence);
172
1/2
✓ Branch 49 → 50 taken 6 times.
✗ Branch 49 → 51 not taken.
6 todayCount += runningToday ? 1 : 0;
173
3/3
✓ Branch 53 → 54 taken 2426 times.
✓ Branch 55 → 56 taken 2146 times.
✓ Branch 55 → 63 taken 280 times.
2426 } else if (occurrence.start > shown.start) {
174
1/1
✓ Branch 56 → 57 taken 2146 times.
2146 timed.append(&occurrence);
175
3/3
✓ Branch 57 → 58 taken 2146 times.
✓ Branch 59 → 60 taken 392 times.
✓ Branch 59 → 61 taken 1754 times.
2146 todayCount += occurrence.start.date() == today ? 1 : 0;
176 }
177 }
178 254 QVariantList result;
179 254 int shownToday = 0;
180
2/2
✓ Branch 105 → 68 taken 508 times.
✓ Branch 105 → 106 taken 254 times.
762 for (const auto *list : {&timed, &allDay})
181
2/2
✓ Branch 103 → 70 taken 268 times.
✓ Branch 103 → 104 taken 485 times.
753 for (const CalendarOccurrence *occurrence : *list) {
182
2/2
✓ Branch 72 → 73 taken 23 times.
✓ Branch 72 → 74 taken 245 times.
268 if (result.size() == 2) break;
183
6/6
✓ Branch 74 → 75 taken 2 times.
✓ Branch 74 → 76 taken 243 times.
✓ Branch 75 → 77 taken 2 times.
✓ Branch 76 → 77 taken 243 times.
✓ Branch 77 → 78 taken 245 times.
✓ Branch 79 → 80 taken 245 times.
245 result.append(entry(*occurrence, occurrence->allDay ? allDayText(*occurrence, today) : followingText(*occurrence, today)));
184
6/8
✓ Branch 83 → 84 taken 2 times.
✓ Branch 83 → 95 taken 243 times.
✓ Branch 84 → 85 taken 2 times.
✓ Branch 87 → 88 taken 2 times.
✗ Branch 87 → 93 not taken.
✓ Branch 88 → 89 taken 2 times.
✓ Branch 91 → 92 taken 2 times.
✗ Branch 91 → 93 not taken.
245 const bool isToday = occurrence->allDay ? occurrence->start.date() <= today && occurrence->end.date() > today
185
1/1
✓ Branch 95 → 96 taken 243 times.
243 : occurrence->start.date() == today;
186
2/2
✓ Branch 98 → 99 taken 22 times.
✓ Branch 98 → 100 taken 223 times.
245 shownToday += isToday ? 1 : 0;
187 }
188
1/2
✓ Branch 106 → 107 taken 254 times.
✗ Branch 106 → 109 not taken.
254 if (moreToday) *moreToday = qMax(0, todayCount - shownToday);
189 254 return result;
190 254 }
191