performance/ContactShowcase.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "ContactShowcase.h" | ||
| 2 | |||
| 3 | #include "data/CollectedAddressStore.h" | ||
| 4 | #include "data/ContactStore.h" | ||
| 5 | #include "data/VCardCodec.h" | ||
| 6 | |||
| 7 | #include <QBuffer> | ||
| 8 | #include <QImage> | ||
| 9 | #include <QPainter> | ||
| 10 | #include <QScopeGuard> | ||
| 11 | #include <QSqlQuery> | ||
| 12 | #include <QTimeZone> | ||
| 13 | |||
| 14 | namespace ContactShowcase { | ||
| 15 | |||
| 16 | namespace { | ||
| 17 | |||
| 18 | struct Person { | ||
| 19 | const char *given; | ||
| 20 | const char *family; | ||
| 21 | const char *book; // "kontakte", "arbeit", "system", "familie", "local" | ||
| 22 | const char *org; | ||
| 23 | const char *title; | ||
| 24 | const char *emails; // comma separated, first = work/home by book | ||
| 25 | const char *phones; | ||
| 26 | const char *city; | ||
| 27 | const char *birthday; // "YYYY-MM-DD", "--MM-DD" or "" | ||
| 28 | const char *groups; // comma separated | ||
| 29 | int photo; // 0 = none, 1…15 = generated image | ||
| 30 | }; | ||
| 31 | |||
| 32 | // Fictional people; the order is irrelevant (the list sorts them). | ||
| 33 | const Person kPeople[] = { | ||
| 34 | {"Mara", "Klein", "kontakte", "Beispiel GmbH", "Teamleitung Vertrieb", "mara.klein@beispiel.example,mara@klein-privat.example", "+49 170 5550101,+49 30 5550100", "Berlin", "1985-04-12", "Team,Kunden", 1}, | ||
| 35 | {"Mara", "Klein", "arbeit", "Beispiel GmbH", "Teamleitung Vertrieb", "mara.klein@beispiel.example", "+49 30 5550100", "Berlin", "", "", 0}, | ||
| 36 | {"Jonas", "Becker", "kontakte", "", "", "jonas.becker@example.net", "+49 151 5550177", "Hamburg", "--08-15", "Verein", 2}, | ||
| 37 | {"Lena", "Wolf", "kontakte", "Studio Nord", "Grafikdesign", "lena@studio-nord.example", "", "Kiel", "1990-07-03", "", 3}, | ||
| 38 | {"Felix", "Schäfer", "kontakte", "", "", "felix.schaefer@example.de,f.schaefer@arbeit.example", "+49 341 5550123", "Leipzig", "", "Familie", 0}, | ||
| 39 | {"Linh", "Nguyen", "arbeit", "Studio Nord", "Art Director", "linh@studio-nord.example", "+49 151 5550144", "Kiel", "", "", 4}, | ||
| 40 | {"Petra", "Fischer", "kontakte", "", "", "petra.fischer@example.de", "+49 89 5550133", "München", "--11-23", "Familie", 0}, | ||
| 41 | {"Leon", "Weber", "arbeit", "Weber & Söhne", "Inhaber", "leon.weber@weber-soehne.example", "+49 211 5550170", "Düsseldorf", "", "", 5}, | ||
| 42 | {"Sophie", "Hartmann", "kontakte", "Kanzlei Hartmann & Partner", "Rechtsanwältin", "s.hartmann@kanzlei.example,sophie.hartmann@example.com", "0171 5550142", "München", "1982-02-28", "", 0}, | ||
| 43 | {"Tim", "Okafor", "kontakte", "", "", "tim@verein.example", "+44 20 7946 0958", "London", "", "Verein", 6}, | ||
| 44 | {"Jürgen", "Müller", "kontakte", "Bäckerei Müller", "Meister", "juergen.mueller@baeckerei.example", "+49 89 5550170", "Augsburg", "", "", 0}, | ||
| 45 | {"Anna", "Schmidt", "familie", "", "", "anna.schmidt@example.de", "+49 160 5550133", "Potsdam", "1993-05-09", "Laufgruppe", 7}, | ||
| 46 | {"Peter", "Lange", "arbeit", "Lange Logistik", "Disposition", "peter.lange@lange-logistik.example", "+49 221 5550101", "Köln", "", "", 0}, | ||
| 47 | {"Carla", "Brandt", "kontakte", "Klinikum Süd", "Oberärztin", "carla.brandt@klinikum.example", "+49 711 5550100,+49 172 5550144", "Stuttgart", "1978-09-30", "", 8}, | ||
| 48 | {"Hannah", "Vogel", "familie", "", "", "hannah.vogel@example.org,hannah@vogel.example", "+49 176 5550188", "Dresden", "--03-21", "Elternbeirat", 0}, | ||
| 49 | {"Moritz", "von Ahlen", "arbeit", "Universität Beispiel", "Professor", "ahlen@uni.example", "+49 351 5550147", "Dresden", "", "Projekt Nordlicht", 0}, | ||
| 50 | {"Aylin", "Demir", "familie", "", "", "aylin.demir@example.com", "+49 157 5550161", "Bremen", "1996-12-01", "Laufgruppe", 9}, | ||
| 51 | {"Noah", "Richter", "familie", "", "", "noah.richter@example.com", "", "Bremen", "", "Laufgruppe,Elternbeirat", 0}, | ||
| 52 | {"Greta", "Lorenz", "arbeit", "Lorenz Consulting", "Beraterin", "greta.lorenz@example.org", "+49 163 5550155", "Frankfurt", "", "Projekt Nordlicht", 10}, | ||
| 53 | {"Matthias", "Krüger", "kontakte", "", "", "matthias.krueger@example.de,mk@example.net", "", "Rostock", "", "Team", 0}, | ||
| 54 | {"Ömer", "Yıldız", "kontakte", "Yıldız Bau", "Bauleiter", "oemer@yildiz-bau.example", "+49 30 5550199", "Berlin", "1987-06-17", "Kunden", 0}, | ||
| 55 | {"Zoë", "Ångström", "kontakte", "", "", "zoe@example.test", "+46 8 5550 1234", "Stockholm", "", "", 11}, | ||
| 56 | {"Ines", "Notiz", "local", "", "", "ines@example.test", "", "", "", "", 0}, | ||
| 57 | {"Kenji", "Ito", "kontakte", "Ito Trading", "Sales Manager", "kenji.ito@ito-trading.example", "+81 3 5550 1234", "Tokyo", "", "Kunden", 0}, | ||
| 58 | {"Ewa", "Kowalski", "kontakte", "", "", "ewa.kowalski@example.pl", "+48 601 555 012", "Wrocław", "1988-02-14", "", 12}, | ||
| 59 | {"Bastian", "Roth", "arbeit", "Beispiel GmbH", "Entwickler", "bastian.roth@beispiel.example", "+49 30 5550112", "Berlin", "", "Projekt Nordlicht", 0}, | ||
| 60 | {"Clara", "Neumann", "arbeit", "Beispiel GmbH", "Buchhaltung", "clara.neumann@beispiel.example", "+49 30 5550113", "Berlin", "", "", 0}, | ||
| 61 | {"David", "Schwarz", "kontakte", "", "", "david.schwarz@example.de", "", "Bonn", "", "Verein", 0}, | ||
| 62 | {"Emma", "Zimmermann", "familie", "", "", "emma.zimmermann@example.de", "+49 152 5550120", "Erfurt", "--10-04", "Elternbeirat", 13}, | ||
| 63 | {"Finn", "Hoffmann", "kontakte", "", "", "finn.hoffmann@example.de", "+49 152 5550121", "Kassel", "", "Team", 0}, | ||
| 64 | {"Gina", "Braun", "kontakte", "Praxis Braun", "Physiotherapeutin", "termine@praxis-braun.example", "+49 69 5550122", "Frankfurt", "", "", 0}, | ||
| 65 | {"Henrik", "Koch", "arbeit", "Koch IT", "Administrator", "henrik.koch@koch-it.example", "+49 40 5550123", "Hamburg", "", "", 0}, | ||
| 66 | {"Ida", "Schulz", "familie", "", "", "ida.schulz@example.de", "", "Weimar", "2001-01-01", "", 14}, | ||
| 67 | {"Jan", "Meyer", "kontakte", "", "", "jan.meyer@example.de", "+49 170 5550124", "Hannover", "", "Verein", 0}, | ||
| 68 | {"Anke", "Berger", "kontakte", "Stadtbibliothek", "", "anke.berger@example.de", "", "Potsdam", "", "", 0}, | ||
| 69 | {"Sven", "van der Berg", "arbeit", "Van der Berg BV", "Directeur", "sven@vanderberg.example", "+31 20 5550125", "Amsterdam", "", "", 0}, | ||
| 70 | {"Priya", "Sharma", "kontakte", "", "", "priya.sharma@example.in", "+91 22 5550 1260", "Mumbai", "", "", 15}, | ||
| 71 | {"Lukas", "Wagner", "familie", "", "", "lukas.wagner@example.de", "+49 171 5550127", "Graz", "--07-30", "", 0}, | ||
| 72 | {"Marie", "Dubois", "kontakte", "", "", "marie.dubois@example.fr", "+33 1 5550 1280", "Lyon", "", "", 0}, | ||
| 73 | {"Oliver", "Smith", "kontakte", "Smith Ltd", "CEO", "oliver@smith-ltd.example", "+44 161 5550129", "Manchester", "", "Kunden", 0}, | ||
| 74 | {"Ronja", "", "familie", "", "", "ronja@example.de", "", "", "", "", 0}, | ||
| 75 | {"", "", "kontakte", "Stadtwerke Beispielstadt", "", "service@stadtwerke.example", "+49 800 5550000", "Beispielstadt", "", "", 0}, | ||
| 76 | {"", "", "arbeit", "Muster AG", "", "info@muster.example", "+49 30 5550300", "Berlin", "", "", 0}, | ||
| 77 | {"Max", "Admin", "system", "", "", "admin@cloud.example", "", "", "", "", 0}, | ||
| 78 | {"Nina", "Nutzerin", "system", "", "", "nina@cloud.example", "", "", "", "", 0}, | ||
| 79 | {"Otto", "Oberer", "system", "", "", "otto@cloud.example", "", "", "", "", 0}, | ||
| 80 | }; | ||
| 81 | |||
| 82 | const char *kFirstNames[] = {"Alexander", "Benedikt", "Charlotte", "Dominik", "Elif", "Frieda", "Georg", "Helena", | ||
| 83 | "Ivan", "Johanna", "Karim", "Laura", "Mehmet", "Nora", "Oskar", "Paula", | ||
| 84 | "Quentin", "Rosa", "Samuel", "Tanja", "Ulrich", "Valentina", "Wilhelm", "Yasmin"}; | ||
| 85 | const char *kFamilyNames[] = {"Albrecht", "Bauer", "Conrad", "Dietrich", "Engel", "Franke", "Graf", "Haas", | ||
| 86 | "Jäger", "Kaiser", "Ludwig", "Martin", "Nowak", "Otto", "Peters", "Quast", | ||
| 87 | "Reuter", "Sommer", "Thiel", "Ulrich", "Vogt", "Winter", "Ziegler", "Özdemir"}; | ||
| 88 | const char *kCities[] = {"Berlin", "Hamburg", "München", "Köln", "Leipzig", "Mainz", "Wien", "Zürich"}; | ||
| 89 | const char *kCompanies[] = {"", "", "Beispiel GmbH", "Nordwind KG", "", "Stadtwerke", "", "Kreativbüro Süd"}; | ||
| 90 | |||
| 91 | 1740 | ContactCard cardFor(const Person &person, int index) { | |
| 92 |
1/1✓ Branch 2 → 3 taken 1740 times.
|
1740 | ContactCard card; |
| 93 |
1/1✓ Branch 8 → 9 taken 1740 times.
|
1740 | card.uid = QStringLiteral("showcase-%1").arg(index, 3, 10, QLatin1Char('0')); |
| 94 |
1/1✓ Branch 14 → 15 taken 1740 times.
|
1740 | card.name.given = QString::fromUtf8(person.given); |
| 95 |
1/1✓ Branch 18 → 19 taken 1740 times.
|
1740 | card.name.family = QString::fromUtf8(person.family); |
| 96 |
1/1✓ Branch 22 → 23 taken 1740 times.
|
1740 | card.organization = QString::fromUtf8(person.org); |
| 97 |
1/1✓ Branch 26 → 27 taken 1740 times.
|
1740 | card.title = QString::fromUtf8(person.title); |
| 98 |
6/9✓ Branch 29 → 30 taken 1740 times.
✓ Branch 31 → 32 taken 1575 times.
✓ Branch 31 → 34 taken 165 times.
✓ Branch 33 → 34 taken 690 times.
✓ Branch 33 → 35 taken 885 times.
✓ Branch 36 → 37 taken 1740 times.
✗ Branch 36 → 38 not taken.
✗ Branch 181 → 182 not taken.
✗ Branch 181 → 183 not taken.
|
1740 | const bool work = QByteArray(person.book) == "arbeit" || !card.organization.isEmpty(); |
| 99 |
2/2✓ Branch 39 → 40 taken 1740 times.
✓ Branch 43 → 44 taken 1740 times.
|
1740 | const QStringList emails = QString::fromUtf8(person.emails).split(QLatin1Char(','), Qt::SkipEmptyParts); |
| 100 |
2/2✓ Branch 68 → 46 taken 765 times.
✓ Branch 68 → 69 taken 1740 times.
|
2505 | for (int i = 0; i < emails.size(); ++i) { |
| 101 | 765 | ContactValue value; | |
| 102 | 765 | value.value = emails.at(i); | |
| 103 |
8/14✓ Branch 49 → 50 taken 330 times.
✓ Branch 49 → 53 taken 360 times.
✓ Branch 58 → 59 taken 765 times.
✓ Branch 58 → 60 taken 765 times.
✓ Branch 60 → 61 taken 435 times.
✓ Branch 60 → 62 taken 330 times.
✓ Branch 62 → 63 taken 330 times.
✓ Branch 62 → 64 taken 435 times.
✗ Branch 194 → 195 not taken.
✗ Branch 194 → 196 not taken.
✗ Branch 197 → 198 not taken.
✗ Branch 197 → 199 not taken.
✗ Branch 201 → 202 not taken.
✗ Branch 201 → 203 not taken.
|
2220 | value.types = {i == 0 && work ? QStringLiteral("work") : QStringLiteral("home")}; |
| 104 |
1/1✓ Branch 64 → 65 taken 765 times.
|
765 | card.emails.append(value); |
| 105 | 765 | } | |
| 106 |
2/2✓ Branch 70 → 71 taken 1740 times.
✓ Branch 74 → 75 taken 1740 times.
|
1740 | const QStringList phones = QString::fromUtf8(person.phones).split(QLatin1Char(','), Qt::SkipEmptyParts); |
| 107 |
2/2✓ Branch 103 → 77 taken 1335 times.
✓ Branch 103 → 104 taken 1740 times.
|
3075 | for (int i = 0; i < phones.size(); ++i) { |
| 108 | 1335 | ContactValue value; | |
| 109 | 1335 | value.value = phones.at(i); | |
| 110 |
5/9✓ Branch 82 → 83 taken 1305 times.
✓ Branch 83 → 84 taken 1020 times.
✓ Branch 83 → 87 taken 285 times.
✓ Branch 92 → 93 taken 1335 times.
✓ Branch 92 → 95 taken 1335 times.
✗ Branch 222 → 223 not taken.
✗ Branch 222 → 225 not taken.
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 232 not taken.
|
4995 | value.types = {i == 0 && phones.at(i).contains(QLatin1String(" 1")) ? QStringLiteral("cell") |
| 111 |
4/6✓ Branch 95 → 96 taken 315 times.
✓ Branch 95 → 97 taken 1020 times.
✓ Branch 97 → 98 taken 1020 times.
✓ Branch 97 → 99 taken 315 times.
✗ Branch 226 → 227 not taken.
✗ Branch 226 → 228 not taken.
|
4005 | : QStringLiteral("work")}; |
| 112 |
1/1✓ Branch 99 → 100 taken 1335 times.
|
1335 | card.phones.append(value); |
| 113 | 1335 | } | |
| 114 |
2/2✓ Branch 104 → 105 taken 1665 times.
✓ Branch 104 → 145 taken 75 times.
|
1740 | if (*person.city) { |
| 115 | 1665 | ContactAddress address; | |
| 116 |
1/1✓ Branch 109 → 110 taken 1665 times.
|
3330 | address.street = QStringLiteral("Beispielweg %1").arg(index % 40 + 1); |
| 117 |
1/1✓ Branch 118 → 119 taken 1665 times.
|
3330 | address.postalCode = QStringLiteral("%1").arg(10000 + index * 731 % 89999); |
| 118 |
1/1✓ Branch 124 → 125 taken 1665 times.
|
1665 | address.locality = QString::fromUtf8(person.city); |
| 119 |
6/12✓ Branch 136 → 137 taken 1665 times.
✓ Branch 136 → 138 taken 1665 times.
✓ Branch 138 → 139 taken 810 times.
✓ Branch 138 → 140 taken 855 times.
✓ Branch 140 → 141 taken 855 times.
✓ Branch 140 → 142 taken 810 times.
✗ Branch 263 → 264 not taken.
✗ Branch 263 → 265 not taken.
✗ Branch 266 → 267 not taken.
✗ Branch 266 → 268 not taken.
✗ Branch 270 → 271 not taken.
✗ Branch 270 → 272 not taken.
|
3330 | address.types = {work ? QStringLiteral("work") : QStringLiteral("home")}; |
| 120 |
1/1✓ Branch 142 → 143 taken 1665 times.
|
1665 | card.addresses.append(address); |
| 121 | 1665 | } | |
| 122 |
2/2✓ Branch 146 → 147 taken 1740 times.
✓ Branch 147 → 148 taken 1740 times.
|
1740 | card.birthday = PartialDate::fromIso(QString::fromUtf8(person.birthday)); |
| 123 |
2/2✓ Branch 149 → 150 taken 225 times.
✓ Branch 149 → 160 taken 1515 times.
|
1740 | if (person.photo > 0) { |
| 124 | 225 | card.photo.kind = ContactPhoto::Kind::Inline; | |
| 125 | 225 | card.photo.mimeType = QStringLiteral("image/jpeg"); | |
| 126 |
1/1✓ Branch 156 → 157 taken 225 times.
|
225 | card.photo.data = photo(person.photo); |
| 127 | } | ||
| 128 | 1740 | return card; | |
| 129 | 11265 | } | |
| 130 | |||
| 131 | 1770 | bool putRemote(ContactStore &store, qint64 bookId, const QString &path, const ContactCard &card, | |
| 132 | const QString &version) { | ||
| 133 | 1770 | StoredCard stored; | |
| 134 | 1770 | stored.bookId = bookId; | |
| 135 | 1770 | stored.uid = card.uid; | |
| 136 |
3/3✓ Branch 9 → 10 taken 1770 times.
✓ Branch 10 → 11 taken 1770 times.
✓ Branch 11 → 12 taken 1770 times.
|
3540 | stored.href = QStringLiteral("https://cloud.example") + path + card.uid + QStringLiteral(".vcf"); |
| 137 |
1/1✓ Branch 24 → 25 taken 1770 times.
|
3540 | stored.etag = QStringLiteral("\"%1\"").arg(card.uid); |
| 138 |
1/1✓ Branch 30 → 31 taken 1770 times.
|
1770 | stored.raw = VCardCodec::create(card, version); |
| 139 | 1770 | stored.baseRaw = stored.raw; | |
| 140 |
3/5✓ Branch 36 → 37 taken 1770 times.
✗ Branch 36 → 40 not taken.
✓ Branch 37 → 38 taken 1770 times.
✓ Branch 38 → 39 taken 1770 times.
✗ Branch 38 → 40 not taken.
|
3540 | return !stored.raw.isEmpty() && store.putCard(stored) > 0; |
| 141 | 1770 | } | |
| 142 | |||
| 143 | 64 | qint64 book(ContactStore &store, const QString &account, const QString &path, const QString &name, bool readOnly, | |
| 144 | const QStringList &versions = {}) { | ||
| 145 |
1/1✓ Branch 2 → 3 taken 64 times.
|
64 | const qint64 id = store.ensureBook(account, path); |
| 146 |
3/3✓ Branch 3 → 4 taken 60 times.
✓ Branch 3 → 5 taken 4 times.
✓ Branch 4 → 6 taken 60 times.
|
64 | const auto existing = id > 0 ? store.book(id) : std::nullopt; |
| 147 |
2/2✓ Branch 7 → 8 taken 4 times.
✓ Branch 7 → 9 taken 60 times.
|
64 | if (!existing) return 0; // S106-218: the caller reports the degraded store |
| 148 | 60 | AddressBookInfo info = *existing; | |
| 149 | 60 | info.displayName = name; | |
| 150 | 60 | info.readOnly = readOnly; | |
| 151 | 60 | info.fetched = true; | |
| 152 | 60 | info.supportedVersions = versions; | |
| 153 |
4/4✓ Branch 13 → 14 taken 60 times.
✓ Branch 14 → 15 taken 60 times.
✓ Branch 15 → 16 taken 60 times.
✓ Branch 16 → 17 taken 60 times.
|
60 | info.lastSync = QDateTime(QDate(2026, 10, 4), QTime(9, 0), QTimeZone::utc()); |
| 154 |
1/1✓ Branch 20 → 21 taken 60 times.
|
60 | store.updateBook(info); |
| 155 | 60 | return id; | |
| 156 | 64 | } | |
| 157 | |||
| 158 | } // namespace | ||
| 159 | |||
| 160 | 324 | QByteArray photo(int seed) { | |
| 161 | // Abstract, generated image: two overlapping circles on a gradient. | ||
| 162 |
1/1✓ Branch 2 → 3 taken 324 times.
|
324 | QImage image(128, 128, QImage::Format_RGB32); |
| 163 |
1/1✓ Branch 3 → 4 taken 324 times.
|
324 | QPainter painter(&image); |
| 164 |
1/1✓ Branch 4 → 5 taken 324 times.
|
324 | painter.setRenderHint(QPainter::Antialiasing); |
| 165 |
1/1✓ Branch 5 → 6 taken 324 times.
|
324 | QLinearGradient gradient(0, 0, 128, 128); |
| 166 |
2/2✓ Branch 6 → 7 taken 324 times.
✓ Branch 7 → 8 taken 324 times.
|
324 | gradient.setColorAt(0, QColor::fromHsv((seed * 47) % 360, 120, 230)); |
| 167 |
2/2✓ Branch 8 → 9 taken 324 times.
✓ Branch 9 → 10 taken 324 times.
|
324 | gradient.setColorAt(1, QColor::fromHsv((seed * 47 + 90) % 360, 160, 160)); |
| 168 |
3/3✓ Branch 10 → 11 taken 324 times.
✓ Branch 11 → 12 taken 324 times.
✓ Branch 12 → 13 taken 324 times.
|
324 | painter.fillRect(image.rect(), gradient); |
| 169 |
1/1✓ Branch 14 → 15 taken 324 times.
|
324 | painter.setPen(Qt::NoPen); |
| 170 |
3/3✓ Branch 15 → 16 taken 324 times.
✓ Branch 16 → 17 taken 324 times.
✓ Branch 17 → 18 taken 324 times.
|
324 | painter.setBrush(QColor::fromHsv((seed * 83) % 360, 90, 250, 170)); |
| 171 |
1/1✓ Branch 20 → 21 taken 324 times.
|
324 | painter.drawEllipse(QPointF(40 + seed % 30, 50), 36, 36); |
| 172 |
3/3✓ Branch 21 → 22 taken 324 times.
✓ Branch 22 → 23 taken 324 times.
✓ Branch 23 → 24 taken 324 times.
|
324 | painter.setBrush(QColor::fromHsv((seed * 131) % 360, 140, 120, 150)); |
| 173 |
1/1✓ Branch 26 → 27 taken 324 times.
|
324 | painter.drawEllipse(QPointF(84, 80 - seed % 20), 30, 30); |
| 174 |
1/1✓ Branch 27 → 28 taken 324 times.
|
324 | painter.end(); |
| 175 | 324 | QByteArray bytes; | |
| 176 |
1/1✓ Branch 28 → 29 taken 324 times.
|
324 | QBuffer buffer(&bytes); |
| 177 |
1/1✓ Branch 30 → 31 taken 324 times.
|
324 | buffer.open(QIODevice::WriteOnly); |
| 178 |
1/1✓ Branch 31 → 32 taken 324 times.
|
324 | image.save(&buffer, "JPG", 80); |
| 179 | 324 | return bytes; | |
| 180 | 324 | } | |
| 181 | |||
| 182 | 16 | bool seed(ContactStore &store, QString *error) { | |
| 183 | 1 | const auto fail = [error](const QString &message) { | |
| 184 |
1/2✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
|
1 | if (error) |
| 185 | 1 | *error = message; | |
| 186 | 1 | return false; | |
| 187 | 16 | }; | |
| 188 | struct Book { | ||
| 189 | qint64 id; | ||
| 190 | QString path; | ||
| 191 | QString version; | ||
| 192 | }; | ||
| 193 | const QHash<QByteArray, Book> books{ | ||
| 194 |
3/3✓ Branch 4 → 5 taken 16 times.
✓ Branch 5 → 6 taken 16 times.
✓ Branch 6 → 7 taken 16 times.
|
32 | {"kontakte", {book(store, AccountCloud, "/remote.php/dav/addressbooks/users/jens/contacts/", "Kontakte", false), |
| 195 | "/remote.php/dav/addressbooks/users/jens/contacts/", "3.0"}}, | ||
| 196 |
3/3✓ Branch 12 → 13 taken 16 times.
✓ Branch 13 → 14 taken 16 times.
✓ Branch 14 → 15 taken 16 times.
|
32 | {"arbeit", {book(store, AccountCloud, "/remote.php/dav/addressbooks/users/jens/arbeit/", "Arbeit", false), |
| 197 | "/remote.php/dav/addressbooks/users/jens/arbeit/", "3.0"}}, | ||
| 198 |
3/3✓ Branch 20 → 21 taken 16 times.
✓ Branch 21 → 22 taken 16 times.
✓ Branch 22 → 23 taken 16 times.
|
32 | {"system", {book(store, AccountCloud, "/remote.php/dav/addressbooks/system/system/system/", "Systemadressbuch", true), |
| 199 | "/remote.php/dav/addressbooks/system/system/system/", "3.0"}}, | ||
| 200 |
5/7✓ Branch 29 → 30 taken 16 times.
✓ Branch 30 → 31 taken 16 times.
✓ Branch 31 → 32 taken 16 times.
✓ Branch 44 → 45 taken 16 times.
✓ Branch 44 → 46 taken 16 times.
✗ Branch 496 → 497 not taken.
✗ Branch 496 → 498 not taken.
|
48 | {"familie", {book(store, AccountRadicale, "/jens/familie/", "Familie & Freunde", false, {"4.0"}), "/jens/familie/", |
| 201 | "4.0"}}, | ||
| 202 |
2/4✓ Branch 37 → 38 taken 64 times.
✓ Branch 37 → 39 taken 16 times.
✗ Branch 479 → 480 not taken.
✗ Branch 479 → 481 not taken.
|
80 | }; |
| 203 |
2/2✓ Branch 75 → 64 taken 61 times.
✓ Branch 75 → 76 taken 15 times.
|
76 | for (const Book &target : books) |
| 204 |
2/2✓ Branch 65 → 66 taken 1 time.
✓ Branch 65 → 73 taken 60 times.
|
62 | if (target.id <= 0) return fail(QStringLiteral("Cannot create the showcase address books")); |
| 205 | // S106-218: every error return below rolls the unit back instead of | ||
| 206 | // leaving the transaction open on the store. | ||
| 207 |
2/3✓ Branch 76 → 77 taken 15 times.
✗ Branch 77 → 78 not taken.
✓ Branch 77 → 85 taken 15 times.
|
15 | if (!store.beginTransaction()) return fail(QStringLiteral("Cannot start the showcase transaction")); |
| 208 | 15 | auto rollback = qScopeGuard([&store] { store.rollbackTransaction(); }); | |
| 209 | 15 | int index = 0; | |
| 210 | 15 | QHash<QByteArray, QStringList> groupMembers; // book:group → member UIDs | |
| 211 |
2/2✓ Branch 196 → 87 taken 690 times.
✓ Branch 196 → 197 taken 15 times.
|
705 | for (const Person &person : kPeople) { |
| 212 |
1/1✓ Branch 87 → 88 taken 690 times.
|
690 | ContactCard card = cardFor(person, index++); |
| 213 | // A company without a person is an organisation (S106-218); a vCard 3.0 | ||
| 214 | // book cannot store KIND:org, so only 4.0 books keep it. | ||
| 215 |
10/16✓ Branch 88 → 89 taken 690 times.
✓ Branch 90 → 91 taken 30 times.
✓ Branch 90 → 95 taken 660 times.
✓ Branch 91 → 92 taken 30 times.
✓ Branch 93 → 94 taken 30 times.
✗ Branch 93 → 95 not taken.
✓ Branch 96 → 97 taken 30 times.
✓ Branch 96 → 98 taken 660 times.
✓ Branch 98 → 99 taken 690 times.
✗ Branch 98 → 100 not taken.
✓ Branch 100 → 101 taken 30 times.
✓ Branch 100 → 108 taken 660 times.
✗ Branch 570 → 571 not taken.
✗ Branch 570 → 572 not taken.
✗ Branch 574 → 575 not taken.
✗ Branch 574 → 576 not taken.
|
690 | if (QByteArray(person.given).isEmpty() && QByteArray(person.family).isEmpty()) |
| 216 | 30 | card.kind = QStringLiteral("org"); | |
| 217 |
2/2✓ Branch 109 → 110 taken 690 times.
✓ Branch 113 → 114 taken 690 times.
|
690 | const QStringList groups = QString::fromUtf8(person.groups).split(QLatin1Char(','), Qt::SkipEmptyParts); |
| 218 |
1/1✓ Branch 115 → 116 taken 690 times.
|
690 | const QByteArray bookName(person.book); |
| 219 |
2/2✓ Branch 117 → 118 taken 345 times.
✓ Branch 117 → 119 taken 345 times.
|
690 | if (bookName == "kontakte") |
| 220 | 345 | card.categories = groups; // Nextcloud model (D-7) | |
| 221 |
2/2✓ Branch 132 → 121 taken 330 times.
✓ Branch 132 → 133 taken 690 times.
|
1020 | for (const QString &group : groups) |
| 222 |
5/5✓ Branch 122 → 123 taken 330 times.
✓ Branch 123 → 124 taken 330 times.
✓ Branch 124 → 125 taken 330 times.
✓ Branch 125 → 126 taken 330 times.
✓ Branch 126 → 127 taken 330 times.
|
330 | groupMembers[bookName + ':' + group.toUtf8()].append(card.uid); |
| 223 |
2/2✓ Branch 135 → 136 taken 15 times.
✓ Branch 135 → 149 taken 675 times.
|
690 | if (card.uid == QLatin1String("showcase-000")) { |
| 224 | 15 | card.note = QStringLiteral( | |
| 225 | "Kennengelernt auf der Messe 2025.\n\nBevorzugt Termine am Vormittag, nie montags. " | ||
| 226 | "Rückfragen zum Angebot über das Projektpostfach.\n\n— Zweitwohnsitz in Potsdam, " | ||
| 227 | "Assistenz: Clara Neumann."); | ||
| 228 | 15 | card.nickname = QStringLiteral("Mara"); | |
| 229 | } | ||
| 230 |
2/2✓ Branch 150 → 151 taken 15 times.
✓ Branch 150 → 161 taken 675 times.
|
690 | if (bookName == "local") { |
| 231 |
2/3✓ Branch 151 → 152 taken 15 times.
✗ Branch 152 → 153 not taken.
✓ Branch 152 → 160 taken 15 times.
|
15 | if (store.addLocalCard(card) <= 0) |
| 232 | ✗ | return fail(QStringLiteral("Cannot store a local showcase contact")); | |
| 233 | 15 | continue; | |
| 234 | } | ||
| 235 | 675 | const Book target = books.value(bookName); | |
| 236 |
2/3✓ Branch 162 → 163 taken 675 times.
✗ Branch 163 → 164 not taken.
✓ Branch 163 → 174 taken 675 times.
|
675 | if (!putRemote(store, target.id, target.path, card, target.version)) |
| 237 | ✗ | return fail(QStringLiteral("Cannot store showcase contact %1").arg(card.uid)); | |
| 238 | 720 | } | |
| 239 | // Generated people fill the list to about 120 entries. | ||
| 240 |
2/2✓ Branch 300 → 198 taken 1050 times.
✓ Branch 300 → 301 taken 15 times.
|
1065 | for (int i = 0; i < 70; ++i) { |
| 241 | // Every first/family pair is unique (the second term shifts the family | ||
| 242 | // name once per round of first names). | ||
| 243 | 1050 | Person person{kFirstNames[i % 24], kFamilyNames[(i * 7 + i / 24) % 24], i % 3 == 0 ? "familie" : "kontakte", | |
| 244 |
4/4✓ Branch 198 → 199 taken 360 times.
✓ Branch 198 → 200 taken 690 times.
✓ Branch 201 → 202 taken 270 times.
✓ Branch 201 → 203 taken 780 times.
|
2100 | kCompanies[i % 8], "", "", i % 4 == 0 ? "" : "+49 151 5550", kCities[i % 8], "", "", 0}; |
| 245 |
1/1✓ Branch 204 → 205 taken 1050 times.
|
1050 | ContactCard card = cardFor(person, index++); |
| 246 | 1050 | ContactValue email; | |
| 247 | 2100 | email.value = QStringLiteral("%1.%2@example.%3") | |
| 248 |
4/4✓ Branch 231 → 232 taken 1050 times.
✓ Branch 233 → 234 taken 1050 times.
✓ Branch 234 → 235 taken 1050 times.
✓ Branch 235 → 236 taken 1050 times.
|
2100 | .arg(QString::fromUtf8(person.given).toLower(), |
| 249 |
3/3✓ Branch 216 → 217 taken 1050 times.
✓ Branch 217 → 218 taken 1050 times.
✓ Branch 224 → 225 taken 1050 times.
|
4200 | QString::fromUtf8(person.family).toLower().replace(QStringLiteral("ä"), QStringLiteral("ae")) |
| 250 | 3150 | .replace(QStringLiteral("ö"), QStringLiteral("oe")), | |
| 251 |
6/10✓ Branch 208 → 209 taken 525 times.
✓ Branch 208 → 212 taken 525 times.
✓ Branch 251 → 252 taken 525 times.
✓ Branch 251 → 253 taken 525 times.
✓ Branch 253 → 254 taken 525 times.
✓ Branch 253 → 255 taken 525 times.
✗ Branch 652 → 653 not taken.
✗ Branch 652 → 654 not taken.
✗ Branch 656 → 657 not taken.
✗ Branch 656 → 658 not taken.
|
4200 | i % 2 ? QStringLiteral("de") : QStringLiteral("org")); |
| 252 |
2/2✓ Branch 257 → 258 taken 840 times.
✓ Branch 257 → 264 taken 210 times.
|
1050 | if (i % 5 != 0) |
| 253 |
2/4✓ Branch 261 → 262 taken 840 times.
✓ Branch 261 → 263 taken 840 times.
✗ Branch 669 → 670 not taken.
✗ Branch 669 → 671 not taken.
|
1680 | card.emails = {email}; |
| 254 |
2/2✓ Branch 265 → 266 taken 780 times.
✓ Branch 265 → 271 taken 270 times.
|
1050 | if (!card.phones.isEmpty()) |
| 255 |
3/3✓ Branch 266 → 267 taken 780 times.
✓ Branch 267 → 268 taken 780 times.
✓ Branch 268 → 269 taken 780 times.
|
780 | card.phones.first().value += QString::number(200 + i); |
| 256 |
1/1✓ Branch 271 → 272 taken 1050 times.
|
1050 | const Book target = books.value(person.book); |
| 257 |
2/3✓ Branch 274 → 275 taken 1050 times.
✗ Branch 275 → 276 not taken.
✓ Branch 275 → 286 taken 1050 times.
|
1050 | if (!putRemote(store, target.id, target.path, card, target.version)) |
| 258 | ✗ | return fail(QStringLiteral("Cannot store generated contact %1").arg(i)); | |
| 259 | 1050 | } | |
| 260 | // Group cards: Apple model in "Arbeit", vCard 4 lists in "Familie & Freunde". | ||
| 261 |
2/2✓ Branch 389 → 302 taken 105 times.
✓ Branch 389 → 390 taken 15 times.
|
120 | for (auto it = groupMembers.cbegin(); it != groupMembers.cend(); ++it) { |
| 262 |
1/1✓ Branch 305 → 306 taken 105 times.
|
105 | const QByteArray bookName = it.key().left(it.key().indexOf(':')); |
| 263 |
6/6✓ Branch 307 → 308 taken 90 times.
✓ Branch 307 → 311 taken 15 times.
✓ Branch 309 → 310 taken 60 times.
✓ Branch 309 → 311 taken 30 times.
✓ Branch 312 → 313 taken 60 times.
✓ Branch 312 → 314 taken 45 times.
|
105 | if (bookName != "arbeit" && bookName != "familie") |
| 264 | 60 | continue; | |
| 265 |
1/1✓ Branch 314 → 315 taken 45 times.
|
45 | ContactCard group; |
| 266 |
3/3✓ Branch 320 → 321 taken 45 times.
✓ Branch 325 → 326 taken 45 times.
✓ Branch 326 → 327 taken 45 times.
|
90 | group.uid = QStringLiteral("showcase-group-%1").arg(QString::fromUtf8(it.key()).replace(QLatin1Char(':'), QLatin1Char('-'))); |
| 267 |
2/2✓ Branch 335 → 336 taken 45 times.
✓ Branch 336 → 337 taken 45 times.
|
45 | group.formattedName = QString::fromUtf8(it.key().mid(it.key().indexOf(':') + 1)); |
| 268 | 45 | group.kind = QStringLiteral("group"); | |
| 269 |
2/2✓ Branch 360 → 349 taken 135 times.
✓ Branch 360 → 361 taken 45 times.
|
180 | for (const QString &uid : it.value()) |
| 270 |
2/2✓ Branch 353 → 354 taken 135 times.
✓ Branch 354 → 355 taken 135 times.
|
135 | group.members.append(QStringLiteral("urn:uuid:") + uid); |
| 271 | 45 | const Book target = books.value(bookName); | |
| 272 |
2/3✓ Branch 362 → 363 taken 45 times.
✗ Branch 363 → 364 not taken.
✓ Branch 363 → 371 taken 45 times.
|
45 | if (!putRemote(store, target.id, target.path, group, target.version)) |
| 273 | ✗ | return fail(QStringLiteral("Cannot store a showcase group")); | |
| 274 | 105 | } | |
| 275 |
2/3✓ Branch 390 → 391 taken 15 times.
✗ Branch 391 → 392 not taken.
✓ Branch 391 → 399 taken 15 times.
|
15 | if (!store.commitTransaction()) return fail(QStringLiteral("Cannot commit the showcase contacts")); |
| 276 | 15 | rollback.dismiss(); | |
| 277 | // Collected addresses and usage (frequently contacted, completion ranking). | ||
| 278 |
2/2✓ Branch 400 → 401 taken 15 times.
✓ Branch 401 → 402 taken 15 times.
|
15 | CollectedAddressStore collected(store.database()); |
| 279 |
4/4✓ Branch 403 → 404 taken 15 times.
✓ Branch 404 → 405 taken 15 times.
✓ Branch 405 → 406 taken 15 times.
✓ Branch 406 → 407 taken 15 times.
|
15 | const QDateTime now(QDate(2026, 10, 4), QTime(9, 0), QTimeZone::utc()); |
| 280 |
2/2✓ Branch 434 → 409 taken 90 times.
✓ Branch 434 → 435 taken 15 times.
|
105 | for (int round = 0; round < 6; ++round) |
| 281 |
3/5✓ Branch 423 → 424 taken 90 times.
✓ Branch 426 → 427 taken 180 times.
✓ Branch 426 → 428 taken 90 times.
✗ Branch 745 → 746 not taken.
✗ Branch 745 → 747 not taken.
|
360 | collected.recordSent({{QStringLiteral("Mara Klein"), QStringLiteral("mara.klein@beispiel.example")}, |
| 282 | 90 | {QStringLiteral("Jonas Becker"), QStringLiteral("jonas.becker@example.net")}}, | |
| 283 |
1/1✓ Branch 409 → 410 taken 90 times.
|
180 | true, now.addDays(-round)); |
| 284 |
3/5✓ Branch 458 → 459 taken 15 times.
✓ Branch 461 → 462 taken 60 times.
✓ Branch 461 → 463 taken 15 times.
✗ Branch 779 → 780 not taken.
✗ Branch 779 → 781 not taken.
|
90 | collected.recordSent({{QStringLiteral("Paketdienst"), QStringLiteral("versand@paket.example")}, |
| 285 | 15 | {QString(), QStringLiteral("rechnung@shop.example")}, | |
| 286 | 15 | {QStringLiteral("Hausverwaltung Lindner"), QStringLiteral("info@hv-lindner.example")}, | |
| 287 | 15 | {QStringLiteral("Lena Wolf"), QStringLiteral("lena@studio-nord.example")}}, | |
| 288 |
1/1✓ Branch 435 → 436 taken 15 times.
|
30 | true, now.addDays(-3)); |
| 289 | 15 | return true; | |
| 290 | 1586 | } | |
| 291 | |||
| 292 | } // namespace ContactShowcase | ||
| 293 |