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: 88.3% 53 / 0 / 60
Functions: 100.0% 13 / 0 / 13
Branches: 73.9% 65 / 0 / 88

presentation/KeyHint.cpp
Line Branch Exec Source
1 #include "KeyHint.h"
2
3 #include "KeyOverlayScrim.h"
4
5 #include <QMetaMethod>
6 #include <QQmlEngine>
7 #include <QQuickWindow>
8 #include <QSet>
9 #include <mutex>
10
11 namespace {
12 // Live entries; the GUI thread only (QML items live there).
13 511378 QList<KeyHint *> &registry() {
14
3/4
✓ Branch 2 → 3 taken 26 times.
✓ Branch 2 → 7 taken 511352 times.
✓ Branch 4 → 5 taken 26 times.
✗ Branch 4 → 7 not taken.
511378 static QList<KeyHint *> entries;
15 511378 return entries;
16 }
17 } // namespace
18
19
1/1
✓ Branch 15 → 16 taken 255292 times.
510584 KeyHint::KeyHint(QObject *parent) : QObject(parent) { registry().append(this); }
20
21 510580 KeyHint::~KeyHint() { registry().removeOne(this); }
22
23
2/5
✓ Branch 3 → 4 taken 255292 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 255292 times.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
510584 KeyHint *KeyHint::qmlAttachedProperties(QObject *object) { return new KeyHint(object); }
24
25 121735 KeyHint *KeyHint::of(const QObject *item) {
26
1/2
✓ Branch 2 → 3 taken 121735 times.
✗ Branch 2 → 6 not taken.
121735 return item ? qobject_cast<KeyHint *>(qmlAttachedPropertiesObject<KeyHint>(item, false)) : nullptr;
27 }
28
29 796 QList<KeyHint *> KeyHint::all() { return registry(); }
30
31 891 void KeyHint::registerTypes() {
32 static std::once_flag once;
33
1/1
✓ Branch 2 → 3 taken 891 times.
919 std::call_once(once, [] {
34
1/1
✓ Branch 5 → 6 taken 28 times.
28 qmlRegisterUncreatableType<KeyHint>("MailJD.Keys", 1, 0, "KeyHint",
35 56 QStringLiteral("KeyHint is an attached property"));
36 28 qmlRegisterType<KeyOverlayScrim>("MailJD.Keys", 1, 0, "KeyOverlayScrim");
37 28 });
38 891 }
39
40 1093 void KeyHint::setFocusTarget(QQuickItem *value) {
41
2/2
✓ Branch 3 → 4 taken 81 times.
✓ Branch 3 → 5 taken 1012 times.
1093 if (m_focusTarget == value) return;
42 1012 m_focusTarget = value;
43 1012 emit changed();
44 }
45
46 1588 QString KeyHint::effectiveLabel() const {
47
2/2
✓ Branch 3 → 4 taken 1315 times.
✓ Branch 3 → 5 taken 273 times.
1588 if (!m_label.isEmpty()) return m_label;
48
2/2
✓ Branch 6 → 7 taken 172 times.
✓ Branch 6 → 8 taken 101 times.
273 if (!m_pane.isEmpty()) return m_pane;
49 101 const QQuickItem *element = item();
50
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 101 times.
101 if (!element) return {};
51
2/2
✓ Branch 11 → 12 taken 101 times.
✓ Branch 12 → 13 taken 101 times.
101 const QString text = element->property("text").toString();
52 // Icon buttons carry a glyph as text; their name is the tooltip/accessible name.
53
6/7
✓ Branch 15 → 16 taken 25 times.
✓ Branch 15 → 20 taken 76 times.
✓ Branch 16 → 17 taken 25 times.
✓ Branch 18 → 19 taken 25 times.
✗ Branch 18 → 20 not taken.
✓ Branch 21 → 22 taken 25 times.
✓ Branch 21 → 23 taken 76 times.
101 if (!text.isEmpty() && text.front().isLetterOrNumber()) return text;
54
2/2
✓ Branch 23 → 24 taken 76 times.
✓ Branch 24 → 25 taken 76 times.
76 const QString tip = element->property("tip").toString();
55
4/8
✓ Branch 27 → 28 taken 76 times.
✗ Branch 27 → 30 not taken.
✓ Branch 28 → 29 taken 76 times.
✓ Branch 29 → 31 taken 76 times.
✓ Branch 32 → 33 taken 76 times.
✗ Branch 32 → 34 not taken.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 47 not taken.
76 return tip.isEmpty() ? element->property("name").toString() : tip;
56 101 }
57
58 9 void KeyHint::activate() {
59
4/7
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 7 taken 7 times.
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 7 not taken.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
9 static const QMetaMethod signal = QMetaMethod::fromSignal(&KeyHint::activated);
60
2/2
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 11 taken 8 times.
9 if (isSignalConnected(signal)) {
61 1 emit activated();
62 1 return;
63 }
64 8 QQuickItem *element = item();
65
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 8 times.
8 if (!element) return;
66 // A Controls button: click() runs its onClicked handler and the checked
67 // logic exactly like a pointer click.
68
1/2
✓ Branch 16 → 17 taken 8 times.
✗ Branch 16 → 19 not taken.
8 if (element->metaObject()->indexOfMethod("click()") >= 0) {
69 8 QMetaObject::invokeMethod(element, "click");
70 8 return;
71 }
72 // Older Controls have no click(): emitting clicked() runs onClicked.
73 ✗ if (element->metaObject()->indexOfSignal("clicked()") >= 0) {
74 ✗ QMetaObject::invokeMethod(element, "clicked");
75 ✗ return;
76 }
77 ✗ if (element->metaObject()->indexOfMethod("toggle()") >= 0) {
78 ✗ QMetaObject::invokeMethod(element, "toggle");
79 ✗ return;
80 }
81 ✗ focusPane();
82 }
83
84 1583 QString KeyHint::paneOf(const QQuickItem *item) {
85
2/2
✓ Branch 16 → 3 taken 10553 times.
✓ Branch 16 → 17 taken 908 times.
11461 for (const QQuickItem *current = item; current; current = current->parentItem())
86
8/8
✓ Branch 4 → 5 taken 2091 times.
✓ Branch 4 → 9 taken 8462 times.
✓ Branch 7 → 8 taken 675 times.
✓ Branch 7 → 9 taken 1416 times.
✓ Branch 10 → 11 taken 2091 times.
✓ Branch 10 → 12 taken 8462 times.
✓ Branch 12 → 13 taken 675 times.
✓ Branch 12 → 14 taken 9878 times.
10553 if (const KeyHint *hint = of(current); hint && !hint->pane().isEmpty()) return hint->pane();
87 908 return {};
88 }
89
90 491 void KeyHint::focusPane() {
91
2/2
✓ Branch 3 → 4 taken 45 times.
✓ Branch 3 → 5 taken 446 times.
491 QQuickItem *target = m_focusTarget ? m_focusTarget.data() : item();
92
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 491 times.
491 if (!target) return;
93 491 target->forceActiveFocus(Qt::ShortcutFocusReason);
94 // S105.9.10: a pane that is only a container (no Tab stop of its own,
95 // e.g. a sidebar's ScrollView) draws no focus ring; its first Tab stop
96 // takes the focus instead. A pane that moved the focus on by itself
97 // (the folder tree to the open folder) is left alone.
98 491 QQuickWindow *window = target->window();
99
7/8
✓ Branch 11 → 12 taken 448 times.
✓ Branch 11 → 15 taken 43 times.
✓ Branch 12 → 13 taken 448 times.
✗ Branch 12 → 15 not taken.
✓ Branch 14 → 15 taken 180 times.
✓ Branch 14 → 16 taken 268 times.
✓ Branch 17 → 18 taken 223 times.
✓ Branch 17 → 19 taken 268 times.
491 if (target->activeFocusOnTab() || !window || window->activeFocusItem() != target) return;
100 268 QQuickItem *next = target->nextItemInFocusChain(true);
101
7/8
✓ Branch 20 → 21 taken 268 times.
✗ Branch 20 → 25 not taken.
✓ Branch 21 → 22 taken 263 times.
✓ Branch 21 → 25 taken 5 times.
✓ Branch 23 → 24 taken 221 times.
✓ Branch 23 → 25 taken 42 times.
✓ Branch 26 → 27 taken 221 times.
✓ Branch 26 → 28 taken 47 times.
268 if (next && next != target && target->isAncestorOf(next)) next->forceActiveFocus(Qt::ShortcutFocusReason);
102 }
103