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: 98.5% 134 / 0 / 136
Functions: 90.9% 10 / 0 / 11
Branches: 77.9% 212 / 0 / 272

presentation/QuickContactHistory.cpp
Line Branch Exec Source
1 // The card's history of QuickContactMailHistory (Sprint 103 S103.6.2/S103.6.4,
2 // I-9): mails, linked mails, events and the first meeting in one list.
3
4 #include "QuickContactMailHistory.h"
5
6 #include "data/CalendarStore.h"
7
8 #include <QDate>
9 #include <QDateTime>
10 #include <QElapsedTimer>
11 #include <QJsonDocument>
12 #include <QJsonObject>
13 #include <QLocale>
14 #include <QLoggingCategory>
15 #include <algorithm>
16
17 Q_DECLARE_LOGGING_CATEGORY(lcContactMailHistory)
18
19 namespace {
20
21 13 QString dateText(const QDateTime &when) {
22
1/1
✓ Branch 2 → 3 taken 13 times.
13 const QDateTime local = when.toLocalTime();
23
1/1
✓ Branch 3 → 4 taken 13 times.
13 const QDate today = QDate::currentDate();
24
2/3
✓ Branch 4 → 5 taken 13 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 13 taken 13 times.
13 if (local.date() == today)
25 ✗ return QLocale().toString(local.time(), QLocale::ShortFormat);
26
3/4
✓ Branch 13 → 14 taken 13 times.
✓ Branch 14 → 15 taken 13 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 19 taken 13 times.
13 if (local.date() == today.addDays(-1))
27 ✗ return QuickContactMailHistory::tr("Yesterday");
28
3/3
✓ Branch 19 → 20 taken 13 times.
✓ Branch 20 → 21 taken 13 times.
✓ Branch 21 → 22 taken 13 times.
13 return QLocale().toString(local.date(), QLocale::ShortFormat);
29 13 }
30
31 } // namespace
32
33 CalendarStore *contactHistoryCalendar(const QString &path); // QuickContactHistoryStore.cpp
34
35 236 QuickContactMailHistory::History QuickContactMailHistory::readHistory(const QString &mailDatabase,
36 const QString &calendarDatabase,
37 const QVariantMap &person, int limit) {
38 struct Item {
39 QDateTime when;
40 QVariantMap map;
41 };
42 236 QList<Item> past, upcoming;
43
1/1
✓ Branch 2 → 3 taken 236 times.
236 const QDateTime now = QDateTime::currentDateTime();
44
2/2
✓ Branch 7 → 8 taken 236 times.
✓ Branch 8 → 9 taken 236 times.
472 const QStringList addresses = person.value(QStringLiteral("addresses")).toStringList();
45
6/6
✓ Branch 14 → 15 taken 234 times.
✓ Branch 14 → 18 taken 2 times.
✓ Branch 16 → 17 taken 135 times.
✓ Branch 16 → 18 taken 99 times.
✓ Branch 19 → 20 taken 135 times.
✓ Branch 19 → 136 taken 101 times.
236 if (!mailDatabase.isEmpty() && !addresses.isEmpty())
46
5/5
✓ Branch 20 → 21 taken 135 times.
✓ Branch 21 → 22 taken 135 times.
✓ Branch 22 → 23 taken 135 times.
✓ Branch 133 → 24 taken 42 times.
✓ Branch 133 → 134 taken 135 times.
177 for (const QVariant &value : read(mailDatabase, addresses, limit)) {
47
1/1
✓ Branch 25 → 26 taken 42 times.
42 QVariantMap mail = value.toMap();
48
2/2
✓ Branch 30 → 31 taken 42 times.
✓ Branch 31 → 32 taken 42 times.
84 const QString from = mail.value(QStringLiteral("from")).toString();
49
1/1
✓ Branch 40 → 41 taken 42 times.
378 past.append({mail.value(QStringLiteral("date")).toDateTime(),
50 126 {{QStringLiteral("kind"), QStringLiteral("mail")},
51
1/1
✓ Branch 56 → 57 taken 42 times.
126 {QStringLiteral("dateText"), mail.value(QStringLiteral("dateText"))},
52
1/1
✓ Branch 65 → 66 taken 42 times.
126 {QStringLiteral("title"), mail.value(QStringLiteral("subject"))},
53
5/5
✓ Branch 74 → 75 taken 42 times.
✓ Branch 75 → 76 taken 42 times.
✓ Branch 76 → 77 taken 17 times.
✓ Branch 76 → 78 taken 25 times.
✓ Branch 77 → 79 taken 17 times.
126 {QStringLiteral("detail"), mail.value(QStringLiteral("sent")).toBool() ? tr("Sent") : from},
54
1/1
✓ Branch 87 → 88 taken 42 times.
126 {QStringLiteral("messageId"), mail.value(QStringLiteral("messageId"))}}});
55 177 }
56 // D-15: mails linked to the card, with the subject and date they store.
57
6/6
✓ Branch 140 → 141 taken 236 times.
✓ Branch 141 → 142 taken 236 times.
✓ Branch 146 → 147 taken 236 times.
✓ Branch 147 → 148 taken 236 times.
✓ Branch 237 → 149 taken 9 times.
✓ Branch 237 → 238 taken 236 times.
481 for (const QVariant &value : person.value(QStringLiteral("links")).toList()) {
58
1/1
✓ Branch 150 → 151 taken 9 times.
9 const QVariantMap link = value.toMap();
59
5/5
✓ Branch 151 → 152 taken 9 times.
✓ Branch 156 → 157 taken 9 times.
✓ Branch 157 → 158 taken 9 times.
✓ Branch 158 → 159 taken 9 times.
✓ Branch 159 → 160 taken 9 times.
18 const QDateTime when(QDate::fromString(link.value(QStringLiteral("date")).toString(), Qt::ISODate), QTime(12, 0));
60 54 past.append({when,
61 27 {{QStringLiteral("kind"), QStringLiteral("linked")},
62
3/4
✓ Branch 176 → 177 taken 9 times.
✓ Branch 177 → 178 taken 9 times.
✗ Branch 177 → 179 not taken.
✓ Branch 178 → 180 taken 9 times.
18 {QStringLiteral("dateText"), when.isValid() ? dateText(when) : QString()},
63 //: History row of a mail linked to the contact (D-15): "About Ana: project idea".
64
1/1
✓ Branch 188 → 189 taken 9 times.
27 {QStringLiteral("title"), link.value(QStringLiteral("subject"))},
65
1/1
✓ Branch 193 → 194 taken 9 times.
18 {QStringLiteral("detail"), tr("About this person")},
66
1/1
✓ Branch 202 → 203 taken 9 times.
27 {QStringLiteral("messageId"), link.value(QStringLiteral("messageId"))}}});
67 245 }
68
2/2
✓ Branch 243 → 244 taken 236 times.
✓ Branch 244 → 245 taken 236 times.
472 const QString uid = person.value(QStringLiteral("uid")).toString();
69 // S105.5.3: the worker keeps the calendar store open between requests.
70
3/3
✓ Branch 249 → 250 taken 236 times.
✓ Branch 250 → 251 taken 235 times.
✓ Branch 250 → 367 taken 1 time.
236 if (CalendarStore *store = contactHistoryCalendar(calendarDatabase)) {
71 235 for (const CalendarPeopleIndex::EventRef &event :
72
11/15
✓ Branch 252 → 253 taken 87 times.
✓ Branch 252 → 254 taken 148 times.
✓ Branch 256 → 257 taken 235 times.
✓ Branch 258 → 259 taken 148 times.
✓ Branch 258 → 262 taken 87 times.
✓ Branch 260 → 261 taken 148 times.
✓ Branch 260 → 262 taken 148 times.
✓ Branch 262 → 263 taken 235 times.
✓ Branch 263 → 264 taken 235 times.
✓ Branch 364 → 265 taken 6 times.
✓ Branch 364 → 365 taken 235 times.
✗ Branch 849 → 850 not taken.
✗ Branch 849 → 853 not taken.
✗ Branch 851 → 852 not taken.
✗ Branch 851 → 853 not taken.
772 store->eventsOfPerson(uid.isEmpty() ? QStringList{} : QStringList{uid}, addresses, limit * 2)) {
73
1/1
✓ Branch 266 → 267 taken 6 times.
6 const QDateTime start = event.start.toLocalTime();
74
1/1
✓ Branch 267 → 268 taken 6 times.
6 const bool isUpcoming = start > now;
75 18 const QVariantMap map{{QStringLiteral("kind"), QStringLiteral("event")},
76
8/10
✓ Branch 279 → 280 taken 2 times.
✓ Branch 279 → 283 taken 4 times.
✓ Branch 280 → 281 taken 2 times.
✓ Branch 281 → 282 taken 2 times.
✓ Branch 282 → 284 taken 2 times.
✓ Branch 283 → 284 taken 4 times.
✓ Branch 345 → 346 taken 2 times.
✓ Branch 345 → 347 taken 4 times.
✗ Branch 932 → 933 not taken.
✗ Branch 932 → 934 not taken.
12 {QStringLiteral("dateText"), isUpcoming ? QLocale().toString(start.date(), QLocale::ShortFormat)
77 : dateText(start)},
78 12 {QStringLiteral("title"), event.summary},
79 12 {QStringLiteral("detail"), event.location},
80 12 {QStringLiteral("upcoming"), isUpcoming},
81 30 {QStringLiteral("event"), QVariantMap{{QStringLiteral("uid"), event.uid},
82 12 {QStringLiteral("accountId"), event.accountId},
83 12 {QStringLiteral("calendarPath"), event.calendarPath},
84 12 {QStringLiteral("startIso"),
85
5/9
✓ Branch 315 → 316 taken 6 times.
✓ Branch 321 → 322 taken 36 times.
✓ Branch 321 → 323 taken 6 times.
✓ Branch 325 → 326 taken 24 times.
✓ Branch 325 → 327 taken 6 times.
✗ Branch 863 → 864 not taken.
✗ Branch 863 → 865 not taken.
✗ Branch 869 → 870 not taken.
✗ Branch 869 → 871 not taken.
84 event.start.toString(Qt::ISODate)}}}};
86
2/2
✓ Branch 353 → 354 taken 2 times.
✓ Branch 353 → 355 taken 4 times.
12 (isUpcoming ? upcoming : past).append({start, map});
87 241 }
88 }
89 // The first meeting (★).
90
2/2
✓ Branch 371 → 372 taken 236 times.
✓ Branch 372 → 373 taken 236 times.
472 const QVariantMap met = person.value(QStringLiteral("met")).toMap();
91
4/4
✓ Branch 381 → 382 taken 236 times.
✓ Branch 382 → 383 taken 236 times.
✓ Branch 388 → 389 taken 12 times.
✓ Branch 388 → 467 taken 224 times.
472 if (const QString text = met.value(QStringLiteral("text")).toString(); !text.isEmpty()) {
92
2/2
✓ Branch 393 → 394 taken 12 times.
✓ Branch 394 → 395 taken 12 times.
24 QString iso = met.value(QStringLiteral("date")).toString();
93
2/2
✓ Branch 400 → 401 taken 3 times.
✓ Branch 400 → 408 taken 9 times.
12 if (iso.size() == 4)
94
1/1
✓ Branch 404 → 405 taken 3 times.
3 iso += QStringLiteral("-01");
95
2/2
✓ Branch 409 → 410 taken 6 times.
✓ Branch 409 → 417 taken 6 times.
12 if (iso.size() == 7)
96
1/1
✓ Branch 413 → 414 taken 6 times.
6 iso += QStringLiteral("-01");
97
1/1
✓ Branch 417 → 418 taken 12 times.
72 past.append({QDateTime(QDate::fromString(iso, Qt::ISODate), QTime(0, 0)),
98 36 {{QStringLiteral("kind"), QStringLiteral("met")},
99 24 {QStringLiteral("dateText"), QString()},
100 //: History row of the first meeting: "Met June 2019 at Chaos Communication Camp".
101
2/2
✓ Branch 435 → 436 taken 12 times.
✓ Branch 437 → 438 taken 12 times.
36 {QStringLiteral("title"), tr("Met %1").arg(text)},
102 24 {QStringLiteral("detail"), QString()}}});
103 236 }
104
3/3
✓ Branch 468 → 469 taken 236 times.
✓ Branch 469 → 470 taken 236 times.
✓ Branch 470 → 471 taken 236 times.
236 std::sort(upcoming.begin(), upcoming.end(), [](const Item &a, const Item &b) { return a.when < b.when; });
105
3/3
✓ Branch 471 → 472 taken 236 times.
✓ Branch 472 → 473 taken 236 times.
✓ Branch 473 → 474 taken 236 times.
298 std::stable_sort(past.begin(), past.end(), [](const Item &a, const Item &b) { return a.when > b.when; });
106 236 History history;
107 // Stamps first: a change committed while reading makes the next request refresh.
108
1/1
✓ Branch 474 → 475 taken 236 times.
236 const auto [mailVersion, calendarVersion] = stamps(mailDatabase, calendarDatabase);
109 236 history.mailVersion = mailVersion;
110 236 history.calendarVersion = calendarVersion;
111
5/5
✓ Branch 477 → 478 taken 236 times.
✓ Branch 478 → 479 taken 236 times.
✓ Branch 479 → 480 taken 236 times.
✓ Branch 487 → 481 taken 2 times.
✓ Branch 487 → 488 taken 236 times.
238 for (const Item &item : upcoming.mid(0, 2)) // the next ones on top, then the past
112
1/1
✓ Branch 483 → 484 taken 2 times.
238 history.items.append(item.map);
113
4/4
✓ Branch 489 → 490 taken 236 times.
✓ Branch 490 → 491 taken 236 times.
✓ Branch 501 → 492 taken 66 times.
✓ Branch 501 → 502 taken 233 times.
299 for (const Item &item : past) {
114
2/2
✓ Branch 494 → 495 taken 3 times.
✓ Branch 494 → 496 taken 63 times.
66 if (history.items.size() >= limit)
115 3 break;
116
1/1
✓ Branch 497 → 498 taken 63 times.
63 history.items.append(item.map);
117 }
118
2/2
✓ Branch 559 → 505 taken 55 times.
✓ Branch 559 → 560 taken 232 times.
287 for (const Item &item : std::as_const(past))
119
14/30
✓ Branch 507 → 508 taken 55 times.
✓ Branch 512 → 513 taken 55 times.
✓ Branch 513 → 514 taken 55 times.
✓ Branch 514 → 515 taken 4 times.
✓ Branch 514 → 518 taken 51 times.
✓ Branch 515 → 516 taken 4 times.
✓ Branch 516 → 517 taken 4 times.
✗ Branch 516 → 518 not taken.
✓ Branch 519 → 520 taken 55 times.
✗ Branch 519 → 521 not taken.
✓ Branch 521 → 522 taken 55 times.
✗ Branch 521 → 523 not taken.
✓ Branch 523 → 524 taken 55 times.
✗ Branch 523 → 525 not taken.
✓ Branch 525 → 526 taken 55 times.
✗ Branch 525 → 527 not taken.
✓ Branch 527 → 528 taken 55 times.
✗ Branch 527 → 529 not taken.
✓ Branch 529 → 530 taken 4 times.
✓ Branch 529 → 557 taken 51 times.
✗ Branch 1100 → 1101 not taken.
✗ Branch 1100 → 1102 not taken.
✗ Branch 1104 → 1105 not taken.
✗ Branch 1104 → 1106 not taken.
✗ Branch 1108 → 1109 not taken.
✗ Branch 1108 → 1110 not taken.
✗ Branch 1112 → 1113 not taken.
✗ Branch 1112 → 1114 not taken.
✗ Branch 1116 → 1117 not taken.
✗ Branch 1116 → 1118 not taken.
110 if (item.map.value(QStringLiteral("kind")) == QLatin1String("event") && item.when.daysTo(now) <= 365) {
120 //: First line of the history: "Last seen: 28 Sep · Dinner at Taberna".
121
1/1
✓ Branch 530 → 531 taken 4 times.
4 history.lastSeen = tr("Last seen: %1 · %2")
122
4/4
✓ Branch 537 → 538 taken 4 times.
✓ Branch 541 → 542 taken 4 times.
✓ Branch 542 → 543 taken 4 times.
✓ Branch 543 → 544 taken 4 times.
12 .arg(QLocale().toString(item.when.date(), QStringLiteral("d MMM")),
123
2/2
✓ Branch 535 → 536 taken 4 times.
✓ Branch 536 → 537 taken 4 times.
16 item.map.value(QStringLiteral("title")).toString());
124 4 break;
125 }
126 236 return history;
127 1251 }
128
129 261 void QuickContactMailHistory::requestPerson(const QVariantMap &person, int limit) {
130 261 const quint64 generation = ++m_generation;
131
2/3
✓ Branch 3 → 4 taken 261 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 6 taken 261 times.
261 const QString mailPath = m_databasePath ? m_databasePath() : QString();
132 261 const QString calendarPath = m_calendarPath;
133
1/1
✓ Branch 7 → 8 taken 261 times.
261 const int bounded = qBound(1, limit, 50);
134
1/1
✓ Branch 8 → 9 taken 261 times.
261 const QString key = cacheKey(person, bounded);
135 261 const auto cached = m_cache.constFind(key);
136 261 m_lastFromCache = cached != m_cache.constEnd();
137
2/2
✓ Branch 12 → 13 taken 84 times.
✓ Branch 12 → 15 taken 177 times.
261 const History previous = m_lastFromCache ? cached->history : History{};
138
2/2
✓ Branch 16 → 17 taken 84 times.
✓ Branch 16 → 20 taken 177 times.
261 if (m_lastFromCache) {
139 // Same frame: the cached items, then a background check of the stamps.
140 84 m_items = previous.items;
141 84 m_lastSeen = previous.lastSeen;
142 84 m_loading = false;
143
1/1
✓ Branch 19 → 21 taken 84 times.
84 remember(key, previous);
144 } else {
145 177 m_loading = true;
146 }
147
1/1
✓ Branch 21 → 22 taken 261 times.
261 emit mailsChanged();
148 261 const bool fromCache = m_lastFromCache;
149
1/11
✓ Branch 27 → 28 taken 261 times.
✗ Branch 38 → 39 not taken.
✗ Branch 38 → 40 not taken.
✗ Branch 41 → 42 not taken.
✗ Branch 41 → 43 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
✗ Branch 50 → 51 not taken.
✗ Branch 50 → 52 not taken.
261 m_pool.start([this, generation, mailPath, calendarPath, person, bounded, key, previous, fromCache] {
150 261 QElapsedTimer timer;
151 261 timer.start();
152
7/8
✓ Branch 3 → 4 taken 84 times.
✓ Branch 3 → 9 taken 177 times.
✓ Branch 4 → 5 taken 84 times.
✓ Branch 5 → 6 taken 84 times.
✓ Branch 7 → 8 taken 84 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 84 times.
✓ Branch 10 → 25 taken 177 times.
261 if (fromCache && stamps(mailPath, calendarPath) == qMakePair(previous.mailVersion, previous.calendarVersion)) {
153
7/7
✓ Branch 11 → 12 taken 84 times.
✓ Branch 15 → 16 taken 84 times.
✓ Branch 16 → 17 taken 84 times.
✓ Branch 18 → 19 taken 84 times.
✓ Branch 19 → 20 taken 84 times.
✓ Branch 23 → 13 taken 84 times.
✓ Branch 23 → 24 taken 84 times.
168 qCDebug(lcContactMailHistory) << "History unchanged (stamps) in" << timer.elapsed() << "ms";
154 84 return;
155 }
156
1/1
✓ Branch 25 → 26 taken 177 times.
177 const History history = readHistory(mailPath, calendarPath, person, bounded);
157
9/9
✓ Branch 26 → 27 taken 177 times.
✓ Branch 30 → 31 taken 177 times.
✓ Branch 31 → 32 taken 177 times.
✓ Branch 33 → 34 taken 177 times.
✓ Branch 34 → 35 taken 177 times.
✓ Branch 36 → 37 taken 177 times.
✓ Branch 37 → 38 taken 177 times.
✓ Branch 41 → 28 taken 177 times.
✓ Branch 41 → 42 taken 177 times.
354 qCDebug(lcContactMailHistory) << "History:" << history.items.size() << "items in" << timer.elapsed() << "ms";
158 177 QMetaObject::invokeMethod(
159 this,
160
1/3
✓ Branch 44 → 45 taken 177 times.
✗ Branch 63 → 64 not taken.
✗ Branch 63 → 65 not taken.
177 [this, generation, history, key] {
161 171 remember(key, history);
162
2/2
✓ Branch 3 → 4 taken 55 times.
✓ Branch 3 → 5 taken 116 times.
171 if (generation != m_generation) return;
163
4/6
✓ Branch 6 → 7 taken 94 times.
✓ Branch 6 → 11 taken 22 times.
✓ Branch 8 → 9 taken 94 times.
✗ Branch 8 → 11 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 94 times.
116 const bool same = history.items == m_items && history.lastSeen == m_lastSeen && !m_loading;
164 116 m_items = history.items;
165 116 m_lastSeen = history.lastSeen;
166 116 m_loading = false;
167
1/2
✓ Branch 14 → 15 taken 116 times.
✗ Branch 14 → 16 not taken.
116 if (!same) emit mailsChanged(); // rows stay as they are when nothing changed
168 },
169 Qt::QueuedConnection);
170 177 });
171 261 }
172
173 // S105.5.4: the cache key covers everything the history is computed from.
174 320 QString QuickContactMailHistory::cacheKey(const QVariantMap &person, int limit) const {
175
4/4
✓ Branch 13 → 14 taken 320 times.
✓ Branch 14 → 15 taken 320 times.
✓ Branch 15 → 16 taken 320 times.
✓ Branch 16 → 17 taken 320 times.
640 return QString::fromUtf8(QJsonDocument(QJsonObject::fromVariantMap(person)).toJson(QJsonDocument::Compact))
176
7/8
✓ Branch 5 → 6 taken 320 times.
✗ Branch 5 → 7 not taken.
✓ Branch 6 → 8 taken 320 times.
✓ Branch 10 → 11 taken 320 times.
✓ Branch 17 → 18 taken 320 times.
✓ Branch 18 → 19 taken 320 times.
✓ Branch 19 → 20 taken 320 times.
✓ Branch 20 → 21 taken 320 times.
1280 + QLatin1Char('|') + QString::number(limit) + QLatin1Char('|') + (m_databasePath ? m_databasePath() : QString())
177
2/2
✓ Branch 21 → 22 taken 320 times.
✓ Branch 22 → 23 taken 320 times.
1280 + QLatin1Char('|') + m_calendarPath;
178 }
179
180 59 void QuickContactMailHistory::prefetchPerson(const QVariantMap &person, int limit) {
181
1/1
✓ Branch 2 → 3 taken 59 times.
59 const int bounded = qBound(1, limit, 50);
182
1/1
✓ Branch 3 → 4 taken 59 times.
59 const QString key = cacheKey(person, bounded);
183
2/2
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 7 taken 57 times.
59 if (m_cache.contains(key)) return;
184
2/3
✓ Branch 8 → 9 taken 57 times.
✗ Branch 8 → 10 not taken.
✓ Branch 9 → 11 taken 57 times.
57 const QString mailPath = m_databasePath ? m_databasePath() : QString();
185 57 const QString calendarPath = m_calendarPath;
186
1/7
✓ Branch 16 → 17 taken 57 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
✗ Branch 34 → 35 not taken.
✗ Branch 34 → 36 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 39 not taken.
57 m_pool.start([this, mailPath, calendarPath, person, bounded, key] {
187
1/1
✓ Branch 2 → 3 taken 57 times.
57 const History history = readHistory(mailPath, calendarPath, person, bounded);
188
1/3
✓ Branch 5 → 6 taken 57 times.
✗ Branch 11 → 12 not taken.
✗ Branch 11 → 13 not taken.
114 QMetaObject::invokeMethod(this, [this, key, history] { remember(key, history); }, Qt::QueuedConnection);
189 57 });
190 59 }
191