data/VCardPatch.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // Write side of VCardCodec (S97.1.1): patch() and create(). | ||
| 2 | #include "VCardCodec.h" | ||
| 3 | #include "VCardWriter.h" | ||
| 4 | |||
| 5 | #include <QLoggingCategory> | ||
| 6 | #include <QSet> | ||
| 7 | #include <QTimeZone> | ||
| 8 | |||
| 9 | Q_DECLARE_LOGGING_CATEGORY(lcVCard) | ||
| 10 | |||
| 11 | namespace VCardCodec { | ||
| 12 | |||
| 13 | namespace detail { | ||
| 14 | |||
| 15 | const QSet<QString> kStructuredNames{QStringLiteral("N"), QStringLiteral("ADR"), QStringLiteral("ORG")}; | ||
| 16 | |||
| 17 | 28781 | QString escapeComponents(const QStringList &parts) { | |
| 18 | 28781 | QStringList escaped; | |
| 19 |
2/2✓ Branch 10 → 4 taken 146156 times.
✓ Branch 10 → 11 taken 28781 times.
|
174937 | for (const QString &part : parts) |
| 20 |
2/2✓ Branch 5 → 6 taken 146156 times.
✓ Branch 6 → 7 taken 146156 times.
|
146156 | escaped.append(ICal::escapeText(part)); |
| 21 |
1/1✓ Branch 13 → 14 taken 28781 times.
|
57562 | return escaped.join(QLatin1Char(';')); |
| 22 | 28781 | } | |
| 23 | |||
| 24 | // ─── vCard 2.1 → 3.0 (first write of an old card) ─── | ||
| 25 | |||
| 26 | // vCard 2.1 values are not TEXT-escaped, but writers escape the separator | ||
| 27 | // (\;) and, in practice, \, and \\ as well. S106-151: the escapes are | ||
| 28 | // read in order — "\\;" is a backslash and then a separator — and undone | ||
| 29 | // before the value is escaped for 3.0 (a stray backslash used to remain). | ||
| 30 | 180 | QStringList splitRaw21(const QString &value, bool structured) { | |
| 31 | 180 | QStringList parts; | |
| 32 | 180 | QString current; | |
| 33 |
2/2✓ Branch 42 → 3 taken 3600 times.
✓ Branch 42 → 43 taken 180 times.
|
3780 | for (qsizetype i = 0; i < value.size(); ++i) { |
| 34 | 3600 | const QChar c = value.at(i); | |
| 35 |
2/2✓ Branch 5 → 6 taken 3423 times.
✓ Branch 5 → 7 taken 177 times.
|
3600 | const QChar next = i + 1 < value.size() ? value.at(i + 1) : QChar(); |
| 36 |
4/4✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 25 taken 3597 times.
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 24 taken 1 time.
|
3605 | if (c == QLatin1Char('\\') && |
| 37 |
5/6✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 24 taken 1 time.
✓ Branch 23 → 24 taken 1 time.
✗ Branch 23 → 25 not taken.
✓ Branch 26 → 27 taken 3 times.
✓ Branch 26 → 29 taken 3597 times.
|
3605 | (next == QLatin1Char('\\') || next == QLatin1Char(';') || next == QLatin1Char(','))) { |
| 38 |
1/1✓ Branch 27 → 28 taken 3 times.
|
3 | current += next; |
| 39 | 3 | ++i; | |
| 40 |
6/6✓ Branch 29 → 30 taken 997 times.
✓ Branch 29 → 35 taken 2600 times.
✓ Branch 33 → 34 taken 94 times.
✓ Branch 33 → 35 taken 903 times.
✓ Branch 36 → 37 taken 94 times.
✓ Branch 36 → 39 taken 3503 times.
|
3597 | } else if (structured && c == QLatin1Char(';')) { |
| 41 |
1/1✓ Branch 37 → 38 taken 94 times.
|
94 | parts.append(current); |
| 42 | 94 | current.clear(); | |
| 43 | } else { | ||
| 44 |
1/1✓ Branch 39 → 40 taken 3503 times.
|
3503 | current += c; |
| 45 | } | ||
| 46 | } | ||
| 47 |
1/1✓ Branch 43 → 44 taken 180 times.
|
180 | parts.append(current); |
| 48 | 180 | return parts; | |
| 49 | 180 | } | |
| 50 | |||
| 51 | 180 | void upgradeProperty(ICal::Property *property) { | |
| 52 |
1/1✓ Branch 2 → 3 taken 180 times.
|
180 | const QString name = baseName(*property); |
| 53 |
2/2✓ Branch 6 → 7 taken 180 times.
✓ Branch 7 → 8 taken 180 times.
|
360 | const QString encoding = property->parameter(QStringLiteral("ENCODING")).toUpper(); |
| 54 |
8/13✓ Branch 13 → 14 taken 146 times.
✓ Branch 13 → 19 taken 34 times.
✓ Branch 17 → 18 taken 146 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 146 times.
✓ Branch 21 → 22 taken 146 times.
✓ Branch 21 → 23 taken 34 times.
✓ Branch 23 → 24 taken 146 times.
✓ Branch 23 → 25 taken 34 times.
✗ Branch 135 → 136 not taken.
✗ Branch 135 → 137 not taken.
✗ Branch 139 → 140 not taken.
✗ Branch 139 → 141 not taken.
|
326 | const bool qp = encoding == QLatin1String("QUOTED-PRINTABLE") || property->hasParameter(QStringLiteral("QUOTED-PRINTABLE")); |
| 55 |
5/13✓ Branch 27 → 28 taken 180 times.
✗ Branch 27 → 33 not taken.
✓ Branch 31 → 32 taken 180 times.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 180 times.
✓ Branch 35 → 36 taken 180 times.
✗ Branch 35 → 37 not taken.
✓ Branch 37 → 38 taken 180 times.
✗ Branch 37 → 39 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
|
360 | const bool base64 = encoding == QLatin1String("BASE64") || property->hasParameter(QStringLiteral("BASE64")); |
| 56 | // 2.1 values are not TEXT-escaped; decode quoted-printable first. | ||
| 57 |
3/3✓ Branch 39 → 40 taken 34 times.
✓ Branch 39 → 41 taken 146 times.
✓ Branch 40 → 42 taken 34 times.
|
180 | const QString text = qp ? decodedValue(*property) : property->value; |
| 58 | 180 | QList<ICal::Parameter> parameters; | |
| 59 | 180 | QStringList types; | |
| 60 |
4/4✓ Branch 42 → 43 taken 180 times.
✓ Branch 43 → 44 taken 180 times.
✓ Branch 72 → 45 taken 196 times.
✓ Branch 72 → 73 taken 180 times.
|
376 | for (const ICal::Parameter ¶meter : property->parameters) { |
| 61 |
3/4✓ Branch 51 → 52 taken 121 times.
✓ Branch 51 → 58 taken 35 times.
✓ Branch 54 → 55 taken 121 times.
✗ Branch 54 → 58 not taken.
|
473 | if (parameter.name == QLatin1String("ENCODING") || parameter.name == QLatin1String("CHARSET") || |
| 62 |
5/6✓ Branch 48 → 49 taken 156 times.
✓ Branch 48 → 58 taken 40 times.
✗ Branch 57 → 58 not taken.
✓ Branch 57 → 59 taken 121 times.
✓ Branch 60 → 61 taken 75 times.
✓ Branch 60 → 62 taken 121 times.
|
473 | parameter.name == QLatin1String("QUOTED-PRINTABLE") || parameter.name == QLatin1String("8BIT")) |
| 63 | 75 | continue; | |
| 64 |
1/2✗ Branch 64 → 65 not taken.
✓ Branch 64 → 66 taken 121 times.
|
121 | if (parameter.name == QLatin1String("BASE64")) |
| 65 | ✗ | continue; | |
| 66 |
2/2✓ Branch 67 → 68 taken 113 times.
✓ Branch 67 → 69 taken 8 times.
|
121 | if (parameter.value.isNull()) |
| 67 |
1/1✓ Branch 68 → 70 taken 113 times.
|
113 | types.append(parameter.name); |
| 68 | else | ||
| 69 |
1/1✓ Branch 69 → 70 taken 8 times.
|
8 | parameters.append(parameter); |
| 70 | } | ||
| 71 |
1/2✗ Branch 73 → 74 not taken.
✓ Branch 73 → 85 taken 180 times.
|
180 | if (base64) |
| 72 | ✗ | parameters.prepend({QStringLiteral("ENCODING"), QStringLiteral("b")}); | |
| 73 |
4/4✓ Branch 85 → 86 taken 180 times.
✓ Branch 86 → 87 taken 180 times.
✓ Branch 98 → 88 taken 113 times.
✓ Branch 98 → 99 taken 180 times.
|
293 | for (const QString &type : types) |
| 74 | 113 | parameters.append({QStringLiteral("TYPE"), type}); | |
| 75 | 180 | property->parameters = parameters; | |
| 76 |
1/2✓ Branch 100 → 101 taken 180 times.
✗ Branch 100 → 119 not taken.
|
180 | if (!base64) { |
| 77 |
2/2✓ Branch 102 → 103 taken 56 times.
✓ Branch 102 → 109 taken 124 times.
|
180 | if (kStructuredNames.contains(name)) |
| 78 |
2/2✓ Branch 103 → 104 taken 56 times.
✓ Branch 104 → 105 taken 56 times.
|
56 | property->value = escapeComponents(splitRaw21(text, true)); |
| 79 |
1/2✓ Branch 111 → 112 taken 124 times.
✗ Branch 111 → 119 not taken.
|
124 | else if (name != QLatin1String("VERSION")) |
| 80 |
3/3✓ Branch 112 → 113 taken 124 times.
✓ Branch 113 → 114 taken 124 times.
✓ Branch 114 → 115 taken 124 times.
|
124 | property->value = ICal::escapeText(splitRaw21(text, false).first()); |
| 81 | } | ||
| 82 | 180 | property->originalLine.clear(); | |
| 83 | 293 | } | |
| 84 | |||
| 85 | // `origin` (the patch writer's line mapping) gains -1 for a line added | ||
| 86 | // here, so its indices keep matching the properties. | ||
| 87 | 38 | void upgradeTo30(ICal::Component *card, QList<int> *origin) { | |
| 88 |
4/4✓ Branch 2 → 3 taken 38 times.
✓ Branch 3 → 4 taken 38 times.
✓ Branch 21 → 5 taken 218 times.
✓ Branch 21 → 22 taken 38 times.
|
256 | for (ICal::Property &property : card->properties) { |
| 89 |
3/3✓ Branch 7 → 8 taken 218 times.
✓ Branch 10 → 11 taken 38 times.
✓ Branch 10 → 18 taken 180 times.
|
218 | if (baseName(property) == QLatin1String("VERSION")) |
| 90 |
1/1✓ Branch 14 → 15 taken 38 times.
|
38 | property.setValue(QStringLiteral("3.0")); |
| 91 | else | ||
| 92 |
1/1✓ Branch 18 → 19 taken 180 times.
|
180 | upgradeProperty(&property); |
| 93 | } | ||
| 94 | // A 2.1 AGENT holds a nested card; 3.0 has no nested components but | ||
| 95 | // carries the agent's card as the escaped text value of AGENT (RFC 2426 | ||
| 96 | // §3.5.4). S106-151: the nested card used to be dropped. | ||
| 97 | 38 | int agent = 0; | |
| 98 |
4/4✓ Branch 22 → 23 taken 38 times.
✓ Branch 23 → 24 taken 38 times.
✓ Branch 82 → 25 taken 4 times.
✓ Branch 82 → 83 taken 38 times.
|
42 | for (ICal::Component nested : card->components) { |
| 99 |
1/2✗ Branch 29 → 30 not taken.
✓ Branch 29 → 31 taken 4 times.
|
4 | if (nested.name != QLatin1String("VCARD")) |
| 100 | ✗ | continue; | |
| 101 |
1/1✓ Branch 31 → 32 taken 4 times.
|
4 | upgradeTo30(&nested, nullptr); |
| 102 |
2/2✓ Branch 32 → 33 taken 4 times.
✓ Branch 33 → 34 taken 4 times.
|
4 | const QString value = ICal::escapeText(ICal::serialize(nested)); |
| 103 |
2/2✓ Branch 38 → 39 taken 16 times.
✓ Branch 38 → 49 taken 1 time.
|
33 | while (agent < card->properties.size() && |
| 104 |
5/7✓ Branch 41 → 42 taken 16 times.
✓ Branch 43 → 44 taken 3 times.
✓ Branch 43 → 48 taken 13 times.
✓ Branch 54 → 36 taken 13 times.
✓ Branch 54 → 55 taken 4 times.
✗ Branch 101 → 102 not taken.
✗ Branch 101 → 103 not taken.
|
33 | !(baseName(card->properties.at(agent)) == QLatin1String("AGENT") && |
| 105 |
6/9✓ Branch 45 → 46 taken 3 times.
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 49 taken 3 times.
✓ Branch 50 → 51 taken 3 times.
✓ Branch 50 → 52 taken 14 times.
✓ Branch 52 → 53 taken 16 times.
✓ Branch 52 → 54 taken 1 time.
✗ Branch 97 → 98 not taken.
✗ Branch 97 → 99 not taken.
|
20 | card->properties.at(agent).value.trimmed().isEmpty())) |
| 106 | 13 | ++agent; | |
| 107 |
2/2✓ Branch 56 → 57 taken 3 times.
✓ Branch 56 → 60 taken 1 time.
|
4 | if (agent < card->properties.size()) { |
| 108 |
2/2✓ Branch 57 → 58 taken 3 times.
✓ Branch 58 → 59 taken 3 times.
|
3 | card->properties[agent].setValue(value); |
| 109 | 3 | ++agent; | |
| 110 | } else { | ||
| 111 | 1 | ICal::Property property; | |
| 112 | 1 | property.name = QStringLiteral("AGENT"); | |
| 113 | 1 | property.value = value; | |
| 114 |
1/1✓ Branch 67 → 68 taken 1 time.
|
1 | card->appendProperty(property); |
| 115 |
1/2✓ Branch 68 → 69 taken 1 time.
✗ Branch 68 → 70 not taken.
|
1 | if (origin) |
| 116 |
1/1✓ Branch 69 → 70 taken 1 time.
|
1 | origin->append(-1); |
| 117 | 1 | agent = int(card->properties.size()); | |
| 118 | 1 | } | |
| 119 | 4 | } | |
| 120 | 38 | card->components.clear(); | |
| 121 | 38 | } | |
| 122 | |||
| 123 | // ─── single-valued properties ─── | ||
| 124 | |||
| 125 | 136607 | int indexOfName(const ICal::Component &card, const QString &name) { | |
| 126 |
2/2✓ Branch 11 → 3 taken 840736 times.
✓ Branch 11 → 12 taken 104231 times.
|
944967 | for (int i = 0; i < card.properties.size(); ++i) |
| 127 |
3/3✓ Branch 4 → 5 taken 840736 times.
✓ Branch 7 → 8 taken 32376 times.
✓ Branch 7 → 9 taken 808360 times.
|
840736 | if (baseName(card.properties.at(i)) == name) |
| 128 | 32376 | return i; | |
| 129 | 104231 | return -1; | |
| 130 | } | ||
| 131 | |||
| 132 | // Sets (or removes, for an empty value) the first property `name`, keeping | ||
| 133 | // its position, group and other parameters. | ||
| 134 | 77547 | void setSingle(Writer *w, const QString &name, const QString &wireValue) { | |
| 135 |
1/1✓ Branch 2 → 3 taken 77547 times.
|
77547 | const int index = indexOfName(w->card, name); |
| 136 |
2/2✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 8 taken 77545 times.
|
77547 | if (wireValue.isEmpty()) { |
| 137 |
1/2✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 7 not taken.
|
2 | if (index >= 0) |
| 138 |
1/1✓ Branch 6 → 7 taken 2 times.
|
2 | w->removeAt(index); |
| 139 | 971 | return; | |
| 140 | } | ||
| 141 |
2/2✓ Branch 8 → 9 taken 969 times.
✓ Branch 8 → 16 taken 76576 times.
|
77545 | if (index >= 0) { |
| 142 |
2/2✓ Branch 11 → 12 taken 859 times.
✓ Branch 11 → 15 taken 110 times.
|
969 | if (w->card.properties.at(index).value != wireValue) { |
| 143 |
2/2✓ Branch 12 → 13 taken 859 times.
✓ Branch 13 → 14 taken 859 times.
|
859 | w->card.properties[index].setValue(wireValue); |
| 144 | 859 | w->changed = true; | |
| 145 | } | ||
| 146 | 969 | return; | |
| 147 | } | ||
| 148 | 76576 | ICal::Property created; | |
| 149 | 76576 | created.name = name; | |
| 150 | 76576 | created.value = wireValue; | |
| 151 |
1/1✓ Branch 18 → 19 taken 76576 times.
|
76576 | w->append(created); |
| 152 | 76576 | } | |
| 153 | |||
| 154 | 488 | QString dateWire(const PartialDate &date, bool v4) { | |
| 155 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 488 times.
|
488 | if (!date.isValid()) |
| 156 | ✗ | return {}; | |
| 157 |
2/2✓ Branch 10 → 11 taken 488 times.
✓ Branch 13 → 14 taken 488 times.
|
488 | const QString monthDay = QStringLiteral("%1%2").arg(date.month, 2, 10, QLatin1Char('0')).arg(date.day, 2, 10, QLatin1Char('0')); |
| 158 |
2/2✓ Branch 17 → 18 taken 119 times.
✓ Branch 17 → 43 taken 369 times.
|
488 | if (v4) |
| 159 |
5/11✓ Branch 25 → 26 taken 71 times.
✓ Branch 38 → 39 taken 71 times.
✓ Branch 38 → 40 taken 48 times.
✓ Branch 40 → 41 taken 71 times.
✓ Branch 40 → 42 taken 48 times.
✗ Branch 86 → 87 not taken.
✗ Branch 86 → 88 not taken.
✗ Branch 92 → 93 not taken.
✗ Branch 92 → 94 not taken.
✗ Branch 96 → 97 not taken.
✗ Branch 96 → 98 not taken.
|
309 | return date.hasYear() ? QStringLiteral("%1").arg(date.year, 4, 10, QLatin1Char('0')) + monthDay |
| 160 |
10/14✓ Branch 19 → 20 taken 71 times.
✓ Branch 19 → 27 taken 48 times.
✓ Branch 26 → 31 taken 71 times.
✓ Branch 30 → 31 taken 48 times.
✓ Branch 32 → 33 taken 48 times.
✓ Branch 32 → 34 taken 71 times.
✓ Branch 34 → 35 taken 48 times.
✓ Branch 34 → 36 taken 71 times.
✓ Branch 36 → 37 taken 71 times.
✓ Branch 36 → 38 taken 48 times.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 80 not taken.
✗ Branch 82 → 83 not taken.
✗ Branch 82 → 84 not taken.
|
357 | : QStringLiteral("--") + monthDay; |
| 161 |
14/22✓ Branch 44 → 45 taken 307 times.
✓ Branch 44 → 46 taken 62 times.
✓ Branch 45 → 52 taken 307 times.
✓ Branch 46 → 47 taken 62 times.
✓ Branch 47 → 48 taken 62 times.
✓ Branch 51 → 52 taken 62 times.
✓ Branch 53 → 54 taken 62 times.
✓ Branch 53 → 55 taken 307 times.
✓ Branch 55 → 56 taken 62 times.
✓ Branch 55 → 57 taken 307 times.
✓ Branch 57 → 58 taken 62 times.
✓ Branch 57 → 59 taken 307 times.
✓ Branch 59 → 60 taken 62 times.
✓ Branch 59 → 61 taken 307 times.
✗ 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.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 114 not taken.
|
431 | return date.hasYear() ? date.toIso() : QStringLiteral("1604-") + date.toIso().mid(2); |
| 162 | 488 | } | |
| 163 | |||
| 164 | 352 | void setDate(Writer *w, const QString &name, const PartialDate &date) { | |
| 165 |
1/1✓ Branch 2 → 3 taken 352 times.
|
352 | const int index = indexOfName(w->card, name); |
| 166 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 351 times.
|
352 | if (index >= 0) |
| 167 |
1/1✓ Branch 4 → 5 taken 1 time.
|
1 | w->removeAt(index); |
| 168 |
1/2✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 352 times.
|
352 | if (!date.isValid()) |
| 169 | ✗ | return; | |
| 170 | 352 | ICal::Property created; | |
| 171 | 352 | created.name = name; | |
| 172 |
1/1✓ Branch 9 → 10 taken 352 times.
|
352 | created.value = dateWire(date, w->v4); |
| 173 | // Apple's marker for a date without a year; vCard 4 writes "--MMDD". | ||
| 174 |
6/6✓ Branch 12 → 13 taken 261 times.
✓ Branch 12 → 16 taken 91 times.
✓ Branch 14 → 15 taken 51 times.
✓ Branch 14 → 16 taken 210 times.
✓ Branch 17 → 18 taken 51 times.
✓ Branch 17 → 29 taken 301 times.
|
352 | if (!w->v4 && !date.hasYear()) |
| 175 | 51 | created.parameters.append({QStringLiteral("X-APPLE-OMIT-YEAR"), QStringLiteral("1604")}); | |
| 176 |
3/3✓ Branch 29 → 30 taken 351 times.
✓ Branch 29 → 32 taken 1 time.
✓ Branch 33 → 34 taken 352 times.
|
352 | w->insert(index < 0 ? int(w->card.properties.size()) : index, created); |
| 177 | 454 | } | |
| 178 | |||
| 179 | // ─── multi-valued properties ─── | ||
| 180 | |||
| 181 | 738 | QString freeGroup(const ICal::Component &card) { | |
| 182 | 738 | int highest = 0; | |
| 183 |
2/2✓ Branch 19 → 4 taken 12634 times.
✓ Branch 19 → 20 taken 738 times.
|
13372 | for (const ICal::Property &property : card.properties) { |
| 184 |
2/2✓ Branch 5 → 6 taken 12634 times.
✓ Branch 6 → 7 taken 12634 times.
|
12634 | const QString group = groupOf(property).toUpper(); |
| 185 |
3/3✓ Branch 9 → 10 taken 12634 times.
✓ Branch 10 → 11 taken 2391 times.
✓ Branch 10 → 16 taken 10243 times.
|
12634 | if (group.startsWith(QLatin1String("ITEM"))) |
| 186 |
2/2✓ Branch 11 → 12 taken 2391 times.
✓ Branch 12 → 13 taken 2391 times.
|
2391 | highest = qMax(highest, group.mid(4).toInt()); |
| 187 | 12634 | } | |
| 188 |
1/1✓ Branch 24 → 25 taken 738 times.
|
1476 | return QStringLiteral("item%1").arg(highest + 1); |
| 189 | } | ||
| 190 | |||
| 191 | 27698 | int labelIndex(const ICal::Component &card, const QString &group) { | |
| 192 |
2/2✓ Branch 3 → 4 taken 27691 times.
✓ Branch 3 → 5 taken 7 times.
|
27698 | if (group.isEmpty()) |
| 193 | 27691 | return -1; | |
| 194 |
1/2✓ Branch 25 → 6 taken 74 times.
✗ Branch 25 → 26 not taken.
|
74 | for (int i = 0; i < card.properties.size(); ++i) |
| 195 |
11/16✓ Branch 7 → 8 taken 74 times.
✓ Branch 9 → 10 taken 14 times.
✓ Branch 9 → 16 taken 60 times.
✓ Branch 12 → 13 taken 14 times.
✓ Branch 14 → 15 taken 7 times.
✓ Branch 14 → 16 taken 7 times.
✓ Branch 17 → 18 taken 14 times.
✓ Branch 17 → 19 taken 60 times.
✓ Branch 19 → 20 taken 74 times.
✗ Branch 19 → 21 not taken.
✓ Branch 21 → 22 taken 7 times.
✓ Branch 21 → 23 taken 67 times.
✗ Branch 28 → 29 not taken.
✗ Branch 28 → 30 not taken.
✗ Branch 33 → 34 not taken.
✗ Branch 33 → 35 not taken.
|
74 | if (groupOf(card.properties.at(i)) == group && baseName(card.properties.at(i)) == QLatin1String("X-ABLABEL")) |
| 196 | 7 | return i; | |
| 197 | ✗ | return -1; | |
| 198 | } | ||
| 199 | |||
| 200 | ✗ | QString labelText(const ICal::Component &card, int index) { | |
| 201 | ✗ | const int at = labelIndex(card, groupOf(card.properties.at(index))); | |
| 202 | ✗ | if (at < 0) | |
| 203 | ✗ | return {}; | |
| 204 | ✗ | QString label = ICal::unescapeText(card.properties.at(at).value); | |
| 205 | ✗ | if (label.startsWith(QLatin1String("_$!<")) && label.endsWith(QLatin1String(">!$_"))) | |
| 206 | ✗ | label = label.mid(4, label.size() - 8); | |
| 207 | ✗ | return label; | |
| 208 | ✗ | } | |
| 209 | |||
| 210 | // Gives the property at `index` the label; a new label line goes directly | ||
| 211 | // behind the property (Apple's layout), a cleared label removes its line. | ||
| 212 | 27692 | void setLabel(Writer *w, int index, const QString &label) { | |
| 213 |
1/1✓ Branch 3 → 4 taken 27692 times.
|
27692 | QString group = groupOf(w->card.properties.at(index)); |
| 214 |
1/1✓ Branch 4 → 5 taken 27692 times.
|
27692 | const int existing = labelIndex(w->card, group); |
| 215 |
2/2✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 20 taken 27691 times.
|
27692 | if (existing >= 0) { |
| 216 |
1/2✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 1 time.
|
1 | if (label.isEmpty()) |
| 217 | ✗ | w->removeAt(existing); | |
| 218 |
2/3✓ Branch 10 → 11 taken 1 time.
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 19 not taken.
|
1 | else if (ICal::unescapeText(w->card.properties.at(existing).value) != label) { |
| 219 |
3/3✓ Branch 14 → 15 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
|
1 | w->card.properties[existing].setValue(ICal::escapeText(label)); |
| 220 | 1 | w->changed = true; | |
| 221 | } | ||
| 222 | 1 | return; | |
| 223 | } | ||
| 224 |
2/2✓ Branch 21 → 22 taken 27690 times.
✓ Branch 21 → 23 taken 1 time.
|
27691 | if (label.isEmpty()) |
| 225 | 27690 | return; | |
| 226 |
1/2✓ Branch 24 → 25 taken 1 time.
✗ Branch 24 → 39 not taken.
|
1 | if (group.isEmpty()) { |
| 227 |
1/1✓ Branch 25 → 26 taken 1 time.
|
1 | group = freeGroup(w->card); |
| 228 |
1/1✓ Branch 28 → 29 taken 1 time.
|
1 | ICal::Property &property = w->card.properties[index]; |
| 229 |
3/3✓ Branch 29 → 30 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 33 → 34 taken 1 time.
|
1 | property.name = group + QLatin1Char('.') + baseName(property); |
| 230 | 1 | property.originalLine.clear(); | |
| 231 | } | ||
| 232 | 1 | ICal::Property created; | |
| 233 |
1/1✓ Branch 42 → 43 taken 1 time.
|
1 | created.name = group + QStringLiteral(".X-ABLabel"); |
| 234 |
1/1✓ Branch 47 → 48 taken 1 time.
|
1 | created.value = ICal::escapeText(label); |
| 235 |
1/1✓ Branch 50 → 51 taken 1 time.
|
1 | w->insert(index + 1, created); |
| 236 | 27692 | } | |
| 237 | |||
| 238 | 27694 | void setTypes(ICal::Property *property, const QStringList &types, bool preferred, bool v4) { | |
| 239 | 27694 | property->parameters.removeIf([](const ICal::Parameter ¶meter) { | |
| 240 |
3/6✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 13 taken 2 times.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 13 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 14 not taken.
|
3 | return parameter.name == QLatin1String("TYPE") || parameter.name == QLatin1String("PREF") || |
| 241 |
0/2✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
|
3 | (parameter.value.isNull() && parameter.name != QLatin1String("ENCODING")); |
| 242 | }); | ||
| 243 |
2/2✓ Branch 17 → 5 taken 4497 times.
✓ Branch 17 → 18 taken 27694 times.
|
32191 | for (const QString &type : types) |
| 244 | 8994 | property->parameters.append({QStringLiteral("TYPE"), v4 ? type.toLower() : type.toUpper()}); | |
| 245 |
2/2✓ Branch 18 → 19 taken 4 times.
✓ Branch 18 → 42 taken 27690 times.
|
27694 | if (preferred) { |
| 246 |
2/2✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 31 taken 3 times.
|
4 | if (v4) |
| 247 | 2 | property->parameters.append({QStringLiteral("PREF"), QStringLiteral("1")}); | |
| 248 | else | ||
| 249 | 6 | property->parameters.append({QStringLiteral("TYPE"), QStringLiteral("pref")}); | |
| 250 | } | ||
| 251 | 27694 | property->originalLine.clear(); | |
| 252 | 32199 | } | |
| 253 | |||
| 254 | // One edited value in wire form, with what parse() saw for its base line. | ||
| 255 | struct Entry { | ||
| 256 | QString wire; | ||
| 257 | QStringList types; | ||
| 258 | bool preferred = false; | ||
| 259 | QString label; | ||
| 260 | int sourceIndex = -1; | ||
| 261 | }; | ||
| 262 | |||
| 263 | 69 | QString currentWire(const ICal::Property &property, const QString &name) { | |
| 264 |
7/7✓ Branch 4 → 5 taken 4 times.
✓ Branch 4 → 9 taken 65 times.
✓ Branch 6 → 7 taken 4 times.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 3 times.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 68 times.
|
69 | if (name == QLatin1String("TEL") && property.value.startsWith(QLatin1String("tel:"), Qt::CaseInsensitive)) |
| 265 | 1 | return property.value.mid(4); | |
| 266 | 68 | return property.value; | |
| 267 | } | ||
| 268 | |||
| 269 | 69 | void updateKept(Writer *w, const QString &name, const Entry &entry, const Entry &old) { | |
| 270 | 69 | const int index = w->currentIndex(entry.sourceIndex); | |
| 271 | 69 | ICal::Property &property = w->card.properties[index]; | |
| 272 |
3/3✓ Branch 4 → 5 taken 69 times.
✓ Branch 7 → 8 taken 45 times.
✓ Branch 7 → 42 taken 24 times.
|
69 | if (currentWire(property, name) != entry.wire) { |
| 273 |
4/4✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 22 taken 43 times.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 21 taken 1 time.
|
48 | const bool uri = name == QLatin1String("TEL") && |
| 274 |
5/11✓ Branch 14 → 15 taken 2 times.
✓ Branch 25 → 26 taken 2 times.
✓ Branch 25 → 27 taken 43 times.
✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 29 taken 43 times.
✗ Branch 57 → 58 not taken.
✗ Branch 57 → 59 not taken.
✗ Branch 61 → 62 not taken.
✗ Branch 61 → 63 not taken.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
|
47 | (property.parameter(QStringLiteral("VALUE")).compare(QLatin1String("uri"), Qt::CaseInsensitive) == 0 || |
| 275 |
4/5✓ Branch 19 → 20 taken 1 time.
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 1 time.
✓ Branch 23 → 24 taken 2 times.
✓ Branch 23 → 25 taken 43 times.
|
46 | property.value.startsWith(QLatin1String("tel:"), Qt::CaseInsensitive)); |
| 276 |
8/12✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 34 taken 44 times.
✓ Branch 33 → 35 taken 1 time.
✓ Branch 35 → 36 taken 45 times.
✓ Branch 37 → 38 taken 1 time.
✓ Branch 37 → 39 taken 44 times.
✓ Branch 39 → 40 taken 1 time.
✓ Branch 39 → 41 taken 44 times.
✗ Branch 72 → 73 not taken.
✗ Branch 72 → 74 not taken.
✗ Branch 76 → 77 not taken.
✗ Branch 76 → 78 not taken.
|
46 | property.setValue(uri ? QStringLiteral("tel:") + entry.wire : entry.wire); |
| 277 | 45 | w->changed = true; | |
| 278 | } | ||
| 279 |
5/6✓ Branch 43 → 44 taken 69 times.
✗ Branch 43 → 45 not taken.
✓ Branch 44 → 45 taken 3 times.
✓ Branch 44 → 46 taken 66 times.
✓ Branch 47 → 48 taken 3 times.
✓ Branch 47 → 50 taken 66 times.
|
69 | if (entry.types != old.types || entry.preferred != old.preferred) { |
| 280 | 3 | setTypes(&property, entry.types, entry.preferred, w->v4); | |
| 281 | 3 | w->changed = true; | |
| 282 | } | ||
| 283 |
2/2✓ Branch 51 → 52 taken 1 time.
✓ Branch 51 → 53 taken 68 times.
|
69 | if (entry.label != old.label) |
| 284 | 1 | setLabel(w, index, entry.label); | |
| 285 | 69 | } | |
| 286 | |||
| 287 | 32 | void removeWithGroup(Writer *w, int index) { | |
| 288 |
1/1✓ Branch 3 → 4 taken 32 times.
|
32 | const QString group = groupOf(w->card.properties.at(index)); |
| 289 |
1/1✓ Branch 4 → 5 taken 32 times.
|
32 | w->removeAt(index); |
| 290 |
2/2✓ Branch 6 → 7 taken 20 times.
✓ Branch 6 → 8 taken 12 times.
|
32 | if (group.isEmpty()) |
| 291 | 20 | return; | |
| 292 |
4/4✓ Branch 8 → 9 taken 12 times.
✓ Branch 9 → 10 taken 12 times.
✓ Branch 35 → 11 taken 165 times.
✓ Branch 35 → 36 taken 12 times.
|
177 | for (const ICal::Property &property : w->card.properties) |
| 293 |
7/14✓ Branch 12 → 13 taken 165 times.
✓ Branch 14 → 15 taken 12 times.
✓ Branch 14 → 24 taken 153 times.
✓ Branch 16 → 17 taken 12 times.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 24 taken 12 times.
✓ Branch 29 → 30 taken 165 times.
✗ Branch 29 → 31 not taken.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 33 taken 165 times.
✗ Branch 49 → 50 not taken.
✗ Branch 49 → 51 not taken.
✗ Branch 54 → 55 not taken.
✗ Branch 54 → 56 not taken.
|
330 | if (groupOf(property) == group && baseName(property) != QLatin1String("X-ABLABEL") && |
| 294 |
3/10✗ Branch 19 → 20 not taken.
✗ Branch 21 → 22 not taken.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 24 not taken.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 165 times.
✓ Branch 27 → 28 taken 12 times.
✓ Branch 27 → 29 taken 153 times.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 47 not taken.
|
165 | !baseName(property).startsWith(QLatin1String("X-AB"))) |
| 295 | ✗ | return; | |
| 296 |
2/2✓ Branch 2 → 3 taken 165 times.
✓ Branch 36 → 37 taken 12 times.
|
177 | w->removeWhere([&group](const ICal::Property &property) { return groupOf(property) == group; }); |
| 297 | 32 | } | |
| 298 | |||
| 299 | // Applies the edited values of one property kind: kept lines are updated in | ||
| 300 | // place, missing ones removed (with their label group), new ones inserted | ||
| 301 | // behind the last line of the kind. | ||
| 302 | 27585 | void applyValues(Writer *w, const QString &name, const QList<Entry> &entries, const QList<Entry> &before) { | |
| 303 | 27585 | QSet<int> kept; | |
| 304 |
2/2✓ Branch 25 → 5 taken 27760 times.
✓ Branch 25 → 26 taken 27585 times.
|
55345 | for (const Entry &entry : entries) { |
| 305 |
5/6✓ Branch 6 → 7 taken 71 times.
✓ Branch 6 → 9 taken 27689 times.
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 10 taken 71 times.
✓ Branch 11 → 12 taken 27689 times.
✓ Branch 11 → 13 taken 71 times.
|
27760 | if (entry.sourceIndex < 0 || w->currentIndex(entry.sourceIndex) < 0) |
| 306 | 27689 | continue; | |
| 307 |
2/2✓ Branch 21 → 15 taken 109 times.
✓ Branch 21 → 22 taken 71 times.
|
180 | for (const Entry &old : before) |
| 308 |
2/2✓ Branch 16 → 17 taken 69 times.
✓ Branch 16 → 19 taken 40 times.
|
109 | if (old.sourceIndex == entry.sourceIndex) { |
| 309 |
1/1✓ Branch 17 → 18 taken 69 times.
|
69 | kept.insert(entry.sourceIndex); |
| 310 |
1/1✓ Branch 18 → 19 taken 69 times.
|
69 | updateKept(w, name, entry, old); |
| 311 | } | ||
| 312 | } | ||
| 313 |
2/2✓ Branch 39 → 28 taken 73 times.
✓ Branch 39 → 40 taken 27585 times.
|
27658 | for (const Entry &old : before) { |
| 314 | 73 | const int index = w->currentIndex(old.sourceIndex); | |
| 315 |
5/6✓ Branch 31 → 32 taken 4 times.
✓ Branch 31 → 34 taken 69 times.
✓ Branch 32 → 33 taken 4 times.
✗ Branch 32 → 34 not taken.
✓ Branch 35 → 36 taken 4 times.
✓ Branch 35 → 37 taken 69 times.
|
73 | if (!kept.contains(old.sourceIndex) && index >= 0) |
| 316 |
1/1✓ Branch 36 → 37 taken 4 times.
|
4 | removeWithGroup(w, index); |
| 317 | } | ||
| 318 | 27585 | int insertAt = -1; | |
| 319 |
2/2✓ Branch 49 → 41 taken 87562 times.
✓ Branch 49 → 50 taken 27585 times.
|
115147 | for (int i = 0; i < w->card.properties.size(); ++i) |
| 320 |
3/3✓ Branch 42 → 43 taken 87562 times.
✓ Branch 45 → 46 taken 69 times.
✓ Branch 45 → 47 taken 87493 times.
|
87562 | if (baseName(w->card.properties.at(i)) == name) |
| 321 | 69 | insertAt = i + 1; | |
| 322 |
2/2✓ Branch 50 → 51 taken 27528 times.
✓ Branch 50 → 53 taken 57 times.
|
27585 | if (insertAt < 0) |
| 323 | 27528 | insertAt = int(w->card.properties.size()); | |
| 324 |
2/2✓ Branch 78 → 55 taken 27760 times.
✓ Branch 78 → 79 taken 27585 times.
|
55345 | for (const Entry &entry : entries) { |
| 325 |
7/8✓ Branch 56 → 57 taken 71 times.
✓ Branch 56 → 59 taken 27689 times.
✓ Branch 58 → 59 taken 2 times.
✓ Branch 58 → 61 taken 69 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 27691 times.
✓ Branch 63 → 64 taken 69 times.
✓ Branch 63 → 65 taken 27691 times.
|
27760 | if ((entry.sourceIndex >= 0 && kept.contains(entry.sourceIndex)) || entry.wire.isEmpty()) |
| 326 | 69 | continue; | |
| 327 | 27691 | ICal::Property created; | |
| 328 | 27691 | created.name = name; | |
| 329 | 27691 | created.value = entry.wire; | |
| 330 |
1/1✓ Branch 67 → 68 taken 27691 times.
|
27691 | setTypes(&created, entry.types, entry.preferred, w->v4); |
| 331 |
1/1✓ Branch 68 → 69 taken 27691 times.
|
27691 | w->insert(insertAt, created); |
| 332 |
1/1✓ Branch 69 → 70 taken 27691 times.
|
27691 | setLabel(w, insertAt, entry.label); |
| 333 |
2/2✓ Branch 71 → 72 taken 27690 times.
✓ Branch 71 → 73 taken 1 time.
|
27691 | insertAt += entry.label.isEmpty() ? 1 : 2; |
| 334 | 27691 | } | |
| 335 | 27585 | } | |
| 336 | |||
| 337 | // F-28 (SPRINT-104): TEL and URL are SINGLE values, not text lists — a | ||
| 338 | // comma or semicolon in them has no structural meaning and must reach the | ||
| 339 | // wire verbatim (the blanket escapeText rewrote | ||
| 340 | // "…?q=52.5,13.4;z=12" into "…?q=52.5\,13.4\;z=12" and | ||
| 341 | // "+49 30 1234;ext=56" gained backslashes; URI consumers saw them). | ||
| 342 | 158712 | QList<Entry> entriesOf(const QList<ContactValue> &values, bool verbatim) { | |
| 343 | 158712 | QList<Entry> entries; | |
| 344 |
2/2✓ Branch 17 → 4 taken 29597 times.
✓ Branch 17 → 18 taken 158712 times.
|
188309 | for (const ContactValue &value : values) |
| 345 | 29597 | entries.append({verbatim ? value.value.trimmed() | |
| 346 |
3/5✓ Branch 7 → 8 taken 26829 times.
✓ Branch 13 → 14 taken 26829 times.
✓ Branch 13 → 15 taken 2768 times.
✗ Branch 31 → 32 not taken.
✗ Branch 31 → 33 not taken.
|
56426 | : ICal::escapeText(value.value.trimmed()), |
| 347 | 59194 | value.types, value.preferred, value.label, | |
| 348 | 29597 | value.sourceIndex}); | |
| 349 | 158712 | return entries; | |
| 350 | 56426 | } | |
| 351 | |||
| 352 | 52904 | QList<Entry> entriesOf(const QList<ContactAddress> &addresses) { | |
| 353 | 52904 | QList<Entry> entries; | |
| 354 |
2/2✓ Branch 28 → 4 taken 3053 times.
✓ Branch 28 → 29 taken 52904 times.
|
55957 | for (const ContactAddress &a : addresses) { |
| 355 |
3/3✓ Branch 5 → 6 taken 3053 times.
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 3052 times.
|
3053 | if (a.isEmpty()) |
| 356 | 1 | continue; | |
| 357 |
2/4✓ Branch 23 → 24 taken 21364 times.
✓ Branch 23 → 25 taken 3052 times.
✗ Branch 45 → 46 not taken.
✗ Branch 45 → 47 not taken.
|
24416 | entries.append({escapeComponents({a.poBox, a.extended, a.street, a.locality, a.region, a.postalCode, a.country}), |
| 358 | 9156 | a.types, a.preferred, a.label, a.sourceIndex}); | |
| 359 | } | ||
| 360 | 52904 | return entries; | |
| 361 | 3052 | } | |
| 362 | |||
| 363 | 105808 | bool sameEntries(const QList<Entry> &a, const QList<Entry> &b) { | |
| 364 |
2/2✓ Branch 4 → 5 taken 27536 times.
✓ Branch 4 → 6 taken 78272 times.
|
105808 | if (a.size() != b.size()) |
| 365 | 27536 | return false; | |
| 366 |
2/2✓ Branch 31 → 7 taken 2458 times.
✓ Branch 31 → 32 taken 78223 times.
|
80681 | for (int i = 0; i < a.size(); ++i) |
| 367 |
3/4✓ Branch 14 → 15 taken 2411 times.
✗ Branch 14 → 25 not taken.
✓ Branch 17 → 18 taken 2409 times.
✓ Branch 17 → 25 taken 2 times.
|
4869 | if (a.at(i).wire != b.at(i).wire || a.at(i).types != b.at(i).types || a.at(i).preferred != b.at(i).preferred || |
| 368 |
6/8✓ Branch 10 → 11 taken 2411 times.
✓ Branch 10 → 25 taken 47 times.
✓ Branch 21 → 22 taken 2409 times.
✗ Branch 21 → 25 not taken.
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 26 taken 2409 times.
✓ Branch 27 → 28 taken 49 times.
✓ Branch 27 → 29 taken 2409 times.
|
4869 | a.at(i).label != b.at(i).label || a.at(i).sourceIndex != b.at(i).sourceIndex) |
| 369 | 49 | return false; | |
| 370 | 78223 | return true; | |
| 371 | } | ||
| 372 | |||
| 373 | // ─── whole-property replacements ─── | ||
| 374 | |||
| 375 | 303 | void setCategories(Writer *w, const QStringList &categories) { | |
| 376 |
1/1✓ Branch 5 → 6 taken 303 times.
|
303 | int position = indexOfName(w->card, QStringLiteral("CATEGORIES")); |
| 377 |
2/2✓ Branch 3 → 4 taken 2495 times.
✓ Branch 8 → 9 taken 303 times.
|
2798 | w->removeWhere([](const ICal::Property &p) { return baseName(p) == QLatin1String("CATEGORIES"); }); |
| 378 | 303 | w->changed = true; | |
| 379 |
2/2✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 302 times.
|
303 | if (categories.isEmpty()) |
| 380 | 1 | return; | |
| 381 | 302 | QStringList escaped; | |
| 382 |
2/2✓ Branch 20 → 14 taken 323 times.
✓ Branch 20 → 21 taken 302 times.
|
625 | for (const QString &category : categories) |
| 383 |
2/2✓ Branch 15 → 16 taken 323 times.
✓ Branch 16 → 17 taken 323 times.
|
323 | escaped.append(ICal::escapeText(category)); |
| 384 | 302 | ICal::Property created; | |
| 385 | 302 | created.name = QStringLiteral("CATEGORIES"); | |
| 386 |
1/1✓ Branch 29 → 30 taken 302 times.
|
302 | created.value = escaped.join(QLatin1Char(',')); |
| 387 |
2/2✓ Branch 32 → 33 taken 299 times.
✓ Branch 32 → 35 taken 3 times.
|
302 | if (position < 0) |
| 388 | 299 | position = int(w->card.properties.size()); | |
| 389 |
1/1✓ Branch 35 → 36 taken 302 times.
|
302 | w->insert(position, created); |
| 390 | 302 | } | |
| 391 | |||
| 392 | 51 | void setMembers(Writer *w, const QStringList &members) { | |
| 393 | // D-7: write in the model the card uses (vCard 4 MEMBER or Apple's | ||
| 394 | // X-ADDRESSBOOKSERVER-MEMBER). | ||
| 395 |
4/9✓ Branch 5 → 6 taken 51 times.
✓ Branch 6 → 7 taken 33 times.
✓ Branch 6 → 12 taken 18 times.
✓ Branch 20 → 21 taken 51 times.
✗ Branch 20 → 22 not taken.
✗ Branch 54 → 55 not taken.
✗ Branch 54 → 56 not taken.
✗ Branch 58 → 59 not taken.
✗ Branch 58 → 60 not taken.
|
186 | const bool apple = indexOfName(w->card, QStringLiteral("X-ADDRESSBOOKSERVER-KIND")) >= 0 || |
| 396 |
7/13✓ Branch 10 → 11 taken 33 times.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 33 times.
✓ Branch 14 → 15 taken 33 times.
✓ Branch 14 → 16 taken 18 times.
✓ Branch 16 → 17 taken 33 times.
✓ Branch 16 → 18 taken 18 times.
✓ Branch 18 → 19 taken 51 times.
✗ Branch 18 → 20 not taken.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 48 not taken.
✗ Branch 50 → 51 not taken.
✗ Branch 50 → 52 not taken.
|
84 | indexOfName(w->card, QStringLiteral("X-ADDRESSBOOKSERVER-MEMBER")) >= 0; |
| 397 |
6/6✓ Branch 22 → 23 taken 18 times.
✓ Branch 22 → 26 taken 33 times.
✓ Branch 29 → 30 taken 33 times.
✓ Branch 29 → 31 taken 18 times.
✓ Branch 31 → 32 taken 18 times.
✓ Branch 31 → 33 taken 33 times.
|
102 | const QString name = apple ? QStringLiteral("X-ADDRESSBOOKSERVER-MEMBER") : QStringLiteral("MEMBER"); |
| 398 |
1/1✓ Branch 33 → 34 taken 51 times.
|
51 | w->removeWhere([](const ICal::Property &p) { |
| 399 |
7/14✓ Branch 3 → 4 taken 309 times.
✓ Branch 5 → 6 taken 309 times.
✗ Branch 5 → 10 not taken.
✓ Branch 7 → 8 taken 309 times.
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 308 times.
✓ Branch 13 → 14 taken 309 times.
✗ Branch 13 → 15 not taken.
✓ Branch 15 → 16 taken 309 times.
✗ Branch 15 → 17 not taken.
✗ Branch 19 → 20 not taken.
✗ Branch 19 → 21 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
|
309 | return baseName(p) == QLatin1String("MEMBER") || baseName(p) == QLatin1String("X-ADDRESSBOOKSERVER-MEMBER"); |
| 400 | }); | ||
| 401 |
2/2✓ Branch 43 → 36 taken 144 times.
✓ Branch 43 → 44 taken 51 times.
|
195 | for (const QString &member : members) { |
| 402 | 144 | ICal::Property created; | |
| 403 | 144 | created.name = name; | |
| 404 | 144 | created.value = member; | |
| 405 |
1/1✓ Branch 39 → 40 taken 144 times.
|
144 | w->append(created); |
| 406 | 144 | } | |
| 407 | 51 | w->changed = true; | |
| 408 | 51 | } | |
| 409 | |||
| 410 | 333 | void setPhoto(Writer *w, const ContactPhoto &photo) { | |
| 411 |
1/1✓ Branch 5 → 6 taken 333 times.
|
333 | const int position = indexOfName(w->card, QStringLiteral("PHOTO")); |
| 412 |
2/2✓ Branch 3 → 4 taken 3145 times.
✓ Branch 8 → 9 taken 333 times.
|
3478 | w->removeWhere([](const ICal::Property &p) { return baseName(p) == QLatin1String("PHOTO"); }); |
| 413 | 333 | w->changed = true; | |
| 414 |
2/2✓ Branch 9 → 10 taken 3 times.
✓ Branch 9 → 11 taken 330 times.
|
333 | if (photo.kind == ContactPhoto::Kind::None) |
| 415 | 3 | return; | |
| 416 | 330 | ICal::Property created; | |
| 417 | 330 | created.name = QStringLiteral("PHOTO"); | |
| 418 |
4/4✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 22 taken 329 times.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 25 taken 329 times.
|
331 | const QString mime = photo.mimeType.isEmpty() ? QStringLiteral("image/jpeg") : photo.mimeType; |
| 419 |
2/2✓ Branch 25 → 26 taken 1 time.
✓ Branch 25 → 45 taken 329 times.
|
330 | if (photo.kind == ContactPhoto::Kind::Uri) { |
| 420 | 1 | created.value = photo.uri; | |
| 421 |
2/8✓ Branch 39 → 40 taken 1 time.
✗ Branch 39 → 41 not taken.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 1 time.
✗ Branch 115 → 116 not taken.
✗ Branch 115 → 117 not taken.
✗ Branch 119 → 120 not taken.
✗ Branch 119 → 121 not taken.
|
1 | created.parameters.append({QStringLiteral("VALUE"), w->v4 ? QStringLiteral("uri") : QStringLiteral("URI")}); |
| 422 |
2/2✓ Branch 45 → 46 taken 60 times.
✓ Branch 45 → 69 taken 269 times.
|
329 | } else if (w->v4) { |
| 423 |
5/5✓ Branch 47 → 48 taken 60 times.
✓ Branch 48 → 49 taken 60 times.
✓ Branch 55 → 56 taken 60 times.
✓ Branch 56 → 57 taken 60 times.
✓ Branch 57 → 58 taken 60 times.
|
180 | created.value = QStringLiteral("data:") + mime + QStringLiteral(";base64,") + QString::fromLatin1(photo.data.toBase64()); |
| 424 | } else { | ||
| 425 | 269 | created.parameters.append({QStringLiteral("ENCODING"), QStringLiteral("b")}); | |
| 426 |
1/1✓ Branch 85 → 86 taken 269 times.
|
538 | created.parameters.append({QStringLiteral("TYPE"), mime.section(QLatin1Char('/'), 1).toUpper()}); |
| 427 |
2/2✓ Branch 92 → 93 taken 269 times.
✓ Branch 93 → 94 taken 269 times.
|
269 | created.value = QString::fromLatin1(photo.data.toBase64()); |
| 428 | } | ||
| 429 |
3/3✓ Branch 98 → 99 taken 329 times.
✓ Branch 98 → 101 taken 1 time.
✓ Branch 102 → 103 taken 330 times.
|
330 | w->insert(position < 0 ? int(w->card.properties.size()) : position, created); |
| 430 | 1408 | } | |
| 431 | |||
| 432 | 26452 | QString displayNameFor(const ContactCard &card) { | |
| 433 |
3/3✓ Branch 2 → 3 taken 26452 times.
✓ Branch 5 → 6 taken 24267 times.
✓ Branch 5 → 8 taken 2185 times.
|
26452 | if (!card.formattedName.trimmed().isEmpty()) |
| 434 |
1/1✓ Branch 6 → 7 taken 24267 times.
|
24267 | return card.formattedName.trimmed(); |
| 435 | ✗ | const QString composed = QStringList{card.name.prefix, card.name.given, card.name.additional, card.name.family, | |
| 436 |
2/4✓ Branch 21 → 22 taken 10925 times.
✓ Branch 21 → 23 taken 2185 times.
✗ Branch 46 → 47 not taken.
✗ Branch 46 → 48 not taken.
|
13110 | card.name.suffix} |
| 437 |
1/1✓ Branch 16 → 17 taken 2185 times.
|
4370 | .join(QLatin1Char(' ')) |
| 438 |
1/1✓ Branch 17 → 18 taken 2185 times.
|
2185 | .simplified(); |
| 439 |
2/2✓ Branch 24 → 25 taken 2154 times.
✓ Branch 24 → 26 taken 31 times.
|
2185 | if (!composed.isEmpty()) |
| 440 | 2154 | return composed; | |
| 441 |
1/2✓ Branch 27 → 28 taken 31 times.
✗ Branch 27 → 29 not taken.
|
31 | if (!card.organization.isEmpty()) |
| 442 | 31 | return card.organization; | |
| 443 | ✗ | return card.emails.isEmpty() ? QString() : card.emails.first().value; | |
| 444 | 4370 | } | |
| 445 | |||
| 446 | 26452 | void applyFields(Writer *w, const ContactCard &before, const ContactCard &after) { | |
| 447 |
1/1✓ Branch 2 → 3 taken 26452 times.
|
26452 | const QString fn = displayNameFor(after); |
| 448 |
10/15✓ Branch 4 → 5 taken 1378 times.
✓ Branch 4 → 10 taken 25074 times.
✓ Branch 8 → 9 taken 1378 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 1378 times.
✓ Branch 12 → 13 taken 1378 times.
✓ Branch 12 → 14 taken 25074 times.
✓ Branch 14 → 15 taken 1378 times.
✓ Branch 14 → 16 taken 25074 times.
✓ Branch 16 → 17 taken 25074 times.
✓ Branch 16 → 26 taken 1378 times.
✗ Branch 208 → 209 not taken.
✗ Branch 208 → 210 not taken.
✗ Branch 212 → 213 not taken.
✗ Branch 212 → 214 not taken.
|
27830 | if (fn != before.formattedName || indexOfName(w->card, QStringLiteral("FN")) < 0) |
| 449 |
2/2✓ Branch 17 → 18 taken 25074 times.
✓ Branch 21 → 22 taken 25074 times.
|
50148 | setSingle(w, QStringLiteral("FN"), ICal::escapeText(fn)); |
| 450 |
11/15✓ Branch 27 → 28 taken 24211 times.
✓ Branch 27 → 33 taken 2241 times.
✓ Branch 31 → 32 taken 24211 times.
✓ Branch 32 → 33 taken 22501 times.
✓ Branch 32 → 34 taken 1710 times.
✓ Branch 35 → 36 taken 24211 times.
✓ Branch 35 → 37 taken 2241 times.
✓ Branch 37 → 38 taken 24211 times.
✓ Branch 37 → 39 taken 2241 times.
✓ Branch 39 → 40 taken 24742 times.
✓ Branch 39 → 59 taken 1710 times.
✗ Branch 225 → 226 not taken.
✗ Branch 225 → 227 not taken.
✗ Branch 229 → 230 not taken.
✗ Branch 229 → 231 not taken.
|
50663 | if (after.name != before.name || indexOfName(w->card, QStringLiteral("N")) < 0) |
| 451 |
1/1✓ Branch 50 → 51 taken 24742 times.
|
24742 | setSingle(w, QStringLiteral("N"), |
| 452 |
3/5✓ Branch 46 → 47 taken 24742 times.
✓ Branch 56 → 57 taken 123710 times.
✓ Branch 56 → 58 taken 24742 times.
✗ Branch 244 → 245 not taken.
✗ Branch 244 → 246 not taken.
|
173194 | escapeComponents({after.name.family, after.name.given, after.name.additional, after.name.prefix, |
| 453 | 24742 | after.name.suffix})); | |
| 454 |
2/2✓ Branch 60 → 61 taken 19 times.
✓ Branch 60 → 70 taken 26433 times.
|
26452 | if (after.nickname != before.nickname) |
| 455 |
2/2✓ Branch 61 → 62 taken 19 times.
✓ Branch 65 → 66 taken 19 times.
|
38 | setSingle(w, QStringLiteral("NICKNAME"), ICal::escapeText(after.nickname)); |
| 456 |
5/6✓ Branch 71 → 72 taken 25521 times.
✓ Branch 71 → 74 taken 931 times.
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 75 taken 25521 times.
✓ Branch 76 → 77 taken 931 times.
✓ Branch 76 → 125 taken 25521 times.
|
26452 | if (after.organization != before.organization || after.department != before.department) { |
| 457 |
2/4✓ Branch 81 → 82 taken 1862 times.
✓ Branch 81 → 83 taken 931 times.
✗ Branch 265 → 266 not taken.
✗ Branch 265 → 267 not taken.
|
2793 | QStringList parts{after.organization, after.department}; |
| 458 |
1/1✓ Branch 86 → 87 taken 931 times.
|
931 | const int index = indexOfName(w->card, QStringLiteral("ORG")); |
| 459 |
2/2✓ Branch 89 → 90 taken 1 time.
✓ Branch 89 → 105 taken 930 times.
|
931 | if (index >= 0) { |
| 460 | // Further organisational units (beyond the department) survive. | ||
| 461 |
1/1✓ Branch 94 → 95 taken 1 time.
|
1 | const QStringList old = w->card.properties.at(index).value.split(QLatin1Char(';')); |
| 462 |
1/2✗ Branch 102 → 96 not taken.
✓ Branch 102 → 103 taken 1 time.
|
1 | for (int i = 2; i < old.size(); ++i) |
| 463 | ✗ | parts.append(ICal::unescapeText(old.at(i))); | |
| 464 | 1 | } | |
| 465 |
6/7✓ Branch 108 → 109 taken 1861 times.
✗ Branch 108 → 113 not taken.
✓ Branch 109 → 110 taken 1861 times.
✓ Branch 111 → 112 taken 930 times.
✓ Branch 111 → 113 taken 931 times.
✓ Branch 114 → 106 taken 930 times.
✓ Branch 114 → 115 taken 931 times.
|
1861 | while (!parts.isEmpty() && parts.last().isEmpty()) |
| 466 | 930 | parts.removeLast(); | |
| 467 |
2/2✓ Branch 115 → 116 taken 931 times.
✓ Branch 119 → 120 taken 931 times.
|
1862 | setSingle(w, QStringLiteral("ORG"), escapeComponents(parts)); |
| 468 | 931 | } | |
| 469 |
2/2✓ Branch 126 → 127 taken 367 times.
✓ Branch 126 → 136 taken 26085 times.
|
26452 | if (after.title != before.title) |
| 470 |
2/2✓ Branch 127 → 128 taken 367 times.
✓ Branch 131 → 132 taken 367 times.
|
734 | setSingle(w, QStringLiteral("TITLE"), ICal::escapeText(after.title)); |
| 471 |
2/2✓ Branch 137 → 138 taken 32 times.
✓ Branch 137 → 147 taken 26420 times.
|
26452 | if (after.note != before.note) |
| 472 |
2/2✓ Branch 138 → 139 taken 32 times.
✓ Branch 142 → 143 taken 32 times.
|
64 | setSingle(w, QStringLiteral("NOTE"), ICal::escapeText(after.note)); |
| 473 |
2/2✓ Branch 148 → 149 taken 305 times.
✓ Branch 148 → 156 taken 26147 times.
|
26452 | if (after.birthday != before.birthday) |
| 474 |
1/1✓ Branch 152 → 153 taken 305 times.
|
610 | setDate(w, QStringLiteral("BDAY"), after.birthday); |
| 475 |
2/2✓ Branch 157 → 158 taken 47 times.
✓ Branch 157 → 178 taken 26405 times.
|
26452 | if (after.anniversary != before.anniversary) { |
| 476 |
1/1✓ Branch 161 → 162 taken 47 times.
|
47 | const bool x = indexOfName(w->card, QStringLiteral("X-ANNIVERSARY")) >= 0; |
| 477 |
4/11✗ Branch 164 → 165 not taken.
✓ Branch 164 → 168 taken 47 times.
✓ Branch 171 → 172 taken 47 times.
✓ Branch 173 → 174 taken 47 times.
✗ Branch 173 → 175 not taken.
✗ Branch 175 → 176 not taken.
✓ Branch 175 → 177 taken 47 times.
✗ Branch 333 → 334 not taken.
✗ Branch 333 → 335 not taken.
✗ Branch 337 → 338 not taken.
✗ Branch 337 → 339 not taken.
|
94 | setDate(w, x ? QStringLiteral("X-ANNIVERSARY") : QStringLiteral("ANNIVERSARY"), after.anniversary); |
| 478 | } | ||
| 479 |
3/3✓ Branch 178 → 179 taken 26452 times.
✓ Branch 179 → 180 taken 303 times.
✓ Branch 179 → 181 taken 26149 times.
|
26452 | if (after.categories != before.categories) |
| 480 |
1/1✓ Branch 180 → 181 taken 303 times.
|
303 | setCategories(w, after.categories); |
| 481 |
3/3✓ Branch 181 → 182 taken 26452 times.
✓ Branch 182 → 183 taken 51 times.
✓ Branch 182 → 184 taken 26401 times.
|
26452 | if (after.members != before.members) |
| 482 |
1/1✓ Branch 183 → 184 taken 51 times.
|
51 | setMembers(w, after.members); |
| 483 |
2/2✓ Branch 186 → 187 taken 10 times.
✓ Branch 186 → 203 taken 26442 times.
|
26452 | if (after.isFamily() != before.isFamily()) // X-MAILJD-KIND:family, both versions (ContactCard::isFamily) |
| 484 |
5/7✓ Branch 188 → 189 taken 8 times.
✓ Branch 188 → 192 taken 2 times.
✓ Branch 196 → 197 taken 10 times.
✓ Branch 200 → 201 taken 8 times.
✓ Branch 200 → 202 taken 2 times.
✗ Branch 350 → 351 not taken.
✗ Branch 350 → 352 not taken.
|
28 | setSingle(w, QStringLiteral("X-MAILJD-KIND"), after.isFamily() ? QStringLiteral("family") : QString()); |
| 485 |
2/2✓ Branch 204 → 205 taken 333 times.
✓ Branch 204 → 206 taken 26119 times.
|
26452 | if (after.photo != before.photo) |
| 486 |
1/1✓ Branch 205 → 206 taken 333 times.
|
333 | setPhoto(w, after.photo); |
| 487 | 52125 | } | |
| 488 | |||
| 489 | 26452 | void applyMultiValues(Writer *w, const ContactCard &before, const ContactCard &after) { | |
| 490 | const QList<QPair<QString, QPair<QList<Entry>, QList<Entry>>>> kinds{ | ||
| 491 |
2/2✓ Branch 5 → 6 taken 26452 times.
✓ Branch 6 → 7 taken 26452 times.
|
79356 | {QStringLiteral("EMAIL"), {entriesOf(before.emails, false), entriesOf(after.emails, false)}}, |
| 492 |
2/2✓ Branch 12 → 13 taken 26452 times.
✓ Branch 13 → 14 taken 26452 times.
|
79356 | {QStringLiteral("TEL"), {entriesOf(before.phones, true), entriesOf(after.phones, true)}}, |
| 493 |
2/2✓ Branch 19 → 20 taken 26452 times.
✓ Branch 20 → 21 taken 26452 times.
|
79356 | {QStringLiteral("URL"), {entriesOf(before.urls, true), entriesOf(after.urls, true)}}, |
| 494 |
4/6✓ Branch 26 → 27 taken 26452 times.
✓ Branch 27 → 28 taken 26452 times.
✓ Branch 32 → 33 taken 105808 times.
✓ Branch 32 → 34 taken 26452 times.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
|
370328 | {QStringLiteral("ADR"), {entriesOf(before.addresses), entriesOf(after.addresses)}}}; |
| 495 |
2/2✓ Branch 62 → 56 taken 105808 times.
✓ Branch 62 → 63 taken 26452 times.
|
132260 | for (const auto &kind : kinds) |
| 496 |
3/3✓ Branch 57 → 58 taken 105808 times.
✓ Branch 58 → 59 taken 27585 times.
✓ Branch 58 → 60 taken 78223 times.
|
105808 | if (!sameEntries(kind.second.first, kind.second.second)) |
| 497 |
1/1✓ Branch 59 → 60 taken 27585 times.
|
27585 | applyValues(w, kind.first, kind.second.second, kind.second.first); |
| 498 | 158712 | } | |
| 499 | |||
| 500 | 26372 | void touchRevision(Writer *w, const QDateTime &now) { | |
| 501 |
5/5✓ Branch 2 → 3 taken 26372 times.
✓ Branch 3 → 4 taken 1485 times.
✓ Branch 3 → 5 taken 24887 times.
✓ Branch 5 → 6 taken 24887 times.
✓ Branch 6 → 7 taken 26372 times.
|
26372 | const QDateTime stamp = (now.isValid() ? now : QDateTime::currentDateTimeUtc()).toUTC(); |
| 502 |
2/2✓ Branch 11 → 12 taken 26372 times.
✓ Branch 15 → 16 taken 26372 times.
|
52744 | setSingle(w, QStringLiteral("REV"), stamp.toString(QStringLiteral("yyyyMMdd'T'HHmmss'Z'"))); |
| 503 |
1/1✓ Branch 24 → 25 taken 26372 times.
|
26372 | const int index = indexOfName(w->card, QStringLiteral("REV")); |
| 504 |
1/2✓ Branch 27 → 28 taken 26372 times.
✗ Branch 27 → 36 not taken.
|
26372 | if (index >= 0) |
| 505 |
2/2✓ Branch 28 → 29 taken 26372 times.
✓ Branch 32 → 33 taken 26372 times.
|
52744 | w->card.properties[index].removeParameter(QStringLiteral("VALUE")); |
| 506 | 26372 | } | |
| 507 | |||
| 508 | } // namespace detail | ||
| 509 | |||
| 510 | using namespace detail; | ||
| 511 | |||
| 512 | 26464 | QString patch(const QString &base, const ContactCard &edited, QString *error, const QDateTime &now) { | |
| 513 |
2/3✓ Branch 2 → 3 taken 26464 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 14 taken 26464 times.
|
26464 | if (base.trimmed().isEmpty()) |
| 514 | ✗ | return create(edited, QStringLiteral("3.0"), now); | |
| 515 | 26464 | Writer w; | |
| 516 | 26464 | int skipped = 0; | |
| 517 |
2/3✓ Branch 14 → 15 taken 26464 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 26464 times.
|
26464 | if (!parseTree(base, &w.card, error, &skipped)) |
| 518 | ✗ | return {}; | |
| 519 |
2/2✓ Branch 21 → 18 taken 106016 times.
✓ Branch 21 → 22 taken 26464 times.
|
132480 | for (int i = 0; i < w.card.properties.size(); ++i) |
| 520 |
1/1✓ Branch 18 → 19 taken 106016 times.
|
106016 | w.origin.append(i); |
| 521 |
2/2✓ Branch 22 → 23 taken 12 times.
✓ Branch 22 → 32 taken 26452 times.
|
26464 | if (skipped > 0) { |
| 522 |
2/2✓ Branch 23 → 24 taken 1 time.
✓ Branch 23 → 31 taken 11 times.
|
12 | if (error) |
| 523 | 1 | *error = QStringLiteral("The stored card has lines MailJD cannot read; it is not rewritten"); | |
| 524 | 12 | return {}; | |
| 525 | } | ||
| 526 |
1/1✓ Branch 32 → 33 taken 26452 times.
|
26452 | ContactCard before; |
| 527 |
2/3✓ Branch 33 → 34 taken 26452 times.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 26452 times.
|
26452 | if (!parse(base, &before, error)) |
| 528 | ✗ | return {}; | |
| 529 |
2/2✓ Branch 38 → 39 taken 34 times.
✓ Branch 38 → 41 taken 26418 times.
|
26452 | if (before.version == QLatin1String("2.1")) { |
| 530 |
1/1✓ Branch 39 → 40 taken 34 times.
|
34 | upgradeTo30(&w.card, &w.origin); // same properties in the same order: indices hold |
| 531 | 34 | w.changed = true; | |
| 532 | } | ||
| 533 | 26452 | w.v4 = before.version == QLatin1String("4.0"); | |
| 534 |
1/1✓ Branch 43 → 44 taken 26452 times.
|
26452 | applyMultiValues(&w, before, edited); |
| 535 |
1/1✓ Branch 44 → 45 taken 26452 times.
|
26452 | applyFields(&w, before, edited); |
| 536 |
1/1✓ Branch 45 → 46 taken 26452 times.
|
26452 | applyPeople(&w, before, edited); // Sprint 103 (VCardPeoplePatch.cpp) |
| 537 |
2/2✓ Branch 46 → 47 taken 80 times.
✓ Branch 46 → 49 taken 26372 times.
|
26452 | if (!w.changed) |
| 538 |
1/1✓ Branch 47 → 48 taken 80 times.
|
80 | return ICal::serialize(w.card); |
| 539 |
1/1✓ Branch 49 → 50 taken 26372 times.
|
26372 | touchRevision(&w, now); |
| 540 |
1/1✓ Branch 50 → 51 taken 26372 times.
|
26372 | return ICal::serialize(w.card); |
| 541 | 26464 | } | |
| 542 | |||
| 543 | 24523 | QString create(const ContactCard &card, const QString &version, const QDateTime &now) { | |
| 544 | 24523 | const bool v4 = version == QLatin1String("4.0"); | |
| 545 |
7/11✓ Branch 11 → 12 taken 519 times.
✓ Branch 11 → 15 taken 24004 times.
✓ Branch 21 → 22 taken 24523 times.
✓ Branch 31 → 32 taken 24004 times.
✓ Branch 31 → 33 taken 519 times.
✓ Branch 33 → 34 taken 519 times.
✓ Branch 33 → 35 taken 24004 times.
✗ Branch 164 → 165 not taken.
✗ Branch 164 → 166 not taken.
✗ Branch 168 → 169 not taken.
✗ Branch 168 → 170 not taken.
|
98092 | QString skeleton = QStringLiteral("BEGIN:VCARD\r\nVERSION:") + (v4 ? QStringLiteral("4.0") : QStringLiteral("3.0")) + |
| 546 |
3/3✓ Branch 7 → 8 taken 24523 times.
✓ Branch 22 → 23 taken 24523 times.
✓ Branch 23 → 24 taken 24523 times.
|
122615 | QStringLiteral("\r\nPRODID:-//MailJD//MailJD Contacts//EN\r\nUID:") + ICal::escapeText(card.uid) + |
| 547 |
1/1✓ Branch 24 → 25 taken 24523 times.
|
73569 | QStringLiteral("\r\n"); |
| 548 |
2/2✓ Branch 41 → 42 taken 52 times.
✓ Branch 41 → 56 taken 24471 times.
|
24523 | if (card.isGroup()) |
| 549 |
7/11✓ Branch 42 → 43 taken 34 times.
✓ Branch 42 → 46 taken 18 times.
✓ Branch 49 → 50 taken 52 times.
✓ Branch 51 → 52 taken 18 times.
✓ Branch 51 → 53 taken 34 times.
✓ Branch 53 → 54 taken 34 times.
✓ Branch 53 → 55 taken 18 times.
✗ Branch 193 → 194 not taken.
✗ Branch 193 → 195 not taken.
✗ Branch 197 → 198 not taken.
✗ Branch 197 → 199 not taken.
|
104 | skeleton += v4 ? QStringLiteral("KIND:group\r\n") : QStringLiteral("X-ADDRESSBOOKSERVER-KIND:group\r\n"); |
| 550 |
4/6✓ Branch 56 → 57 taken 485 times.
✓ Branch 56 → 61 taken 23986 times.
✗ Branch 59 → 60 not taken.
✓ Branch 59 → 61 taken 485 times.
✗ Branch 62 → 63 not taken.
✓ Branch 62 → 70 taken 24471 times.
|
24471 | else if (v4 && card.kind == QLatin1String("org")) |
| 551 | ✗ | skeleton += QStringLiteral("KIND:org\r\n"); | |
| 552 |
1/1✓ Branch 73 → 74 taken 24523 times.
|
24523 | skeleton += QStringLiteral("END:VCARD\r\n"); |
| 553 | 24523 | ContactCard fresh = card; | |
| 554 |
2/2✓ Branch 87 → 79 taken 73569 times.
✓ Branch 87 → 88 taken 24523 times.
|
98092 | for (auto *values : {&fresh.emails, &fresh.phones, &fresh.urls}) |
| 555 |
4/4✓ Branch 79 → 80 taken 73569 times.
✓ Branch 80 → 81 taken 73569 times.
✓ Branch 85 → 82 taken 25608 times.
✓ Branch 85 → 86 taken 73569 times.
|
99177 | for (ContactValue &value : *values) |
| 556 | 25608 | value.sourceIndex = -1; | |
| 557 |
4/4✓ Branch 88 → 89 taken 24523 times.
✓ Branch 89 → 90 taken 24523 times.
✓ Branch 94 → 91 taken 2062 times.
✓ Branch 94 → 95 taken 24523 times.
|
26585 | for (ContactAddress &address : fresh.addresses) |
| 558 | 2062 | address.sourceIndex = -1; | |
| 559 |
4/4✓ Branch 95 → 96 taken 24523 times.
✓ Branch 96 → 97 taken 24523 times.
✓ Branch 101 → 98 taken 410 times.
✓ Branch 101 → 102 taken 24523 times.
|
24933 | for (ContactRelation &relation : fresh.relations) |
| 560 | 410 | relation.sourceIndex = -1; | |
| 561 |
4/4✓ Branch 102 → 103 taken 24523 times.
✓ Branch 103 → 104 taken 24523 times.
✓ Branch 108 → 105 taken 48 times.
✓ Branch 108 → 109 taken 24523 times.
|
24571 | for (ContactPersonRef &ref : fresh.met.via) |
| 562 | 48 | ref.sourceIndex = -1; | |
| 563 |
4/4✓ Branch 109 → 110 taken 24523 times.
✓ Branch 110 → 111 taken 24523 times.
✓ Branch 115 → 112 taken 131 times.
✓ Branch 115 → 116 taken 24523 times.
|
24654 | for (ContactSocial &social : fresh.social) |
| 564 | 131 | social.sourceIndex = -1; | |
| 565 |
4/4✓ Branch 116 → 117 taken 24523 times.
✓ Branch 117 → 118 taken 24523 times.
✓ Branch 122 → 119 taken 20 times.
✓ Branch 122 → 123 taken 24523 times.
|
24543 | for (ContactDate &date : fresh.otherDates) |
| 566 | 20 | date.sourceIndex = -1; | |
| 567 |
4/4✓ Branch 123 → 124 taken 24523 times.
✓ Branch 124 → 125 taken 24523 times.
✓ Branch 129 → 126 taken 10 times.
✓ Branch 129 → 130 taken 24523 times.
|
24533 | for (ContactMailLink &link : fresh.mailLinks) |
| 568 | 10 | link.sourceIndex = -1; | |
| 569 | 24523 | QString error; | |
| 570 |
1/1✓ Branch 130 → 131 taken 24523 times.
|
24523 | const QString result = patch(skeleton, fresh, &error, now); |
| 571 |
1/2✗ Branch 132 → 133 not taken.
✓ Branch 132 → 145 taken 24523 times.
|
24523 | if (result.isEmpty()) |
| 572 | ✗ | qCWarning(lcVCard) << "Creating a card failed:" << error; | |
| 573 | 24523 | return result; | |
| 574 | 24523 | } | |
| 575 | |||
| 576 | } // namespace VCardCodec | ||
| 577 |