MailJDTourDownloadDocsQualityTestsCoverage

Which source lines and branches the tests execute. Lines 91.5 %, branches 75.0 % (minimum 85 % and 72 %). main @ 399ffe3d · 21 October 2026 · pipeline 7238.

GCC Code Coverage Report


Directory: src/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 90.6% 116 / 0 / 128
Functions: 100.0% 9 / 0 / 9
Branches: 63.6% 194 / 0 / 305

presentation/QuickComposeBackendScheduling.cpp
Line Branch Exec Source
1 // Sprint 108 S108.8.8/8.9 (D-23, D-24 client mode): meetings the user
2 // organizes, seen from the calendar — the attendees of a stored event,
3 // the recipient field of the event editor, and the iMIP mails when an
4 // organized event changes (REQUEST with SEQUENCE+1 to the attendees,
5 // CANCEL to removed ones) or is deleted (CANCEL to everyone). The mails go
6 // through the outbox like every message; the stored event is patched
7 // (attendees, SEQUENCE) and keeps everything else.
8 #include "QuickComposeBackend.h"
9 #include "ComposeLog.h"
10 #include "RecipientChipModel.h"
11
12 #include "app/core/AccountSession.h"
13 #include "app/core/CalendarSyncCoordinator.h"
14 #include "app/core/CalendarSyncStatus.h"
15 #include "app/core/MailSessionCore.h"
16 #include "data/CalendarModels.h"
17 #include "data/ICalendar.h"
18 #include "data/ImipInvitation.h"
19 #include "service/Rfc2822Builder.h"
20
21 #include <QSettings>
22
23 namespace {
24
25 4 QList<Imip::Attendee> attendeesFrom(const QVariantList &list) {
26 4 QList<Imip::Attendee> out;
27
2/2
✓ Branch 57 → 4 taken 7 times.
✓ Branch 57 → 58 taken 4 times.
11 for (const QVariant &value : list) {
28
1/1
✓ Branch 5 → 6 taken 7 times.
7 const QVariantMap map = value.toMap();
29 7 Imip::Attendee attendee;
30
4/4
✓ Branch 10 → 11 taken 7 times.
✓ Branch 11 → 12 taken 7 times.
✓ Branch 12 → 13 taken 7 times.
✓ Branch 13 → 14 taken 7 times.
14 attendee.email = map.value(QStringLiteral("email")).toString().trimmed().toLower();
31
3/3
✓ Branch 26 → 27 taken 7 times.
✓ Branch 27 → 28 taken 7 times.
✓ Branch 28 → 29 taken 7 times.
14 attendee.name = map.value(QStringLiteral("name")).toString().trimmed();
32
2/2
✓ Branch 40 → 41 taken 7 times.
✓ Branch 41 → 42 taken 7 times.
14 attendee.role = map.value(QStringLiteral("role")).toString();
33
3/4
✓ Branch 50 → 51 taken 7 times.
✓ Branch 51 → 52 taken 7 times.
✗ Branch 51 → 53 not taken.
✓ Branch 52 → 53 taken 7 times.
7 if (attendee.email.contains(QLatin1Char('@'))) out.append(attendee);
34 7 }
35 4 return out;
36 ✗ }
37
38 10 QStringList addressesOf(const QList<Imip::Attendee> &attendees) {
39 10 QStringList out;
40
3/3
✓ Branch 5 → 6 taken 16 times.
✓ Branch 8 → 4 taken 16 times.
✓ Branch 8 → 9 taken 10 times.
26 for (const Imip::Attendee &attendee : attendees) out.append(attendee.email);
41 10 return out;
42 ✗ }
43
44 } // namespace
45
46 67 QString QuickComposeBackend::invitationDeliveryMode(const QString &calendarAccount, const QString &organizer) const {
47
3/3
✓ Branch 2 → 3 taken 67 times.
✓ Branch 11 → 12 taken 67 times.
✓ Branch 12 → 13 taken 67 times.
201 const QString override = QSettings().value(QStringLiteral("calendar/imipReplies"), QStringLiteral("auto")).toString();
48
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 27 taken 67 times.
67 if (calendarAccount.isEmpty()) return QStringLiteral("client");
49
1/1
✓ Branch 31 → 32 taken 67 times.
67 return Imip::deliveryMode(override, CalendarSyncStatus::serverScheduling(calendarAccount),
50 CalendarSyncStatus::autoSchedule(calendarAccount),
51
5/5
✓ Branch 27 → 28 taken 67 times.
✓ Branch 28 → 29 taken 67 times.
✓ Branch 29 → 30 taken 67 times.
✓ Branch 30 → 31 taken 67 times.
✓ Branch 32 → 33 taken 67 times.
134 CalendarSyncStatus::schedulingAddresses(calendarAccount), organizer.trimmed().toLower());
52 67 }
53
54 58 QVariantMap QuickComposeBackend::invitationDelivery(const QString &calendarAccount, const QString &organizer) const {
55
1/1
✓ Branch 2 → 3 taken 58 times.
58 const QString mode = invitationDeliveryMode(calendarAccount, organizer);
56 58 QString note;
57
2/2
✓ Branch 5 → 6 taken 40 times.
✓ Branch 5 → 10 taken 18 times.
58 if (mode == QLatin1String("server"))
58
1/1
✓ Branch 6 → 7 taken 40 times.
40 note = tr("Your server sends the invitation — your text becomes its description.");
59
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 24 taken 18 times.
18 else if (mode == QLatin1String("fallback"))
60 ✗ note = tr("Your server can only invite as %1; MailJD sends this invitation.")
61 ✗ .arg(CalendarSyncStatus::schedulingAddresses(calendarAccount).value(0));
62 else
63
1/1
✓ Branch 24 → 25 taken 18 times.
18 note = tr("To are invited, Cc are optional. Your text becomes the description; MailJD sends the invitation and saves the appointment when it leaves.");
64
2/4
✓ Branch 38 → 39 taken 116 times.
✓ Branch 38 → 40 taken 58 times.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
348 return {{QStringLiteral("mode"), mode}, {QStringLiteral("note"), note}};
65 232 }
66
67 56 QStringList QuickComposeBackend::ownAddresses() const {
68 56 QStringList out;
69
5/5
✓ Branch 6 → 7 taken 60 times.
✓ Branch 7 → 8 taken 60 times.
✓ Branch 8 → 9 taken 60 times.
✓ Branch 13 → 5 taken 60 times.
✓ Branch 13 → 14 taken 56 times.
116 for (const Identity &identity : m_identityStore.identities()) out.append(identity.email.trimmed().toLower());
70 56 return out;
71 ✗ }
72
73 49 QVariantMap QuickComposeBackend::organizedEvent(const QString &uid, const QString &accountId,
74 const QString &calendarPath) const {
75 49 auto *sync = m_session.calendarSync();
76
2/3
✓ Branch 3 → 4 taken 49 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 6 taken 49 times.
49 const auto event = sync ? sync->eventFor(uid, accountId, calendarPath) : std::nullopt;
77
1/6
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 19 taken 49 times.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 157 → 158 not taken.
✗ Branch 157 → 159 not taken.
49 if (!event) return {{QStringLiteral("organized"), false}};
78
2/2
✓ Branch 19 → 20 taken 49 times.
✓ Branch 21 → 22 taken 49 times.
49 const auto organized = Imip::organizedBy(event->icalRaw, ownAddresses());
79 // Someone else's meeting: its attendees are not ours to change.
80
7/13
✓ Branch 24 → 25 taken 39 times.
✓ Branch 24 → 36 taken 10 times.
✓ Branch 29 → 30 taken 39 times.
✓ Branch 43 → 44 taken 39 times.
✓ Branch 43 → 45 taken 10 times.
✓ Branch 45 → 46 taken 39 times.
✓ Branch 45 → 47 taken 10 times.
✗ Branch 184 → 185 not taken.
✗ Branch 184 → 186 not taken.
✗ Branch 188 → 189 not taken.
✗ Branch 188 → 190 not taken.
✗ Branch 192 → 193 not taken.
✗ Branch 192 → 194 not taken.
176 const bool foreign = !organized && ICal::parseFirst(event->icalRaw, QStringLiteral("VEVENT"))
81
9/13
✓ Branch 33 → 34 taken 39 times.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 34 → 36 taken 38 times.
✓ Branch 37 → 38 taken 39 times.
✓ Branch 37 → 39 taken 10 times.
✓ Branch 39 → 40 taken 39 times.
✓ Branch 39 → 41 taken 10 times.
✓ Branch 41 → 42 taken 39 times.
✓ Branch 41 → 43 taken 10 times.
✗ Branch 176 → 177 not taken.
✗ Branch 176 → 178 not taken.
✗ Branch 180 → 181 not taken.
✗ Branch 180 → 182 not taken.
88 .hasProperty(QStringLiteral("ORGANIZER"));
82 49 QVariantList attendees;
83
2/2
✓ Branch 48 → 49 taken 10 times.
✓ Branch 48 → 105 taken 39 times.
49 if (organized)
84
2/2
✓ Branch 103 → 52 taken 24 times.
✓ Branch 103 → 104 taken 10 times.
34 for (const Imip::Attendee &attendee : organized->attendees)
85
1/1
✓ Branch 85 → 86 taken 24 times.
72 attendees.append(QVariantMap{{QStringLiteral("email"), attendee.email},
86 48 {QStringLiteral("name"), attendee.name},
87 48 {QStringLiteral("partstat"), attendee.partstat},
88 48 {QStringLiteral("role"), attendee.role},
89 // RFC 6638: 1.x/2.x delivered, 3.x/5.x not.
90
2/3
✓ Branch 74 → 75 taken 24 times.
✓ Branch 75 → 76 taken 24 times.
✗ Branch 75 → 80 not taken.
72 {QStringLiteral("undelivered"), attendee.scheduleStatus.startsWith(QLatin1Char('3')) ||
91
4/7
✓ Branch 78 → 79 taken 24 times.
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 81 taken 24 times.
✓ Branch 89 → 90 taken 120 times.
✓ Branch 89 → 91 taken 24 times.
✗ Branch 201 → 202 not taken.
✗ Branch 201 → 203 not taken.
192 attendee.scheduleStatus.startsWith(QLatin1Char('5'))}});
92 98 return {{QStringLiteral("organized"), organized.has_value()},
93 98 {QStringLiteral("foreign"), foreign},
94
2/2
✓ Branch 118 → 119 taken 10 times.
✓ Branch 118 → 121 taken 39 times.
98 {QStringLiteral("organizerEmail"), organized ? organized->organizerEmail : QString()},
95
2/2
✓ Branch 127 → 128 taken 10 times.
✓ Branch 127 → 130 taken 39 times.
98 {QStringLiteral("sequence"), organized ? organized->sequence : 0},
96
2/4
✓ Branch 138 → 139 taken 245 times.
✓ Branch 138 → 140 taken 49 times.
✗ Branch 249 → 250 not taken.
✗ Branch 249 → 251 not taken.
343 {QStringLiteral("attendees"), attendees}};
97 487 }
98
99 123 QObject *QuickComposeBackend::newRecipientField(QObject *owner, const QString &label) {
100 // Owned by the QML item that asked: it goes with that item.
101
2/5
✓ Branch 3 → 4 taken 123 times.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 123 times.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
246 return new RecipientChipModel(label, owner);
102 }
103
104 7 bool QuickComposeBackend::sendMeetingChange(const QString &uid, const QString &accountId, const QString &calendarPath,
105 const QString &kind, const QVariantList &attendees) {
106 7 auto *sync = m_session.calendarSync();
107
2/3
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 6 taken 7 times.
7 const auto stored = sync ? sync->eventFor(uid, accountId, calendarPath) : std::nullopt;
108
4/8
✓ Branch 7 → 8 taken 7 times.
✗ Branch 7 → 11 not taken.
✓ Branch 8 → 9 taken 7 times.
✓ Branch 10 → 12 taken 7 times.
✓ Branch 12 → 13 taken 7 times.
✗ Branch 12 → 14 not taken.
✗ Branch 202 → 203 not taken.
✗ Branch 202 → 204 not taken.
7 const auto organized = stored ? Imip::organizedBy(stored->icalRaw, ownAddresses()) : std::nullopt;
109
5/6
✓ Branch 15 → 16 taken 7 times.
✗ Branch 15 → 18 not taken.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 19 taken 6 times.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 34 taken 6 times.
7 if (!stored || !organized) {
110
7/7
✓ Branch 21 → 22 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 26 → 27 taken 1 time.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
✓ Branch 32 → 23 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
2 qCWarning(lcCompose) << "meeting change for an event the user does not organize" << uid << kind;
111 1 return false;
112 }
113 6 const bool cancel = kind == QLatin1String("cancel");
114 // D-24: with server scheduling the server tells the attendees about the
115 // stored change (a PUT, or the DELETE of a cancelled meeting).
116
1/1
✓ Branch 38 → 39 taken 6 times.
6 const bool server = invitationDeliveryMode(accountId, organized->organizerEmail) == QLatin1String("server");
117
1/2
✗ Branch 43 → 44 not taken.
✓ Branch 43 → 68 taken 6 times.
6 if (kind == QLatin1String("mail")) {
118 // *Send by mail instead* for attendees the server could not reach.
119 ✗ Imip::Meeting meeting = Imip::meetingOf(*stored, *organized);
120 ✗ const QList<Imip::Attendee> to = attendeesFrom(attendees);
121 ✗ return !to.isEmpty() && sendMeetingMail(meeting, QStringLiteral("REQUEST"), to);
122 ✗ }
123
3/4
✓ Branch 70 → 71 taken 4 times.
✓ Branch 70 → 73 taken 2 times.
✓ Branch 71 → 72 taken 4 times.
✗ Branch 71 → 73 not taken.
6 const bool mail = kind != QLatin1String("silent") && !server;
124
3/3
✓ Branch 74 → 75 taken 2 times.
✓ Branch 74 → 77 taken 4 times.
✓ Branch 77 → 78 taken 4 times.
6 const QList<Imip::Attendee> next = cancel ? organized->attendees : attendeesFrom(attendees);
125
3/3
✓ Branch 78 → 79 taken 2 times.
✓ Branch 78 → 80 taken 4 times.
✓ Branch 81 → 82 taken 4 times.
6 const QList<Imip::Attendee> removed = cancel ? QList<Imip::Attendee>{} : Imip::removedAttendees(organized->attendees, next);
126
2/2
✓ Branch 85 → 86 taken 4 times.
✓ Branch 85 → 87 taken 2 times.
6 const int sequence = organized->sequence + (kind != QLatin1String("silent") ? 1 : 0);
127 // The stored copy first: attendees and SEQUENCE (a cancelled meeting is
128 // deleted by the caller after this).
129
2/2
✓ Branch 88 → 89 taken 4 times.
✓ Branch 88 → 114 taken 2 times.
6 if (!cancel) {
130 4 CalendarEvent updated = *stored;
131
1/1
✓ Branch 94 → 95 taken 4 times.
8 updated.icalRaw = Imip::withMeetingAttendees(stored->icalRaw, organized->organizerEmail, organized->organizerName,
132 4 next, sequence, server);
133
4/7
✓ Branch 98 → 99 taken 4 times.
✗ Branch 98 → 101 not taken.
✓ Branch 99 → 100 taken 4 times.
✗ Branch 100 → 101 not taken.
✓ Branch 100 → 102 taken 4 times.
✗ Branch 103 → 104 not taken.
✓ Branch 103 → 108 taken 4 times.
4 if (updated.icalRaw.isEmpty() || !sync->saveEvent(updated, false)) {
134 ✗ m_deps.reportError(tr("The appointment could not be saved."));
135 ✗ return false;
136 }
137 4 }
138
2/2
✓ Branch 114 → 115 taken 2 times.
✓ Branch 114 → 116 taken 4 times.
6 if (!mail) return true;
139
1/1
✓ Branch 118 → 119 taken 4 times.
4 Imip::Meeting meeting = Imip::meetingOf(*stored, *organized);
140 4 meeting.sequence = sequence;
141 4 bool sent = true;
142
5/6
✓ Branch 119 → 120 taken 2 times.
✓ Branch 119 → 124 taken 2 times.
✓ Branch 122 → 123 taken 2 times.
✗ Branch 122 → 124 not taken.
✓ Branch 125 → 126 taken 2 times.
✓ Branch 125 → 136 taken 2 times.
4 if (cancel && !organized->attendees.isEmpty()) {
143
1/1
✓ Branch 131 → 132 taken 2 times.
4 sent = sendMeetingMail(meeting, QStringLiteral("CANCEL"), organized->attendees);
144
1/2
✓ Branch 136 → 137 taken 2 times.
✗ Branch 136 → 173 not taken.
2 } else if (!cancel) {
145 2 meeting.attendees = next;
146 // "removed": the others get the invitation the composer writes next.
147
4/7
✓ Branch 139 → 140 taken 2 times.
✗ Branch 139 → 144 not taken.
✓ Branch 142 → 143 taken 2 times.
✗ Branch 142 → 144 not taken.
✓ Branch 145 → 146 taken 2 times.
✗ Branch 145 → 155 not taken.
✓ Branch 150 → 151 taken 2 times.
4 if (!next.isEmpty() && kind != QLatin1String("removed")) sent = sendMeetingMail(meeting, QStringLiteral("REQUEST"), next);
148
8/19
✓ Branch 156 → 157 taken 1 time.
✓ Branch 156 → 173 taken 1 time.
✓ Branch 161 → 162 taken 1 time.
✓ Branch 162 → 163 taken 1 time.
✗ Branch 162 → 165 not taken.
✓ Branch 163 → 164 taken 1 time.
✗ Branch 163 → 165 not taken.
✓ Branch 166 → 167 taken 1 time.
✗ Branch 166 → 168 not taken.
✓ Branch 168 → 169 taken 1 time.
✗ Branch 168 → 170 not taken.
✓ Branch 170 → 171 taken 1 time.
✗ Branch 170 → 172 not taken.
✗ Branch 255 → 256 not taken.
✗ Branch 255 → 257 not taken.
✗ Branch 259 → 260 not taken.
✗ Branch 259 → 261 not taken.
✗ Branch 263 → 264 not taken.
✗ Branch 263 → 265 not taken.
3 if (!removed.isEmpty()) sent = sendMeetingMail(meeting, QStringLiteral("CANCEL"), removed) && sent;
149 }
150
2/11
✓ Branch 173 → 174 taken 4 times.
✗ Branch 177 → 178 not taken.
✗ Branch 178 → 179 not taken.
✗ Branch 179 → 180 not taken.
✗ Branch 180 → 181 not taken.
✗ Branch 181 → 182 not taken.
✗ Branch 183 → 184 not taken.
✗ Branch 184 → 185 not taken.
✗ Branch 186 → 187 not taken.
✗ Branch 194 → 175 not taken.
✓ Branch 194 → 195 taken 4 times.
4 qCInfo(lcCompose) << "meeting change" << kind << uid << "attendees" << next.size() << "removed" << removed.size()
151 ✗ << "sequence" << sequence << "queued" << sent;
152 4 return sent;
153 7 }
154
155 5 bool QuickComposeBackend::sendMeetingMail(Imip::Meeting meeting, const QString &method,
156 const QList<Imip::Attendee> &to) {
157
2/2
✓ Branch 4 → 5 taken 3 times.
✓ Branch 4 → 6 taken 2 times.
5 meeting.attendees = method == QLatin1String("CANCEL") ? to : meeting.attendees;
158
2/2
✓ Branch 8 → 9 taken 5 times.
✓ Branch 9 → 10 taken 5 times.
5 const QByteArray calendar = Imip::buildRequest(meeting, method);
159
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 5 times.
5 if (calendar.isEmpty()) return false;
160 5 std::optional<Identity> identity;
161
2/2
✓ Branch 27 → 17 taken 5 times.
✓ Branch 27 → 28 taken 5 times.
10 for (const Identity &candidate : m_identityStore.identities())
162
3/4
✓ Branch 18 → 19 taken 5 times.
✓ Branch 19 → 20 taken 5 times.
✓ Branch 23 → 24 taken 5 times.
✗ Branch 23 → 25 not taken.
5 if (candidate.email.trimmed().toLower() == meeting.organizerEmail) identity = candidate;
163
2/4
✓ Branch 29 → 30 taken 5 times.
✗ Branch 29 → 33 not taken.
✓ Branch 32 → 36 taken 5 times.
✗ Branch 35 → 36 not taken.
5 const auto account = identity ? m_session.accounts()->configuration(identity->accountId) : m_session.accounts()->primary();
164
1/2
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 5 times.
5 if (!account) return false;
165 5 Rfc2822Builder builder;
166
3/5
✓ Branch 41 → 42 taken 5 times.
✗ Branch 41 → 44 not taken.
✓ Branch 47 → 48 taken 5 times.
✗ Branch 47 → 50 not taken.
✓ Branch 52 → 53 taken 5 times.
5 builder.setFrom(identity ? identity->name : account->name, identity ? identity->email : account->email);
167
2/2
✓ Branch 53 → 54 taken 5 times.
✓ Branch 54 → 55 taken 5 times.
5 builder.setTo(addressesOf(to));
168 5 const bool cancel = method == QLatin1String("CANCEL");
169
6/6
✓ Branch 58 → 59 taken 3 times.
✓ Branch 58 → 60 taken 2 times.
✓ Branch 59 → 61 taken 3 times.
✓ Branch 60 → 61 taken 2 times.
✓ Branch 62 → 63 taken 5 times.
✓ Branch 63 → 64 taken 5 times.
10 builder.setSubject((cancel ? tr("Cancelled: %1") : tr("Updated invitation: %1")).arg(meeting.summary));
170
1/3
✓ Branch 67 → 68 taken 3 times.
✗ Branch 137 → 138 not taken.
✗ Branch 137 → 139 not taken.
6 QString body = cancel ? tr("“%1” has been cancelled.").arg(meeting.summary)
171
9/11
✓ Branch 66 → 67 taken 3 times.
✓ Branch 66 → 70 taken 2 times.
✓ Branch 69 → 73 taken 3 times.
✓ Branch 70 → 71 taken 2 times.
✓ Branch 72 → 73 taken 2 times.
✓ Branch 73 → 74 taken 2 times.
✓ Branch 73 → 75 taken 3 times.
✓ Branch 75 → 76 taken 3 times.
✓ Branch 75 → 77 taken 2 times.
✗ Branch 132 → 133 not taken.
✗ Branch 132 → 134 not taken.
8 : tr("“%1” has changed. The invitation below is up to date.").arg(meeting.summary);
172
1/1
✓ Branch 77 → 78 taken 5 times.
5 builder.setBodyText(body);
173
1/1
✓ Branch 78 → 79 taken 5 times.
5 builder.setCalendarPart(calendar, method);
174
1/1
✓ Branch 80 → 81 taken 5 times.
5 builder.setMessageId();
175
1/1
✓ Branch 82 → 83 taken 5 times.
5 const QByteArray bytes = builder.build(Rfc2822Builder::BccHeader::Omit);
176
2/2
✓ Branch 95 → 96 taken 5 times.
✓ Branch 96 → 97 taken 5 times.
10 return enqueuePrepared(addressesOf(to), bytes,
177
4/6
✓ Branch 88 → 89 taken 3 times.
✓ Branch 88 → 92 taken 2 times.
✓ Branch 89 → 90 taken 3 times.
✓ Branch 91 → 95 taken 3 times.
✗ Branch 155 → 156 not taken.
✗ Branch 155 → 157 not taken.
15 cancel ? tr("Cancellation sent for “%1”.").arg(meeting.summary)
178
6/8
✓ Branch 92 → 93 taken 2 times.
✓ Branch 94 → 95 taken 2 times.
✓ Branch 100 → 101 taken 2 times.
✓ Branch 100 → 102 taken 3 times.
✓ Branch 102 → 103 taken 3 times.
✓ Branch 102 → 104 taken 2 times.
✗ Branch 150 → 151 not taken.
✗ Branch 150 → 152 not taken.
9 : tr("Update sent for “%1”.").arg(meeting.summary),
179
1/2
✓ Branch 84 → 85 taken 5 times.
✗ Branch 84 → 87 not taken.
15 identity ? identity->id : QString());
180 5 }
181