data/RelationGraphEgo.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // The ego layout of the relationship graph (declared in RelationGraphLayout.h, | ||
| 2 | // split from RelationGraphLayout.cpp): the centre inside its family tree, | ||
| 3 | // the other relationships in columns beside it. | ||
| 4 | #include "RelationGraphLayout.h" | ||
| 5 | |||
| 6 | #include "RelationGraphBlocks.h" | ||
| 7 | #include "RelationGraphRows.h" | ||
| 8 | #include "RelationVocabulary.h" | ||
| 9 | |||
| 10 | #include <algorithm> | ||
| 11 | |||
| 12 | namespace RelationGraphLayout { | ||
| 13 | |||
| 14 | namespace { | ||
| 15 | |||
| 16 | // What `node` is to the centre (canonical type; "" when only an introduction or a layer links them). | ||
| 17 | 838 | QString typeToCentre(const RelationGraph::Graph &graph, int centre, int node) { | |
| 18 | 838 | QString best; | |
| 19 |
2/2✓ Branch 47 → 4 taken 39150 times.
✓ Branch 47 → 48 taken 838 times.
|
39988 | for (const RelationGraph::Edge &e : graph.edges) { |
| 20 |
8/8✓ Branch 5 → 6 taken 3062 times.
✓ Branch 5 → 8 taken 36088 times.
✓ Branch 6 → 7 taken 154 times.
✓ Branch 6 → 8 taken 2908 times.
✓ Branch 9 → 10 taken 7510 times.
✓ Branch 9 → 12 taken 31640 times.
✓ Branch 10 → 11 taken 86 times.
✓ Branch 10 → 12 taken 7424 times.
|
39150 | const bool out = e.from == centre && e.to == node, in = e.to == centre && e.from == node; |
| 21 |
9/10✓ Branch 13 → 14 taken 38996 times.
✓ Branch 13 → 15 taken 154 times.
✓ Branch 14 → 15 taken 86 times.
✓ Branch 14 → 21 taken 38910 times.
✓ Branch 17 → 18 taken 106 times.
✓ Branch 17 → 22 taken 134 times.
✓ Branch 20 → 21 taken 106 times.
✗ Branch 20 → 22 not taken.
✓ Branch 23 → 24 taken 39016 times.
✓ Branch 23 → 25 taken 134 times.
|
39150 | if ((!out && !in) || (e.kind != QLatin1String("relation") && e.kind != QLatin1String("inferred"))) |
| 22 | 39016 | continue; | |
| 23 |
1/1✓ Branch 25 → 26 taken 134 times.
|
134 | const QString inverse = RelationVocabulary::inverseOf(e.type); |
| 24 |
2/6✗ Branch 27 → 28 not taken.
✓ Branch 27 → 31 taken 134 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
✓ Branch 33 → 34 taken 134 times.
✗ Branch 33 → 43 not taken.
|
134 | if (best.isEmpty() || e.kind == QLatin1String("relation")) |
| 25 |
4/5✓ Branch 34 → 35 taken 38 times.
✓ Branch 34 → 37 taken 96 times.
✗ Branch 36 → 37 not taken.
✓ Branch 36 → 38 taken 38 times.
✓ Branch 39 → 40 taken 134 times.
|
134 | best = RelationVocabulary::canonical(out || inverse.isEmpty() ? e.type : inverse); |
| 26 | 134 | } | |
| 27 | 838 | return best; | |
| 28 | ✗ | } | |
| 29 | |||
| 30 | // Inside a column: managers above colleagues above the team; friends above acquaintances. | ||
| 31 | 838 | int roleRank(const QString &type) { | |
| 32 | 3 | static const QStringList order{QStringLiteral("x-manager"), QStringLiteral("colleague"), QStringLiteral("co-worker"), | |
| 33 | 3 | QStringLiteral("agent"), QStringLiteral("x-assisted"), QStringLiteral("x-report"), | |
| 34 |
5/10✓ Branch 2 → 3 taken 3 times.
✓ Branch 2 → 44 taken 835 times.
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 44 not taken.
✓ Branch 33 → 34 taken 24 times.
✓ Branch 33 → 35 taken 3 times.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 54 not taken.
✗ Branch 85 → 86 not taken.
✗ Branch 85 → 87 not taken.
|
868 | QStringLiteral("friend"), QStringLiteral("acquaintance")}; |
| 35 | 838 | const int index = int(order.indexOf(type)); | |
| 36 |
2/2✓ Branch 45 → 46 taken 710 times.
✓ Branch 45 → 48 taken 128 times.
|
838 | return index < 0 ? int(order.size()) : index; |
| 37 | 27 | } | |
| 38 | |||
| 39 | struct Column { | ||
| 40 | QString sector; | ||
| 41 | int side = 1; // −1 left, +1 right | ||
| 42 | int lane = 0; // the group's bus and spine on its side | ||
| 43 | QList<int> members; | ||
| 44 | }; | ||
| 45 | |||
| 46 | // The shown members of every family that has someone among `nodes` join | ||
| 47 | // them (repeated, so a family reached through a joined member comes, too): | ||
| 48 | // a family stays in one place instead of one area in the tree and another | ||
| 49 | // in a column. | ||
| 50 | 67 | QSet<int> withTheirFamilies(const RelationGraph::Graph &graph, const QList<int> &nodes) { | |
| 51 | 67 | QSet<int> joined(nodes.cbegin(), nodes.cend()); | |
| 52 |
2/2✓ Branch 38 → 6 taken 69 times.
✓ Branch 38 → 39 taken 67 times.
|
136 | for (bool grew = true; grew;) { |
| 53 | 69 | grew = false; | |
| 54 |
2/2✓ Branch 36 → 8 taken 57 times.
✓ Branch 36 → 37 taken 69 times.
|
126 | for (const RelationGraph::Area &area : graph.areas) { |
| 55 |
3/3✓ Branch 11 → 12 taken 57 times.
✓ Branch 12 → 13 taken 25 times.
✓ Branch 12 → 14 taken 32 times.
|
116 | if (std::none_of(area.members.cbegin(), area.members.cend(), [&](int m) { return joined.contains(m); })) |
| 56 | 25 | continue; | |
| 57 |
2/2✓ Branch 32 → 16 taken 91 times.
✓ Branch 32 → 33 taken 32 times.
|
123 | for (int member : area.members) |
| 58 | 91 | if (const RelationGraph::Node &node = graph.nodes.at(member); | |
| 59 |
6/8✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 26 taken 89 times.
✓ Branch 21 → 22 taken 2 times.
✗ Branch 21 → 26 not taken.
✓ Branch 24 → 25 taken 2 times.
✗ Branch 24 → 26 not taken.
✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 30 taken 89 times.
|
91 | !joined.contains(member) && isShown(node) && node.sector != QLatin1String("suggestions")) { |
| 60 |
1/1✓ Branch 28 → 29 taken 2 times.
|
2 | joined.insert(member); |
| 61 | 2 | grew = true; | |
| 62 | } | ||
| 63 | } | ||
| 64 | } | ||
| 65 | 67 | return joined; | |
| 66 | ✗ | } | |
| 67 | |||
| 68 | // A family whose members are related to the centre in different ways (a | ||
| 69 | // friend on the left, the introducer on the right) moves into the column | ||
| 70 | // that holds most of them (on a tie the first), so its area is one. | ||
| 71 | 67 | void oneColumnPerFamily(const RelationGraph::Graph &graph, QList<Column> *columns) { | |
| 72 |
2/2✓ Branch 58 → 4 taken 53 times.
✓ Branch 58 → 59 taken 67 times.
|
120 | for (const RelationGraph::Area &area : graph.areas) { |
| 73 |
1/1✓ Branch 6 → 7 taken 53 times.
|
53 | QList<int> count(columns->size(), 0); |
| 74 |
2/2✓ Branch 22 → 8 taken 212 times.
✓ Branch 22 → 23 taken 53 times.
|
265 | for (int c = 0; c < columns->size(); ++c) |
| 75 |
2/2✓ Branch 19 → 10 taken 436 times.
✓ Branch 19 → 20 taken 212 times.
|
648 | for (int member : area.members) |
| 76 |
4/4✓ Branch 11 → 12 taken 436 times.
✓ Branch 13 → 14 taken 24 times.
✓ Branch 13 → 15 taken 412 times.
✓ Branch 16 → 17 taken 436 times.
|
436 | count[c] += (*columns)[c].members.contains(member) ? 1 : 0; |
| 77 |
1/1✓ Branch 26 → 27 taken 53 times.
|
53 | const int target = int(std::max_element(count.cbegin(), count.cend()) - count.cbegin()); |
| 78 |
2/2✓ Branch 29 → 30 taken 30 times.
✓ Branch 29 → 31 taken 23 times.
|
53 | if (count.at(target) == 0) |
| 79 | 30 | continue; | |
| 80 |
2/2✓ Branch 49 → 32 taken 92 times.
✓ Branch 49 → 50 taken 23 times.
|
115 | for (int c = 0; c < columns->size(); ++c) |
| 81 |
2/2✓ Branch 46 → 34 taken 96 times.
✓ Branch 46 → 47 taken 92 times.
|
188 | for (int member : area.members) |
| 82 |
8/8✓ Branch 35 → 36 taken 72 times.
✓ Branch 35 → 40 taken 24 times.
✓ Branch 36 → 37 taken 72 times.
✓ Branch 37 → 38 taken 72 times.
✓ Branch 38 → 39 taken 1 time.
✓ Branch 38 → 40 taken 71 times.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 41 → 44 taken 95 times.
|
96 | if (c != target && (*columns)[c].members.removeOne(member)) |
| 83 |
2/2✓ Branch 42 → 43 taken 1 time.
✓ Branch 43 → 44 taken 1 time.
|
1 | (*columns)[target].members.append(member); |
| 84 | 53 | } | |
| 85 | 67 | } | |
| 86 | |||
| 87 | // The column's people in their order, each family's members right after | ||
| 88 | // the first of them, so a family stands together. | ||
| 89 | 101 | QList<int> familiesTogether(const RelationGraph::Graph &graph, const QList<int> &sorted) { | |
| 90 | 101 | QList<int> out; | |
| 91 |
2/2✓ Branch 35 → 4 taken 236 times.
✓ Branch 35 → 36 taken 101 times.
|
337 | for (int node : sorted) { |
| 92 |
2/2✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 235 times.
|
236 | if (out.contains(node)) |
| 93 | 1 | continue; | |
| 94 |
1/1✓ Branch 8 → 9 taken 235 times.
|
235 | out.append(node); |
| 95 |
2/2✓ Branch 31 → 11 taken 193 times.
✓ Branch 31 → 32 taken 235 times.
|
428 | for (const RelationGraph::Area &area : graph.areas) |
| 96 |
2/2✓ Branch 13 → 14 taken 23 times.
✓ Branch 13 → 29 taken 170 times.
|
193 | if (area.members.contains(node)) |
| 97 |
2/2✓ Branch 27 → 16 taken 47 times.
✓ Branch 27 → 28 taken 23 times.
|
70 | for (int mate : sorted) |
| 98 |
6/6✓ Branch 18 → 19 taken 24 times.
✓ Branch 18 → 22 taken 23 times.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 22 taken 23 times.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 25 taken 46 times.
|
47 | if (area.members.contains(mate) && !out.contains(mate)) |
| 99 |
1/1✓ Branch 24 → 25 taken 1 time.
|
1 | out.append(mate); |
| 100 | } | ||
| 101 | 101 | return out; | |
| 102 | ✗ | } | |
| 103 | |||
| 104 | } // namespace | ||
| 105 | |||
| 106 | 67 | Layout egoLayout(const RelationGraph::Graph &graph, const Options &) { | |
| 107 | 67 | Layout layout; | |
| 108 | 67 | const int n = int(graph.nodes.size()); | |
| 109 |
1/1✓ Branch 3 → 4 taken 67 times.
|
67 | layout.positions = QList<QPointF>(n); |
| 110 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 67 times.
|
67 | if (n == 0) |
| 111 | ✗ | return layout; | |
| 112 | 67 | int centre = 0; | |
| 113 |
2/2✓ Branch 13 → 9 taken 599 times.
✓ Branch 13 → 14 taken 67 times.
|
666 | for (int i = 0; i < n; ++i) |
| 114 |
2/2✓ Branch 10 → 11 taken 67 times.
✓ Branch 10 → 12 taken 532 times.
|
599 | if (graph.nodes.at(i).center) |
| 115 | 67 | centre = i; | |
| 116 | // The family as a tree around the centre. | ||
| 117 |
1/1✓ Branch 14 → 15 taken 67 times.
|
67 | QList<int> candidates{centre}; |
| 118 |
2/2✓ Branch 29 → 16 taken 599 times.
✓ Branch 29 → 30 taken 67 times.
|
666 | for (int i = 0; i < n; ++i) |
| 119 |
7/8✓ Branch 16 → 17 taken 532 times.
✓ Branch 16 → 25 taken 67 times.
✓ Branch 19 → 20 taken 532 times.
✗ Branch 19 → 25 not taken.
✓ Branch 23 → 24 taken 299 times.
✓ Branch 23 → 25 taken 233 times.
✓ Branch 26 → 27 taken 299 times.
✓ Branch 26 → 28 taken 300 times.
|
599 | if (i != centre && isShown(graph.nodes.at(i)) && graph.nodes.at(i).sector == QLatin1String("family")) |
| 120 |
1/1✓ Branch 27 → 28 taken 299 times.
|
299 | candidates.append(i); |
| 121 |
1/1✓ Branch 30 → 31 taken 67 times.
|
67 | const QSet<int> joined = withTheirFamilies(graph, candidates); |
| 122 |
2/2✓ Branch 41 → 32 taken 599 times.
✓ Branch 41 → 42 taken 67 times.
|
666 | for (int i = 0; i < n; ++i) |
| 123 |
6/6✓ Branch 33 → 34 taken 368 times.
✓ Branch 33 → 37 taken 231 times.
✓ Branch 35 → 36 taken 2 times.
✓ Branch 35 → 37 taken 366 times.
✓ Branch 38 → 39 taken 2 times.
✓ Branch 38 → 40 taken 597 times.
|
599 | if (joined.contains(i) && !candidates.contains(i)) |
| 124 |
1/1✓ Branch 39 → 40 taken 2 times.
|
2 | candidates.append(i); |
| 125 |
1/1✓ Branch 42 → 43 taken 67 times.
|
67 | const QHash<int, int> generation = generations(graph, candidates, centre); |
| 126 | // A household member without known kinship shares the centre's row, so | ||
| 127 | // does someone who is in a family with another of the tree. | ||
| 128 | 12 | const auto sharesAFamily = [&](int i) { | |
| 129 | 12 | return std::any_of(graph.areas.cbegin(), graph.areas.cend(), [&](const RelationGraph::Area &area) { | |
| 130 | ✗ | return area.members.contains(i) && std::any_of(area.members.cbegin(), area.members.cend(), [&](int m) { | |
| 131 | ✗ | return m != i && joined.contains(m); | |
| 132 | ✗ | }); | |
| 133 | 12 | }); | |
| 134 | 67 | }; | |
| 135 | 67 | QList<int> family; | |
| 136 |
2/2✓ Branch 59 → 46 taken 368 times.
✓ Branch 59 → 60 taken 67 times.
|
435 | for (int i : std::as_const(candidates)) |
| 137 |
8/9✓ Branch 48 → 49 taken 16 times.
✓ Branch 48 → 53 taken 352 times.
✓ Branch 50 → 51 taken 12 times.
✓ Branch 50 → 53 taken 4 times.
✓ Branch 51 → 52 taken 12 times.
✗ Branch 52 → 53 not taken.
✓ Branch 52 → 54 taken 12 times.
✓ Branch 55 → 56 taken 356 times.
✓ Branch 55 → 57 taken 12 times.
|
368 | if (generation.contains(i) || graph.nodes.at(i).depth <= 1 || sharesAFamily(i)) |
| 138 |
1/1✓ Branch 56 → 57 taken 356 times.
|
356 | family.append(i); |
| 139 |
1/1✓ Branch 60 → 61 taken 67 times.
|
67 | const QHash<int, QPointF> tree = rows(graph, family, generation); |
| 140 | 67 | const double originX = tree.value(centre).x(); | |
| 141 | 67 | double left = 0, right = 0, bottom = 0; | |
| 142 |
2/2✓ Branch 84 → 64 taken 356 times.
✓ Branch 84 → 85 taken 67 times.
|
423 | for (auto it = tree.cbegin(); it != tree.cend(); ++it) { |
| 143 |
1/1✓ Branch 68 → 69 taken 356 times.
|
356 | layout.positions[it.key()] = it.value() - QPointF(originX, 0); |
| 144 | 356 | left = std::min(left, layout.positions.at(it.key()).x()); | |
| 145 | 356 | right = std::max(right, layout.positions.at(it.key()).x()); | |
| 146 | 356 | bottom = std::max(bottom, layout.positions.at(it.key()).y()); | |
| 147 | } | ||
| 148 | // Everyone else in columns beside the family: friends and other left, work and introductions right. | ||
| 149 | ✗ | QList<Column> columns{{QStringLiteral("friends"), -1, 0, {}}, | |
| 150 | 67 | {QStringLiteral("other"), -1, 1, {}}, | |
| 151 | 67 | {QStringLiteral("work"), 1, 0, {}}, | |
| 152 |
2/4✓ Branch 99 → 100 taken 268 times.
✓ Branch 99 → 101 taken 67 times.
✗ Branch 306 → 307 not taken.
✗ Branch 306 → 308 not taken.
|
335 | {QStringLiteral("introductions"), 1, 1, {}}}; |
| 153 | 67 | QList<int> suggested, familyMore; | |
| 154 |
2/2✓ Branch 152 → 106 taken 599 times.
✓ Branch 152 → 153 taken 67 times.
|
666 | for (int i = 0; i < n; ++i) { |
| 155 | 599 | const RelationGraph::Node &node = graph.nodes.at(i); | |
| 156 |
5/6✓ Branch 108 → 109 taken 243 times.
✓ Branch 108 → 110 taken 356 times.
✗ Branch 109 → 110 not taken.
✓ Branch 109 → 111 taken 243 times.
✓ Branch 112 → 113 taken 356 times.
✓ Branch 112 → 114 taken 243 times.
|
599 | if (tree.contains(i) || node.family) |
| 157 | 363 | continue; | |
| 158 |
2/2✓ Branch 116 → 117 taken 7 times.
✓ Branch 116 → 119 taken 236 times.
|
243 | if (node.sector == QLatin1String("suggestions")) { |
| 159 |
1/1✓ Branch 117 → 118 taken 7 times.
|
7 | suggested.append(i); |
| 160 | 7 | continue; | |
| 161 | } | ||
| 162 |
4/6✓ Branch 121 → 122 taken 12 times.
✓ Branch 121 → 124 taken 224 times.
✗ Branch 122 → 123 not taken.
✓ Branch 122 → 124 taken 12 times.
✗ Branch 125 → 126 not taken.
✓ Branch 125 → 128 taken 236 times.
|
236 | if (node.sector == QLatin1String("family") && node.moreCount > 0) { |
| 163 | ✗ | familyMore.append(i); | |
| 164 | ✗ | continue; | |
| 165 | } | ||
| 166 |
4/4✓ Branch 130 → 131 taken 12 times.
✓ Branch 130 → 134 taken 224 times.
✓ Branch 135 → 136 taken 12 times.
✓ Branch 135 → 137 taken 224 times.
|
248 | const QString sector = node.sector == QLatin1String("family") ? QStringLiteral("other") : node.sector; |
| 167 |
3/3✓ Branch 137 → 138 taken 236 times.
✓ Branch 138 → 139 taken 236 times.
✓ Branch 139 → 140 taken 236 times.
|
765 | auto column = std::find_if(columns.begin(), columns.end(), [&](const Column &c) { return c.sector == sector; }); |
| 168 |
3/6✓ Branch 140 → 141 taken 236 times.
✓ Branch 142 → 143 taken 236 times.
✗ Branch 142 → 144 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 145 → 146 not taken.
✓ Branch 147 → 148 taken 236 times.
|
236 | (column != columns.end() ? column : columns.begin() + 1)->members.append(i); |
| 169 | 236 | } | |
| 170 |
1/1✓ Branch 153 → 154 taken 67 times.
|
67 | oneColumnPerFamily(graph, &columns); |
| 171 |
1/2✗ Branch 162 → 157 not taken.
✓ Branch 162 → 163 taken 67 times.
|
67 | for (int i : std::as_const(familyMore)) { // "+N more" at the end of the centre's row |
| 172 | ✗ | right += TreeGap; | |
| 173 | ✗ | layout.positions[i] = {right, 0}; | |
| 174 | } | ||
| 175 | 510 | const auto byRole = [&](int a, int b) { | |
| 176 | 510 | const RelationGraph::Node &na = graph.nodes.at(a), &nb = graph.nodes.at(b); | |
| 177 |
1/2✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 510 times.
|
510 | if ((na.moreCount > 0) != (nb.moreCount > 0)) |
| 178 | ✗ | return nb.moreCount > 0; // "+N more" last | |
| 179 |
2/2✓ Branch 6 → 7 taken 91 times.
✓ Branch 6 → 8 taken 419 times.
|
510 | if (na.depth != nb.depth) |
| 180 | 91 | return na.depth < nb.depth; | |
| 181 |
4/4✓ Branch 8 → 9 taken 419 times.
✓ Branch 9 → 10 taken 419 times.
✓ Branch 11 → 12 taken 419 times.
✓ Branch 12 → 13 taken 419 times.
|
419 | const int ra = roleRank(typeToCentre(graph, centre, a)), rb = roleRank(typeToCentre(graph, centre, b)); |
| 182 |
2/2✓ Branch 14 → 15 taken 10 times.
✓ Branch 14 → 16 taken 409 times.
|
419 | if (ra != rb) |
| 183 | 10 | return ra < rb; | |
| 184 | 409 | const int c = na.name.localeAwareCompare(nb.name); | |
| 185 |
1/2✓ Branch 17 → 18 taken 409 times.
✗ Branch 17 → 19 not taken.
|
409 | return c != 0 ? c < 0 : na.key < nb.key; |
| 186 | 67 | }; | |
| 187 | struct Lane { | ||
| 188 | double busY = 0; | ||
| 189 | double spineX = 0; | ||
| 190 | }; | ||
| 191 | 67 | QHash<int, Lane> laneOf; // first-ring member → its group's bus | |
| 192 | 67 | double columnsBottom = 0; | |
| 193 |
2/2✓ Branch 225 → 165 taken 134 times.
✓ Branch 225 → 226 taken 67 times.
|
201 | for (const int side : {-1, 1}) { |
| 194 | // The groups of a side are stacked and centred on the centre's row; sub-columns go outwards, | ||
| 195 | // every second one half a step lower so the lines into it pass between the people of the first. | ||
| 196 |
2/2✓ Branch 165 → 166 taken 67 times.
✓ Branch 165 → 168 taken 67 times.
|
134 | const double innerX = side > 0 ? std::max(right, 0.0) + ColumnGap : std::min(left, 0.0) - ColumnGap; |
| 197 | 134 | double height = 0; | |
| 198 |
4/4✓ Branch 170 → 171 taken 134 times.
✓ Branch 171 → 172 taken 134 times.
✓ Branch 191 → 173 taken 536 times.
✓ Branch 191 → 192 taken 134 times.
|
670 | for (Column &column : columns) |
| 199 |
6/6✓ Branch 174 → 175 taken 268 times.
✓ Branch 174 → 178 taken 268 times.
✓ Branch 176 → 177 taken 101 times.
✓ Branch 176 → 178 taken 167 times.
✓ Branch 179 → 180 taken 101 times.
✓ Branch 179 → 189 taken 435 times.
|
536 | if (column.side == side && !column.members.isEmpty()) { |
| 200 |
3/3✓ Branch 180 → 181 taken 101 times.
✓ Branch 181 → 182 taken 101 times.
✓ Branch 182 → 183 taken 101 times.
|
101 | std::sort(column.members.begin(), column.members.end(), byRole); |
| 201 |
1/1✓ Branch 183 → 184 taken 101 times.
|
101 | column.members = familiesTogether(graph, column.members); |
| 202 | 101 | height += std::min<int>(int(column.members.size()), ColumnHeight) * ColumnStep + ColumnStep / 2; | |
| 203 | } | ||
| 204 | 134 | double top = -height / 2 + ColumnStep / 2; | |
| 205 |
2/2✓ Branch 223 → 195 taken 536 times.
✓ Branch 223 → 224 taken 134 times.
|
670 | for (const Column &column : std::as_const(columns)) { |
| 206 |
6/6✓ Branch 196 → 197 taken 268 times.
✓ Branch 196 → 199 taken 268 times.
✓ Branch 198 → 199 taken 167 times.
✓ Branch 198 → 200 taken 101 times.
✓ Branch 201 → 202 taken 435 times.
✓ Branch 201 → 203 taken 101 times.
|
536 | if (column.side != side || column.members.isEmpty()) |
| 207 | 435 | continue; | |
| 208 | // The bus runs in the corridor between the centre's row and the next one | ||
| 209 | // below (under the names, above the children's descent bars), where it | ||
| 210 | // only crosses lines of descent; the lanes of one side 9 px apart. | ||
| 211 | 101 | const Lane lane{TreeRowHeight / 2 + 9 * column.lane, innerX - side * (44 + 9 * column.lane)}; | |
| 212 | // The group's heading above its first person. | ||
| 213 | 101 | layout.groups.append({column.sector, QPointF(innerX, top - ColumnStep * 0.55)}); | |
| 214 |
2/2✓ Branch 217 → 208 taken 236 times.
✓ Branch 217 → 218 taken 101 times.
|
337 | for (int k = 0; k < column.members.size(); ++k) { |
| 215 | 236 | const int sub = k / ColumnHeight; | |
| 216 | 236 | const QPointF at(innerX + side * sub * ColumnGap, top + (k % ColumnHeight) * ColumnStep + (sub % 2) * ColumnStep / 2); | |
| 217 |
1/1✓ Branch 210 → 211 taken 236 times.
|
236 | layout.positions[column.members.at(k)] = at; |
| 218 |
1/1✓ Branch 212 → 213 taken 236 times.
|
236 | laneOf.insert(column.members.at(k), lane); |
| 219 | 236 | columnsBottom = std::max(columnsBottom, at.y()); | |
| 220 | } | ||
| 221 | 101 | top += std::min<int>(int(column.members.size()), ColumnHeight) * ColumnStep + ColumnStep / 2; | |
| 222 | } | ||
| 223 | } | ||
| 224 |
3/3✓ Branch 226 → 227 taken 67 times.
✓ Branch 227 → 228 taken 67 times.
✓ Branch 228 → 229 taken 67 times.
|
67 | std::sort(suggested.begin(), suggested.end(), byRole); |
| 225 | 67 | const double suggestionRow = std::max(bottom, columnsBottom) + 140; | |
| 226 |
2/2✓ Branch 237 → 231 taken 7 times.
✓ Branch 237 → 238 taken 67 times.
|
74 | for (int k = 0; k < suggested.size(); ++k) |
| 227 |
1/1✓ Branch 234 → 235 taken 7 times.
|
7 | layout.positions[suggested.at(k)] = {-TreeGap * (suggested.size() - 1) / 2 + TreeGap * k, suggestionRow}; |
| 228 | // A hidden family card sits in the middle of the shown people (never drawn). | ||
| 229 |
2/2✓ Branch 245 → 239 taken 599 times.
✓ Branch 245 → 246 taken 67 times.
|
666 | for (int i = 0; i < n; ++i) |
| 230 |
1/2✗ Branch 240 → 241 not taken.
✓ Branch 240 → 244 taken 599 times.
|
599 | if (graph.nodes.at(i).family) |
| 231 | ✗ | layout.positions[i] = layout.positions.at(centre); | |
| 232 |
1/1✓ Branch 246 → 247 taken 67 times.
|
67 | layout.routes = routes(graph, layout.positions); |
| 233 | // Lines between the centre and a column: one bus per group, never across the family. | ||
| 234 |
2/2✓ Branch 287 → 250 taken 1199 times.
✓ Branch 287 → 288 taken 67 times.
|
1266 | for (int e = 0; e < graph.edges.size(); ++e) { |
| 235 | 1199 | const RelationGraph::Edge &edge = graph.edges.at(e); | |
| 236 |
4/4✓ Branch 251 → 252 taken 305 times.
✓ Branch 251 → 253 taken 894 times.
✓ Branch 253 → 254 taken 162 times.
✓ Branch 253 → 255 taken 732 times.
|
1199 | const int other = edge.from == centre ? edge.to : edge.to == centre ? edge.from : -1; |
| 237 |
6/8✓ Branch 257 → 258 taken 467 times.
✓ Branch 257 → 266 taken 732 times.
✓ Branch 259 → 260 taken 160 times.
✓ Branch 259 → 266 taken 307 times.
✓ Branch 261 → 262 taken 160 times.
✗ Branch 261 → 266 not taken.
✗ Branch 265 → 266 not taken.
✓ Branch 265 → 267 taken 160 times.
|
1359 | if (other < 0 || !laneOf.contains(other) || graph.nodes.at(other).depth != 1 || |
| 238 |
2/2✓ Branch 268 → 269 taken 1039 times.
✓ Branch 268 → 270 taken 160 times.
|
1359 | layout.routes.at(e).shape == QLatin1String("none")) |
| 239 | 1039 | continue; | |
| 240 | 160 | const Lane lane = laneOf.value(other); | |
| 241 |
1/1✓ Branch 273 → 274 taken 160 times.
|
160 | const Route bus = busRoute(layout.positions.at(centre), layout.positions.at(other), lane.busY, lane.spineX); |
| 242 |
4/8✓ Branch 275 → 276 taken 81 times.
✓ Branch 275 → 277 taken 79 times.
✓ Branch 279 → 280 taken 79 times.
✓ Branch 280 → 281 taken 160 times.
✗ Branch 363 → 364 not taken.
✗ Branch 363 → 365 not taken.
✗ Branch 368 → 369 not taken.
✗ Branch 368 → 370 not taken.
|
160 | layout.routes[e] = Route{bus.shape, edge.from == centre ? bus.points : QList<QPointF>(bus.points.crbegin(), bus.points.crend())}; |
| 243 | 160 | } | |
| 244 | 67 | return layout; | |
| 245 | 503 | } | |
| 246 | |||
| 247 | 6 | QList<QPointF> ego(const RelationGraph::Graph &graph, const Options &options) { | |
| 248 |
1/1✓ Branch 2 → 3 taken 6 times.
|
6 | return egoLayout(graph, options).positions; |
| 249 | } | ||
| 250 | |||
| 251 | } // namespace RelationGraphLayout | ||
| 252 |