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: 92.5% 62 / 0 / 67
Functions: 100.0% 7 / 0 / 7
Branches: 60.3% 44 / 0 / 73

presentation/ComposePreview.cpp
Line Branch Exec Source
1 #include "ComposePreview.h"
2 #include "ComposeLog.h"
3 #include "ComposeSession.h"
4
5 #include "service/NativeMailDocument.h"
6
7 #include <QCoreApplication>
8 #include <QElapsedTimer>
9 #include <QQuickTextDocument>
10 #include <QTextCursor>
11 #include <QTextDocumentFragment>
12 #include <QThreadPool>
13
14 6 void ComposePreview::build(QObject *sessionObject) {
15
1/1
✓ Branch 2 → 3 taken 6 times.
6 auto *session = qobject_cast<ComposeSession *>(sessionObject);
16 6 const quint64 generation = ++m_generation;
17 6 m_ready = false;
18 6 m_notice.clear();
19
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 6 times.
6 if (!session) {
20 ✗ emit changed();
21 ✗ return;
22 }
23
1/1
✓ Branch 8 → 9 taken 6 times.
6 const ComposeMessage message = session->message(ComposeMessage::Form::Smtp);
24
2/4
✓ Branch 9 → 10 taken 6 times.
✗ Branch 9 → 13 not taken.
✓ Branch 11 → 12 taken 6 times.
✗ Branch 11 → 13 not taken.
6 m_formatted = message.formatted && !message.html.isEmpty();
25 6 m_plainText = message.text;
26 6 m_subject = message.subject;
27
2/2
✓ Branch 16 → 17 taken 6 times.
✓ Branch 20 → 21 taken 6 times.
12 m_recipients = (message.to + message.cc).join(QStringLiteral(", "));
28
1/1
✓ Branch 26 → 27 taken 6 times.
6 m_fragment.reset();
29
1/1
✓ Branch 27 → 28 taken 6 times.
6 fill();
30
2/2
✓ Branch 29 → 30 taken 4 times.
✓ Branch 29 → 34 taken 2 times.
6 if (!message.inlineImages.isEmpty())
31
1/1
✓ Branch 30 → 31 taken 4 times.
4 m_notice = tr("Pictures in the text appear here as their descriptions.");
32
1/2
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 37 taken 6 times.
6 if (!m_formatted) {
33 ✗ m_ready = true;
34 ✗ emit changed();
35 ✗ return;
36 }
37
1/1
✓ Branch 37 → 38 taken 6 times.
6 emit changed();
38
1/1
✓ Branch 38 → 39 taken 6 times.
6 const QByteArray html = message.html.toUtf8();
39
1/1
✓ Branch 39 → 40 taken 6 times.
6 QPointer<ComposePreview> self(this);
40
2/4
✓ Branch 40 → 41 taken 6 times.
✓ Branch 43 → 44 taken 6 times.
✗ Branch 67 → 68 not taken.
✗ Branch 67 → 69 not taken.
6 QThreadPool::globalInstance()->start([self, generation, html] {
41 6 QElapsedTimer timer;
42 6 timer.start();
43
1/1
✓ Branch 3 → 4 taken 6 times.
6 const NativeMailDocument document = NativeMailDocument::prepare(html);
44 6 QSharedPointer<const QTextDocumentFragment> fragment = document.fragment;
45 6 const bool limited = document.outcome != NativeMailDocument::Outcome::Ready;
46
3/6
✓ Branch 5 → 6 taken 6 times.
✗ Branch 5 → 9 not taken.
✓ Branch 7 → 8 taken 6 times.
✗ Branch 7 → 9 not taken.
✓ Branch 10 → 11 taken 6 times.
✗ Branch 10 → 17 not taken.
6 if (!limited && !fragment)
47
2/2
✓ Branch 11 → 12 taken 6 times.
✓ Branch 12 → 13 taken 6 times.
6 fragment = QSharedPointer<const QTextDocumentFragment>::create(QTextDocumentFragment::fromHtml(document.html));
48 // As the reader (NativeDocumentService): Qt 6.8 creates a fragment's
49 // root frame lazily on first traversal — materialize it here, so the
50 // GUI-thread insertion never creates children of this thread's objects.
51
2/3
✓ Branch 18 → 19 taken 6 times.
✗ Branch 18 → 23 not taken.
✓ Branch 20 → 21 taken 6 times.
6 if (fragment) (void)fragment->toHtml();
52
2/8
✓ Branch 23 → 24 taken 6 times.
✗ Branch 27 → 28 not taken.
✗ Branch 28 → 29 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 31 → 32 not taken.
✗ Branch 32 → 33 not taken.
✗ Branch 36 → 25 not taken.
✓ Branch 36 → 37 taken 6 times.
6 qCInfo(lcCompose) << "preview prepared ms" << timer.elapsed() << "limited" << limited;
53
1/1
✓ Branch 40 → 41 taken 6 times.
6 QMetaObject::invokeMethod(
54 6 qApp,
55
0/4
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 59 not taken.
✗ Branch 60 → 61 not taken.
✗ Branch 60 → 62 not taken.
12 [self, generation, fragment, limited] {
56
3/6
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 6 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 6 times.
6 if (!self || generation != self->m_generation) return;
57
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 6 times.
6 self->m_fragment = limited ? nullptr : fragment;
58 6 self->fill();
59
1/3
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 25 taken 6 times.
✗ Branch 20 → 21 not taken.
6 if (limited) self->m_notice = tr("This message is too large or complex for the preview; the plain part is shown.");
60 6 self->m_formatted = !limited;
61 6 self->m_ready = true;
62 6 emit self->changed();
63 },
64 Qt::QueuedConnection);
65 6 });
66 6 }
67
68 5 void ComposePreview::clear() {
69 5 ++m_generation;
70 5 m_ready = false;
71 5 m_fragment.reset();
72 5 m_plainText.clear();
73 5 fill();
74 5 emit changed();
75 5 }
76
77 284 void ComposePreview::attachDocument(QObject *quickTextDocument) {
78 284 auto *quick = qobject_cast<QQuickTextDocument *>(quickTextDocument);
79
2/2
✓ Branch 3 → 4 taken 142 times.
✓ Branch 3 → 6 taken 142 times.
284 m_target = quick ? quick->textDocument() : nullptr;
80 284 fill();
81 284 }
82
83 301 void ComposePreview::fill() {
84
2/2
✓ Branch 3 → 4 taken 142 times.
✓ Branch 3 → 5 taken 159 times.
454 if (!m_target) return;
85
1/1
✓ Branch 6 → 7 taken 159 times.
159 m_target->clear();
86
2/2
✓ Branch 8 → 9 taken 153 times.
✓ Branch 8 → 10 taken 6 times.
159 if (!m_fragment) return;
87
1/1
✓ Branch 11 → 12 taken 6 times.
6 QTextCursor cursor(m_target);
88
1/1
✓ Branch 13 → 14 taken 6 times.
6 cursor.insertFragment(*m_fragment);
89 6 }
90
91
1/2
✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 6 not taken.
1 QString ComposePreview::renderedText() const { return m_fragment ? m_fragment->toPlainText() : QString(); }
92