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: 99.4% 164 / 0 / 165
Functions: 100.0% 9 / 0 / 9
Branches: 95.3% 262 / 0 / 275

data/RelationGraphRows.cpp
Line Branch Exec Source
1 #include "RelationGraphRows.h"
2
3 #include "RelationVocabulary.h"
4
5 #include <QMap>
6 #include <QSet>
7 #include <algorithm>
8 #include <cmath>
9 #include <vector>
10
11 namespace RelationGraphLayout {
12
13 namespace {
14
15 struct Neighbour {
16 int node = -1;
17 double weight = 1;
18 };
19
20 } // namespace
21
22 6390 QList<double> place(const QList<double> &targets, double gap) {
23 struct Block {
24 double sum = 0;
25 int count = 0;
26 36219 double mean() const { return sum / count; }
27 };
28 6390 std::vector<Block> blocks;
29
2/2
✓ Branch 26 → 3 taken 15661 times.
✓ Branch 26 → 27 taken 6390 times.
22051 for (int k = 0; k < targets.size(); ++k) {
30
1/1
✓ Branch 4 → 5 taken 15661 times.
15661 blocks.push_back({targets.at(k) - k * gap, 1});
31
6/6
✓ Branch 14 → 15 taken 10279 times.
✓ Branch 14 → 22 taken 7514 times.
✓ Branch 20 → 21 taken 2132 times.
✓ Branch 20 → 22 taken 8147 times.
✓ Branch 23 → 6 taken 2132 times.
✓ Branch 23 → 24 taken 15661 times.
17793 while (blocks.size() > 1 && blocks[blocks.size() - 2].mean() > blocks.back().mean()) {
32 2132 blocks[blocks.size() - 2].sum += blocks.back().sum;
33 2132 blocks[blocks.size() - 2].count += blocks.back().count;
34 2132 blocks.pop_back();
35 }
36 }
37 6390 QList<double> out;
38
2/2
✓ Branch 38 → 29 taken 13529 times.
✓ Branch 38 → 39 taken 6390 times.
19919 for (const Block &block : blocks)
39
2/2
✓ Branch 35 → 31 taken 15661 times.
✓ Branch 35 → 36 taken 13529 times.
29190 for (int i = 0; i < block.count; ++i)
40
1/1
✓ Branch 33 → 34 taken 15661 times.
15661 out.append(block.mean() + double(out.size()) * gap);
41 6390 return out;
42 6390 }
43
44 namespace {
45
46 // The weighted mean x of the neighbours of the strongest kind only: a
47 // parent or child decides alone, an aunt or an in-law counts only for
48 // someone without either (otherwise a mother stands off-centre over her sons
49 // because of her daughter-in-law).
50 15128 double meanOf(const QList<Neighbour> &neighbours, const QHash<int, double> &x, bool *found) {
51 15128 double strongest = 0;
52
2/2
✓ Branch 8 → 4 taken 8016 times.
✓ Branch 8 → 9 taken 15128 times.
23144 for (const Neighbour &n : neighbours)
53 8016 strongest = std::max(strongest, n.weight);
54 15128 double sum = 0, weight = 0;
55
2/2
✓ Branch 18 → 11 taken 8016 times.
✓ Branch 18 → 19 taken 15128 times.
23144 for (const Neighbour &n : neighbours) {
56
2/2
✓ Branch 12 → 13 taken 1272 times.
✓ Branch 12 → 14 taken 6744 times.
8016 if (n.weight < strongest)
57 1272 continue;
58 6744 sum += x.value(n.node) * n.weight;
59 6744 weight += n.weight;
60 }
61 15128 *found = weight > 0;
62
2/2
✓ Branch 19 → 20 taken 5152 times.
✓ Branch 19 → 21 taken 9976 times.
15128 return weight > 0 ? sum / weight : 0;
63 }
64
65 } // namespace
66
67 409 QHash<int, QPointF> rows(const RelationGraph::Graph &graph, const QList<int> &nodes,
68 const QHash<int, int> &generation) {
69 409 QMap<int, QList<int>> byGeneration;
70
2/2
✓ Branch 10 → 4 taken 1891 times.
✓ Branch 10 → 11 taken 409 times.
2300 for (int node : nodes)
71
2/2
✓ Branch 6 → 7 taken 1891 times.
✓ Branch 7 → 8 taken 1891 times.
1891 byGeneration[generation.value(node, 0)].append(node);
72
1/1
✓ Branch 13 → 14 taken 409 times.
409 const QSet<int> members(nodes.cbegin(), nodes.cend());
73 409 QHash<int, QList<Neighbour>> above, below; // parents (one row up), children (one row down)
74 409 QHash<int, int> partnerOf;
75 409 QSet<QPair<int, int>> siblings;
76 409 QList<const RelationGraph::Edge *> partnerEdges;
77
2/2
✓ Branch 72 → 17 taken 238649 times.
✓ Branch 72 → 73 taken 409 times.
239058 for (const RelationGraph::Edge &edge : graph.edges) {
78 238649 int step = 0;
79
10/11
✓ Branch 18 → 19 taken 238649 times.
✗ Branch 18 → 25 not taken.
✓ Branch 20 → 21 taken 3263 times.
✓ Branch 20 → 25 taken 235386 times.
✓ Branch 22 → 23 taken 2344 times.
✓ Branch 22 → 25 taken 919 times.
✓ Branch 23 → 24 taken 2344 times.
✓ Branch 24 → 25 taken 44 times.
✓ Branch 24 → 26 taken 2300 times.
✓ Branch 27 → 28 taken 236349 times.
✓ Branch 27 → 29 taken 2300 times.
238649 if (edge.from == edge.to || !members.contains(edge.from) || !members.contains(edge.to) || !kinStep(edge, &step))
80 236349 continue;
81 2300 const int gf = generation.value(edge.from, 0), gt = generation.value(edge.to, 0);
82 // Parents pull hardest; an aunt or an in-law only a little.
83
3/3
✓ Branch 31 → 32 taken 2300 times.
✓ Branch 32 → 33 taken 781 times.
✓ Branch 32 → 34 taken 1519 times.
2300 const double weight = isParentEdge(edge) ? 1.0 : 0.25;
84
2/2
✓ Branch 35 → 36 taken 898 times.
✓ Branch 35 → 41 taken 1402 times.
2300 if (gt == gf + 1) {
85
2/2
✓ Branch 36 → 37 taken 898 times.
✓ Branch 37 → 38 taken 898 times.
898 above[edge.from].append({edge.to, weight});
86
2/2
✓ Branch 38 → 39 taken 898 times.
✓ Branch 39 → 40 taken 898 times.
898 below[edge.to].append({edge.from, weight});
87
2/2
✓ Branch 41 → 42 taken 104 times.
✓ Branch 41 → 47 taken 1298 times.
1402 } else if (gf == gt + 1) {
88
2/2
✓ Branch 42 → 43 taken 104 times.
✓ Branch 43 → 44 taken 104 times.
104 above[edge.to].append({edge.from, weight});
89
2/2
✓ Branch 44 → 45 taken 104 times.
✓ Branch 45 → 46 taken 104 times.
104 below[edge.from].append({edge.to, weight});
90
9/11
✓ Branch 47 → 48 taken 1080 times.
✓ Branch 47 → 53 taken 218 times.
✓ Branch 49 → 50 taken 1080 times.
✓ Branch 51 → 52 taken 538 times.
✓ Branch 51 → 53 taken 542 times.
✓ Branch 54 → 55 taken 1080 times.
✓ Branch 54 → 56 taken 218 times.
✓ Branch 56 → 57 taken 538 times.
✓ Branch 56 → 62 taken 760 times.
✗ Branch 243 → 244 not taken.
✗ Branch 243 → 245 not taken.
1298 } else if (gf == gt && RelationVocabulary::canonical(edge.type) == QLatin1String("sibling")) {
91
1/1
✓ Branch 60 → 61 taken 538 times.
538 siblings.insert({std::min(edge.from, edge.to), std::max(edge.from, edge.to)});
92
7/7
✓ Branch 62 → 63 taken 542 times.
✓ Branch 62 → 66 taken 218 times.
✓ Branch 63 → 64 taken 542 times.
✓ Branch 64 → 65 taken 431 times.
✓ Branch 64 → 66 taken 111 times.
✓ Branch 67 → 68 taken 431 times.
✓ Branch 67 → 69 taken 329 times.
760 } else if (gf == gt && isPartnerEdge(edge)) {
93
1/1
✓ Branch 68 → 69 taken 431 times.
431 partnerEdges.append(&edge);
94 }
95 }
96 // One partner per person beside them: a spouse before an ex-partner, else the first stored.
97
3/3
✓ Branch 73 → 74 taken 409 times.
✓ Branch 74 → 75 taken 409 times.
✓ Branch 75 → 76 taken 409 times.
409 std::stable_sort(partnerEdges.begin(), partnerEdges.end(), [](const RelationGraph::Edge *a, const RelationGraph::Edge *b) {
98
3/5
✓ Branch 3 → 4 taken 366 times.
✓ Branch 5 → 6 taken 358 times.
✓ Branch 5 → 11 taken 8 times.
✗ Branch 23 → 24 not taken.
✗ Branch 23 → 25 not taken.
1090 return RelationVocabulary::canonical(a->type) == QLatin1String("spouse") &&
99
6/9
✓ Branch 7 → 8 taken 358 times.
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 356 times.
✓ Branch 12 → 13 taken 358 times.
✓ Branch 12 → 14 taken 8 times.
✓ Branch 14 → 15 taken 366 times.
✗ Branch 14 → 16 not taken.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
1090 RelationVocabulary::canonical(b->type) != QLatin1String("spouse");
100 });
101
2/2
✓ Branch 91 → 79 taken 431 times.
✓ Branch 91 → 92 taken 409 times.
840 for (const RelationGraph::Edge *edge : std::as_const(partnerEdges))
102
6/6
✓ Branch 81 → 82 taken 402 times.
✓ Branch 81 → 85 taken 29 times.
✓ Branch 83 → 84 taken 335 times.
✓ Branch 83 → 85 taken 67 times.
✓ Branch 86 → 87 taken 335 times.
✓ Branch 86 → 89 taken 96 times.
431 if (!partnerOf.contains(edge->from) && !partnerOf.contains(edge->to)) {
103
1/1
✓ Branch 87 → 88 taken 335 times.
335 partnerOf.insert(edge->from, edge->to);
104
1/1
✓ Branch 88 → 89 taken 335 times.
335 partnerOf.insert(edge->to, edge->from);
105 }
106 // The other members of the same family areas: someone joined to the family
107 // only by its card (no parent or child shown) stands beside them, not on
108 // the far side of another family of the block.
109 409 QHash<int, QList<int>> areaMates;
110
2/2
✓ Branch 125 → 94 taken 77 times.
✓ Branch 125 → 126 taken 409 times.
486 for (const RelationGraph::Area &area : graph.areas)
111
2/2
✓ Branch 122 → 97 taken 175 times.
✓ Branch 122 → 123 taken 77 times.
252 for (int member : area.members)
112
2/2
✓ Branch 99 → 100 taken 126 times.
✓ Branch 99 → 120 taken 49 times.
175 if (members.contains(member))
113
2/2
✓ Branch 118 → 102 taken 370 times.
✓ Branch 118 → 119 taken 126 times.
496 for (int mate : area.members)
114
8/10
✓ Branch 103 → 104 taken 244 times.
✓ Branch 103 → 110 taken 126 times.
✓ Branch 105 → 106 taken 244 times.
✗ Branch 105 → 110 not taken.
✓ Branch 108 → 109 taken 244 times.
✗ Branch 108 → 110 not taken.
✓ Branch 111 → 112 taken 244 times.
✓ Branch 111 → 113 taken 126 times.
✓ Branch 113 → 114 taken 244 times.
✓ Branch 113 → 116 taken 126 times.
370 if (mate != member && members.contains(mate) && !areaMates.value(member).contains(mate))
115
2/2
✓ Branch 114 → 115 taken 244 times.
✓ Branch 115 → 116 taken 244 times.
244 areaMates[member].append(mate);
116 // Start: every row in household order (siblings together, partners side
117 // by side, see households), centred.
118 409 QHash<int, double> x;
119 409 QHash<int, QList<QList<int>>> householdsOf; // generation → its households
120
4/4
✓ Branch 126 → 127 taken 409 times.
✓ Branch 153 → 154 taken 1172 times.
✓ Branch 155 → 128 taken 763 times.
✓ Branch 155 → 156 taken 409 times.
1172 for (auto it = byGeneration.begin(); it != byGeneration.end(); ++it) {
121 763 QList<int> &row = it.value();
122
2/2
✓ Branch 129 → 130 taken 763 times.
✓ Branch 131 → 132 taken 763 times.
763 householdsOf.insert(it.key(), households(graph, row, siblings, partnerOf));
123
1/1
✓ Branch 133 → 134 taken 763 times.
763 row.clear();
124
4/4
✓ Branch 136 → 137 taken 763 times.
✓ Branch 137 → 138 taken 763 times.
✓ Branch 143 → 139 taken 1046 times.
✓ Branch 143 → 144 taken 763 times.
1809 for (const QList<int> &household : householdsOf.value(it.key()))
125
1/1
✓ Branch 140 → 141 taken 1046 times.
1809 row += household;
126
2/2
✓ Branch 151 → 146 taken 1891 times.
✓ Branch 151 → 152 taken 763 times.
2654 for (int k = 0; k < row.size(); ++k)
127
1/1
✓ Branch 148 → 149 taken 1891 times.
1891 x.insert(row.at(k), (k - (row.size() - 1) / 2.0) * TreeGap);
128 }
129 // Where each person of a row wants to stand: over their children (upward)
130 // or under their parents (downward). Partners stay a pair: with one shared
131 // target the pair is centred on it, with a target for one only the other
132 // stands beside them. `onlyParentless` (the last step) moves nobody who has
133 // parents in the graph.
134 6104 const auto targetsOf = [&](const QList<int> &row, bool downward, bool onlyParentless) {
135 6104 QHash<int, double> target;
136
2/2
✓ Branch 53 → 4 taken 15128 times.
✓ Branch 53 → 54 taken 6104 times.
21232 for (int node : row) {
137 15128 bool found = false;
138
3/3
✓ Branch 5 → 6 taken 7564 times.
✓ Branch 5 → 7 taken 7564 times.
✓ Branch 8 → 9 taken 15128 times.
15128 const double mean = meanOf(downward ? above.value(node) : below.value(node), x, &found);
139
10/10
✓ Branch 10 → 11 taken 5152 times.
✓ Branch 10 → 16 taken 9976 times.
✓ Branch 11 → 12 taken 624 times.
✓ Branch 11 → 15 taken 4528 times.
✓ Branch 14 → 15 taken 356 times.
✓ Branch 14 → 16 taken 268 times.
✓ Branch 17 → 18 taken 624 times.
✓ Branch 17 → 19 taken 14504 times.
✓ Branch 19 → 20 taken 4884 times.
✓ Branch 19 → 21 taken 10244 times.
15128 if (found && !(onlyParentless && !above.value(node).isEmpty()))
140
1/1
✓ Branch 20 → 51 taken 4884 times.
4884 target.insert(node, mean);
141
11/12
✓ Branch 23 → 24 taken 8392 times.
✓ Branch 23 → 30 taken 1852 times.
✓ Branch 26 → 27 taken 6968 times.
✓ Branch 26 → 30 taken 1424 times.
✓ Branch 28 → 29 taken 112 times.
✓ Branch 28 → 30 taken 6856 times.
✓ Branch 31 → 32 taken 8392 times.
✓ Branch 31 → 33 taken 1852 times.
✓ Branch 33 → 34 taken 10244 times.
✗ Branch 33 → 35 not taken.
✓ Branch 35 → 36 taken 112 times.
✓ Branch 35 → 51 taken 10132 times.
10244 else if (above.value(node).isEmpty() && below.value(node).isEmpty() && areaMates.contains(node)) {
142 112 double sum = 0;
143
4/4
✓ Branch 37 → 38 taken 112 times.
✓ Branch 38 → 39 taken 112 times.
✓ Branch 44 → 40 taken 224 times.
✓ Branch 44 → 45 taken 112 times.
336 for (int mate : areaMates.value(node))
144 336 sum += x.value(mate);
145
1/1
✓ Branch 48 → 49 taken 112 times.
112 target.insert(node, sum / areaMates.value(node).size());
146 }
147 }
148
2/2
✓ Branch 118 → 56 taken 15128 times.
✓ Branch 118 → 119 taken 6104 times.
21232 for (int node : row) {
149 15128 const int partner = partnerOf.value(node, -1);
150
5/6
✓ Branch 58 → 59 taken 2680 times.
✓ Branch 58 → 61 taken 12448 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 2680 times.
✓ Branch 63 → 64 taken 12448 times.
✓ Branch 63 → 65 taken 2680 times.
15128 if (partner < node || !row.contains(partner))
151 12448 continue; // each pair once, both in this row
152
2/2
✓ Branch 67 → 68 taken 2240 times.
✓ Branch 67 → 69 taken 440 times.
2680 const int left = x.value(node) <= x.value(partner) ? node : partner;
153
2/2
✓ Branch 70 → 71 taken 440 times.
✓ Branch 70 → 72 taken 2240 times.
2680 const int right = left == node ? partner : node;
154
12/12
✓ Branch 73 → 74 taken 335 times.
✓ Branch 73 → 81 taken 2345 times.
✓ Branch 76 → 77 taken 218 times.
✓ Branch 76 → 80 taken 117 times.
✓ Branch 79 → 80 taken 20 times.
✓ Branch 79 → 81 taken 198 times.
✓ Branch 82 → 83 taken 218 times.
✓ Branch 82 → 84 taken 2462 times.
✓ Branch 84 → 85 taken 335 times.
✓ Branch 84 → 86 taken 2345 times.
✓ Branch 86 → 87 taken 137 times.
✓ Branch 86 → 89 taken 2543 times.
2680 if (onlyParentless && (!above.value(left).isEmpty() || !above.value(right).isEmpty())) {
155
1/1
✓ Branch 87 → 88 taken 137 times.
137 target.remove(left);
156
1/1
✓ Branch 88 → 115 taken 137 times.
137 target.remove(right);
157
8/8
✓ Branch 90 → 91 taken 959 times.
✓ Branch 90 → 98 taken 1584 times.
✓ Branch 92 → 93 taken 594 times.
✓ Branch 92 → 98 taken 365 times.
✓ Branch 96 → 97 taken 388 times.
✓ Branch 96 → 98 taken 206 times.
✓ Branch 99 → 100 taken 388 times.
✓ Branch 99 → 104 taken 2155 times.
3137 } else if (target.contains(left) && target.contains(right) &&
158 594 std::abs(target.value(left) - target.value(right)) < 1) {
159 388 const double middle = target.value(left);
160
1/1
✓ Branch 101 → 102 taken 388 times.
388 target.insert(left, middle - TreeGap / 2);
161
1/1
✓ Branch 102 → 103 taken 388 times.
388 target.insert(right, middle + TreeGap / 2);
162
2/2
✓ Branch 106 → 107 taken 564 times.
✓ Branch 106 → 115 taken 1591 times.
2155 } else if (target.contains(left) != target.contains(right)) {
163
2/2
✓ Branch 108 → 109 taken 365 times.
✓ Branch 108 → 112 taken 199 times.
564 if (target.contains(left))
164
1/1
✓ Branch 110 → 111 taken 365 times.
365 target.insert(right, target.value(left) + TreeGap);
165 else
166
1/1
✓ Branch 113 → 114 taken 199 times.
199 target.insert(left, target.value(right) - TreeGap);
167 }
168 }
169
2/2
✓ Branch 129 → 121 taken 15128 times.
✓ Branch 129 → 130 taken 6104 times.
21232 for (int node : row)
170
2/2
✓ Branch 123 → 124 taken 9583 times.
✓ Branch 123 → 127 taken 5545 times.
15128 if (!target.contains(node))
171
1/1
✓ Branch 125 → 126 taken 9583 times.
9583 target.insert(node, x.value(node));
172 6104 return target;
173 ✗ };
174 // One pass orders and places every row by its neighbours in one direction:
175 // each household as a whole, at the mean of its people's targets, its
176 // people side by side around it in their fixed order.
177 2863 const auto pass = [&](bool downward) {
178
1/1
✓ Branch 2 → 3 taken 2863 times.
2863 QList<int> order = byGeneration.keys();
179
2/2
✓ Branch 3 → 4 taken 1636 times.
✓ Branch 3 → 7 taken 1227 times.
2863 if (downward)
180
3/3
✓ Branch 4 → 5 taken 1636 times.
✓ Branch 5 → 6 taken 1636 times.
✓ Branch 6 → 7 taken 1636 times.
1636 std::reverse(order.begin(), order.end()); // oldest first
181
2/2
✓ Branch 51 → 10 taken 5341 times.
✓ Branch 51 → 52 taken 2863 times.
8204 for (int gen : std::as_const(order)) {
182
2/2
✓ Branch 12 → 13 taken 5341 times.
✓ Branch 13 → 14 taken 5341 times.
5341 const QHash<int, double> target = targetsOf(byGeneration.value(gen), downward, false);
183
1/1
✓ Branch 16 → 17 taken 5341 times.
5341 QList<QList<int>> &units = householdsOf[gen];
184 13128 const auto meanTarget = [&](const QList<int> &unit) {
185 13128 double sum = 0;
186
2/2
✓ Branch 8 → 4 taken 23902 times.
✓ Branch 8 → 9 taken 13128 times.
37030 for (int node : unit)
187 23902 sum += target.value(node);
188 13128 return sum / unit.size();
189 5341 };
190 // Targets closer than half a pixel are one target (weighted means
191 // differ in the last bits): the current order decides.
192
3/3
✓ Branch 17 → 18 taken 5341 times.
✓ Branch 18 → 19 taken 5341 times.
✓ Branch 19 → 20 taken 5341 times.
5341 std::stable_sort(units.begin(), units.end(), [&](const QList<int> &a, const QList<int> &b) {
193 2903 const double ta = meanTarget(a), tb = meanTarget(b);
194
2/2
✓ Branch 5 → 6 taken 2734 times.
✓ Branch 5 → 7 taken 169 times.
2903 return std::abs(ta - tb) >= 0.5 ? ta < tb : x.value(a.first()) < x.value(b.first());
195 });
196
1/1
✓ Branch 20 → 21 taken 5341 times.
5341 QList<int> &row = byGeneration[gen];
197
1/1
✓ Branch 21 → 22 taken 5341 times.
5341 row.clear();
198 5341 QList<double> targets;
199
2/2
✓ Branch 37 → 25 taken 7322 times.
✓ Branch 37 → 38 taken 5341 times.
12663 for (const QList<int> &unit : std::as_const(units)) {
200
1/1
✓ Branch 26 → 27 taken 7322 times.
7322 const double middle = meanTarget(unit);
201
2/2
✓ Branch 34 → 28 taken 13237 times.
✓ Branch 34 → 35 taken 7322 times.
20559 for (int k = 0; k < unit.size(); ++k) {
202
1/1
✓ Branch 29 → 30 taken 13237 times.
13237 row.append(unit.at(k));
203
1/1
✓ Branch 31 → 32 taken 13237 times.
13237 targets.append(middle + (k - (unit.size() - 1) / 2.0) * TreeGap);
204 }
205 }
206
1/1
✓ Branch 38 → 39 taken 5341 times.
5341 const QList<double> placed = place(targets, TreeGap);
207
2/2
✓ Branch 45 → 40 taken 13237 times.
✓ Branch 45 → 46 taken 5341 times.
18578 for (int k = 0; k < row.size(); ++k)
208
1/1
✓ Branch 42 → 43 taken 13237 times.
13237 x.insert(row.at(k), placed.at(k));
209 5341 }
210 2863 };
211
2/2
✓ Branch 160 → 157 taken 1227 times.
✓ Branch 160 → 161 taken 409 times.
1636 for (int round = 0; round < 3; ++round) {
212
1/1
✓ Branch 157 → 158 taken 1227 times.
1227 pass(true);
213
1/1
✓ Branch 158 → 159 taken 1227 times.
1227 pass(false);
214 }
215
1/1
✓ Branch 161 → 162 taken 409 times.
409 pass(true); // children end under their parents
216 // Then people without parents in the graph settle over their children,
217 // unless that would change the order of their row.
218
4/4
✓ Branch 162 → 163 taken 409 times.
✓ Branch 199 → 200 taken 1172 times.
✓ Branch 201 → 164 taken 763 times.
✓ Branch 201 → 202 taken 409 times.
1172 for (auto it = byGeneration.begin(); it != byGeneration.end(); ++it) {
219 763 const QList<int> &row = it.value();
220
1/1
✓ Branch 165 → 166 taken 763 times.
763 const QHash<int, double> target = targetsOf(row, false, true);
221 763 QList<double> targets;
222
2/2
✓ Branch 173 → 168 taken 1891 times.
✓ Branch 173 → 174 taken 763 times.
2654 for (int node : row)
223
1/1
✓ Branch 170 → 171 taken 1891 times.
1891 targets.append(target.value(node));
224
3/3
✓ Branch 176 → 177 taken 763 times.
✓ Branch 177 → 178 taken 10 times.
✓ Branch 177 → 179 taken 753 times.
763 if (!std::is_sorted(targets.cbegin(), targets.cend()))
225 10 continue;
226
1/1
✓ Branch 179 → 180 taken 753 times.
753 const QList<double> placed = place(targets, TreeGap);
227
2/2
✓ Branch 186 → 181 taken 1809 times.
✓ Branch 186 → 187 taken 753 times.
2562 for (int k = 0; k < row.size(); ++k)
228
1/1
✓ Branch 183 → 184 taken 1809 times.
1809 x.insert(row.at(k), placed.at(k));
229 773 }
230 409 double sum = 0;
231
2/2
✓ Branch 208 → 204 taken 1891 times.
✓ Branch 208 → 209 taken 409 times.
2300 for (int node : nodes)
232 1891 sum += x.value(node);
233
1/2
✗ Branch 210 → 211 not taken.
✓ Branch 210 → 212 taken 409 times.
409 const double shift = nodes.isEmpty() ? 0 : sum / nodes.size();
234 409 QHash<int, QPointF> out;
235
2/2
✓ Branch 223 → 216 taken 1891 times.
✓ Branch 223 → 224 taken 409 times.
2300 for (int node : nodes)
236
1/1
✓ Branch 220 → 221 taken 1891 times.
1891 out.insert(node, QPointF(x.value(node) - shift, -generation.value(node, 0) * TreeRowHeight));
237 409 return out;
238 409 }
239
240 } // namespace RelationGraphLayout
241