data/ContactPeopleMerge.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ContactPeopleMerge.h" | ||
| 2 | |||
| 3 | #include "RelationVocabulary.h" | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | |||
| 7 | namespace ContactPeopleMerge { | ||
| 8 | |||
| 9 | namespace { | ||
| 10 | |||
| 11 | const QString kUrnUuid = QStringLiteral("urn:uuid:"); | ||
| 12 | |||
| 13 |
2/2✓ Branch 2 → 3 taken 10 times.
✓ Branch 3 → 4 taken 10 times.
|
10 | QString folded(const QString &text) { return text.trimmed().toCaseFolded(); } |
| 14 | |||
| 15 | // The UID a reference names: its uid, else the UID inside an urn:uuid URI. | ||
| 16 | 38 | QString referencedUid(const QString &uid, const QString &uri) { | |
| 17 |
3/3✓ Branch 2 → 3 taken 38 times.
✓ Branch 5 → 6 taken 33 times.
✓ Branch 5 → 11 taken 5 times.
|
38 | if (!uid.trimmed().isEmpty()) |
| 18 |
2/2✓ Branch 6 → 7 taken 33 times.
✓ Branch 7 → 8 taken 33 times.
|
33 | return uid.trimmed().toLower(); |
| 19 |
1/1✓ Branch 11 → 12 taken 5 times.
|
5 | const QString value = uri.trimmed(); |
| 20 |
3/3✓ Branch 12 → 13 taken 5 times.
✓ Branch 13 → 14 taken 3 times.
✓ Branch 13 → 20 taken 2 times.
|
5 | if (value.startsWith(kUrnUuid, Qt::CaseInsensitive)) |
| 21 |
2/2✓ Branch 15 → 16 taken 3 times.
✓ Branch 16 → 17 taken 3 times.
|
3 | return value.mid(kUrnUuid.size()).toLower(); |
| 22 | 2 | return {}; | |
| 23 | 5 | } | |
| 24 | |||
| 25 | // Two relationships say the same: same type (and custom label) and the same person. | ||
| 26 | 16 | bool sameRelation(const ContactRelation &a, const ContactRelation &b) { | |
| 27 |
7/12✓ Branch 2 → 3 taken 16 times.
✓ Branch 3 → 4 taken 16 times.
✓ Branch 5 → 6 taken 5 times.
✓ Branch 5 → 10 taken 11 times.
✓ Branch 18 → 19 taken 16 times.
✗ Branch 18 → 20 not taken.
✓ Branch 20 → 21 taken 11 times.
✓ Branch 20 → 22 taken 5 times.
✗ Branch 69 → 70 not taken.
✗ Branch 69 → 71 not taken.
✗ Branch 73 → 74 not taken.
✗ Branch 73 → 75 not taken.
|
37 | if (RelationVocabulary::canonical(a.type) != RelationVocabulary::canonical(b.type) || |
| 28 |
8/14✓ Branch 6 → 7 taken 5 times.
✓ Branch 7 → 8 taken 5 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 5 times.
✓ Branch 12 → 13 taken 5 times.
✓ Branch 12 → 14 taken 11 times.
✓ Branch 14 → 15 taken 5 times.
✓ Branch 14 → 16 taken 11 times.
✓ Branch 16 → 17 taken 16 times.
✗ Branch 16 → 18 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 61 → 63 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
|
21 | folded(a.label) != folded(b.label)) |
| 29 | 11 | return false; | |
| 30 |
2/2✓ Branch 22 → 23 taken 5 times.
✓ Branch 23 → 24 taken 5 times.
|
5 | const QString ua = referencedUid(a.targetUid, a.targetUri), ub = referencedUid(b.targetUid, b.targetUri); |
| 31 |
2/6✗ Branch 25 → 26 not taken.
✓ Branch 25 → 28 taken 5 times.
✗ Branch 27 → 28 not taken.
✗ Branch 27 → 29 not taken.
✓ Branch 30 → 31 taken 5 times.
✗ Branch 30 → 32 not taken.
|
5 | if (!ua.isEmpty() || !ub.isEmpty()) |
| 32 | 5 | return ua == ub; | |
| 33 | ✗ | if (!a.targetUri.trimmed().isEmpty() || !b.targetUri.trimmed().isEmpty()) | |
| 34 | ✗ | return a.targetUri.trimmed() == b.targetUri.trimmed(); | |
| 35 | ✗ | return folded(a.targetName) == folded(b.targetName); | |
| 36 | 5 | } | |
| 37 | |||
| 38 | ✗ | bool samePerson(const ContactPersonRef &a, const ContactPersonRef &b) { | |
| 39 | ✗ | const QString ua = referencedUid(a.uid, a.uri), ub = referencedUid(b.uid, b.uri); | |
| 40 | ✗ | if (!ua.isEmpty() || !ub.isEmpty()) | |
| 41 | ✗ | return ua == ub; | |
| 42 | ✗ | return folded(a.uri) == folded(b.uri) && folded(a.name) == folded(b.name); | |
| 43 | ✗ | } | |
| 44 | |||
| 45 | 24 | void uniteText(QStringList *into, const QStringList &extra) { | |
| 46 |
2/2✓ Branch 24 → 4 taken 2 times.
✓ Branch 24 → 25 taken 24 times.
|
26 | for (const QString &value : extra) |
| 47 |
9/16✓ Branch 5 → 6 taken 2 times.
✓ Branch 7 → 8 taken 2 times.
✗ Branch 7 → 12 not taken.
✓ Branch 8 → 9 taken 2 times.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 1 time.
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 15 not taken.
✓ Branch 15 → 16 taken 2 times.
✗ Branch 15 → 17 not taken.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 22 taken 1 time.
✗ Branch 26 → 27 not taken.
✗ Branch 26 → 28 not taken.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
2 | if (!value.trimmed().isEmpty() && !into->contains(value.trimmed(), Qt::CaseInsensitive)) |
| 48 |
2/2✓ Branch 18 → 19 taken 1 time.
✓ Branch 19 → 20 taken 1 time.
|
1 | into->append(value.trimmed()); |
| 49 | 24 | } | |
| 50 | |||
| 51 | 24 | void fill(QString *into, const QString &value) { | |
| 52 |
9/16✓ Branch 2 → 3 taken 24 times.
✓ Branch 4 → 5 taken 24 times.
✗ Branch 4 → 9 not taken.
✓ Branch 5 → 6 taken 24 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 23 times.
✓ Branch 10 → 11 taken 24 times.
✗ Branch 10 → 12 not taken.
✓ Branch 12 → 13 taken 24 times.
✗ Branch 12 → 14 not taken.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 19 taken 23 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 22 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
|
24 | if (into->trimmed().isEmpty() && !value.trimmed().isEmpty()) |
| 53 |
1/1✓ Branch 15 → 16 taken 1 time.
|
1 | *into = value.trimmed(); |
| 54 | 24 | } | |
| 55 | |||
| 56 | // The relationships of the merged card: the keeper's own first, then the | ||
| 57 | // others' new ones; none names one of the merged cards. | ||
| 58 | 16 | QList<ContactRelation> unitedRelations(const ContactCard &keeper, const QList<ContactCard> &others, | |
| 59 | const QSet<QString> &mergedUids) { | ||
| 60 | 16 | QList<ContactRelation> united; | |
| 61 |
2/2✓ Branch 10 → 4 taken 4 times.
✓ Branch 10 → 11 taken 16 times.
|
20 | for (const ContactRelation &relation : keeper.relations) |
| 62 |
3/3✓ Branch 5 → 6 taken 4 times.
✓ Branch 6 → 7 taken 2 times.
✓ Branch 6 → 8 taken 2 times.
|
4 | if (!namesAny(relation.targetUid, relation.targetUri, mergedUids)) |
| 63 |
1/1✓ Branch 7 → 8 taken 2 times.
|
2 | united.append(relation); |
| 64 |
2/2✓ Branch 37 → 13 taken 25 times.
✓ Branch 37 → 38 taken 16 times.
|
41 | for (const ContactCard &other : others) |
| 65 |
2/2✓ Branch 34 → 16 taken 14 times.
✓ Branch 34 → 35 taken 25 times.
|
39 | for (ContactRelation relation : other.relations) { |
| 66 |
3/3✓ Branch 18 → 19 taken 14 times.
✓ Branch 19 → 20 taken 5 times.
✓ Branch 19 → 21 taken 9 times.
|
14 | if (namesAny(relation.targetUid, relation.targetUri, mergedUids)) |
| 67 | 5 | continue; | |
| 68 |
3/3✓ Branch 23 → 24 taken 9 times.
✓ Branch 24 → 25 taken 2 times.
✓ Branch 24 → 26 taken 7 times.
|
9 | if (std::any_of(united.cbegin(), united.cend(), |
| 69 | 8 | [&](const ContactRelation &known) { return sameRelation(known, relation); })) | |
| 70 | 2 | continue; | |
| 71 | 7 | relation.sourceIndex = -1; | |
| 72 | 7 | relation.model.clear(); // written in the kept card's own dialect; a legacy line becomes writable | |
| 73 |
1/1✓ Branch 27 → 28 taken 7 times.
|
7 | united.append(relation); |
| 74 | 14 | } | |
| 75 | 16 | return united; | |
| 76 | ✗ | } | |
| 77 | |||
| 78 | } // namespace | ||
| 79 | |||
| 80 | 14 | QSet<QString> uidsOf(const QList<ContactCard> &cards) { | |
| 81 | 14 | QSet<QString> uids; | |
| 82 |
2/2✓ Branch 18 → 5 taken 37 times.
✓ Branch 18 → 19 taken 14 times.
|
51 | for (const ContactCard &card : cards) |
| 83 |
2/3✓ Branch 6 → 7 taken 37 times.
✓ Branch 9 → 10 taken 37 times.
✗ Branch 9 → 16 not taken.
|
37 | if (!card.uid.trimmed().isEmpty()) |
| 84 |
3/3✓ Branch 10 → 11 taken 37 times.
✓ Branch 11 → 12 taken 37 times.
✓ Branch 12 → 13 taken 37 times.
|
37 | uids.insert(card.uid.trimmed().toLower()); |
| 85 | 14 | return uids; | |
| 86 | ✗ | } | |
| 87 | |||
| 88 | 28 | bool namesAny(const QString &uid, const QString &uri, const QSet<QString> &uids) { | |
| 89 |
1/1✓ Branch 2 → 3 taken 28 times.
|
28 | const QString named = referencedUid(uid, uri); |
| 90 |
4/4✓ Branch 4 → 5 taken 26 times.
✓ Branch 4 → 8 taken 2 times.
✓ Branch 6 → 7 taken 12 times.
✓ Branch 6 → 8 taken 14 times.
|
56 | return !named.isEmpty() && uids.contains(named); |
| 91 | 28 | } | |
| 92 | |||
| 93 | 8 | void mergeInto(ContactCard *keeper, const QList<ContactCard> &others, const QSet<QString> &mergedUids) { | |
| 94 |
1/1✓ Branch 2 → 3 taken 8 times.
|
8 | keeper->relations = unitedRelations(*keeper, others, mergedUids); |
| 95 | // How we met: the keeper's meeting stays; an empty one is taken from the first other card that has one. | ||
| 96 | 8 | QList<ContactPersonRef> via; | |
| 97 |
1/2✗ Branch 14 → 8 not taken.
✓ Branch 14 → 15 taken 8 times.
|
8 | for (const ContactPersonRef &ref : std::as_const(keeper->met.via)) |
| 98 | ✗ | if (!namesAny(ref.uid, ref.uri, mergedUids)) | |
| 99 | ✗ | via.append(ref); | |
| 100 |
2/2✓ Branch 56 → 17 taken 12 times.
✓ Branch 56 → 57 taken 8 times.
|
20 | for (const ContactCard &other : others) { |
| 101 |
7/8✓ Branch 18 → 19 taken 12 times.
✓ Branch 19 → 20 taken 12 times.
✗ Branch 19 → 23 not taken.
✓ Branch 20 → 21 taken 12 times.
✓ Branch 21 → 22 taken 1 time.
✓ Branch 21 → 23 taken 11 times.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 24 → 32 taken 11 times.
|
12 | if (keeper->met.isEmpty() && !other.met.isEmpty()) { |
| 102 | 1 | const ContactMet met = other.met; | |
| 103 | 1 | keeper->met.date = met.date; | |
| 104 | 1 | keeper->met.place = met.place; | |
| 105 | 1 | keeper->met.placeGeo = met.placeGeo; | |
| 106 | 1 | keeper->met.eventUid = met.eventUid; | |
| 107 | 1 | keeper->met.note = met.note; | |
| 108 | 1 | keeper->met.channel = met.channel; | |
| 109 | 1 | } | |
| 110 |
2/2✓ Branch 53 → 34 taken 1 time.
✓ Branch 53 → 54 taken 12 times.
|
13 | for (ContactPersonRef ref : other.met.via) { |
| 111 |
3/5✓ Branch 36 → 37 taken 1 time.
✓ Branch 37 → 38 taken 1 time.
✗ Branch 37 → 42 not taken.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 1 time.
|
2 | if (namesAny(ref.uid, ref.uri, mergedUids) || |
| 112 |
2/3✓ Branch 40 → 41 taken 1 time.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 1 time.
|
1 | std::any_of(via.cbegin(), via.cend(), [&](const ContactPersonRef &known) { return samePerson(known, ref); })) |
| 113 | ✗ | continue; | |
| 114 | 1 | ref.sourceIndex = -1; | |
| 115 |
1/1✓ Branch 46 → 47 taken 1 time.
|
1 | via.append(ref); |
| 116 | 1 | } | |
| 117 | } | ||
| 118 | 8 | keeper->met.via = via; | |
| 119 |
2/2✓ Branch 148 → 60 taken 12 times.
✓ Branch 148 → 149 taken 8 times.
|
20 | for (const ContactCard &other : others) { |
| 120 |
2/2✓ Branch 86 → 63 taken 1 time.
✓ Branch 86 → 87 taken 12 times.
|
13 | for (ContactSocial social : other.social) { |
| 121 |
1/1✓ Branch 67 → 68 taken 1 time.
|
1 | const bool known = std::any_of(keeper->social.cbegin(), keeper->social.cend(), [&](const ContactSocial &s) { |
| 122 | ✗ | return s.kind == social.kind && folded(s.value) == folded(social.value); | |
| 123 | }); | ||
| 124 |
5/11✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 72 not taken.
✓ Branch 69 → 70 taken 1 time.
✗ Branch 71 → 72 not taken.
✓ Branch 71 → 73 taken 1 time.
✓ Branch 74 → 75 taken 1 time.
✗ Branch 74 → 76 not taken.
✗ Branch 76 → 77 not taken.
✓ Branch 76 → 78 taken 1 time.
✗ Branch 157 → 158 not taken.
✗ Branch 157 → 159 not taken.
|
1 | if (known || social.value.trimmed().isEmpty()) |
| 125 | ✗ | continue; | |
| 126 | 1 | social.sourceIndex = -1; | |
| 127 | 1 | social.property.clear(); | |
| 128 |
1/1✓ Branch 79 → 80 taken 1 time.
|
1 | keeper->social.append(social); |
| 129 | 1 | } | |
| 130 |
1/1✓ Branch 87 → 88 taken 12 times.
|
12 | uniteText(&keeper->languages, other.languages); |
| 131 |
1/1✓ Branch 88 → 89 taken 12 times.
|
12 | uniteText(&keeper->interests, other.interests); |
| 132 |
1/2✗ Branch 110 → 91 not taken.
✓ Branch 110 → 111 taken 12 times.
|
12 | for (ContactDate date : other.otherDates) { |
| 133 | ✗ | const bool known = std::any_of(keeper->otherDates.cbegin(), keeper->otherDates.cend(), [&](const ContactDate &d) { | |
| 134 | ✗ | return d.date == date.date && folded(d.label) == folded(date.label); | |
| 135 | }); | ||
| 136 | ✗ | if (known || !date.date.isValid()) | |
| 137 | ✗ | continue; | |
| 138 | ✗ | date.sourceIndex = -1; | |
| 139 | ✗ | keeper->otherDates.append(date); | |
| 140 | ✗ | } | |
| 141 |
2/2✓ Branch 132 → 113 taken 1 time.
✓ Branch 132 → 133 taken 12 times.
|
13 | for (ContactMailLink link : other.mailLinks) { |
| 142 |
1/1✓ Branch 117 → 118 taken 1 time.
|
1 | const bool known = std::any_of(keeper->mailLinks.cbegin(), keeper->mailLinks.cend(), |
| 143 | ✗ | [&](const ContactMailLink &l) { return l.messageId == link.messageId; }); | |
| 144 |
3/6✓ Branch 118 → 119 taken 1 time.
✗ Branch 118 → 121 not taken.
✗ Branch 120 → 121 not taken.
✓ Branch 120 → 122 taken 1 time.
✗ Branch 123 → 124 not taken.
✓ Branch 123 → 125 taken 1 time.
|
1 | if (known || link.messageId.isEmpty()) |
| 145 | ✗ | continue; | |
| 146 | 1 | link.sourceIndex = -1; | |
| 147 |
1/1✓ Branch 125 → 126 taken 1 time.
|
1 | keeper->mailLinks.append(link); |
| 148 | 1 | } | |
| 149 |
1/1✓ Branch 133 → 134 taken 12 times.
|
12 | fill(&keeper->birthplace, other.birthplace); |
| 150 |
1/1✓ Branch 134 → 135 taken 12 times.
|
12 | fill(&keeper->gender, other.gender); |
| 151 |
5/6✓ Branch 136 → 137 taken 12 times.
✗ Branch 136 → 140 not taken.
✓ Branch 138 → 139 taken 1 time.
✓ Branch 138 → 140 taken 11 times.
✓ Branch 141 → 142 taken 1 time.
✓ Branch 141 → 143 taken 11 times.
|
12 | if (!keeper->anniversary.isValid() && other.anniversary.isValid()) |
| 152 | 1 | keeper->anniversary = other.anniversary; | |
| 153 |
3/4✓ Branch 143 → 144 taken 12 times.
✗ Branch 143 → 146 not taken.
✓ Branch 144 → 145 taken 1 time.
✓ Branch 144 → 146 taken 11 times.
|
12 | if (keeper->photo.kind == ContactPhoto::Kind::None && other.photo.kind != ContactPhoto::Kind::None) |
| 154 | 1 | keeper->photo = other.photo; | |
| 155 | } | ||
| 156 | 8 | } | |
| 157 | |||
| 158 | 8 | int mergedRelationCount(const ContactCard &keeper, const QList<ContactCard> &others, const QSet<QString> &mergedUids) { | |
| 159 |
1/1✓ Branch 2 → 3 taken 8 times.
|
8 | return int(unitedRelations(keeper, others, mergedUids).size()); |
| 160 | } | ||
| 161 | |||
| 162 | 5 | bool retarget(ContactCard *card, const QSet<QString> &goneUids, const QString &keeperUid, const QString &keeperName) { | |
| 163 |
2/2✓ Branch 2 → 3 taken 5 times.
✓ Branch 3 → 4 taken 5 times.
|
5 | const QString ownUid = card->uid.trimmed().toLower(); |
| 164 |
2/2✓ Branch 5 → 6 taken 5 times.
✓ Branch 6 → 7 taken 5 times.
|
5 | const QString keeper = keeperUid.trimmed().toLower(); |
| 165 | 5 | bool changed = false; | |
| 166 | 5 | QList<ContactRelation> relations; | |
| 167 |
2/2✓ Branch 38 → 11 taken 9 times.
✓ Branch 38 → 39 taken 5 times.
|
14 | for (ContactRelation relation : std::as_const(card->relations)) { |
| 168 | // A legacy line is never written (VCardPeoplePatch); it stays as it is. | ||
| 169 |
7/7✓ Branch 14 → 15 taken 7 times.
✓ Branch 14 → 18 taken 2 times.
✓ Branch 15 → 16 taken 7 times.
✓ Branch 16 → 17 taken 4 times.
✓ Branch 16 → 18 taken 3 times.
✓ Branch 19 → 20 taken 4 times.
✓ Branch 19 → 31 taken 5 times.
|
9 | if (!relation.readOnly() && namesAny(relation.targetUid, relation.targetUri, goneUids)) { |
| 170 | 4 | changed = true; | |
| 171 |
1/2✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 4 times.
|
4 | if (keeper == ownUid) |
| 172 | ✗ | continue; // the kept card would be related to itself | |
| 173 | 4 | relation.targetUid = keeperUid; | |
| 174 | 4 | relation.targetUri.clear(); | |
| 175 | 4 | relation.targetName = keeperName; | |
| 176 |
3/3✓ Branch 28 → 29 taken 4 times.
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 31 taken 3 times.
|
4 | if (std::any_of(relations.cbegin(), relations.cend(), |
| 177 | 2 | [&](const ContactRelation &known) { return sameRelation(known, relation); })) | |
| 178 | 1 | continue; | |
| 179 | } | ||
| 180 |
1/1✓ Branch 31 → 32 taken 8 times.
|
8 | relations.append(relation); |
| 181 | 9 | } | |
| 182 | // A line rewritten above may also repeat one that comes later in the card. | ||
| 183 | 5 | QList<ContactRelation> unique; | |
| 184 |
2/2✓ Branch 50 → 42 taken 8 times.
✓ Branch 50 → 51 taken 5 times.
|
13 | for (const ContactRelation &relation : std::as_const(relations)) |
| 185 |
2/3✓ Branch 45 → 46 taken 8 times.
✓ Branch 46 → 47 taken 8 times.
✗ Branch 46 → 48 not taken.
|
8 | if (!std::any_of(unique.cbegin(), unique.cend(), |
| 186 | 6 | [&](const ContactRelation &known) { return sameRelation(known, relation); })) | |
| 187 |
1/1✓ Branch 47 → 48 taken 8 times.
|
8 | unique.append(relation); |
| 188 |
3/4✓ Branch 51 → 52 taken 2 times.
✓ Branch 51 → 55 taken 3 times.
✗ Branch 54 → 55 not taken.
✓ Branch 54 → 56 taken 2 times.
|
5 | changed = changed || unique.size() != relations.size(); |
| 189 | 5 | card->relations = unique; | |
| 190 | 5 | QList<ContactPersonRef> via; | |
| 191 |
2/2✓ Branch 82 → 61 taken 2 times.
✓ Branch 82 → 83 taken 5 times.
|
7 | for (ContactPersonRef ref : std::as_const(card->met.via)) { |
| 192 |
3/3✓ Branch 63 → 64 taken 2 times.
✓ Branch 64 → 65 taken 1 time.
✓ Branch 64 → 71 taken 1 time.
|
2 | if (namesAny(ref.uid, ref.uri, goneUids)) { |
| 193 | 1 | changed = true; | |
| 194 |
1/2✗ Branch 66 → 67 not taken.
✓ Branch 66 → 68 taken 1 time.
|
1 | if (keeper == ownUid) |
| 195 | ✗ | continue; | |
| 196 | 1 | ref.uid = keeperUid; | |
| 197 | 1 | ref.uri.clear(); | |
| 198 | 1 | ref.name = keeperName; | |
| 199 | } | ||
| 200 |
2/3✓ Branch 73 → 74 taken 2 times.
✓ Branch 74 → 75 taken 2 times.
✗ Branch 74 → 76 not taken.
|
2 | if (!std::any_of(via.cbegin(), via.cend(), [&](const ContactPersonRef &known) { return samePerson(known, ref); })) |
| 201 |
1/1✓ Branch 75 → 76 taken 2 times.
|
2 | via.append(ref); |
| 202 | 2 | } | |
| 203 | 5 | card->met.via = via; | |
| 204 | // Group cards: MEMBER urn:uuid:<uid> (or the bare UID) of a removed card names the kept card. | ||
| 205 | 5 | QStringList members; | |
| 206 |
2/2✓ Branch 122 → 87 taken 4 times.
✓ Branch 122 → 123 taken 5 times.
|
9 | for (const QString &member : std::as_const(card->members)) { |
| 207 | 4 | QString value = member; | |
| 208 |
2/2✓ Branch 89 → 90 taken 4 times.
✓ Branch 90 → 91 taken 4 times.
|
4 | const bool urn = member.trimmed().startsWith(kUrnUuid, Qt::CaseInsensitive); |
| 209 |
7/19✓ Branch 92 → 93 taken 4 times.
✗ Branch 92 → 97 not taken.
✓ Branch 93 → 94 taken 4 times.
✓ Branch 95 → 96 taken 4 times.
✓ Branch 96 → 99 taken 4 times.
✗ Branch 97 → 98 not taken.
✗ Branch 98 → 99 not taken.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 4 times.
✓ Branch 101 → 102 taken 4 times.
✗ Branch 101 → 103 not taken.
✓ Branch 103 → 104 taken 4 times.
✗ Branch 103 → 105 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
✗ Branch 152 → 153 not taken.
✗ Branch 152 → 154 not taken.
✗ Branch 156 → 157 not taken.
✗ Branch 156 → 158 not taken.
|
4 | const QString named = urn ? member.trimmed().mid(kUrnUuid.size()).toLower() : member.trimmed().toLower(); |
| 210 |
2/2✓ Branch 106 → 107 taken 2 times.
✓ Branch 106 → 113 taken 2 times.
|
4 | if (goneUids.contains(named)) { |
| 211 | 2 | changed = true; | |
| 212 |
2/3✓ Branch 107 → 108 taken 2 times.
✗ Branch 107 → 109 not taken.
✓ Branch 108 → 110 taken 2 times.
|
2 | value = urn ? kUrnUuid + keeperUid : keeperUid; |
| 213 | } | ||
| 214 |
3/3✓ Branch 115 → 116 taken 4 times.
✓ Branch 116 → 117 taken 3 times.
✓ Branch 116 → 118 taken 1 time.
|
4 | if (!std::any_of(members.cbegin(), members.cend(), |
| 215 | 1 | [&](const QString &known) { return known.compare(value, Qt::CaseInsensitive) == 0; })) | |
| 216 |
1/1✓ Branch 117 → 118 taken 3 times.
|
3 | members.append(value); |
| 217 | 4 | } | |
| 218 | 5 | card->members = members; | |
| 219 | 5 | return changed; | |
| 220 | 5 | } | |
| 221 | |||
| 222 | } // namespace ContactPeopleMerge | ||
| 223 |