presentation/QuickContactActionsPeople.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Sprint 103 relationship writes of QuickContactActions (S103.3.1/S103.3.8, | ||
| 2 | // D-5): a relationship is one RELATED line on one card; adding writes it on | ||
| 3 | // the card it is added from, removing deletes the line from the card that | ||
| 4 | // stores it (the inverse row of the other card disappears with it). Both | ||
| 5 | // leave an "edit" undo step like a saved edit. | ||
| 6 | |||
| 7 | #include "QuickContactActions.h" | ||
| 8 | |||
| 9 | #include "ContactEditorPeople.h" | ||
| 10 | #include "ContactPeopleView.h" | ||
| 11 | #include "MetSentence.h" | ||
| 12 | #include "app/core/ContactOutbox.h" | ||
| 13 | #include "app/core/ContactSyncCoordinator.h" | ||
| 14 | #include "data/ContactIndex.h" | ||
| 15 | #include "data/ContactQueries.h" | ||
| 16 | #include "data/ContactStore.h" | ||
| 17 | #include "data/RelationIndex.h" | ||
| 18 | #include "data/RelationVocabulary.h" | ||
| 19 | #include "data/ServiceCatalog.h" | ||
| 20 | #include "data/VCardCodec.h" | ||
| 21 | |||
| 22 | #include <QHash> | ||
| 23 | #include <QLocale> | ||
| 24 | #include <QMap> | ||
| 25 | #include <QLoggingCategory> | ||
| 26 | #include <QRegularExpression> | ||
| 27 | #include <QSet> | ||
| 28 | #include <QSettings> | ||
| 29 | #include <QSqlQuery> | ||
| 30 | #include <algorithm> | ||
| 31 | |||
| 32 |
4/7✓ Branch 2 → 3 taken 3 times.
✓ Branch 2 → 8 taken 116 times.
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 3 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
119 | Q_LOGGING_CATEGORY(lcContactRelationActions, "mailjd.contacts.relations") |
| 33 | |||
| 34 | namespace { | ||
| 35 | |||
| 36 |
3/9✓ Branch 10 → 11 taken 10 times.
✓ Branch 12 → 13 taken 20 times.
✓ Branch 12 → 14 taken 10 times.
✗ Branch 21 → 22 not taken.
✗ Branch 21 → 23 not taken.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 41 not taken.
✗ Branch 39 → 40 not taken.
✗ Branch 39 → 41 not taken.
|
50 | QVariantMap failure(const QString &error) { return {{QStringLiteral("ok"), false}, {QStringLiteral("error"), error}}; } |
| 37 | |||
| 38 | } // namespace | ||
| 39 | |||
| 40 | 113 | QVariantMap QuickContactActions::editPeople(const QString &key, const std::function<QString(ContactCard *)> &change, | |
| 41 | const QString &message) { | ||
| 42 |
1/1✓ Branch 2 → 3 taken 113 times.
|
113 | ContactSyncCoordinator *sync = m_coordinator(); |
| 43 | 113 | qint64 bookId = 0; | |
| 44 | 113 | QString uid; | |
| 45 |
4/7✓ Branch 3 → 4 taken 113 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 113 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 113 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 14 taken 113 times.
|
113 | if (!sync || !ContactQueries::splitKey(key, &bookId, &uid)) |
| 46 | ✗ | return failure(tr("Contacts are not available right now.")); | |
| 47 |
1/1✓ Branch 15 → 16 taken 113 times.
|
113 | const auto stored = sync->store()->card(bookId, uid); |
| 48 |
1/2✗ Branch 17 → 18 not taken.
✓ Branch 17 → 23 taken 113 times.
|
113 | if (!stored) |
| 49 | ✗ | return failure(tr("The contact no longer exists.")); | |
| 50 |
1/1✓ Branch 23 → 24 taken 113 times.
|
113 | ContactCard card; |
| 51 |
2/3✓ Branch 25 → 26 taken 113 times.
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 32 taken 113 times.
|
113 | if (!VCardCodec::parse(stored->raw, &card)) |
| 52 | ✗ | return failure(tr("This contact cannot be changed in MailJD. Edit it where it was created.")); | |
| 53 |
3/3✓ Branch 32 → 33 taken 113 times.
✓ Branch 34 → 35 taken 3 times.
✓ Branch 34 → 37 taken 110 times.
|
113 | if (const QString refused = change(&card); !refused.isEmpty()) |
| 54 |
3/3✓ Branch 35 → 36 taken 3 times.
✓ Branch 39 → 40 taken 110 times.
✓ Branch 39 → 43 taken 3 times.
|
113 | return failure(refused); |
| 55 | 110 | QString error; | |
| 56 |
1/1✓ Branch 42 → 44 taken 110 times.
|
110 | const QString saved = sync->outbox()->saveCard(bookId, uid, card, &error); |
| 57 |
2/2✓ Branch 45 → 46 taken 2 times.
✓ Branch 45 → 48 taken 108 times.
|
110 | if (saved.isEmpty()) |
| 58 |
1/1✓ Branch 46 → 47 taken 2 times.
|
2 | return failure(error); |
| 59 |
1/1✓ Branch 55 → 56 taken 108 times.
|
108 | pushUndo(tr("Undo edit"), {QStringLiteral("edit"), *stored, key, bookId}); |
| 60 |
1/1✓ Branch 59 → 60 taken 108 times.
|
108 | report(message, true); |
| 61 |
2/4✓ Branch 70 → 71 taken 216 times.
✓ Branch 70 → 72 taken 108 times.
✗ Branch 115 → 116 not taken.
✗ Branch 115 → 117 not taken.
|
648 | return {{QStringLiteral("ok"), true}, {QStringLiteral("key"), saved}}; |
| 62 | 653 | } | |
| 63 | |||
| 64 | 32 | QVariantMap QuickContactActions::addRelation(const QString &key, const QString &otherKey, const QString &type, | |
| 65 | const QString &label) { | ||
| 66 |
1/1✓ Branch 2 → 3 taken 32 times.
|
32 | ContactSyncCoordinator *sync = m_coordinator(); |
| 67 | 32 | qint64 otherBook = 0; | |
| 68 | 32 | QString otherUid; | |
| 69 | 32 | ContactRelation relation; | |
| 70 |
1/1✓ Branch 3 → 4 taken 32 times.
|
32 | relation.type = RelationVocabulary::canonical(type); |
| 71 |
9/11✓ Branch 8 → 9 taken 31 times.
✓ Branch 8 → 13 taken 1 time.
✓ Branch 9 → 10 taken 31 times.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 30 times.
✓ Branch 14 → 15 taken 31 times.
✓ Branch 14 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 22 taken 31 times.
✗ Branch 187 → 188 not taken.
✗ Branch 187 → 189 not taken.
|
32 | if (relation.type != QLatin1String("custom") && !RelationVocabulary::editableTypes().contains(relation.type)) |
| 72 |
2/2✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
|
1 | return failure(tr("Choose how the two are related.")); |
| 73 | // A family's entry has no relationships besides its members (set on the family). | ||
| 74 |
10/10✓ Branch 22 → 23 taken 31 times.
✓ Branch 23 → 24 taken 29 times.
✓ Branch 23 → 26 taken 2 times.
✓ Branch 24 → 25 taken 29 times.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 25 → 30 taken 28 times.
✓ Branch 28 → 29 taken 2 times.
✓ Branch 28 → 30 taken 1 time.
✓ Branch 31 → 32 taken 2 times.
✓ Branch 31 → 37 taken 29 times.
|
31 | if ((isFamily(key) || isFamily(otherKey)) && relation.type != QLatin1String("member")) |
| 75 |
2/2✓ Branch 32 → 33 taken 2 times.
✓ Branch 33 → 34 taken 2 times.
|
2 | return failure(tr("A family has no relationships of its own. Add people to it as members of the family.")); |
| 76 | // S106-272: a member line belongs on a family's entry (F103-10); on the | ||
| 77 | // me card the D-6 flip below turned it into a member-of line on another | ||
| 78 | // person — inverted family data. | ||
| 79 |
11/14✓ Branch 39 → 40 taken 4 times.
✓ Branch 39 → 46 taken 25 times.
✓ Branch 40 → 41 taken 4 times.
✓ Branch 42 → 43 taken 1 time.
✓ Branch 42 → 46 taken 3 times.
✓ Branch 43 → 44 taken 1 time.
✓ Branch 44 → 45 taken 1 time.
✗ Branch 44 → 46 not taken.
✓ Branch 47 → 48 taken 4 times.
✓ Branch 47 → 49 taken 25 times.
✓ Branch 49 → 50 taken 1 time.
✓ Branch 49 → 55 taken 28 times.
✗ Branch 199 → 200 not taken.
✗ Branch 199 → 201 not taken.
|
29 | if (relation.type == QLatin1String("member") && key == meKey() && !isFamily(key)) |
| 80 |
2/2✓ Branch 50 → 51 taken 1 time.
✓ Branch 51 → 52 taken 1 time.
|
1 | return failure(tr("Choose how the two are related.")); |
| 81 |
2/2✓ Branch 57 → 58 taken 1 time.
✓ Branch 57 → 68 taken 27 times.
|
28 | if (relation.type == QLatin1String("custom")) { |
| 82 |
1/1✓ Branch 58 → 59 taken 1 time.
|
1 | relation.label = label.trimmed(); |
| 83 |
1/2✗ Branch 62 → 63 not taken.
✓ Branch 62 → 68 taken 1 time.
|
1 | if (relation.label.isEmpty()) |
| 84 | ✗ | return failure(tr("Enter a name for the relationship.")); | |
| 85 | } | ||
| 86 |
6/7✓ Branch 68 → 69 taken 28 times.
✗ Branch 68 → 72 not taken.
✓ Branch 69 → 70 taken 28 times.
✓ Branch 70 → 71 taken 26 times.
✓ Branch 70 → 72 taken 2 times.
✓ Branch 73 → 74 taken 26 times.
✓ Branch 73 → 102 taken 2 times.
|
28 | if (sync && ContactQueries::splitKey(otherKey, &otherBook, &otherUid)) { |
| 87 |
2/2✓ Branch 75 → 76 taken 1 time.
✓ Branch 75 → 81 taken 25 times.
|
26 | if (otherKey == key) |
| 88 |
2/2✓ Branch 76 → 77 taken 1 time.
✓ Branch 77 → 78 taken 1 time.
|
1 | return failure(tr("A contact cannot be related to itself.")); |
| 89 |
1/1✓ Branch 82 → 83 taken 25 times.
|
25 | const auto other = sync->store()->card(otherBook, otherUid); |
| 90 |
1/2✗ Branch 84 → 85 not taken.
✓ Branch 84 → 90 taken 25 times.
|
25 | if (!other) |
| 91 | ✗ | return failure(tr("The other contact no longer exists.")); | |
| 92 |
1/1✓ Branch 90 → 91 taken 25 times.
|
25 | ContactCard parsed; |
| 93 |
1/1✓ Branch 92 → 93 taken 25 times.
|
25 | VCardCodec::parse(other->raw, &parsed); |
| 94 | 25 | relation.targetUid = otherUid; | |
| 95 | 25 | relation.targetName = parsed.formattedName; | |
| 96 |
1/2✓ Branch 98 → 99 taken 25 times.
✗ Branch 98 → 101 not taken.
|
25 | } else { |
| 97 | // A person who is not a contact ("Grandma Rosa"): the text form (D-3). | ||
| 98 |
1/1✓ Branch 102 → 103 taken 2 times.
|
2 | relation.targetName = otherKey.trimmed(); |
| 99 |
1/2✗ Branch 106 → 107 not taken.
✓ Branch 106 → 112 taken 2 times.
|
2 | if (relation.targetName.isEmpty()) |
| 100 | ✗ | return failure(tr("Choose a person.")); | |
| 101 | } | ||
| 102 | // D-6: "Anna is my sister" is stored on Anna's card, pointing to me. | ||
| 103 | 27 | QString holder = key; | |
| 104 |
1/1✓ Branch 113 → 114 taken 27 times.
|
27 | const QString inverse = RelationVocabulary::inverseOf(relation.type); |
| 105 |
8/13✓ Branch 114 → 115 taken 27 times.
✓ Branch 116 → 117 taken 3 times.
✓ Branch 116 → 122 taken 24 times.
✓ Branch 118 → 119 taken 3 times.
✗ Branch 118 → 122 not taken.
✓ Branch 120 → 121 taken 3 times.
✗ Branch 120 → 122 not taken.
✓ Branch 123 → 124 taken 27 times.
✗ Branch 123 → 125 not taken.
✓ Branch 125 → 126 taken 3 times.
✓ Branch 125 → 146 taken 24 times.
✗ Branch 226 → 227 not taken.
✗ Branch 226 → 228 not taken.
|
27 | if (key == meKey() && !relation.targetUid.isEmpty() && !inverse.isEmpty()) { |
| 106 | 3 | qint64 meBook = 0; | |
| 107 | 3 | QString meUid; | |
| 108 |
1/1✓ Branch 126 → 127 taken 3 times.
|
3 | ContactQueries::splitKey(key, &meBook, &meUid); |
| 109 | 3 | holder = otherKey; | |
| 110 | 3 | relation.type = inverse; | |
| 111 | 3 | relation.targetUid = meUid; | |
| 112 |
3/3✓ Branch 130 → 131 taken 3 times.
✓ Branch 135 → 136 taken 3 times.
✓ Branch 136 → 137 taken 3 times.
|
6 | relation.targetName = personEntry(key).value(QStringLiteral("name")).toString(); |
| 113 | 3 | } | |
| 114 | 27 | const QVariantMap result = editPeople( | |
| 115 | holder, | ||
| 116 | 27 | [&relation](ContactCard *card) -> QString { | |
| 117 |
4/4✓ Branch 2 → 3 taken 27 times.
✓ Branch 3 → 4 taken 27 times.
✓ Branch 25 → 5 taken 6 times.
✓ Branch 25 → 26 taken 26 times.
|
32 | for (const ContactRelation &existing : card->relations) |
| 118 |
5/6✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 19 taken 4 times.
✓ Branch 9 → 10 taken 2 times.
✗ Branch 9 → 19 not taken.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 23 taken 5 times.
|
8 | if (existing.type == relation.type && existing.label == relation.label && |
| 119 |
4/6✓ Branch 11 → 12 taken 2 times.
✗ Branch 11 → 14 not taken.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 18 taken 1 time.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 19 taken 1 time.
|
3 | ((!relation.targetUid.isEmpty() && existing.targetUid == relation.targetUid) || |
| 120 |
0/2✗ Branch 17 → 18 not taken.
✗ Branch 17 → 19 not taken.
|
1 | (relation.targetUid.isEmpty() && existing.targetName == relation.targetName))) |
| 121 |
1/1✓ Branch 21 → 22 taken 1 time.
|
1 | return tr("This relationship is already saved."); |
| 122 |
1/2✗ Branch 27 → 28 not taken.
✓ Branch 27 → 29 taken 26 times.
|
26 | if (card->relations.size() >= VCardCodec::MaxRelations) |
| 123 | ✗ | return tr("This contact has too many relationships."); | |
| 124 | 26 | card->relations.append(relation); | |
| 125 | 26 | return {}; | |
| 126 | }, | ||
| 127 |
2/2✓ Branch 146 → 147 taken 27 times.
✓ Branch 148 → 149 taken 27 times.
|
81 | tr("Relationship added")); |
| 128 |
8/8✓ Branch 151 → 152 taken 27 times.
✓ Branch 155 → 156 taken 27 times.
✓ Branch 156 → 157 taken 27 times.
✓ Branch 157 → 158 taken 27 times.
✓ Branch 158 → 159 taken 27 times.
✓ Branch 159 → 160 taken 27 times.
✓ Branch 177 → 153 taken 27 times.
✓ Branch 177 → 178 taken 27 times.
|
54 | qCInfo(lcContactRelationActions) << "Add relation" << relation.type << "on" << holder |
| 129 |
5/5✓ Branch 164 → 165 taken 27 times.
✓ Branch 165 → 166 taken 27 times.
✓ Branch 166 → 167 taken 26 times.
✓ Branch 166 → 168 taken 1 time.
✓ Branch 169 → 170 taken 27 times.
|
54 | << (result.value(QStringLiteral("ok")).toBool() ? "done" : "refused"); |
| 130 | 27 | return result; | |
| 131 | 32 | } | |
| 132 | |||
| 133 | 4 | QVariantMap QuickContactActions::removeRelation(const QString &storedOnKey, int sourceIndex) { | |
| 134 | 4 | const QVariantMap result = editPeople( | |
| 135 | storedOnKey, | ||
| 136 | 4 | [sourceIndex](ContactCard *card) -> QString { | |
| 137 |
2/2✓ Branch 14 → 3 taken 5 times.
✓ Branch 14 → 15 taken 1 time.
|
6 | for (int i = 0; i < card->relations.size(); ++i) { |
| 138 |
2/2✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 6 taken 3 times.
|
5 | if (card->relations.at(i).sourceIndex != sourceIndex) |
| 139 | 2 | continue; | |
| 140 |
1/2✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 3 times.
|
3 | if (card->relations.at(i).readOnly()) |
| 141 | ✗ | return tr("This relationship was saved by another program and cannot be changed here."); | |
| 142 | 3 | card->relations.removeAt(i); | |
| 143 | 3 | return {}; | |
| 144 | } | ||
| 145 | 1 | return tr("The relationship no longer exists."); | |
| 146 | }, | ||
| 147 |
2/2✓ Branch 2 → 3 taken 4 times.
✓ Branch 4 → 5 taken 4 times.
|
12 | tr("Relationship removed")); |
| 148 |
8/8✓ Branch 7 → 8 taken 4 times.
✓ Branch 11 → 12 taken 4 times.
✓ Branch 12 → 13 taken 4 times.
✓ Branch 13 → 14 taken 4 times.
✓ Branch 14 → 15 taken 4 times.
✓ Branch 15 → 16 taken 4 times.
✓ Branch 33 → 9 taken 4 times.
✓ Branch 33 → 34 taken 4 times.
|
8 | qCInfo(lcContactRelationActions) << "Remove relation" << sourceIndex << "on" << storedOnKey |
| 149 |
5/5✓ Branch 20 → 21 taken 4 times.
✓ Branch 21 → 22 taken 4 times.
✓ Branch 22 → 23 taken 3 times.
✓ Branch 22 → 24 taken 1 time.
✓ Branch 25 → 26 taken 4 times.
|
8 | << (result.value(QStringLiteral("ok")).toBool() ? "done" : "refused"); |
| 150 | 4 | return result; | |
| 151 | ✗ | } | |
| 152 | |||
| 153 | // ─── pins (S103.4.5, D-10, interaction.md §6.6) ─── | ||
| 154 | |||
| 155 | 1 | QVariantMap QuickContactActions::pinAddress(const QString &key, int addressIndex, double latitude, double longitude) { | |
| 156 |
1/1✓ Branch 2 → 3 taken 1 time.
|
1 | const GeoPoint position = GeoPoint::at(latitude, longitude); |
| 157 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 9 taken 1 time.
|
1 | if (!position.valid) |
| 158 | ✗ | return failure(tr("This position is outside the map.")); | |
| 159 | 1 | return editPeople( | |
| 160 | key, | ||
| 161 |
1/1✓ Branch 10 → 11 taken 1 time.
|
1 | [addressIndex, position](ContactCard *card) -> QString { |
| 162 |
3/6✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1 time.
|
1 | if (addressIndex < 0 || addressIndex >= card->addresses.size()) |
| 163 | ✗ | return tr("The address no longer exists."); | |
| 164 | 1 | card->addresses[addressIndex].geo = position; | |
| 165 | 1 | return {}; | |
| 166 | }, | ||
| 167 |
2/2✓ Branch 9 → 10 taken 1 time.
✓ Branch 11 → 12 taken 1 time.
|
3 | tr("Position saved")); |
| 168 | } | ||
| 169 | |||
| 170 | ✗ | QVariantMap QuickContactActions::clearPin(const QString &key, int addressIndex) { | |
| 171 | ✗ | return editPeople( | |
| 172 | key, | ||
| 173 | ✗ | [addressIndex](ContactCard *card) -> QString { | |
| 174 | ✗ | if (addressIndex < 0 || addressIndex >= card->addresses.size()) | |
| 175 | ✗ | return tr("The address no longer exists."); | |
| 176 | ✗ | card->addresses[addressIndex].geo = {}; | |
| 177 | ✗ | return {}; | |
| 178 | }, | ||
| 179 | ✗ | tr("Computed position restored")); | |
| 180 | } | ||
| 181 | |||
| 182 | // ─── editor helpers (S103.3.2/S103.3.3, interaction.md §3/§4) ─── | ||
| 183 | |||
| 184 | 183 | QVariantList QuickContactActions::relationTypes(bool holderSide, const QString &holderGender) const { | |
| 185 | 183 | QVariantList out; | |
| 186 | 183 | QStringList seen; | |
| 187 | 9438 | const auto append = [&](const QString &type, RelationVocabulary::Category category) { | |
| 188 |
2/2✓ Branch 3 → 4 taken 4320 times.
✓ Branch 3 → 5 taken 5118 times.
|
9438 | if (seen.contains(type)) |
| 189 | 4320 | return; | |
| 190 |
1/1✓ Branch 5 → 6 taken 5118 times.
|
5118 | seen.append(type); |
| 191 |
3/3✓ Branch 6 → 7 taken 5040 times.
✓ Branch 6 → 8 taken 78 times.
✓ Branch 7 → 9 taken 5040 times.
|
5118 | const QString holderLabel = holderSide ? RelationVocabulary::holderLabel(type, true, holderGender) : QString(); |
| 192 |
1/1✓ Branch 35 → 36 taken 5118 times.
|
15354 | out.append(QVariantMap{{QStringLiteral("id"), type}, |
| 193 |
7/11✓ Branch 17 → 18 taken 78 times.
✓ Branch 17 → 21 taken 5040 times.
✓ Branch 20 → 22 taken 78 times.
✓ Branch 48 → 49 taken 78 times.
✓ Branch 48 → 50 taken 5040 times.
✓ Branch 50 → 51 taken 78 times.
✓ Branch 50 → 52 taken 5040 times.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
|
10236 | {QStringLiteral("label"), holderLabel.isEmpty() ? RelationVocabulary::label(type) : holderLabel}, |
| 194 |
1/1✓ Branch 26 → 27 taken 5118 times.
|
10236 | {QStringLiteral("category"), RelationVocabulary::categoryId(category)}, |
| 195 |
3/5✓ Branch 31 → 32 taken 5118 times.
✓ Branch 39 → 40 taken 20472 times.
✓ Branch 39 → 41 taken 5118 times.
✗ Branch 64 → 65 not taken.
✗ Branch 64 → 66 not taken.
|
30708 | {QStringLiteral("categoryLabel"), RelationVocabulary::categoryLabel(category)}}); |
| 196 |
1/5✓ Branch 33 → 34 taken 5118 times.
✗ Branch 108 → 109 not taken.
✗ Branch 108 → 112 not taken.
✗ Branch 110 → 111 not taken.
✗ Branch 110 → 112 not taken.
|
30708 | }; |
| 197 | 915 | for (const RelationVocabulary::Category category : | |
| 198 | {RelationVocabulary::Category::Family, RelationVocabulary::Category::Friends, | ||
| 199 |
2/2✓ Branch 51 → 5 taken 732 times.
✓ Branch 51 → 52 taken 183 times.
|
1098 | RelationVocabulary::Category::Work, RelationVocabulary::Category::Other}) { |
| 200 |
1/1✓ Branch 5 → 6 taken 732 times.
|
732 | const QStringList types = RelationVocabulary::typesOf(category); |
| 201 |
2/2✓ Branch 30 → 8 taken 5124 times.
✓ Branch 30 → 31 taken 732 times.
|
5856 | for (const QString &type : types) { |
| 202 | // F103-20: family membership is set on the family's entry (*Family members*), | ||
| 203 | // never as a relationship between two people (one of them became a family). | ||
| 204 |
6/6✓ Branch 11 → 12 taken 4941 times.
✓ Branch 11 → 15 taken 183 times.
✓ Branch 14 → 15 taken 183 times.
✓ Branch 14 → 16 taken 4758 times.
✓ Branch 17 → 18 taken 366 times.
✓ Branch 17 → 19 taken 4758 times.
|
5124 | if (type == QLatin1String("member") || type == QLatin1String("member-of")) |
| 205 | 366 | continue; | |
| 206 | // Holder side: the role in menu order ("Parent of" before "Child of"), | ||
| 207 | // stored as its inverse. | ||
| 208 |
1/1✓ Branch 19 → 20 taken 4758 times.
|
4758 | const QString inverse = RelationVocabulary::inverseOf(type); |
| 209 |
4/5✓ Branch 20 → 21 taken 4680 times.
✓ Branch 20 → 24 taken 78 times.
✓ Branch 22 → 23 taken 4680 times.
✗ Branch 22 → 24 not taken.
✓ Branch 25 → 26 taken 4758 times.
|
4758 | append(holderSide && !inverse.isEmpty() ? inverse : type, category); |
| 210 | 4758 | } | |
| 211 |
2/2✓ Branch 31 → 32 taken 720 times.
✓ Branch 31 → 49 taken 12 times.
|
732 | if (holderSide) // types whose holder role is not editable itself (agent: "Assisted person of") |
| 212 |
2/2✓ Branch 47 → 34 taken 5040 times.
✓ Branch 47 → 48 taken 720 times.
|
5760 | for (const QString &type : types) |
| 213 |
6/6✓ Branch 37 → 38 taken 4860 times.
✓ Branch 37 → 42 taken 180 times.
✓ Branch 40 → 41 taken 4680 times.
✓ Branch 40 → 42 taken 180 times.
✓ Branch 43 → 44 taken 4680 times.
✓ Branch 43 → 45 taken 360 times.
|
5040 | if (type != QLatin1String("member") && type != QLatin1String("member-of")) |
| 214 |
1/1✓ Branch 44 → 45 taken 4680 times.
|
4680 | append(type, category); |
| 215 | 732 | } | |
| 216 | 183 | return out; | |
| 217 | 183 | } | |
| 218 | |||
| 219 | 11 | QString QuickContactActions::relationSentence(const QString &targetName, const QString &type, | |
| 220 | const QString &holderName, const QString &targetGender, | ||
| 221 | const QString &custom) const { | ||
| 222 |
7/11✓ Branch 2 → 3 taken 11 times.
✓ Branch 4 → 5 taken 10 times.
✓ Branch 4 → 7 taken 1 time.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 10 times.
✓ Branch 9 → 10 taken 11 times.
✗ Branch 9 → 11 not taken.
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 10 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
11 | if (targetName.trimmed().isEmpty() || type.isEmpty()) |
| 223 | 1 | return {}; | |
| 224 |
2/2✓ Branch 19 → 20 taken 10 times.
✓ Branch 20 → 21 taken 10 times.
|
20 | return RelationVocabulary::sentence(targetName.trimmed(), RelationVocabulary::canonical(type), |
| 225 |
3/5✓ Branch 14 → 15 taken 10 times.
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 10 times.
✗ Branch 17 → 19 not taken.
✓ Branch 18 → 19 taken 10 times.
|
20 | holderName.trimmed().isEmpty() ? tr("this contact") : holderName.trimmed(), |
| 226 |
2/2✓ Branch 13 → 14 taken 10 times.
✓ Branch 21 → 22 taken 10 times.
|
30 | targetGender, custom.trimmed()); |
| 227 | } | ||
| 228 | |||
| 229 | 413 | QString QuickContactActions::relationHolderSentence(const QString &holderName, const QString &type, | |
| 230 | const QString &targetName, const QString &custom) const { | ||
| 231 |
2/2✓ Branch 2 → 3 taken 413 times.
✓ Branch 3 → 4 taken 413 times.
|
413 | const QString inverse = RelationVocabulary::inverseOf(RelationVocabulary::canonical(type)); |
| 232 |
8/11✓ Branch 6 → 7 taken 404 times.
✓ Branch 6 → 10 taken 9 times.
✓ Branch 7 → 8 taken 404 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 404 times.
✓ Branch 12 → 13 taken 404 times.
✓ Branch 12 → 14 taken 9 times.
✓ Branch 14 → 15 taken 9 times.
✓ Branch 14 → 20 taken 404 times.
✗ Branch 42 → 43 not taken.
✗ Branch 42 → 44 not taken.
|
413 | if (inverse.isEmpty() || holderName.trimmed().isEmpty()) |
| 233 |
1/1✓ Branch 16 → 17 taken 9 times.
|
9 | return relationSentence(targetName, type, holderName, {}, custom); |
| 234 |
2/3✓ Branch 20 → 21 taken 404 times.
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 404 times.
|
404 | if (targetName.trimmed().isEmpty()) |
| 235 | ✗ | return {}; | |
| 236 |
3/3✓ Branch 27 → 28 taken 404 times.
✓ Branch 28 → 29 taken 404 times.
✓ Branch 29 → 30 taken 404 times.
|
404 | return RelationVocabulary::sentence(holderName.trimmed(), inverse, targetName.trimmed()); |
| 237 | 413 | } | |
| 238 | |||
| 239 | 42 | QVariantMap QuickContactActions::parseLooseDate(const QString &text) const { | |
| 240 |
2/3✓ Branch 2 → 3 taken 42 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 33 taken 42 times.
|
42 | if (text.trimmed().isEmpty()) |
| 241 | ✗ | return {{QStringLiteral("ok"), true}, {QStringLiteral("iso"), QString()}, {QStringLiteral("text"), QString()}}; | |
| 242 |
2/2✓ Branch 33 → 34 taken 42 times.
✓ Branch 34 → 35 taken 42 times.
|
42 | const LooseDate date = ContactEditorPeople::parseLooseDate(text); |
| 243 |
3/3✓ Branch 36 → 37 taken 42 times.
✓ Branch 37 → 38 taken 14 times.
✓ Branch 37 → 49 taken 28 times.
|
42 | if (!date.isValid()) |
| 244 |
2/4✓ Branch 44 → 45 taken 14 times.
✓ Branch 44 → 46 taken 14 times.
✗ Branch 120 → 121 not taken.
✗ Branch 120 → 122 not taken.
|
56 | return {{QStringLiteral("ok"), false}}; |
| 245 | 56 | return {{QStringLiteral("ok"), true}, | |
| 246 |
1/1✓ Branch 56 → 57 taken 28 times.
|
56 | {QStringLiteral("iso"), date.toIso()}, |
| 247 |
4/6✓ Branch 61 → 62 taken 28 times.
✓ Branch 62 → 63 taken 28 times.
✓ Branch 66 → 67 taken 84 times.
✓ Branch 66 → 68 taken 28 times.
✗ Branch 137 → 138 not taken.
✗ Branch 137 → 139 not taken.
|
168 | {QStringLiteral("text"), MetSentence::formatDate(date)}}; |
| 248 | 182 | } | |
| 249 | |||
| 250 | 26 | QString QuickContactActions::looseDateText(const QString &iso) const { | |
| 251 |
3/3✓ Branch 2 → 3 taken 26 times.
✓ Branch 3 → 4 taken 26 times.
✓ Branch 4 → 5 taken 26 times.
|
26 | return MetSentence::formatDate(LooseDate::fromIso(iso)); |
| 252 | } | ||
| 253 | |||
| 254 | 48 | QVariantMap QuickContactActions::recognizeSocial(const QString &text, const QString &kind) const { | |
| 255 |
1/1✓ Branch 2 → 3 taken 48 times.
|
48 | const ServiceCatalog &catalog = ServiceCatalog::builtIn(); |
| 256 |
2/2✓ Branch 3 → 4 taken 48 times.
✓ Branch 4 → 5 taken 48 times.
|
48 | const ServiceCatalog::Recognised found = catalog.recognise(text.trimmed(), kind); |
| 257 |
1/1✓ Branch 6 → 7 taken 48 times.
|
48 | const ServiceCatalog::Service *service = catalog.find(found.service); |
| 258 | 96 | return {{QStringLiteral("recognised"), found.recognised}, | |
| 259 | 96 | {QStringLiteral("service"), found.service}, | |
| 260 | 96 | {QStringLiteral("kind"), found.kind}, | |
| 261 |
1/1✓ Branch 23 → 24 taken 48 times.
|
96 | {QStringLiteral("label"), catalog.displayName(found.service)}, |
| 262 | 96 | {QStringLiteral("handle"), found.handle}, | |
| 263 |
1/3✗ Branch 33 → 34 not taken.
✓ Branch 33 → 35 taken 48 times.
✗ Branch 34 → 36 not taken.
|
96 | {QStringLiteral("value"), found.value.isEmpty() ? text.trimmed() : found.value}, |
| 264 |
4/8✓ Branch 40 → 41 taken 48 times.
✗ Branch 40 → 43 not taken.
✓ Branch 41 → 42 taken 48 times.
✗ Branch 41 → 43 not taken.
✓ Branch 47 → 48 taken 336 times.
✓ Branch 47 → 49 taken 48 times.
✗ Branch 73 → 74 not taken.
✗ Branch 73 → 75 not taken.
|
480 | {QStringLiteral("glyph"), int(service && service->codepoint ? service->codepoint : 0xF0339)}}; |
| 265 | 432 | } | |
| 266 | |||
| 267 | 161 | QVariantList QuickContactActions::socialServices(const QString &kind) const { | |
| 268 | 161 | const ServiceCatalog &catalog = ServiceCatalog::builtIn(); | |
| 269 | 161 | QVariantList out; | |
| 270 |
5/5✓ Branch 3 → 4 taken 161 times.
✓ Branch 4 → 5 taken 161 times.
✓ Branch 5 → 6 taken 161 times.
✓ Branch 34 → 7 taken 1367 times.
✓ Branch 34 → 35 taken 161 times.
|
1528 | for (const QString &id : catalog.idsForKind(kind)) |
| 271 |
4/6✓ Branch 16 → 17 taken 1367 times.
✓ Branch 20 → 21 taken 1367 times.
✓ Branch 24 → 25 taken 2734 times.
✓ Branch 24 → 26 taken 1367 times.
✗ Branch 43 → 44 not taken.
✗ Branch 43 → 45 not taken.
|
6996 | out.append(QVariantMap{{QStringLiteral("id"), id}, {QStringLiteral("label"), catalog.displayName(id)}}); |
| 272 | 161 | return out; | |
| 273 | 4101 | } | |
| 274 | |||
| 275 | 1 | QVariantList QuickContactActions::languageOptions(const QString &fragment) const { | |
| 276 |
2/2✓ Branch 2 → 3 taken 1 time.
✓ Branch 3 → 4 taken 1 time.
|
1 | const QString wanted = ContactIndex::foldForSort(fragment.trimmed()); |
| 277 | 1 | QVariantList out; | |
| 278 | 1 | QSet<int> seen; | |
| 279 |
5/6✓ Branch 83 → 84 taken 345 times.
✓ Branch 83 → 87 taken 1 time.
✓ Branch 85 → 86 taken 345 times.
✗ Branch 85 → 87 not taken.
✓ Branch 88 → 7 taken 345 times.
✓ Branch 88 → 89 taken 1 time.
|
346 | for (int value = int(QLocale::Abkhazian); value <= int(QLocale::LastLanguage) && out.size() < 8; ++value) { |
| 280 | 345 | const auto language = QLocale::Language(value); | |
| 281 |
1/1✓ Branch 8 → 9 taken 345 times.
|
345 | const QString code = QLocale::languageToCode(language, QLocale::ISO639Part1); |
| 282 |
5/6✓ Branch 10 → 11 taken 180 times.
✓ Branch 10 → 13 taken 165 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 180 times.
✓ Branch 15 → 16 taken 165 times.
✓ Branch 15 → 17 taken 180 times.
|
345 | if (code.isEmpty() || seen.contains(value)) |
| 283 | 165 | continue; | |
| 284 | // The name in the UI language (QLocale names languages in English; | ||
| 285 | // the native name helps "Port" find Português). | ||
| 286 |
1/1✓ Branch 17 → 18 taken 180 times.
|
180 | const QString english = QLocale::languageToString(language); |
| 287 |
2/2✓ Branch 18 → 19 taken 180 times.
✓ Branch 19 → 20 taken 180 times.
|
180 | const QString native = QLocale(language).nativeLanguageName(); |
| 288 |
6/8✓ Branch 23 → 24 taken 180 times.
✓ Branch 24 → 25 taken 180 times.
✓ Branch 25 → 26 taken 179 times.
✓ Branch 25 → 34 taken 1 time.
✓ Branch 43 → 44 taken 179 times.
✓ Branch 43 → 45 taken 1 time.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 114 not taken.
|
360 | if (!wanted.isEmpty() && !ContactIndex::foldForSort(english).startsWith(wanted) && |
| 289 |
14/24✓ Branch 22 → 23 taken 180 times.
✗ Branch 22 → 34 not taken.
✓ Branch 26 → 27 taken 179 times.
✓ Branch 27 → 28 taken 179 times.
✓ Branch 28 → 29 taken 179 times.
✗ Branch 28 → 34 not taken.
✓ Branch 29 → 30 taken 179 times.
✓ Branch 30 → 31 taken 179 times.
✓ Branch 32 → 33 taken 179 times.
✗ Branch 32 → 34 not taken.
✓ Branch 35 → 36 taken 179 times.
✓ Branch 35 → 37 taken 1 time.
✓ Branch 37 → 38 taken 179 times.
✓ Branch 37 → 39 taken 1 time.
✓ Branch 39 → 40 taken 179 times.
✓ Branch 39 → 41 taken 1 time.
✓ Branch 41 → 42 taken 180 times.
✗ Branch 41 → 43 not taken.
✗ Branch 100 → 101 not taken.
✗ Branch 100 → 102 not taken.
✗ Branch 104 → 105 not taken.
✗ Branch 104 → 106 not taken.
✗ Branch 108 → 109 not taken.
✗ Branch 108 → 110 not taken.
|
360 | !ContactIndex::foldForSort(native).startsWith(wanted) && code != fragment.trimmed().toLower()) |
| 290 | 179 | continue; | |
| 291 |
1/1✓ Branch 45 → 46 taken 1 time.
|
1 | seen.insert(value); |
| 292 |
4/6✓ Branch 53 → 54 taken 1 time.
✓ Branch 57 → 58 taken 1 time.
✓ Branch 61 → 62 taken 2 times.
✓ Branch 61 → 63 taken 1 time.
✗ Branch 122 → 123 not taken.
✗ Branch 122 → 124 not taken.
|
5 | out.append(QVariantMap{{QStringLiteral("code"), code}, {QStringLiteral("name"), languageName(code)}}); |
| 293 | 703 | } | |
| 294 | 1 | return out; | |
| 295 | 4 | } | |
| 296 | |||
| 297 | 14 | QString QuickContactActions::languageName(const QString &code) const { return ContactPeopleView::languageName(code); } | |
| 298 | |||
| 299 | 259 | QVariantMap QuickContactActions::personEntry(const QString &key) const { | |
| 300 |
1/1✓ Branch 2 → 3 taken 259 times.
|
259 | ContactSyncCoordinator *sync = m_coordinator(); |
| 301 | 259 | qint64 bookId = 0; | |
| 302 | 259 | QString uid; | |
| 303 |
6/7✓ Branch 3 → 4 taken 259 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 259 times.
✓ Branch 5 → 6 taken 42 times.
✓ Branch 5 → 7 taken 217 times.
✓ Branch 8 → 9 taken 42 times.
✓ Branch 8 → 10 taken 217 times.
|
259 | if (!sync || !ContactQueries::splitKey(key, &bookId, &uid)) |
| 304 | 42 | return {}; | |
| 305 |
2/2✓ Branch 11 → 12 taken 217 times.
✓ Branch 12 → 13 taken 217 times.
|
217 | QSqlQuery q(sync->store()->database()); |
| 306 |
1/1✓ Branch 17 → 18 taken 217 times.
|
217 | q.prepare(QStringLiteral("SELECT c.display_name, c.has_photo, COALESCE(t.gender, ''), b.display_name," |
| 307 | " (b.account_id = '' AND b.path = 'local'), c.kind" | ||
| 308 | " FROM cards c JOIN address_books b ON b.id = c.book_id " | ||
| 309 | "LEFT JOIN card_traits t ON t.card_id = c.id WHERE c.book_id = ? AND c.uid = ?")); | ||
| 310 |
1/1✓ Branch 22 → 23 taken 217 times.
|
217 | q.addBindValue(bookId); |
| 311 |
1/1✓ Branch 26 → 27 taken 217 times.
|
217 | q.addBindValue(uid); |
| 312 |
7/8✓ Branch 28 → 29 taken 217 times.
✓ Branch 29 → 30 taken 217 times.
✗ Branch 29 → 32 not taken.
✓ Branch 30 → 31 taken 217 times.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 31 → 33 taken 216 times.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 36 taken 216 times.
|
217 | if (!q.exec() || !q.next()) |
| 313 | 1 | return {}; | |
| 314 |
1/1✓ Branch 36 → 37 taken 216 times.
|
216 | ContactCard named; |
| 315 |
2/2✓ Branch 37 → 38 taken 216 times.
✓ Branch 38 → 39 taken 216 times.
|
216 | named.formattedName = q.value(0).toString(); |
| 316 | 432 | return {{QStringLiteral("key"), key}, | |
| 317 | 432 | {QStringLiteral("uid"), uid}, | |
| 318 | 432 | {QStringLiteral("name"), named.formattedName}, | |
| 319 | 432 | {QStringLiteral("address"), QString()}, | |
| 320 |
9/11✓ Branch 62 → 63 taken 216 times.
✓ Branch 63 → 64 taken 216 times.
✓ Branch 64 → 65 taken 14 times.
✓ Branch 64 → 66 taken 202 times.
✓ Branch 65 → 68 taken 14 times.
✓ Branch 66 → 67 taken 202 times.
✓ Branch 67 → 68 taken 202 times.
✓ Branch 120 → 121 taken 202 times.
✓ Branch 120 → 122 taken 14 times.
✗ Branch 218 → 219 not taken.
✗ Branch 218 → 220 not taken.
|
432 | {QStringLiteral("book"), q.value(4).toBool() ? tr("On this computer") : q.value(3).toString()}, |
| 321 |
1/1✓ Branch 72 → 73 taken 216 times.
|
432 | {QStringLiteral("initials"), ContactIndex::initials(named)}, |
| 322 |
1/1✓ Branch 77 → 78 taken 216 times.
|
432 | {QStringLiteral("avatarColor"), ContactIndex::avatarColorIndex(uid)}, |
| 323 |
2/2✓ Branch 82 → 83 taken 216 times.
✓ Branch 83 → 84 taken 216 times.
|
432 | {QStringLiteral("hasPhoto"), q.value(1).toBool()}, |
| 324 |
2/2✓ Branch 88 → 89 taken 216 times.
✓ Branch 89 → 90 taken 216 times.
|
432 | {QStringLiteral("gender"), q.value(2).toString()}, |
| 325 |
4/6✓ Branch 95 → 96 taken 216 times.
✓ Branch 96 → 97 taken 216 times.
✓ Branch 101 → 102 taken 2160 times.
✓ Branch 101 → 103 taken 216 times.
✗ Branch 161 → 162 not taken.
✗ Branch 161 → 163 not taken.
|
2592 | {QStringLiteral("family"), q.value(5).toString() == QLatin1String("family")}}; |
| 326 | 2635 | } | |
| 327 | |||
| 328 | 70 | QVariantList QuickContactActions::searchPeople(const QString &fragment, const QString &exceptKey) const { | |
| 329 |
1/1✓ Branch 2 → 3 taken 70 times.
|
70 | ContactSyncCoordinator *sync = m_coordinator(); |
| 330 |
3/3✓ Branch 3 → 4 taken 70 times.
✓ Branch 4 → 5 taken 70 times.
✓ Branch 5 → 6 taken 70 times.
|
70 | const QString wanted = ContactIndex::foldForSort(fragment.left(64).trimmed()); |
| 331 |
5/6✓ Branch 8 → 9 taken 70 times.
✗ Branch 8 → 11 not taken.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 69 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 69 times.
|
70 | if (!sync || wanted.isEmpty()) |
| 332 | 1 | return {}; | |
| 333 |
1/1✓ Branch 16 → 17 taken 69 times.
|
69 | QSqlDatabase db = sync->store()->database(); |
| 334 |
3/3✓ Branch 19 → 20 taken 69 times.
✓ Branch 20 → 21 taken 69 times.
✓ Branch 21 → 22 taken 69 times.
|
69 | QList<ContactQueries::Row> rows = ContactQueries::page(db, {}, fragment.left(64), 60); |
| 335 | // The search text also holds relation and place names: keep the cards | ||
| 336 | // whose own name or address starts a word with the input (§4). | ||
| 337 |
1/1✓ Branch 30 → 31 taken 69 times.
|
69 | const QString firstWord = wanted.section(QLatin1Char(' '), 0, 0); |
| 338 |
1/1✓ Branch 31 → 32 taken 69 times.
|
69 | rows.removeIf([&firstWord, &exceptKey](const ContactQueries::Row &row) { |
| 339 |
5/6✓ Branch 3 → 4 taken 150 times.
✓ Branch 3 → 7 taken 1 time.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 150 times.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 150 times.
|
151 | if (row.key == exceptKey || row.kind == QLatin1String("group")) |
| 340 | 1 | return true; | |
| 341 |
3/3✓ Branch 13 → 14 taken 150 times.
✓ Branch 14 → 15 taken 150 times.
✓ Branch 15 → 16 taken 150 times.
|
450 | for (const QString &word : ContactIndex::foldForSort(row.displayName + QLatin1Char(' ') + row.primaryAddress) |
| 342 |
6/6✓ Branch 21 → 22 taken 150 times.
✓ Branch 22 → 23 taken 150 times.
✓ Branch 29 → 30 taken 150 times.
✓ Branch 30 → 31 taken 150 times.
✓ Branch 38 → 32 taken 513 times.
✓ Branch 38 → 39 taken 74 times.
|
1037 | .split(QRegularExpression(QStringLiteral("[\\s@.]+")), Qt::SkipEmptyParts)) |
| 343 |
3/3✓ Branch 33 → 34 taken 513 times.
✓ Branch 34 → 35 taken 76 times.
✓ Branch 34 → 36 taken 437 times.
|
513 | if (word.startsWith(firstWord)) |
| 344 |
2/2✓ Branch 41 → 42 taken 74 times.
✓ Branch 41 → 44 taken 76 times.
|
150 | return false; |
| 345 | 74 | return true; | |
| 346 | }); | ||
| 347 |
3/3✓ Branch 32 → 33 taken 69 times.
✓ Branch 33 → 34 taken 69 times.
✓ Branch 34 → 35 taken 69 times.
|
69 | std::stable_sort(rows.begin(), rows.end(), [](const ContactQueries::Row &a, const ContactQueries::Row &b) { |
| 348 | 22 | return a.useCount > b.useCount; | |
| 349 | }); | ||
| 350 | 69 | QVariantList out; | |
| 351 |
1/1✓ Branch 35 → 36 taken 69 times.
|
69 | const QString me = meKey(); |
| 352 |
5/5✓ Branch 36 → 37 taken 69 times.
✓ Branch 37 → 38 taken 69 times.
✓ Branch 38 → 39 taken 69 times.
✓ Branch 66 → 40 taken 76 times.
✓ Branch 66 → 67 taken 69 times.
|
145 | for (const ContactQueries::Row &row : rows.mid(0, 8)) |
| 353 |
2/2✓ Branch 42 → 43 taken 75 times.
✓ Branch 42 → 64 taken 1 time.
|
76 | if (row.key != me) { |
| 354 |
1/1✓ Branch 43 → 44 taken 75 times.
|
75 | QVariantMap entry = personEntry(row.key); |
| 355 |
2/3✓ Branch 44 → 45 taken 75 times.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 75 times.
|
75 | if (entry.isEmpty()) continue; // S106-271: removed meanwhile (F103-19 guard) |
| 356 |
1/1✓ Branch 51 → 52 taken 75 times.
|
150 | entry.insert(QStringLiteral("address"), row.primaryAddress); |
| 357 |
1/1✓ Branch 56 → 57 taken 75 times.
|
75 | out.append(entry); |
| 358 | 144 | } | |
| 359 | // D-6: "me" / "ich" (and the user's own name) find the me card first. | ||
| 360 |
4/4✓ Branch 70 → 71 taken 68 times.
✓ Branch 70 → 74 taken 1 time.
✓ Branch 73 → 74 taken 1 time.
✓ Branch 73 → 75 taken 67 times.
|
69 | const bool asksForMe = wanted == QLatin1String("me") || wanted == QLatin1String("ich"); |
| 361 |
5/6✓ Branch 77 → 78 taken 3 times.
✓ Branch 77 → 81 taken 66 times.
✓ Branch 79 → 80 taken 3 times.
✗ Branch 79 → 81 not taken.
✓ Branch 82 → 83 taken 3 times.
✓ Branch 82 → 102 taken 66 times.
|
69 | if (!me.isEmpty() && me != exceptKey) { |
| 362 |
1/1✓ Branch 85 → 86 taken 3 times.
|
5 | const bool named = std::any_of(rows.cbegin(), rows.cend(), [&me](const auto &row) { return row.key == me; }); |
| 363 |
4/4✓ Branch 86 → 87 taken 2 times.
✓ Branch 86 → 88 taken 1 time.
✓ Branch 87 → 88 taken 1 time.
✓ Branch 87 → 190 taken 1 time.
|
3 | if (asksForMe || named) { |
| 364 |
1/1✓ Branch 88 → 89 taken 2 times.
|
2 | QVariantMap entry = personEntry(me); |
| 365 |
1/1✓ Branch 93 → 94 taken 2 times.
|
4 | entry.insert(QStringLiteral("isMe"), true); |
| 366 |
1/1✓ Branch 98 → 99 taken 2 times.
|
2 | out.prepend(entry); |
| 367 | 2 | } | |
| 368 |
5/6✓ Branch 103 → 104 taken 66 times.
✗ Branch 103 → 106 not taken.
✓ Branch 104 → 105 taken 1 time.
✓ Branch 104 → 106 taken 65 times.
✓ Branch 107 → 108 taken 1 time.
✓ Branch 107 → 190 taken 65 times.
|
66 | } else if (me.isEmpty() && asksForMe) { |
| 369 | // "Is this you?" — the cards with an account address. | ||
| 370 |
5/5✓ Branch 108 → 109 taken 1 time.
✓ Branch 109 → 110 taken 1 time.
✓ Branch 110 → 111 taken 1 time.
✓ Branch 187 → 112 taken 1 time.
✓ Branch 187 → 188 taken 1 time.
|
2 | for (const QVariant &value : meSuggestions()) { |
| 371 |
4/4✓ Branch 113 → 114 taken 1 time.
✓ Branch 118 → 119 taken 1 time.
✓ Branch 119 → 120 taken 1 time.
✓ Branch 120 → 121 taken 1 time.
|
2 | QVariantMap entry = personEntry(value.toMap().value(QStringLiteral("key")).toString()); |
| 372 |
11/29✓ Branch 127 → 128 taken 1 time.
✓ Branch 128 → 129 taken 1 time.
✗ Branch 128 → 137 not taken.
✓ Branch 134 → 135 taken 1 time.
✓ Branch 135 → 136 taken 1 time.
✗ Branch 136 → 137 not taken.
✓ Branch 136 → 138 taken 1 time.
✓ Branch 139 → 140 taken 1 time.
✗ Branch 139 → 141 not taken.
✓ Branch 141 → 142 taken 1 time.
✗ Branch 141 → 143 not taken.
✓ Branch 143 → 144 taken 1 time.
✗ Branch 143 → 145 not taken.
✓ Branch 145 → 146 taken 1 time.
✗ Branch 145 → 147 not taken.
✓ Branch 147 → 148 taken 1 time.
✗ Branch 147 → 149 not taken.
✗ Branch 149 → 150 not taken.
✓ Branch 149 → 151 taken 1 time.
✗ Branch 275 → 276 not taken.
✗ Branch 275 → 277 not taken.
✗ Branch 279 → 280 not taken.
✗ Branch 279 → 281 not taken.
✗ Branch 283 → 284 not taken.
✗ Branch 283 → 285 not taken.
✗ Branch 287 → 288 not taken.
✗ Branch 287 → 289 not taken.
✗ Branch 291 → 292 not taken.
✗ Branch 291 → 293 not taken.
|
2 | if (entry.isEmpty() || entry.value(QStringLiteral("key")) == exceptKey) |
| 373 | ✗ | continue; | |
| 374 |
3/3✓ Branch 151 → 152 taken 1 time.
✓ Branch 156 → 157 taken 1 time.
✓ Branch 160 → 161 taken 1 time.
|
3 | entry.insert(QStringLiteral("address"), value.toMap().value(QStringLiteral("address"))); |
| 375 |
1/1✓ Branch 172 → 173 taken 1 time.
|
2 | entry.insert(QStringLiteral("suggestMe"), true); |
| 376 |
1/1✓ Branch 177 → 178 taken 1 time.
|
1 | out.prepend(entry); |
| 377 | 2 | } | |
| 378 | } | ||
| 379 |
1/1✓ Branch 190 → 191 taken 69 times.
|
69 | return out.mid(0, 9); |
| 380 | 70 | } | |
| 381 | |||
| 382 | 15 | QVariantList QuickContactActions::familyNames(const QString &fragment, const QString &exceptKey) const { | |
| 383 |
1/1✓ Branch 2 → 3 taken 15 times.
|
15 | ContactSyncCoordinator *sync = m_coordinator(); |
| 384 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 15 times.
|
15 | if (!sync) |
| 385 | ✗ | return {}; | |
| 386 |
1/1✓ Branch 6 → 7 taken 15 times.
|
15 | const QSqlDatabase db = sync->store()->database(); |
| 387 | 15 | QHash<qint64, int> cards; // family card id → member count | |
| 388 | 15 | QMap<QString, QPair<QString, int>> named; // folded name → name, member count | |
| 389 |
5/5✓ Branch 7 → 8 taken 15 times.
✓ Branch 8 → 9 taken 15 times.
✓ Branch 9 → 10 taken 15 times.
✓ Branch 51 → 11 taken 386 times.
✓ Branch 51 → 52 taken 15 times.
|
401 | for (const RelationIndex::Edge &edge : RelationIndex::allEdges(db)) { |
| 390 |
2/2✓ Branch 14 → 15 taken 43 times.
✓ Branch 14 → 16 taken 343 times.
|
386 | if (edge.role != QLatin1String("relation")) |
| 391 | 43 | continue; | |
| 392 |
2/2✓ Branch 18 → 19 taken 75 times.
✓ Branch 18 → 21 taken 268 times.
|
343 | if (edge.type == QLatin1String("member")) { |
| 393 |
1/1✓ Branch 19 → 20 taken 75 times.
|
75 | cards[edge.fromCardId] += 1; |
| 394 |
5/6✓ Branch 23 → 24 taken 2 times.
✓ Branch 23 → 26 taken 266 times.
✓ Branch 24 → 25 taken 2 times.
✗ Branch 24 → 26 not taken.
✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 30 taken 266 times.
|
268 | } else if (edge.type == QLatin1String("member-of") && edge.toCardId > 0) { |
| 395 |
1/1✓ Branch 28 → 29 taken 2 times.
|
2 | cards[edge.toCardId] += 1; |
| 396 |
1/2✗ Branch 32 → 33 not taken.
✓ Branch 32 → 49 taken 266 times.
|
266 | } else if (edge.type == QLatin1String("member-of")) { |
| 397 | ✗ | const QString name = edge.toName.simplified(); | |
| 398 | ✗ | if (name.isEmpty()) | |
| 399 | ✗ | continue; | |
| 400 | ✗ | QPair<QString, int> &entry = named[name.toCaseFolded()]; | |
| 401 | ✗ | if (entry.first.isEmpty()) | |
| 402 | ✗ | entry.first = name; | |
| 403 | ✗ | entry.second += 1; | |
| 404 | ✗ | } | |
| 405 | 15 | } | |
| 406 | // Every family's entry, also one without members yet (created on the spot, members removed). | ||
| 407 |
1/1✓ Branch 53 → 54 taken 15 times.
|
15 | QSqlQuery entries(db); |
| 408 |
2/3✓ Branch 57 → 58 taken 15 times.
✓ Branch 60 → 61 taken 15 times.
✗ Branch 60 → 73 not taken.
|
15 | if (entries.exec(QStringLiteral("SELECT id FROM cards WHERE kind = 'family'"))) |
| 409 |
3/3✓ Branch 71 → 72 taken 38 times.
✓ Branch 72 → 62 taken 23 times.
✓ Branch 72 → 73 taken 15 times.
|
38 | while (entries.next()) |
| 410 |
5/5✓ Branch 62 → 63 taken 23 times.
✓ Branch 63 → 64 taken 23 times.
✓ Branch 65 → 66 taken 23 times.
✓ Branch 66 → 67 taken 23 times.
✓ Branch 67 → 68 taken 23 times.
|
23 | cards.insert(entries.value(0).toLongLong(), cards.value(entries.value(0).toLongLong())); |
| 411 |
3/3✓ Branch 73 → 74 taken 15 times.
✓ Branch 74 → 75 taken 15 times.
✓ Branch 75 → 76 taken 15 times.
|
15 | const QString wanted = fragment.left(64).simplified().toCaseFolded(); |
| 412 |
2/2✓ Branch 2 → 3 taken 36 times.
✓ Branch 3 → 4 taken 36 times.
|
36 | const auto matches = [&wanted](const QString &name) { return name.toCaseFolded().contains(wanted); }; |
| 413 | 15 | QList<QVariantMap> out; | |
| 414 | 15 | QSet<QString> cardNames; | |
| 415 |
2/2✓ Branch 172 → 80 taken 37 times.
✓ Branch 172 → 173 taken 15 times.
|
52 | for (auto it = cards.cbegin(); it != cards.cend(); ++it) { |
| 416 |
1/1✓ Branch 80 → 81 taken 37 times.
|
37 | QSqlQuery q(db); |
| 417 |
1/1✓ Branch 84 → 85 taken 37 times.
|
37 | q.prepare(QStringLiteral("SELECT book_id, uid FROM cards WHERE id = ?")); |
| 418 |
1/1✓ Branch 90 → 91 taken 37 times.
|
37 | q.addBindValue(it.key()); |
| 419 |
5/8✓ Branch 92 → 93 taken 37 times.
✓ Branch 93 → 94 taken 37 times.
✗ Branch 93 → 96 not taken.
✓ Branch 94 → 95 taken 37 times.
✗ Branch 95 → 96 not taken.
✓ Branch 95 → 97 taken 37 times.
✗ Branch 98 → 99 not taken.
✓ Branch 98 → 100 taken 37 times.
|
37 | if (!q.exec() || !q.next()) |
| 420 | ✗ | continue; | |
| 421 |
5/5✓ Branch 100 → 101 taken 37 times.
✓ Branch 101 → 102 taken 37 times.
✓ Branch 102 → 103 taken 37 times.
✓ Branch 103 → 104 taken 37 times.
✓ Branch 104 → 105 taken 37 times.
|
37 | const QString key = ContactQueries::cardKey(q.value(0).toLongLong(), q.value(1).toString()); |
| 422 |
1/1✓ Branch 108 → 109 taken 37 times.
|
37 | QVariantMap entry = personEntry(key); |
| 423 |
2/2✓ Branch 113 → 114 taken 37 times.
✓ Branch 114 → 115 taken 37 times.
|
74 | const QString name = entry.value(QStringLiteral("name")).toString(); |
| 424 |
6/7✓ Branch 119 → 120 taken 37 times.
✓ Branch 120 → 121 taken 37 times.
✗ Branch 120 → 123 not taken.
✓ Branch 122 → 123 taken 1 time.
✓ Branch 122 → 124 taken 36 times.
✓ Branch 125 → 126 taken 1 time.
✓ Branch 125 → 127 taken 36 times.
|
37 | if (entry.isEmpty() || key == exceptKey) |
| 425 | 1 | continue; | |
| 426 |
3/3✓ Branch 127 → 128 taken 36 times.
✓ Branch 128 → 129 taken 36 times.
✓ Branch 129 → 130 taken 36 times.
|
36 | cardNames.insert(name.simplified().toCaseFolded()); |
| 427 |
3/3✓ Branch 132 → 133 taken 36 times.
✓ Branch 133 → 134 taken 16 times.
✓ Branch 133 → 135 taken 20 times.
|
36 | if (!matches(name)) |
| 428 | 16 | continue; | |
| 429 | 20 | const int count = it.value(); | |
| 430 |
6/6✓ Branch 136 → 137 taken 1 time.
✓ Branch 136 → 138 taken 19 times.
✓ Branch 137 → 141 taken 1 time.
✓ Branch 139 → 141 taken 9 times.
✓ Branch 140 → 141 taken 10 times.
✓ Branch 145 → 146 taken 20 times.
|
59 | entry.insert(QStringLiteral("detail"), count == 0 ? tr("No members yet") |
| 431 |
2/2✓ Branch 138 → 139 taken 9 times.
✓ Branch 138 → 140 taken 10 times.
|
19 | : count == 1 ? tr("1 member") |
| 432 | : tr("%n members", "", count)); | ||
| 433 |
1/1✓ Branch 150 → 151 taken 20 times.
|
20 | out.append(entry); |
| 434 | 88 | } | |
| 435 |
3/4✓ Branch 173 → 174 taken 15 times.
✓ Branch 250 → 251 taken 15 times.
✗ Branch 252 → 175 not taken.
✓ Branch 252 → 253 taken 15 times.
|
15 | for (auto it = named.cbegin(); it != named.cend(); ++it) { |
| 436 | ✗ | if (cardNames.contains(it.key()) || !matches(it.value().first)) | |
| 437 | ✗ | continue; | |
| 438 | ✗ | ContactCard card; | |
| 439 | ✗ | card.formattedName = it.value().first; | |
| 440 | ✗ | out.append({{QStringLiteral("key"), QString()}, | |
| 441 | ✗ | {QStringLiteral("name"), card.formattedName}, | |
| 442 | ✗ | {QStringLiteral("textOnly"), true}, | |
| 443 | ✗ | {QStringLiteral("initials"), ContactIndex::initials(card)}, | |
| 444 | ✗ | {QStringLiteral("avatarColor"), ContactIndex::avatarColorIndex(card.formattedName)}, | |
| 445 | ✗ | {QStringLiteral("hasPhoto"), false}, | |
| 446 | ✗ | {QStringLiteral("detail"), it.value().second == 1 ? tr("1 member") | |
| 447 | ✗ | : tr("%n members", "", it.value().second)}}); | |
| 448 | ✗ | } | |
| 449 |
3/3✓ Branch 253 → 254 taken 15 times.
✓ Branch 254 → 255 taken 15 times.
✓ Branch 255 → 256 taken 15 times.
|
15 | std::sort(out.begin(), out.end(), [](const QVariantMap &a, const QVariantMap &b) { |
| 450 |
3/3✓ Branch 12 → 13 taken 11 times.
✓ Branch 13 → 14 taken 11 times.
✓ Branch 14 → 15 taken 11 times.
|
33 | return QString::localeAwareCompare(a.value(QStringLiteral("name")).toString(), |
| 451 |
2/2✓ Branch 6 → 7 taken 11 times.
✓ Branch 7 → 8 taken 11 times.
|
44 | b.value(QStringLiteral("name")).toString()) < 0; |
| 452 | }); | ||
| 453 | 15 | QVariantList list; | |
| 454 |
5/5✓ Branch 256 → 257 taken 15 times.
✓ Branch 257 → 258 taken 15 times.
✓ Branch 258 → 259 taken 15 times.
✓ Branch 266 → 260 taken 20 times.
✓ Branch 266 → 267 taken 15 times.
|
35 | for (const QVariantMap &entry : out.mid(0, 8)) |
| 455 |
1/1✓ Branch 262 → 263 taken 20 times.
|
35 | list.append(entry); |
| 456 |
10/10✓ Branch 268 → 269 taken 15 times.
✓ Branch 272 → 273 taken 15 times.
✓ Branch 273 → 274 taken 15 times.
✓ Branch 275 → 276 taken 15 times.
✓ Branch 276 → 277 taken 15 times.
✓ Branch 277 → 278 taken 15 times.
✓ Branch 278 → 279 taken 15 times.
✓ Branch 279 → 280 taken 15 times.
✓ Branch 283 → 270 taken 15 times.
✓ Branch 283 → 284 taken 15 times.
|
30 | qCDebug(lcContactRelationActions) << "Family names:" << cards.size() << "entries," << named.size() << "by name"; |
| 457 | 15 | return list; | |
| 458 | 15 | } | |
| 459 | |||
| 460 | 54 | QVariantList QuickContactActions::pickPeople(const QString &fragment, const QString &exceptKey) const { | |
| 461 |
1/1✓ Branch 2 → 3 taken 54 times.
|
54 | ContactSyncCoordinator *sync = m_coordinator(); |
| 462 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 54 times.
|
54 | if (!sync) |
| 463 | ✗ | return {}; | |
| 464 | 54 | QVariantList found; | |
| 465 |
3/3✓ Branch 5 → 6 taken 54 times.
✓ Branch 8 → 9 taken 6 times.
✓ Branch 8 → 13 taken 48 times.
|
54 | if (!fragment.trimmed().isEmpty()) { |
| 466 |
1/1✓ Branch 9 → 10 taken 6 times.
|
6 | found = searchPeople(fragment, exceptKey); |
| 467 | } else { | ||
| 468 | 48 | const ContactQueries::View frequent{ContactQueries::ViewKind::Frequent}; | |
| 469 | // F103-19: the frequent list also holds collected addresses, which are no | ||
| 470 | // cards (personEntry is empty — they showed as "undefined"). | ||
| 471 |
6/6✓ Branch 17 → 18 taken 48 times.
✓ Branch 18 → 19 taken 48 times.
✓ Branch 23 → 24 taken 48 times.
✓ Branch 24 → 25 taken 48 times.
✓ Branch 48 → 26 taken 84 times.
✓ Branch 48 → 49 taken 48 times.
|
132 | for (const ContactQueries::Row &row : ContactQueries::page(sync->store()->database(), frequent, QString(), 16)) |
| 472 |
4/8✓ Branch 28 → 29 taken 84 times.
✗ Branch 28 → 35 not taken.
✓ Branch 31 → 32 taken 84 times.
✗ Branch 31 → 35 not taken.
✓ Branch 33 → 34 taken 84 times.
✗ Branch 33 → 35 not taken.
✓ Branch 36 → 37 taken 84 times.
✗ Branch 36 → 46 not taken.
|
84 | if (row.key != exceptKey && row.kind != QLatin1String("group") && found.size() < 8) |
| 473 |
4/4✓ Branch 37 → 38 taken 84 times.
✓ Branch 38 → 39 taken 84 times.
✓ Branch 39 → 40 taken 42 times.
✓ Branch 39 → 44 taken 42 times.
|
84 | if (const QVariantMap entry = personEntry(row.key); !entry.isEmpty()) |
| 474 |
1/1✓ Branch 41 → 42 taken 42 times.
|
132 | found.append(entry); |
| 475 | 48 | } | |
| 476 | 54 | QVariantList mine; | |
| 477 |
1/1✓ Branch 52 → 53 taken 54 times.
|
54 | const QString me = meKey(); |
| 478 |
2/2✓ Branch 54 → 55 taken 4 times.
✓ Branch 54 → 71 taken 50 times.
|
54 | if (!me.isEmpty()) { |
| 479 |
2/2✓ Branch 56 → 57 taken 3 times.
✓ Branch 56 → 153 taken 1 time.
|
4 | if (me != exceptKey) { |
| 480 |
1/1✓ Branch 57 → 58 taken 3 times.
|
3 | QVariantMap entry = personEntry(me); |
| 481 |
1/1✓ Branch 62 → 63 taken 3 times.
|
6 | entry.insert(QStringLiteral("isMe"), true); |
| 482 |
1/1✓ Branch 67 → 68 taken 3 times.
|
3 | mine.append(entry); |
| 483 | 3 | } | |
| 484 | } else { | ||
| 485 |
5/5✓ Branch 71 → 72 taken 50 times.
✓ Branch 72 → 73 taken 50 times.
✓ Branch 73 → 74 taken 50 times.
✓ Branch 150 → 75 taken 16 times.
✓ Branch 150 → 151 taken 50 times.
|
66 | for (const QVariant &value : meSuggestions()) { |
| 486 |
4/4✓ Branch 76 → 77 taken 16 times.
✓ Branch 81 → 82 taken 16 times.
✓ Branch 82 → 83 taken 16 times.
✓ Branch 83 → 84 taken 16 times.
|
32 | QVariantMap entry = personEntry(value.toMap().value(QStringLiteral("key")).toString()); |
| 487 |
11/29✓ Branch 90 → 91 taken 16 times.
✓ Branch 91 → 92 taken 16 times.
✗ Branch 91 → 100 not taken.
✓ Branch 97 → 98 taken 16 times.
✓ Branch 98 → 99 taken 16 times.
✗ Branch 99 → 100 not taken.
✓ Branch 99 → 101 taken 16 times.
✓ Branch 102 → 103 taken 16 times.
✗ Branch 102 → 104 not taken.
✓ Branch 104 → 105 taken 16 times.
✗ Branch 104 → 106 not taken.
✓ Branch 106 → 107 taken 16 times.
✗ Branch 106 → 108 not taken.
✓ Branch 108 → 109 taken 16 times.
✗ Branch 108 → 110 not taken.
✓ Branch 110 → 111 taken 16 times.
✗ Branch 110 → 112 not taken.
✗ Branch 112 → 113 not taken.
✓ Branch 112 → 114 taken 16 times.
✗ Branch 266 → 267 not taken.
✗ Branch 266 → 268 not taken.
✗ Branch 270 → 271 not taken.
✗ Branch 270 → 272 not taken.
✗ Branch 274 → 275 not taken.
✗ Branch 274 → 276 not taken.
✗ Branch 278 → 279 not taken.
✗ Branch 278 → 280 not taken.
✗ Branch 282 → 283 not taken.
✗ Branch 282 → 284 not taken.
|
32 | if (entry.isEmpty() || entry.value(QStringLiteral("key")) == exceptKey) |
| 488 | ✗ | continue; | |
| 489 |
3/3✓ Branch 114 → 115 taken 16 times.
✓ Branch 119 → 120 taken 16 times.
✓ Branch 123 → 124 taken 16 times.
|
48 | entry.insert(QStringLiteral("address"), value.toMap().value(QStringLiteral("address"))); |
| 490 |
1/1✓ Branch 135 → 136 taken 16 times.
|
32 | entry.insert(QStringLiteral("suggestMe"), true); |
| 491 |
1/1✓ Branch 140 → 141 taken 16 times.
|
16 | mine.append(entry); |
| 492 | 66 | } | |
| 493 | } | ||
| 494 | 54 | QSet<QString> first; | |
| 495 |
2/2✓ Branch 174 → 157 taken 19 times.
✓ Branch 174 → 175 taken 54 times.
|
73 | for (const QVariant &entry : std::as_const(mine)) |
| 496 |
4/4✓ Branch 158 → 159 taken 19 times.
✓ Branch 163 → 164 taken 19 times.
✓ Branch 164 → 165 taken 19 times.
✓ Branch 165 → 166 taken 19 times.
|
38 | first.insert(entry.toMap().value(QStringLiteral("key")).toString()); |
| 497 |
2/2✓ Branch 197 → 178 taken 49 times.
✓ Branch 197 → 198 taken 54 times.
|
103 | for (const QVariant &entry : std::as_const(found)) |
| 498 |
5/5✓ Branch 179 → 180 taken 49 times.
✓ Branch 184 → 185 taken 49 times.
✓ Branch 185 → 186 taken 49 times.
✓ Branch 193 → 194 taken 48 times.
✓ Branch 193 → 195 taken 1 time.
|
98 | if (!first.contains(entry.toMap().value(QStringLiteral("key")).toString())) |
| 499 |
1/1✓ Branch 194 → 195 taken 48 times.
|
48 | mine.append(entry); |
| 500 | // People only: a family is no one's relative and no member of a family. | ||
| 501 |
4/4✓ Branch 2 → 3 taken 67 times.
✓ Branch 7 → 8 taken 67 times.
✓ Branch 8 → 9 taken 67 times.
✓ Branch 198 → 199 taken 54 times.
|
188 | mine.removeIf([](const QVariant &entry) { return entry.toMap().value(QStringLiteral("family")).toBool(); }); |
| 502 |
1/1✓ Branch 199 → 200 taken 54 times.
|
54 | return mine.mid(0, 9); |
| 503 | 54 | } | |
| 504 | |||
| 505 | 2 | QVariantMap QuickContactActions::createPerson(const QString &name) { | |
| 506 |
1/1✓ Branch 2 → 3 taken 2 times.
|
2 | const QString trimmed = name.simplified(); |
| 507 |
2/2✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 1 time.
|
2 | if (trimmed.isEmpty()) |
| 508 | 1 | return {}; | |
| 509 | // "Rui Costa" → given "Rui", family "Costa"; one word is the given name. | ||
| 510 | 1 | const int split = int(trimmed.lastIndexOf(QLatin1Char(' '))); | |
| 511 | 2 | const QVariantMap fields{{QStringLiteral("formattedName"), trimmed}, | |
| 512 |
2/3✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
|
2 | {QStringLiteral("given"), split > 0 ? trimmed.left(split) : trimmed}, |
| 513 |
4/7✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 25 not taken.
✓ Branch 24 → 26 taken 1 time.
✓ Branch 29 → 30 taken 3 times.
✓ Branch 29 → 31 taken 1 time.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
|
5 | {QStringLiteral("family"), split > 0 ? trimmed.mid(split + 1) : QString()}}; |
| 514 |
2/2✓ Branch 39 → 40 taken 1 time.
✓ Branch 40 → 41 taken 1 time.
|
1 | const QVariantMap created = create(defaultBookId(), fields, true); |
| 515 |
3/4✓ Branch 45 → 46 taken 1 time.
✓ Branch 46 → 47 taken 1 time.
✗ Branch 51 → 52 not taken.
✓ Branch 51 → 53 taken 1 time.
|
2 | if (!created.value(QStringLiteral("ok")).toBool()) |
| 516 | ✗ | return {}; | |
| 517 |
2/2✓ Branch 57 → 58 taken 1 time.
✓ Branch 58 → 59 taken 1 time.
|
2 | const QString key = created.value(QStringLiteral("key")).toString(); |
| 518 |
1/1✓ Branch 68 → 69 taken 1 time.
|
1 | pushUndo(tr("Undo new contact"), {QStringLiteral("created"), {}, key, 0}); |
| 519 |
5/5✓ Branch 72 → 73 taken 1 time.
✓ Branch 76 → 77 taken 1 time.
✓ Branch 77 → 78 taken 1 time.
✓ Branch 81 → 74 taken 1 time.
✓ Branch 81 → 82 taken 1 time.
|
2 | qCInfo(lcContactRelationActions) << "Created a contact from the people picker"; |
| 520 |
1/1✓ Branch 82 → 83 taken 1 time.
|
1 | return personEntry(key); |
| 521 | 8 | } | |
| 522 | |||
| 523 | // ─── me card (S103.1.6, D-6) ─── | ||
| 524 | |||
| 525 | 2241 | QString QuickContactActions::meKey() const { | |
| 526 |
3/3✓ Branch 2 → 3 taken 2241 times.
✓ Branch 7 → 8 taken 2241 times.
✓ Branch 8 → 9 taken 2241 times.
|
4482 | const QString key = QSettings().value(QStringLiteral("contacts/meCard")).toString(); |
| 527 |
1/1✓ Branch 13 → 14 taken 2241 times.
|
2241 | ContactSyncCoordinator *sync = m_coordinator(); |
| 528 | 2241 | qint64 bookId = 0; | |
| 529 | 2241 | QString uid; | |
| 530 | // A deleted me card is no longer "me"; undoing the delete brings it back. | ||
| 531 |
12/16✓ Branch 15 → 16 taken 71 times.
✓ Branch 15 → 23 taken 2170 times.
✓ Branch 16 → 17 taken 71 times.
✗ Branch 16 → 23 not taken.
✓ Branch 17 → 18 taken 71 times.
✓ Branch 18 → 19 taken 71 times.
✗ Branch 18 → 23 not taken.
✓ Branch 20 → 21 taken 71 times.
✓ Branch 22 → 23 taken 1 time.
✓ Branch 22 → 24 taken 70 times.
✓ Branch 25 → 26 taken 71 times.
✓ Branch 25 → 27 taken 2170 times.
✓ Branch 27 → 28 taken 2171 times.
✓ Branch 27 → 29 taken 70 times.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 49 not taken.
|
2241 | if (key.isEmpty() || !sync || !ContactQueries::splitKey(key, &bookId, &uid) || !sync->store()->card(bookId, uid)) |
| 532 | 2171 | return {}; | |
| 533 | 70 | return key; | |
| 534 | 2241 | } | |
| 535 | |||
| 536 | 6 | bool QuickContactActions::setMe(const QString &key) { | |
| 537 |
4/4✓ Branch 2 → 3 taken 6 times.
✓ Branch 3 → 4 taken 6 times.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 5 times.
|
6 | if (personEntry(key).isEmpty()) |
| 538 | 1 | return false; | |
| 539 |
2/2✓ Branch 7 → 8 taken 5 times.
✓ Branch 13 → 14 taken 5 times.
|
10 | QSettings().setValue(QStringLiteral("contacts/meCard"), key); |
| 540 |
5/5✓ Branch 18 → 19 taken 5 times.
✓ Branch 22 → 23 taken 5 times.
✓ Branch 23 → 24 taken 5 times.
✓ Branch 27 → 20 taken 5 times.
✓ Branch 27 → 28 taken 5 times.
|
10 | qCInfo(lcContactRelationActions) << "Me card set"; |
| 541 | 5 | emit meChanged(); | |
| 542 |
2/2✓ Branch 29 → 30 taken 5 times.
✓ Branch 30 → 31 taken 5 times.
|
5 | report(tr("Marked as you"), false); |
| 543 | 5 | return true; | |
| 544 | } | ||
| 545 | |||
| 546 | 4 | void QuickContactActions::clearMe() { | |
| 547 |
2/2✓ Branch 2 → 3 taken 4 times.
✓ Branch 7 → 8 taken 4 times.
|
8 | QSettings().remove(QStringLiteral("contacts/meCard")); |
| 548 |
5/5✓ Branch 11 → 12 taken 4 times.
✓ Branch 15 → 16 taken 4 times.
✓ Branch 16 → 17 taken 4 times.
✓ Branch 20 → 13 taken 4 times.
✓ Branch 20 → 21 taken 4 times.
|
8 | qCInfo(lcContactRelationActions) << "Me card cleared"; |
| 549 | 4 | emit meChanged(); | |
| 550 | 4 | } | |
| 551 | |||
| 552 | 109 | QVariantList QuickContactActions::meSuggestions() const { | |
| 553 |
1/1✓ Branch 2 → 3 taken 109 times.
|
109 | ContactSyncCoordinator *sync = m_coordinator(); |
| 554 |
5/6✓ Branch 3 → 4 taken 109 times.
✗ Branch 3 → 6 not taken.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 108 times.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 108 times.
|
109 | if (!sync || !m_ownAddresses) |
| 555 | 1 | return {}; | |
| 556 | 108 | QVariantList out; | |
| 557 | 108 | QStringList seen; | |
| 558 |
5/5✓ Branch 10 → 11 taken 108 times.
✓ Branch 11 → 12 taken 108 times.
✓ Branch 12 → 13 taken 108 times.
✓ Branch 61 → 14 taken 108 times.
✓ Branch 61 → 62 taken 108 times.
|
216 | for (const QString &address : m_ownAddresses()) { |
| 559 |
2/2✓ Branch 16 → 17 taken 108 times.
✓ Branch 17 → 18 taken 108 times.
|
108 | const ContactQueries::Lookup found = ContactQueries::lookup(sync->store()->database(), address); |
| 560 |
5/6✓ Branch 19 → 20 taken 37 times.
✓ Branch 19 → 22 taken 71 times.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 37 times.
✓ Branch 24 → 25 taken 71 times.
✓ Branch 24 → 26 taken 37 times.
|
108 | if (!found.known || seen.contains(found.key)) |
| 561 | 71 | continue; | |
| 562 |
1/1✓ Branch 26 → 27 taken 37 times.
|
37 | seen.append(found.key); |
| 563 |
1/1✓ Branch 41 → 42 taken 37 times.
|
111 | out.append(QVariantMap{{QStringLiteral("key"), found.key}, |
| 564 | 74 | {QStringLiteral("name"), found.displayName}, | |
| 565 |
2/4✓ Branch 45 → 46 taken 111 times.
✓ Branch 45 → 47 taken 37 times.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
|
185 | {QStringLiteral("address"), address}}); |
| 566 | 216 | } | |
| 567 | 108 | return out; | |
| 568 | 256 | } | |
| 569 |