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.9% 91 / 0 / 92
Functions: 100.0% 9 / 0 / 9
Branches: 89.2% 166 / 0 / 186

data/SignaturePlacement.cpp
Line Branch Exec Source
1 #include "SignaturePlacement.h"
2
3 #include "ComposeDocumentFormat.h"
4 #include "MailTextWriter.h"
5
6 #include <QTextBlock>
7 #include <QTextCursor>
8 #include <QTextDocument>
9
10 using namespace ComposeDocumentFormat;
11
12 namespace SignaturePlacement {
13
14 namespace {
15
16 struct Range {
17 int start = -1; // position of the first signature block
18 int end = -1; // position after the last signature block's text
19 };
20
21 71 Range signatureRange(const QTextDocument &document) {
22 71 Range range;
23
5/5
✓ Branch 2 → 3 taken 71 times.
✓ Branch 13 → 14 taken 119 times.
✓ Branch 16 → 17 taken 190 times.
✓ Branch 17 → 4 taken 119 times.
✓ Branch 17 → 18 taken 71 times.
190 for (QTextBlock block = document.begin(); block.isValid(); block = block.next()) {
24
3/3
✓ Branch 4 → 5 taken 119 times.
✓ Branch 5 → 6 taken 81 times.
✓ Branch 5 → 7 taken 38 times.
119 if (region(block) != SignatureRegion) continue;
25
3/3
✓ Branch 7 → 8 taken 16 times.
✓ Branch 7 → 10 taken 22 times.
✓ Branch 8 → 9 taken 16 times.
38 if (range.start < 0) range.start = block.position();
26
2/2
✓ Branch 10 → 11 taken 38 times.
✓ Branch 11 → 12 taken 38 times.
38 range.end = block.position() + block.length() - 1;
27 }
28 71 return range;
29 }
30
31 44 int firstQuotePosition(const QTextDocument &document) {
32
5/5
✓ Branch 2 → 3 taken 44 times.
✓ Branch 8 → 9 taken 45 times.
✓ Branch 11 → 12 taken 89 times.
✓ Branch 12 → 4 taken 46 times.
✓ Branch 12 → 13 taken 43 times.
89 for (QTextBlock block = document.begin(); block.isValid(); block = block.next())
33
4/4
✓ Branch 4 → 5 taken 46 times.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 8 taken 45 times.
✓ Branch 6 → 7 taken 1 time.
46 if (region(block) == QuoteRegion) return block.position();
34 43 return -1;
35 }
36
37 44 void markSignature(QTextDocument &document, int start, int end) {
38
10/10
✓ Branch 2 → 3 taken 44 times.
✓ Branch 12 → 13 taken 128 times.
✓ Branch 15 → 16 taken 172 times.
✓ Branch 16 → 17 taken 129 times.
✓ Branch 16 → 20 taken 43 times.
✓ Branch 17 → 18 taken 129 times.
✓ Branch 18 → 19 taken 128 times.
✓ Branch 18 → 20 taken 1 time.
✓ Branch 21 → 4 taken 128 times.
✓ Branch 21 → 22 taken 44 times.
172 for (QTextBlock block = document.findBlock(start); block.isValid() && block.position() <= end; block = block.next()) {
39
1/1
✓ Branch 4 → 5 taken 128 times.
128 QTextCursor cursor(block);
40
1/1
✓ Branch 5 → 6 taken 128 times.
128 QTextBlockFormat format = block.blockFormat();
41
1/1
✓ Branch 7 → 8 taken 128 times.
128 format.setProperty(RegionProperty, SignatureRegion);
42
1/1
✓ Branch 9 → 10 taken 128 times.
128 cursor.setBlockFormat(format);
43 128 }
44 44 }
45
46 } // namespace
47
48 21 bool hasSignature(const QTextDocument &document) { return signatureRange(document).start >= 0; }
49
50 55 QString currentText(const QTextDocument &document) {
51 55 QStringList lines;
52
5/5
✓ Branch 2 → 3 taken 55 times.
✓ Branch 26 → 27 taken 235 times.
✓ Branch 29 → 30 taken 290 times.
✓ Branch 30 → 4 taken 235 times.
✓ Branch 30 → 31 taken 55 times.
290 for (QTextBlock block = document.begin(); block.isValid(); block = block.next()) {
53
3/3
✓ Branch 4 → 5 taken 235 times.
✓ Branch 5 → 6 taken 96 times.
✓ Branch 5 → 7 taken 139 times.
235 if (region(block) != SignatureRegion) continue;
54
12/16
✓ Branch 8 → 9 taken 71 times.
✓ Branch 8 → 15 taken 68 times.
✓ Branch 10 → 11 taken 71 times.
✓ Branch 11 → 12 taken 71 times.
✓ Branch 13 → 14 taken 21 times.
✓ Branch 13 → 15 taken 50 times.
✓ Branch 16 → 17 taken 71 times.
✓ Branch 16 → 18 taken 68 times.
✓ Branch 18 → 19 taken 71 times.
✓ Branch 18 → 20 taken 68 times.
✓ Branch 20 → 21 taken 21 times.
✓ Branch 20 → 22 taken 118 times.
✗ Branch 40 → 41 not taken.
✗ Branch 40 → 42 not taken.
✗ Branch 44 → 45 not taken.
✗ Branch 44 → 46 not taken.
139 if (lines.isEmpty() && block.text().trimmed() == QLatin1String("--")) continue;
55
2/2
✓ Branch 22 → 23 taken 118 times.
✓ Branch 23 → 24 taken 118 times.
118 lines.append(block.text());
56 }
57
2/2
✓ Branch 33 → 34 taken 55 times.
✓ Branch 34 → 35 taken 55 times.
110 return lines.join(QLatin1Char('\n')).trimmed();
58 55 }
59
60 10 bool isEdited(const QTextDocument &document, const QString &placedText) {
61
1/1
✓ Branch 2 → 3 taken 10 times.
10 QString placed = placedText.trimmed();
62
5/6
✓ Branch 5 → 6 taken 10 times.
✓ Branch 6 → 7 taken 10 times.
✓ Branch 7 → 8 taken 10 times.
✓ Branch 8 → 9 taken 10 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 19 taken 10 times.
10 if (placed.startsWith(MailTextWriter::signatureSeparator().trimmed() + QLatin1Char('\n')))
63 ✗ placed = placed.mid(3).trimmed();
64
1/1
✓ Branch 19 → 20 taken 10 times.
20 return currentText(document) != placed;
65 10 }
66
67 50 void remove(QTextDocument &document) {
68
1/1
✓ Branch 2 → 3 taken 50 times.
50 const Range range = signatureRange(document);
69
2/2
✓ Branch 3 → 4 taken 46 times.
✓ Branch 3 → 5 taken 4 times.
50 if (range.start < 0) return;
70 4 int from = range.start;
71 // The empty line that separated it from the text goes with it.
72
2/2
✓ Branch 5 → 6 taken 4 times.
✓ Branch 6 → 7 taken 4 times.
4 const QTextBlock before = document.findBlock(range.start).previous();
73
12/15
✓ Branch 7 → 8 taken 4 times.
✓ Branch 8 → 9 taken 3 times.
✓ Branch 8 → 17 taken 1 time.
✓ Branch 9 → 10 taken 3 times.
✓ Branch 10 → 11 taken 3 times.
✗ Branch 10 → 17 not taken.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 12 → 13 taken 3 times.
✗ Branch 12 → 17 not taken.
✓ Branch 13 → 14 taken 3 times.
✓ Branch 14 → 15 taken 3 times.
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 17 not taken.
✓ Branch 18 → 19 taken 3 times.
✓ Branch 18 → 21 taken 1 time.
4 if (before.isValid() && before.length() <= 1 && region(before) == NoRegion && before.previous().isValid())
74
1/1
✓ Branch 19 → 20 taken 3 times.
3 from = before.position();
75
1/1
✓ Branch 21 → 22 taken 4 times.
4 QTextCursor cursor(&document);
76
1/1
✓ Branch 22 → 23 taken 4 times.
4 cursor.beginEditBlock();
77
2/2
✓ Branch 23 → 24 taken 3 times.
✓ Branch 23 → 27 taken 1 time.
4 if (from > 0) {
78 // From the end of the block before: the paragraph separator goes too.
79
1/1
✓ Branch 24 → 25 taken 3 times.
3 cursor.setPosition(from - 1);
80
1/1
✓ Branch 25 → 26 taken 3 times.
3 cursor.setPosition(range.end, QTextCursor::KeepAnchor);
81
1/1
✓ Branch 26 → 35 taken 3 times.
3 cursor.removeSelectedText();
82 } else {
83
1/1
✓ Branch 27 → 28 taken 1 time.
1 cursor.setPosition(0);
84
1/1
✓ Branch 28 → 29 taken 1 time.
1 cursor.setPosition(range.end, QTextCursor::KeepAnchor);
85
1/1
✓ Branch 29 → 30 taken 1 time.
1 cursor.removeSelectedText();
86
1/1
✓ Branch 30 → 31 taken 1 time.
1 QTextBlockFormat format = cursor.blockFormat();
87
1/1
✓ Branch 31 → 32 taken 1 time.
1 format.clearProperty(RegionProperty);
88
1/1
✓ Branch 32 → 33 taken 1 time.
1 cursor.setBlockFormat(format);
89 1 }
90
1/1
✓ Branch 35 → 36 taken 4 times.
4 cursor.endEditBlock();
91 4 }
92
93 9 bool releaseOverwritten(QTextDocument &document) {
94
3/4
✓ Branch 2 → 3 taken 9 times.
✓ Branch 3 → 4 taken 9 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9 times.
9 if (region(document.begin()) != SignatureRegion) return false;
95
5/5
✓ Branch 6 → 7 taken 9 times.
✓ Branch 19 → 20 taken 10 times.
✓ Branch 22 → 23 taken 19 times.
✓ Branch 23 → 8 taken 10 times.
✓ Branch 23 → 24 taken 9 times.
19 for (QTextBlock block = document.begin(); block.isValid(); block = block.next()) {
96
2/3
✓ Branch 8 → 9 taken 10 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 10 times.
10 if (region(block) != SignatureRegion) continue;
97
1/1
✓ Branch 11 → 12 taken 10 times.
10 QTextCursor cursor(block);
98
1/1
✓ Branch 12 → 13 taken 10 times.
10 QTextBlockFormat format = block.blockFormat();
99
1/1
✓ Branch 13 → 14 taken 10 times.
10 format.clearProperty(RegionProperty);
100
1/1
✓ Branch 14 → 15 taken 10 times.
10 cursor.setBlockFormat(format);
101 10 }
102 9 return true;
103 }
104
105 49 void place(QTextDocument &document, const Content &content) {
106
1/1
✓ Branch 2 → 3 taken 49 times.
49 QTextCursor cursor(&document);
107
1/1
✓ Branch 3 → 4 taken 49 times.
49 cursor.beginEditBlock();
108
1/1
✓ Branch 4 → 5 taken 49 times.
49 remove(document);
109
8/12
✓ Branch 5 → 6 taken 49 times.
✓ Branch 7 → 8 taken 5 times.
✓ Branch 7 → 11 taken 44 times.
✓ Branch 8 → 9 taken 5 times.
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 11 not taken.
✓ Branch 12 → 13 taken 49 times.
✗ Branch 12 → 14 not taken.
✓ Branch 14 → 15 taken 5 times.
✓ Branch 14 → 17 taken 44 times.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 83 not taken.
49 if (content.text.trimmed().isEmpty() && content.fragment.isEmpty()) {
110
1/1
✓ Branch 15 → 16 taken 5 times.
5 cursor.endEditBlock();
111 5 return;
112 }
113
1/1
✓ Branch 17 → 18 taken 44 times.
44 const int quote = firstQuotePosition(document);
114
3/3
✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 20 taken 43 times.
✓ Branch 19 → 21 taken 1 time.
44 if (quote > 0) cursor.setPosition(quote - 1); // end of the block above the quote
115
1/1
✓ Branch 20 → 21 taken 43 times.
43 else cursor.movePosition(QTextCursor::End);
116
1/1
✓ Branch 21 → 22 taken 44 times.
44 const QTextBlock anchor = cursor.block();
117
1/1
✓ Branch 22 → 23 taken 44 times.
44 const QTextBlockFormat plain;
118 // Text, one empty line, the signature.
119
9/11
✓ Branch 23 → 24 taken 44 times.
✓ Branch 24 → 25 taken 40 times.
✓ Branch 24 → 28 taken 4 times.
✓ Branch 25 → 26 taken 40 times.
✓ Branch 26 → 27 taken 40 times.
✓ Branch 27 → 28 taken 40 times.
✗ Branch 27 → 29 not taken.
✓ Branch 30 → 31 taken 44 times.
✗ Branch 30 → 35 not taken.
✓ Branch 31 → 32 taken 44 times.
✓ Branch 32 → 33 taken 44 times.
44 if (anchor.length() > 1 || !anchor.previous().isValid()) cursor.insertBlock(plain, QTextCharFormat());
120
2/2
✓ Branch 35 → 36 taken 44 times.
✓ Branch 36 → 37 taken 44 times.
44 cursor.insertBlock(plain, QTextCharFormat());
121
1/1
✓ Branch 38 → 39 taken 44 times.
44 const int start = cursor.position();
122
6/7
✓ Branch 39 → 40 taken 23 times.
✓ Branch 39 → 43 taken 21 times.
✓ Branch 40 → 41 taken 23 times.
✓ Branch 41 → 42 taken 23 times.
✗ Branch 41 → 43 not taken.
✓ Branch 44 → 45 taken 23 times.
✓ Branch 44 → 46 taken 21 times.
44 if (content.formatted && !content.fragment.isEmpty()) {
123
1/1
✓ Branch 45 → 65 taken 23 times.
23 cursor.insertFragment(content.fragment);
124 } else {
125
1/1
✓ Branch 46 → 47 taken 21 times.
21 QString text = content.text.trimmed();
126
5/6
✓ Branch 48 → 49 taken 21 times.
✓ Branch 49 → 50 taken 21 times.
✗ Branch 49 → 60 not taken.
✓ Branch 52 → 53 taken 21 times.
✓ Branch 53 → 54 taken 21 times.
✓ Branch 54 → 55 taken 21 times.
21 if (!text.startsWith(QLatin1String("--"))) text = MailTextWriter::signatureSeparator() + QLatin1Char('\n') + text;
127
2/2
✓ Branch 60 → 61 taken 21 times.
✓ Branch 61 → 62 taken 21 times.
21 cursor.insertText(text, QTextCharFormat());
128 21 }
129
1/1
✓ Branch 65 → 66 taken 44 times.
44 const int end = cursor.position();
130
4/4
✓ Branch 66 → 67 taken 1 time.
✓ Branch 66 → 71 taken 43 times.
✓ Branch 67 → 68 taken 1 time.
✓ Branch 68 → 69 taken 1 time.
44 if (quote > 0) cursor.insertBlock(plain, QTextCharFormat()); // an empty line before the quote
131
1/1
✓ Branch 71 → 72 taken 44 times.
44 markSignature(document, start, end);
132
1/1
✓ Branch 72 → 73 taken 44 times.
44 cursor.endEditBlock();
133 49 }
134
135 } // namespace SignaturePlacement
136