presentation/QuickInvitation.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "QuickInvitation.h" | ||
| 2 | |||
| 3 | #include "CalendarEventDetails.h" | ||
| 4 | #include "CalendarLayout.h" | ||
| 5 | #include "app/core/AccountSession.h" | ||
| 6 | #include "app/core/CalendarSyncCoordinator.h" | ||
| 7 | #include "app/core/CalendarSyncStatus.h" | ||
| 8 | #include "app/core/MailSessionCore.h" | ||
| 9 | #include "data/CalendarStore.h" | ||
| 10 | #include "data/ICalendar.h" | ||
| 11 | #include "data/MailCache.h" | ||
| 12 | #include "data/RecurrenceExpansion.h" | ||
| 13 | #include "service/Rfc2822Builder.h" | ||
| 14 | #include "util/SecurityLog.h" | ||
| 15 | #include "util/HostMatch.h" | ||
| 16 | |||
| 17 | #include <QLocale> | ||
| 18 | #include <QLoggingCategory> | ||
| 19 | #include <QSettings> | ||
| 20 | #include <QTimeZone> | ||
| 21 | |||
| 22 |
4/7✓ Branch 2 → 3 taken 4 times.
✓ Branch 2 → 8 taken 32 times.
✓ Branch 4 → 5 taken 4 times.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 4 times.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
36 | Q_LOGGING_CATEGORY(lcInvitation, "mailjd.quick.invitation") |
| 23 | |||
| 24 | namespace { | ||
| 25 | |||
| 26 | // PARTSTAT of `email` in a stored VEVENT text ("" when not listed). | ||
| 27 | 60 | QString statusIn(const QString &veventText, const QString &email) { | |
| 28 |
1/1✓ Branch 5 → 6 taken 60 times.
|
60 | const ICal::Component vevent = ICal::parseFirst(veventText, QStringLiteral("VEVENT")); |
| 29 |
4/5✓ Branch 11 → 12 taken 60 times.
✓ Branch 14 → 15 taken 60 times.
✓ Branch 15 → 16 taken 60 times.
✓ Branch 43 → 17 taken 60 times.
✗ Branch 43 → 44 not taken.
|
60 | for (const ICal::Property &property : vevent.propertiesNamed(QStringLiteral("ATTENDEE"))) |
| 30 |
2/3✓ Branch 18 → 19 taken 60 times.
✓ Branch 21 → 22 taken 60 times.
✗ Branch 21 → 41 not taken.
|
60 | if (Imip::addressOf(property.value) == email) { |
| 31 |
2/2✓ Branch 25 → 26 taken 60 times.
✓ Branch 26 → 27 taken 60 times.
|
60 | const QString status = property.parameter(QStringLiteral("PARTSTAT")).toUpper(); |
| 32 |
4/4✓ Branch 31 → 32 taken 2 times.
✓ Branch 31 → 35 taken 58 times.
✓ Branch 37 → 38 taken 2 times.
✓ Branch 37 → 39 taken 58 times.
|
62 | return status.isEmpty() ? QStringLiteral("NEEDS-ACTION") : status; |
| 33 | 120 | } | |
| 34 | ✗ | return {}; | |
| 35 | 60 | } | |
| 36 | |||
| 37 | } // namespace | ||
| 38 | |||
| 39 | 803 | QuickInvitation::QuickInvitation(MailSessionCore &session, Deps deps, QObject *parent) | |
| 40 | 803 | : QObject(parent), m_session(session), m_deps(std::move(deps)) { | |
| 41 |
2/2✓ Branch 11 → 12 taken 802 times.
✓ Branch 11 → 15 taken 1 time.
|
803 | if (auto *sync = m_session.calendarSync()) |
| 42 |
1/1✓ Branch 12 → 13 taken 802 times.
|
802 | connect(sync, &CalendarSyncCoordinator::storeChanged, this, [this] { |
| 43 |
2/2✓ Branch 3 → 4 taken 184 times.
✓ Branch 3 → 5 taken 19 times.
|
203 | if (!m_invitation) return; |
| 44 | 19 | rebuildCard(); | |
| 45 | 19 | emit changed(); | |
| 46 | }); | ||
| 47 | 803 | } | |
| 48 | |||
| 49 | 166 | QString QuickInvitation::replyMode() const { | |
| 50 |
3/3✓ Branch 2 → 3 taken 166 times.
✓ Branch 11 → 12 taken 166 times.
✓ Branch 12 → 13 taken 166 times.
|
498 | const QString mode = QSettings().value(QStringLiteral("calendar/imipReplies"), QStringLiteral("auto")).toString(); |
| 51 |
6/6✓ Branch 22 → 23 taken 125 times.
✓ Branch 22 → 26 taken 41 times.
✓ Branch 25 → 26 taken 57 times.
✓ Branch 25 → 27 taken 68 times.
✓ Branch 31 → 32 taken 68 times.
✓ Branch 31 → 33 taken 98 times.
|
566 | return mode == QLatin1String("client") || mode == QLatin1String("server") ? mode : QStringLiteral("auto"); |
| 52 | 166 | } | |
| 53 | |||
| 54 | 11 | void QuickInvitation::setReplyMode(const QString &mode) { | |
| 55 |
3/3✓ Branch 2 → 3 taken 11 times.
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 10 times.
|
11 | if (mode == replyMode()) return; |
| 56 |
2/2✓ Branch 7 → 8 taken 10 times.
✓ Branch 13 → 14 taken 10 times.
|
20 | QSettings().setValue(QStringLiteral("calendar/imipReplies"), mode); |
| 57 |
7/7✓ Branch 18 → 19 taken 10 times.
✓ Branch 22 → 23 taken 10 times.
✓ Branch 23 → 24 taken 10 times.
✓ Branch 24 → 25 taken 10 times.
✓ Branch 25 → 26 taken 10 times.
✓ Branch 30 → 20 taken 10 times.
✓ Branch 30 → 31 taken 10 times.
|
20 | qCInfo(lcInvitation) << "Invitation replies:" << replyMode(); |
| 58 |
2/2✓ Branch 32 → 33 taken 2 times.
✓ Branch 32 → 34 taken 8 times.
|
10 | if (m_invitation) rebuildCard(); |
| 59 | 10 | emit changed(); | |
| 60 | } | ||
| 61 | |||
| 62 | 24 | void QuickInvitation::showCalendarText(const QString &text) { | |
| 63 | 24 | QString error; | |
| 64 |
1/1✓ Branch 2 → 3 taken 24 times.
|
24 | auto invitation = Imip::parse(text, &error); |
| 65 | // A calendar file with several appointments is no invitation: its | ||
| 66 | // attachment offers the import (S93.5.3). | ||
| 67 |
2/2✓ Branch 4 → 5 taken 23 times.
✓ Branch 4 → 25 taken 1 time.
|
24 | if (invitation) { |
| 68 |
4/4✓ Branch 6 → 7 taken 23 times.
✓ Branch 7 → 8 taken 23 times.
✓ Branch 23 → 9 taken 25 times.
✓ Branch 23 → 24 taken 21 times.
|
46 | for (const CalendarEvent &event : invitation->events) |
| 69 |
2/2✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 21 taken 23 times.
|
25 | if (event.uid != invitation->uid) { |
| 70 | 2 | error = QStringLiteral("several appointments (calendar file)"); | |
| 71 | 2 | invitation.reset(); | |
| 72 | 2 | break; | |
| 73 | } | ||
| 74 | } | ||
| 75 |
2/2✓ Branch 26 → 27 taken 3 times.
✓ Branch 26 → 40 taken 21 times.
|
24 | if (!invitation) { |
| 76 |
6/6✓ Branch 27 → 28 taken 3 times.
✓ Branch 31 → 32 taken 3 times.
✓ Branch 32 → 33 taken 3 times.
✓ Branch 33 → 34 taken 3 times.
✓ Branch 37 → 29 taken 3 times.
✓ Branch 37 → 38 taken 3 times.
|
6 | qCInfo(lcInvitation) << "No invitation card for the calendar attachment:" << error; |
| 77 |
1/1✓ Branch 38 → 39 taken 3 times.
|
3 | clear(); |
| 78 | 3 | return; | |
| 79 | } | ||
| 80 | 21 | m_invitation = std::move(invitation); | |
| 81 | 21 | m_replyAutoApplied = false; | |
| 82 |
1/1✓ Branch 42 → 43 taken 21 times.
|
21 | rebuildCard(); |
| 83 |
3/3✓ Branch 46 → 47 taken 3 times.
✓ Branch 46 → 48 taken 18 times.
✓ Branch 47 → 48 taken 3 times.
|
21 | if (m_invitation->method == QLatin1String("REPLY")) applyReplyAutomatically(); |
| 84 |
1/1✓ Branch 48 → 49 taken 21 times.
|
21 | emit changed(); |
| 85 | 27 | } | |
| 86 | |||
| 87 | 7 | void QuickInvitation::clear() { | |
| 88 | 7 | m_invitation.reset(); | |
| 89 | 7 | m_card.clear(); | |
| 90 | 7 | emit changed(); | |
| 91 | 7 | } | |
| 92 | |||
| 93 | 121 | std::optional<QuickInvitation::Stored> QuickInvitation::storedCopy() const { | |
| 94 | 121 | auto *sync = m_session.calendarSync(); | |
| 95 |
7/10✓ Branch 4 → 5 taken 120 times.
✓ Branch 4 → 11 taken 1 time.
✓ Branch 5 → 6 taken 120 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 120 times.
✗ Branch 7 → 11 not taken.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 120 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 120 times.
|
121 | if (!m_invitation || !sync || !sync->store() || !sync->store()->isOpen()) return std::nullopt; |
| 96 | 120 | CalendarStore *store = sync->store(); | |
| 97 |
5/5✓ Branch 17 → 18 taken 120 times.
✓ Branch 18 → 19 taken 120 times.
✓ Branch 19 → 20 taken 120 times.
✓ Branch 52 → 21 taken 79 times.
✓ Branch 52 → 53 taken 41 times.
|
120 | for (const auto &[accountId, path] : store->calendarsWithUid(m_invitation->uid)) { |
| 98 |
1/1✓ Branch 26 → 27 taken 79 times.
|
79 | auto row = store->occurrenceEvent(m_invitation->uid, accountId, path, m_invitation->event.recurrenceId); |
| 99 |
1/3✗ Branch 28 → 29 not taken.
✓ Branch 28 → 36 taken 79 times.
✗ Branch 31 → 32 not taken.
|
79 | if (!row) row = store->occurrenceEvent(m_invitation->uid, accountId, path, {}); |
| 100 |
1/2✓ Branch 37 → 38 taken 79 times.
✗ Branch 37 → 45 not taken.
|
79 | if (row) return Stored{accountId, path, *row}; |
| 101 | 199 | } | |
| 102 | 41 | return std::nullopt; | |
| 103 | } | ||
| 104 | |||
| 105 | 207 | QStringList QuickInvitation::ownAddresses() const { | |
| 106 | 207 | QStringList addresses; | |
| 107 |
3/4✓ Branch 5 → 6 taken 207 times.
✗ Branch 5 → 11 not taken.
✓ Branch 7 → 8 taken 207 times.
✓ Branch 8 → 9 taken 207 times.
|
207 | if (const auto &primary = m_session.accounts()->primary()) addresses << primary->email.toLower(); |
| 108 |
4/4✓ Branch 13 → 14 taken 207 times.
✓ Branch 14 → 15 taken 207 times.
✓ Branch 42 → 16 taken 207 times.
✓ Branch 42 → 43 taken 207 times.
|
414 | for (const QVariant &account : m_session.accounts()->availableAccounts()) { |
| 109 |
4/4✓ Branch 17 → 18 taken 207 times.
✓ Branch 22 → 23 taken 207 times.
✓ Branch 23 → 24 taken 207 times.
✓ Branch 24 → 25 taken 207 times.
|
414 | const QString email = account.toMap().value(QStringLiteral("email")).toString().toLower(); |
| 110 |
3/7✓ Branch 32 → 33 taken 207 times.
✗ Branch 32 → 36 not taken.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 36 taken 207 times.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 207 times.
✗ Branch 38 → 39 not taken.
|
207 | if (!email.isEmpty() && !addresses.contains(email)) addresses << email; |
| 111 | 414 | } | |
| 112 | 207 | return addresses; | |
| 113 | ✗ | } | |
| 114 | |||
| 115 | 131 | QString QuickInvitation::ownAddress() const { | |
| 116 |
1/1✓ Branch 2 → 3 taken 131 times.
|
131 | const QStringList addresses = ownAddresses(); |
| 117 |
3/6✓ Branch 4 → 5 taken 131 times.
✗ Branch 4 → 7 not taken.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 131 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 131 times.
|
131 | if (!m_invitation || addresses.isEmpty()) return {}; |
| 118 | // The active account first: it sends the reply. | ||
| 119 |
5/7✓ Branch 15 → 16 taken 131 times.
✓ Branch 18 → 19 taken 131 times.
✓ Branch 18 → 20 taken 131 times.
✓ Branch 20 → 21 taken 109 times.
✓ Branch 20 → 23 taken 22 times.
✗ Branch 37 → 38 not taken.
✗ Branch 37 → 39 not taken.
|
262 | if (Imip::attendeeIndex(*m_invitation, {addresses.first()}) >= 0) return addresses.first(); |
| 120 |
1/1✓ Branch 24 → 25 taken 22 times.
|
22 | const int index = Imip::attendeeIndex(*m_invitation, addresses); |
| 121 |
1/2✗ Branch 25 → 26 not taken.
✓ Branch 25 → 29 taken 22 times.
|
22 | return index >= 0 ? m_invitation->attendees.at(index).email : QString(); |
| 122 | 262 | } | |
| 123 | |||
| 124 | 109 | bool QuickInvitation::serverSends(const QString &accountId) const { | |
| 125 |
1/1✓ Branch 2 → 3 taken 109 times.
|
109 | const QString mode = replyMode(); |
| 126 |
2/2✓ Branch 5 → 6 taken 76 times.
✓ Branch 5 → 9 taken 33 times.
|
109 | if (mode != QLatin1String("auto")) return mode == QLatin1String("server"); |
| 127 |
3/5✓ Branch 10 → 11 taken 33 times.
✗ Branch 10 → 14 not taken.
✓ Branch 11 → 12 taken 33 times.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 33 times.
|
33 | return !accountId.isEmpty() && CalendarSyncStatus::serverScheduling(accountId); |
| 128 | 109 | } | |
| 129 | |||
| 130 | 101 | bool QuickInvitation::resolveCalendar(const QString &key, QString *accountId, QString *path) const { | |
| 131 |
12/20✓ Branch 3 → 4 taken 8 times.
✓ Branch 3 → 10 taken 93 times.
✓ Branch 8 → 9 taken 8 times.
✓ Branch 9 → 11 taken 8 times.
✓ Branch 11 → 12 taken 8 times.
✓ Branch 11 → 13 taken 93 times.
✓ Branch 13 → 14 taken 8 times.
✓ Branch 13 → 15 taken 93 times.
✓ Branch 15 → 16 taken 8 times.
✓ Branch 15 → 17 taken 93 times.
✓ Branch 17 → 18 taken 8 times.
✓ Branch 17 → 19 taken 93 times.
✗ Branch 102 → 103 not taken.
✗ Branch 102 → 104 not taken.
✗ Branch 106 → 107 not taken.
✗ Branch 106 → 108 not taken.
✗ Branch 110 → 111 not taken.
✗ Branch 110 → 112 not taken.
✗ Branch 114 → 115 not taken.
✗ Branch 114 → 116 not taken.
|
109 | const QString wanted = key.isEmpty() ? m_card.value(QStringLiteral("defaultCalendar")).toString() : key; |
| 132 |
5/5✓ Branch 19 → 20 taken 101 times.
✓ Branch 20 → 21 taken 101 times.
✓ Branch 21 → 22 taken 101 times.
✓ Branch 92 → 23 taken 193 times.
✓ Branch 92 → 93 taken 2 times.
|
195 | for (const QVariant &value : m_deps.calendarChoices()) { |
| 133 |
1/1✓ Branch 24 → 25 taken 193 times.
|
193 | const QVariantMap choice = value.toMap(); |
| 134 |
23/46✓ Branch 29 → 30 taken 193 times.
✓ Branch 30 → 31 taken 193 times.
✓ Branch 32 → 33 taken 101 times.
✓ Branch 32 → 40 taken 92 times.
✓ Branch 37 → 38 taken 101 times.
✓ Branch 38 → 39 taken 101 times.
✓ Branch 39 → 40 taken 2 times.
✓ Branch 39 → 41 taken 99 times.
✓ Branch 42 → 43 taken 101 times.
✓ Branch 42 → 44 taken 92 times.
✓ Branch 44 → 45 taken 101 times.
✓ Branch 44 → 46 taken 92 times.
✓ Branch 46 → 47 taken 101 times.
✓ Branch 46 → 48 taken 92 times.
✓ Branch 48 → 49 taken 101 times.
✓ Branch 48 → 50 taken 92 times.
✓ Branch 50 → 51 taken 193 times.
✗ Branch 50 → 52 not taken.
✓ Branch 52 → 53 taken 193 times.
✗ Branch 52 → 54 not taken.
✓ Branch 54 → 55 taken 193 times.
✗ Branch 54 → 56 not taken.
✓ Branch 56 → 57 taken 193 times.
✗ Branch 56 → 58 not taken.
✓ Branch 58 → 59 taken 193 times.
✗ Branch 58 → 60 not taken.
✓ Branch 60 → 61 taken 94 times.
✓ Branch 60 → 62 taken 99 times.
✗ Branch 118 → 119 not taken.
✗ Branch 118 → 120 not taken.
✗ Branch 122 → 123 not taken.
✗ Branch 122 → 124 not taken.
✗ Branch 126 → 127 not taken.
✗ Branch 126 → 128 not taken.
✗ Branch 130 → 131 not taken.
✗ Branch 130 → 132 not taken.
✗ Branch 134 → 135 not taken.
✗ Branch 134 → 136 not taken.
✗ Branch 138 → 139 not taken.
✗ Branch 138 → 140 not taken.
✗ Branch 142 → 143 not taken.
✗ Branch 142 → 144 not taken.
✗ Branch 146 → 147 not taken.
✗ Branch 146 → 148 not taken.
✗ Branch 150 → 151 not taken.
✗ Branch 150 → 152 not taken.
|
487 | if (choice.value(QStringLiteral("key")).toString() != wanted || choice.value(QStringLiteral("readOnly")).toBool()) |
| 135 | 94 | continue; | |
| 136 |
2/2✓ Branch 66 → 67 taken 99 times.
✓ Branch 67 → 68 taken 99 times.
|
198 | *accountId = choice.value(QStringLiteral("accountId")).toString(); |
| 137 |
2/2✓ Branch 78 → 79 taken 99 times.
✓ Branch 79 → 80 taken 99 times.
|
198 | *path = choice.value(QStringLiteral("path")).toString(); |
| 138 | 99 | return true; | |
| 139 | 294 | } | |
| 140 | 2 | return false; | |
| 141 | 101 | } | |
| 142 | |||
| 143 | 68 | QStringList QuickInvitation::conflicts() const { | |
| 144 | 68 | QStringList result; | |
| 145 | 68 | auto *sync = m_session.calendarSync(); | |
| 146 | 68 | const CalendarEvent &event = m_invitation->event; | |
| 147 |
8/11✓ Branch 4 → 5 taken 68 times.
✗ Branch 4 → 10 not taken.
✓ Branch 6 → 7 taken 68 times.
✗ Branch 6 → 10 not taken.
✓ Branch 7 → 8 taken 64 times.
✓ Branch 7 → 10 taken 4 times.
✓ Branch 8 → 9 taken 64 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 64 times.
✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 14 taken 64 times.
|
68 | if (!sync || !sync->store() || event.allDay || !event.dtStart.isValid()) return result; |
| 148 |
1/1✓ Branch 14 → 15 taken 64 times.
|
64 | const QDateTime start = event.dtStart.toLocalTime(); |
| 149 |
3/5✓ Branch 15 → 16 taken 64 times.
✓ Branch 16 → 17 taken 64 times.
✗ Branch 16 → 18 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 19 → 20 taken 64 times.
|
64 | const QDateTime end = (event.dtEnd.isValid() ? event.dtEnd : event.dtStart.addSecs(3600)).toLocalTime(); |
| 150 |
4/4✓ Branch 25 → 26 taken 64 times.
✓ Branch 26 → 27 taken 64 times.
✓ Branch 27 → 28 taken 64 times.
✓ Branch 28 → 29 taken 64 times.
|
128 | const QList<CalendarEvent> rows = sync->store()->eventsForDateRange(QDateTime(start.date().addDays(-1), QTime(0, 0)), |
| 151 |
4/4✓ Branch 22 → 23 taken 64 times.
✓ Branch 23 → 24 taken 64 times.
✓ Branch 24 → 25 taken 64 times.
✓ Branch 29 → 30 taken 64 times.
|
192 | QDateTime(end.date(), QTime(23, 59, 59))); |
| 152 | 64 | for (const CalendarEvent &other : | |
| 153 |
7/7✓ Branch 33 → 34 taken 64 times.
✓ Branch 34 → 35 taken 64 times.
✓ Branch 35 → 36 taken 64 times.
✓ Branch 37 → 38 taken 64 times.
✓ Branch 38 → 39 taken 64 times.
✓ Branch 90 → 40 taken 70 times.
✓ Branch 90 → 91 taken 64 times.
|
198 | expandEventsForDisplay(rows, start.date(), end.date(), false, {kDisplayOccurrencesPerSeries, {}})) { |
| 154 |
7/9✓ Branch 42 → 43 taken 27 times.
✓ Branch 42 → 46 taken 43 times.
✓ Branch 43 → 44 taken 27 times.
✗ Branch 43 → 46 not taken.
✓ Branch 44 → 45 taken 27 times.
✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 27 times.
✓ Branch 48 → 49 taken 43 times.
✓ Branch 48 → 50 taken 27 times.
|
70 | if (other.uid == event.uid || other.allDay || !other.dtStart.isValid()) continue; |
| 155 |
2/3✓ Branch 50 → 51 taken 27 times.
✓ Branch 51 → 52 taken 27 times.
✗ Branch 51 → 53 not taken.
|
27 | const QDateTime otherEnd = other.dtEnd.isValid() ? other.dtEnd : other.dtStart; |
| 156 |
5/8✓ Branch 55 → 56 taken 27 times.
✓ Branch 57 → 58 taken 27 times.
✗ Branch 57 → 61 not taken.
✓ Branch 58 → 59 taken 27 times.
✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 27 times.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 27 times.
|
27 | if (other.dtStart >= end || otherEnd <= start) continue; |
| 157 |
1/1✓ Branch 65 → 66 taken 27 times.
|
27 | result << tr("Overlaps with %1 %2–%3") |
| 158 |
3/3✓ Branch 68 → 69 taken 27 times.
✓ Branch 69 → 70 taken 27 times.
✓ Branch 70 → 71 taken 27 times.
|
54 | .arg(other.summary, CalendarLayout::timeText(other.dtStart.toLocalTime()), |
| 159 |
3/3✓ Branch 66 → 67 taken 27 times.
✓ Branch 67 → 68 taken 27 times.
✓ Branch 71 → 72 taken 27 times.
|
81 | CalendarLayout::timeText(otherEnd.toLocalTime())); |
| 160 |
1/2✗ Branch 79 → 80 not taken.
✓ Branch 79 → 81 taken 27 times.
|
27 | if (result.size() == 3) break; |
| 161 | 91 | } | |
| 162 | 64 | return result; | |
| 163 | 128 | } | |
| 164 | |||
| 165 | 90 | QVariantList QuickInvitation::attendeeList(const QString &me) const { | |
| 166 | 90 | QVariantList list; | |
| 167 |
2/2✓ Branch 53 → 5 taken 150 times.
✓ Branch 53 → 54 taken 90 times.
|
240 | for (const Imip::Attendee &attendee : m_invitation->attendees) |
| 168 |
1/1✓ Branch 35 → 36 taken 150 times.
|
450 | list.append(QVariantMap{{QStringLiteral("name"), attendee.name.isEmpty() ? attendee.email : attendee.name}, |
| 169 | 300 | {QStringLiteral("email"), attendee.email}, | |
| 170 | 300 | {QStringLiteral("status"), attendee.partstat}, | |
| 171 | 300 | {QStringLiteral("optional"), attendee.role == QLatin1String("OPT-PARTICIPANT")}, | |
| 172 |
2/4✓ Branch 39 → 40 taken 750 times.
✓ Branch 39 → 41 taken 150 times.
✗ Branch 61 → 62 not taken.
✗ Branch 61 → 63 not taken.
|
1200 | {QStringLiteral("me"), attendee.email == me}}); |
| 173 | 90 | return list; | |
| 174 | 900 | } | |
| 175 | |||
| 176 | 90 | void QuickInvitation::rebuildCard() { | |
| 177 | 90 | const Imip::Invitation &invitation = *m_invitation; | |
| 178 | 90 | const CalendarEvent &event = invitation.event; | |
| 179 |
1/1✓ Branch 3 → 4 taken 90 times.
|
90 | const auto stored = storedCopy(); |
| 180 |
1/1✓ Branch 4 → 5 taken 90 times.
|
90 | const QString me = ownAddress(); |
| 181 | 90 | QVariantMap card; | |
| 182 |
1/1✓ Branch 9 → 10 taken 90 times.
|
180 | card[QStringLiteral("method")] = invitation.method; |
| 183 |
4/4✓ Branch 15 → 16 taken 4 times.
✓ Branch 15 → 17 taken 86 times.
✓ Branch 16 → 18 taken 4 times.
✓ Branch 22 → 23 taken 90 times.
|
180 | card[QStringLiteral("title")] = event.summary.isEmpty() ? tr("(No title)") : event.summary; |
| 184 |
2/2✓ Branch 28 → 29 taken 90 times.
✓ Branch 33 → 34 taken 90 times.
|
180 | card[QStringLiteral("whenText")] = CalendarEventDetails::whenText(event); |
| 185 | // The organizer's wall clock when it differs from ours. | ||
| 186 |
4/5✓ Branch 39 → 40 taken 86 times.
✓ Branch 39 → 47 taken 4 times.
✓ Branch 40 → 41 taken 86 times.
✓ Branch 41 → 42 taken 86 times.
✗ Branch 41 → 47 not taken.
|
176 | if (!event.allDay && event.dtStart.timeSpec() == Qt::TimeZone && |
| 187 |
9/11✓ Branch 42 → 43 taken 86 times.
✓ Branch 43 → 44 taken 86 times.
✓ Branch 44 → 45 taken 86 times.
✓ Branch 45 → 46 taken 64 times.
✓ Branch 45 → 47 taken 22 times.
✓ Branch 48 → 49 taken 86 times.
✓ Branch 48 → 50 taken 4 times.
✓ Branch 50 → 51 taken 64 times.
✓ Branch 50 → 73 taken 26 times.
✗ Branch 868 → 869 not taken.
✗ Branch 868 → 870 not taken.
|
176 | event.dtStart.offsetFromUtc() != event.dtStart.toLocalTime().offsetFromUtc()) |
| 188 |
4/4✓ Branch 51 → 52 taken 64 times.
✓ Branch 55 → 56 taken 64 times.
✓ Branch 56 → 57 taken 64 times.
✓ Branch 61 → 62 taken 64 times.
|
320 | card[QStringLiteral("zoneText")] = tr("%1 in %2").arg(CalendarLayout::timeText(event.dtStart), |
| 189 |
3/3✓ Branch 52 → 53 taken 64 times.
✓ Branch 53 → 54 taken 64 times.
✓ Branch 54 → 55 taken 64 times.
|
320 | QString::fromUtf8(event.dtStart.timeZone().id())); |
| 190 |
1/1✓ Branch 77 → 78 taken 90 times.
|
180 | card[QStringLiteral("location")] = event.location; |
| 191 |
1/1✓ Branch 86 → 87 taken 90 times.
|
180 | card[QStringLiteral("meetingUrl")] = invitation.meetingUrl; |
| 192 |
1/1✓ Branch 91 → 92 taken 90 times.
|
90 | const auto meeting = QUrl(invitation.meetingUrl); |
| 193 |
3/3✓ Branch 93 → 94 taken 90 times.
✓ Branch 94 → 95 taken 90 times.
✓ Branch 99 → 100 taken 90 times.
|
180 | card[QStringLiteral("meetingHost")] = HostMatch::canonicalName(meeting.host()); |
| 194 |
2/2✓ Branch 106 → 107 taken 90 times.
✓ Branch 111 → 112 taken 90 times.
|
180 | card[QStringLiteral("meetingKnown")] = HostMatch::isKnownMeetingUrl(meeting); |
| 195 |
1/1✓ Branch 127 → 128 taken 90 times.
|
270 | card[QStringLiteral("organizer")] = invitation.organizerName.isEmpty() |
| 196 |
2/2✓ Branch 117 → 118 taken 22 times.
✓ Branch 117 → 119 taken 68 times.
|
180 | ? invitation.organizerEmail |
| 197 |
5/9✓ Branch 122 → 123 taken 68 times.
✓ Branch 133 → 134 taken 68 times.
✓ Branch 133 → 135 taken 22 times.
✓ Branch 135 → 136 taken 68 times.
✓ Branch 135 → 137 taken 22 times.
✗ Branch 952 → 953 not taken.
✗ Branch 952 → 954 not taken.
✗ Branch 956 → 957 not taken.
✗ Branch 956 → 958 not taken.
|
360 | : QStringLiteral("%1 <%2>").arg(invitation.organizerName, invitation.organizerEmail); |
| 198 |
2/2✓ Branch 137 → 138 taken 90 times.
✓ Branch 142 → 143 taken 90 times.
|
180 | card[QStringLiteral("attendees")] = attendeeList(me); |
| 199 |
1/1✓ Branch 152 → 153 taken 90 times.
|
180 | card[QStringLiteral("rrule")] = event.rrule; |
| 200 |
3/3✓ Branch 157 → 158 taken 90 times.
✓ Branch 158 → 159 taken 90 times.
✓ Branch 163 → 164 taken 90 times.
|
180 | card[QStringLiteral("startIso")] = event.dtStart.toUTC().toString(Qt::ISODate); |
| 201 |
4/4✓ Branch 170 → 171 taken 90 times.
✓ Branch 171 → 172 taken 90 times.
✓ Branch 172 → 173 taken 90 times.
✓ Branch 177 → 178 taken 90 times.
|
180 | card[QStringLiteral("dateIso")] = event.dtStart.toLocalTime().date().toString(Qt::ISODate); |
| 202 |
1/1✓ Branch 188 → 189 taken 90 times.
|
180 | card[QStringLiteral("uid")] = invitation.uid; |
| 203 |
1/1✓ Branch 197 → 198 taken 90 times.
|
180 | card[QStringLiteral("comment")] = invitation.comment; |
| 204 |
1/1✓ Branch 207 → 208 taken 90 times.
|
180 | card[QStringLiteral("inCalendar")] = stored.has_value(); |
| 205 | // F-52: an occurrence-only mail (RECURRENCE-ID) can only merge into a | ||
| 206 | // stored series — without one, the card offers neither the answer nor | ||
| 207 | // the add/remove buttons. | ||
| 208 |
1/1✓ Branch 222 → 223 taken 90 times.
|
180 | card[QStringLiteral("occurrenceSeriesMissing")] = |
| 209 |
2/5✓ Branch 212 → 213 taken 90 times.
✗ Branch 213 → 214 not taken.
✓ Branch 213 → 217 taken 90 times.
✗ Branch 215 → 216 not taken.
✗ Branch 215 → 217 not taken.
|
270 | event.recurrenceId.isValid() && !stored.has_value(); |
| 210 |
3/3✓ Branch 228 → 229 taken 61 times.
✓ Branch 228 → 231 taken 29 times.
✓ Branch 232 → 233 taken 90 times.
|
90 | const auto consistency = Imip::consistency(invitation, stored ? &stored->master : nullptr, m_mailSender); |
| 211 | 90 | QString trust = QStringLiteral("ok"); | |
| 212 |
2/2✓ Branch 237 → 238 taken 9 times.
✓ Branch 237 → 245 taken 81 times.
|
99 | if (!consistency.organizerMatches) trust = QStringLiteral("organizerChanged"); |
| 213 |
4/6✓ Branch 247 → 248 taken 9 times.
✓ Branch 247 → 250 taken 72 times.
✗ Branch 248 → 249 not taken.
✓ Branch 248 → 250 taken 9 times.
✗ Branch 251 → 252 not taken.
✓ Branch 251 → 259 taken 81 times.
|
81 | else if (invitation.method == QLatin1String("REPLY") && !consistency.replierIsAttendee) |
| 214 | ✗ | trust = QStringLiteral("replierUnknown"); | |
| 215 |
4/4✓ Branch 261 → 262 taken 9 times.
✓ Branch 261 → 263 taken 72 times.
✓ Branch 264 → 265 taken 27 times.
✓ Branch 264 → 272 taken 54 times.
|
81 | else if (invitation.method == QLatin1String("REPLY") ? !consistency.senderIsReplier : !consistency.senderIsOrganizer) |
| 216 | 27 | trust = QStringLiteral("senderUnknown"); | |
| 217 |
1/1✓ Branch 276 → 277 taken 90 times.
|
180 | card[QStringLiteral("trust")] = trust; |
| 218 |
4/4✓ Branch 282 → 283 taken 4 times.
✓ Branch 282 → 284 taken 86 times.
✓ Branch 283 → 285 taken 4 times.
✓ Branch 289 → 290 taken 90 times.
|
180 | card[QStringLiteral("mailSender")] = m_mailSender.isEmpty() ? tr("an unknown sender") : m_mailSender; |
| 219 |
14/24✓ Branch 296 → 297 taken 61 times.
✓ Branch 296 → 306 taken 29 times.
✓ Branch 301 → 302 taken 61 times.
✓ Branch 305 → 307 taken 61 times.
✓ Branch 307 → 308 taken 61 times.
✓ Branch 307 → 309 taken 29 times.
✓ Branch 309 → 310 taken 61 times.
✓ Branch 309 → 311 taken 29 times.
✓ Branch 311 → 312 taken 61 times.
✓ Branch 311 → 313 taken 29 times.
✓ Branch 313 → 314 taken 61 times.
✓ Branch 313 → 315 taken 29 times.
✓ Branch 315 → 316 taken 61 times.
✓ Branch 315 → 317 taken 29 times.
✗ Branch 1071 → 1072 not taken.
✗ Branch 1071 → 1073 not taken.
✗ Branch 1075 → 1076 not taken.
✗ Branch 1075 → 1077 not taken.
✗ Branch 1079 → 1080 not taken.
✗ Branch 1079 → 1081 not taken.
✗ Branch 1083 → 1084 not taken.
✗ Branch 1083 → 1085 not taken.
✗ Branch 1087 → 1088 not taken.
✗ Branch 1087 → 1089 not taken.
|
212 | const auto storedOrganizer = stored ? ICal::parseFirst(stored->master.icalRaw, QStringLiteral("VEVENT")).value(QStringLiteral("ORGANIZER")) : QString(); |
| 220 |
2/2✓ Branch 317 → 318 taken 90 times.
✓ Branch 322 → 323 taken 90 times.
|
180 | card[QStringLiteral("storedOrganizer")] = Imip::addressOf(storedOrganizer); |
| 221 |
5/5✓ Branch 329 → 330 taken 61 times.
✓ Branch 329 → 334 taken 29 times.
✓ Branch 332 → 333 taken 25 times.
✓ Branch 332 → 334 taken 36 times.
✓ Branch 339 → 340 taken 90 times.
|
180 | card[QStringLiteral("requiresConfirmation")] = stored && trust != QLatin1String("ok"); |
| 222 | 90 | QString state; | |
| 223 | 90 | const QString method = invitation.method; | |
| 224 |
5/6✓ Branch 347 → 348 taken 27 times.
✓ Branch 347 → 351 taken 63 times.
✗ Branch 350 → 351 not taken.
✓ Branch 350 → 352 taken 27 times.
✓ Branch 353 → 354 taken 63 times.
✓ Branch 353 → 399 taken 27 times.
|
90 | if (method == QLatin1String("REQUEST") || method == QLatin1String("ADD")) { |
| 225 | 63 | state = QStringLiteral("new"); | |
| 226 |
2/2✓ Branch 361 → 362 taken 43 times.
✓ Branch 361 → 524 taken 20 times.
|
63 | if (stored) { |
| 227 |
1/1✓ Branch 363 → 364 taken 43 times.
|
43 | const int storedSequence = Imip::sequenceOf(stored->master.icalRaw); |
| 228 |
2/2✓ Branch 364 → 365 taken 10 times.
✓ Branch 364 → 368 taken 33 times.
|
139 | state = invitation.sequence > storedSequence ? QStringLiteral("updated") |
| 229 |
8/8✓ Branch 368 → 369 taken 2 times.
✓ Branch 368 → 372 taken 31 times.
✓ Branch 377 → 378 taken 31 times.
✓ Branch 377 → 379 taken 12 times.
✓ Branch 379 → 380 taken 2 times.
✓ Branch 379 → 381 taken 41 times.
✓ Branch 381 → 382 taken 10 times.
✓ Branch 381 → 383 taken 33 times.
|
119 | : invitation.sequence < storedSequence ? QStringLiteral("outdated") : QStringLiteral("answered"); |
| 230 |
2/2✓ Branch 385 → 386 taken 10 times.
✓ Branch 385 → 524 taken 33 times.
|
43 | if (state == QLatin1String("updated")) |
| 231 |
2/2✓ Branch 387 → 388 taken 10 times.
✓ Branch 392 → 393 taken 10 times.
|
20 | card[QStringLiteral("changes")] = Imip::changedFields(stored->master, event); |
| 232 | } | ||
| 233 |
2/2✓ Branch 401 → 402 taken 13 times.
✓ Branch 401 → 409 taken 14 times.
|
27 | } else if (method == QLatin1String("CANCEL")) { |
| 234 | 13 | state = QStringLiteral("cancelled"); | |
| 235 |
2/2✓ Branch 411 → 412 taken 9 times.
✓ Branch 411 → 507 taken 5 times.
|
14 | } else if (method == QLatin1String("REPLY")) { |
| 236 | 9 | state = QStringLiteral("reply"); | |
| 237 |
1/2✓ Branch 419 → 420 taken 9 times.
✗ Branch 419 → 524 not taken.
|
9 | if (!invitation.attendees.isEmpty()) { |
| 238 | 9 | const Imip::Attendee &replier = invitation.attendees.first(); | |
| 239 |
2/3✗ Branch 422 → 423 not taken.
✓ Branch 422 → 424 taken 9 times.
✓ Branch 429 → 430 taken 9 times.
|
18 | card[QStringLiteral("replier")] = replier.name.isEmpty() ? replier.email : replier.name; |
| 240 |
1/1✓ Branch 438 → 439 taken 9 times.
|
18 | card[QStringLiteral("replierStatus")] = replier.partstat; |
| 241 |
1/1✓ Branch 455 → 456 taken 9 times.
|
18 | card[QStringLiteral("replyApplied")] = |
| 242 |
5/9✓ Branch 444 → 445 taken 9 times.
✗ Branch 444 → 450 not taken.
✓ Branch 446 → 447 taken 9 times.
✓ Branch 448 → 449 taken 4 times.
✓ Branch 448 → 450 taken 5 times.
✓ Branch 460 → 461 taken 9 times.
✗ Branch 460 → 462 not taken.
✗ Branch 1151 → 1152 not taken.
✗ Branch 1151 → 1153 not taken.
|
27 | stored && statusIn(stored->master.icalRaw, replier.email) == replier.partstat; |
| 243 |
1/1✓ Branch 466 → 467 taken 9 times.
|
18 | card[QStringLiteral("autoApplied")] = m_replyAutoApplied; // S108.8.7 (QuickInvitationMail.cpp) |
| 244 |
6/8✓ Branch 471 → 472 taken 2 times.
✓ Branch 471 → 473 taken 7 times.
✓ Branch 472 → 488 taken 2 times.
✓ Branch 476 → 477 taken 7 times.
✗ Branch 477 → 478 not taken.
✓ Branch 477 → 487 taken 7 times.
✗ Branch 485 → 486 not taken.
✓ Branch 492 → 493 taken 9 times.
|
43 | card[QStringLiteral("replyNote")] = m_replyAutoApplied ? tr("calendar updated") : stored && serverSends(stored->accountId) |
| 245 |
5/22✓ Branch 474 → 475 taken 7 times.
✗ Branch 474 → 487 not taken.
✗ Branch 482 → 483 not taken.
✗ Branch 483 → 484 not taken.
✗ Branch 484 → 485 not taken.
✗ Branch 484 → 487 not taken.
✗ Branch 498 → 499 not taken.
✓ Branch 498 → 500 taken 9 times.
✗ Branch 500 → 501 not taken.
✓ Branch 500 → 502 taken 9 times.
✗ Branch 502 → 503 not taken.
✓ Branch 502 → 504 taken 9 times.
✗ Branch 504 → 505 not taken.
✓ Branch 504 → 506 taken 9 times.
✗ Branch 1175 → 1176 not taken.
✗ Branch 1175 → 1177 not taken.
✗ Branch 1179 → 1180 not taken.
✗ Branch 1179 → 1181 not taken.
✗ Branch 1183 → 1184 not taken.
✗ Branch 1183 → 1185 not taken.
✗ Branch 1187 → 1188 not taken.
✗ Branch 1187 → 1189 not taken.
|
43 | && card.value(QStringLiteral("replyApplied")).toBool() ? tr("already recorded by your server") : QString(); |
| 246 | } | ||
| 247 |
2/2✓ Branch 509 → 510 taken 1 time.
✓ Branch 509 → 517 taken 4 times.
|
5 | } else if (method == QLatin1String("COUNTER")) { |
| 248 | 1 | state = QStringLiteral("counter"); | |
| 249 | } else { | ||
| 250 | 4 | state = QStringLiteral("publish"); | |
| 251 | } | ||
| 252 |
1/1✓ Branch 528 → 529 taken 90 times.
|
180 | card[QStringLiteral("state")] = state; |
| 253 |
6/6✓ Branch 534 → 535 taken 61 times.
✓ Branch 534 → 540 taken 29 times.
✓ Branch 536 → 537 taken 48 times.
✓ Branch 536 → 540 taken 13 times.
✓ Branch 538 → 539 taken 48 times.
✓ Branch 552 → 553 taken 90 times.
|
378 | card[QStringLiteral("myStatus")] = stored && !me.isEmpty() ? statusIn(stored->master.icalRaw, me) |
| 254 |
2/2✓ Branch 541 → 542 taken 18 times.
✓ Branch 541 → 543 taken 24 times.
|
42 | : me.isEmpty() ? QString() |
| 255 |
7/13✓ Branch 545 → 546 taken 24 times.
✓ Branch 558 → 559 taken 24 times.
✓ Branch 558 → 560 taken 66 times.
✓ Branch 560 → 561 taken 24 times.
✓ Branch 560 → 564 taken 66 times.
✓ Branch 562 → 563 taken 24 times.
✓ Branch 562 → 564 taken 24 times.
✗ Branch 1212 → 1213 not taken.
✗ Branch 1212 → 1214 not taken.
✗ Branch 1216 → 1217 not taken.
✗ Branch 1216 → 1220 not taken.
✗ Branch 1218 → 1219 not taken.
✗ Branch 1218 → 1220 not taken.
|
384 | : invitation.attendees.at(Imip::attendeeIndex(invitation, {me})).partstat; |
| 256 |
1/1✓ Branch 568 → 569 taken 90 times.
|
180 | card[QStringLiteral("replyAs")] = me; |
| 257 | 90 | const bool hasAccount = m_session.accounts()->primary().has_value(); | |
| 258 |
5/7✓ Branch 576 → 577 taken 90 times.
✗ Branch 576 → 585 not taken.
✓ Branch 578 → 579 taken 72 times.
✓ Branch 578 → 585 taken 18 times.
✓ Branch 580 → 581 taken 72 times.
✗ Branch 580 → 585 not taken.
✓ Branch 590 → 591 taken 90 times.
|
342 | card[QStringLiteral("canReply")] = hasAccount && !me.isEmpty() && !invitation.organizerEmail.isEmpty() && |
| 259 |
4/7✓ Branch 581 → 582 taken 72 times.
✓ Branch 583 → 584 taken 72 times.
✗ Branch 583 → 585 not taken.
✓ Branch 595 → 596 taken 72 times.
✓ Branch 595 → 597 taken 18 times.
✗ Branch 1247 → 1248 not taken.
✗ Branch 1247 → 1249 not taken.
|
342 | !ownAddresses().contains(invitation.organizerEmail); |
| 260 |
8/8✓ Branch 599 → 600 taken 81 times.
✓ Branch 599 → 604 taken 9 times.
✓ Branch 602 → 603 taken 68 times.
✓ Branch 602 → 604 taken 13 times.
✓ Branch 605 → 606 taken 68 times.
✓ Branch 605 → 618 taken 22 times.
✓ Branch 606 → 607 taken 68 times.
✓ Branch 611 → 612 taken 68 times.
|
158 | if (state != QLatin1String("reply") && state != QLatin1String("cancelled")) card[QStringLiteral("conflicts")] = conflicts(); |
| 261 | // Writable calendars; the stored copy's or the last used one is the default. | ||
| 262 | 90 | QVariantList calendars; | |
| 263 | 90 | QString defaultKey; | |
| 264 | ✗ | const QString lastKey = [this] { | |
| 265 |
2/2✓ Branch 2 → 3 taken 90 times.
✓ Branch 6 → 7 taken 90 times.
|
180 | const QStringList parts = m_deps.lastCalendar().split(QLatin1Char('\n')); |
| 266 |
3/3✓ Branch 9 → 10 taken 82 times.
✓ Branch 9 → 13 taken 8 times.
✓ Branch 12 → 14 taken 82 times.
|
180 | return parts.size() == 2 ? calendarSelectionKey(parts.at(0), parts.at(1)) : QString(); |
| 267 |
1/1✓ Branch 618 → 619 taken 90 times.
|
180 | }(); |
| 268 |
5/5✓ Branch 619 → 620 taken 90 times.
✓ Branch 620 → 621 taken 90 times.
✓ Branch 621 → 622 taken 90 times.
✓ Branch 734 → 623 taken 172 times.
✓ Branch 734 → 735 taken 90 times.
|
262 | for (const QVariant &value : m_deps.calendarChoices()) { |
| 269 |
1/1✓ Branch 624 → 625 taken 172 times.
|
172 | const QVariantMap choice = value.toMap(); |
| 270 |
4/4✓ Branch 629 → 630 taken 172 times.
✓ Branch 630 → 631 taken 172 times.
✓ Branch 635 → 636 taken 82 times.
✓ Branch 635 → 637 taken 90 times.
|
344 | if (choice.value(QStringLiteral("readOnly")).toBool()) continue; |
| 271 |
2/2✓ Branch 644 → 645 taken 90 times.
✓ Branch 666 → 667 taken 90 times.
|
360 | calendars.append(QVariantMap{{QStringLiteral("key"), choice.value(QStringLiteral("key"))}, |
| 272 |
1/1✓ Branch 653 → 654 taken 90 times.
|
270 | {QStringLiteral("displayName"), choice.value(QStringLiteral("displayName"))}, |
| 273 |
3/5✓ Branch 662 → 663 taken 90 times.
✓ Branch 670 → 671 taken 270 times.
✓ Branch 670 → 672 taken 90 times.
✗ Branch 1282 → 1283 not taken.
✗ Branch 1282 → 1284 not taken.
|
540 | {QStringLiteral("color"), choice.value(QStringLiteral("color"))}}); |
| 274 |
7/28✗ Branch 691 → 692 not taken.
✓ Branch 691 → 700 taken 90 times.
✗ Branch 696 → 697 not taken.
✗ Branch 697 → 698 not taken.
✗ Branch 699 → 700 not taken.
✗ Branch 699 → 701 not taken.
✗ Branch 702 → 703 not taken.
✓ Branch 702 → 704 taken 90 times.
✗ Branch 704 → 705 not taken.
✓ Branch 704 → 706 taken 90 times.
✗ Branch 706 → 707 not taken.
✓ Branch 706 → 708 taken 90 times.
✗ Branch 708 → 709 not taken.
✓ Branch 708 → 710 taken 90 times.
✗ Branch 710 → 711 not taken.
✓ Branch 710 → 712 taken 90 times.
✓ Branch 712 → 713 taken 90 times.
✗ Branch 712 → 726 not taken.
✗ Branch 1347 → 1348 not taken.
✗ Branch 1347 → 1349 not taken.
✗ Branch 1351 → 1352 not taken.
✗ Branch 1351 → 1353 not taken.
✗ Branch 1355 → 1356 not taken.
✗ Branch 1355 → 1357 not taken.
✗ Branch 1359 → 1360 not taken.
✗ Branch 1359 → 1361 not taken.
✗ Branch 1363 → 1364 not taken.
✗ Branch 1363 → 1365 not taken.
|
90 | if (defaultKey.isEmpty() || choice.value(QStringLiteral("key")).toString() == lastKey) |
| 275 |
2/2✓ Branch 717 → 718 taken 90 times.
✓ Branch 718 → 719 taken 90 times.
|
180 | defaultKey = choice.value(QStringLiteral("key")).toString(); |
| 276 | 262 | } | |
| 277 |
2/2✓ Branch 737 → 738 taken 61 times.
✓ Branch 737 → 787 taken 29 times.
|
90 | if (stored) { |
| 278 |
1/1✓ Branch 740 → 741 taken 61 times.
|
61 | defaultKey = calendarSelectionKey(stored->accountId, stored->calendarPath); |
| 279 |
5/5✓ Branch 743 → 744 taken 61 times.
✓ Branch 744 → 745 taken 61 times.
✓ Branch 745 → 746 taken 61 times.
✓ Branch 784 → 747 taken 118 times.
✓ Branch 784 → 785 taken 61 times.
|
179 | for (const QVariant &value : m_deps.calendarChoices()) |
| 280 |
5/5✓ Branch 748 → 749 taken 118 times.
✓ Branch 753 → 754 taken 118 times.
✓ Branch 754 → 755 taken 118 times.
✓ Branch 762 → 763 taken 61 times.
✓ Branch 762 → 782 taken 57 times.
|
236 | if (value.toMap().value(QStringLiteral("key")).toString() == defaultKey) |
| 281 |
3/3✓ Branch 763 → 764 taken 61 times.
✓ Branch 768 → 769 taken 61 times.
✓ Branch 772 → 773 taken 61 times.
|
244 | card[QStringLiteral("calendarName")] = value.toMap().value(QStringLiteral("displayName")); |
| 282 | } | ||
| 283 |
1/1✓ Branch 791 → 792 taken 90 times.
|
180 | card[QStringLiteral("calendars")] = calendars; |
| 284 |
1/1✓ Branch 800 → 801 taken 90 times.
|
180 | card[QStringLiteral("defaultCalendar")] = defaultKey; |
| 285 | 90 | QString accountId, path; | |
| 286 |
6/7✓ Branch 805 → 806 taken 90 times.
✓ Branch 806 → 807 taken 90 times.
✗ Branch 806 → 810 not taken.
✓ Branch 807 → 808 taken 90 times.
✓ Branch 808 → 809 taken 44 times.
✓ Branch 808 → 810 taken 46 times.
✓ Branch 815 → 816 taken 90 times.
|
180 | card[QStringLiteral("serverSends")] = resolveCalendar(defaultKey, &accountId, &path) && serverSends(accountId); |
| 287 | 90 | m_card = card; | |
| 288 | 474 | } | |
| 289 | |||
| 290 | 14 | bool QuickInvitation::storeRows(const QString &accountId, const QString &path, const QString &partstat) { | |
| 291 | 14 | auto *sync = m_session.calendarSync(); | |
| 292 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 14 times.
|
14 | if (!sync) return false; |
| 293 | 14 | QString name; | |
| 294 |
1/2✓ Branch 8 → 9 taken 14 times.
✗ Branch 8 → 11 not taken.
|
14 | if (const auto &primary = m_session.accounts()->primary()) name = primary->name; |
| 295 |
8/10✓ Branch 11 → 12 taken 14 times.
✓ Branch 13 → 14 taken 2 times.
✓ Branch 13 → 16 taken 12 times.
✓ Branch 14 → 15 taken 2 times.
✓ Branch 15 → 17 taken 2 times.
✓ Branch 16 → 17 taken 12 times.
✓ Branch 17 → 18 taken 2 times.
✓ Branch 17 → 19 taken 12 times.
✗ Branch 101 → 102 not taken.
✗ Branch 101 → 103 not taken.
|
14 | const QString me = ownAddress().isEmpty() ? ownAddresses().value(0) : ownAddress(); |
| 296 |
2/2✓ Branch 23 → 24 taken 2 times.
✓ Branch 23 → 30 taken 12 times.
|
14 | QList<CalendarEvent> rows = me.isEmpty() || partstat.isEmpty() |
| 297 |
7/14✓ Branch 21 → 22 taken 14 times.
✗ Branch 21 → 24 not taken.
✓ Branch 32 → 33 taken 2 times.
✓ Branch 32 → 34 taken 12 times.
✓ Branch 34 → 35 taken 2 times.
✓ Branch 34 → 36 taken 12 times.
✓ Branch 36 → 37 taken 2 times.
✓ Branch 36 → 38 taken 12 times.
✗ Branch 108 → 109 not taken.
✗ Branch 108 → 110 not taken.
✗ Branch 112 → 113 not taken.
✗ Branch 112 → 114 not taken.
✗ Branch 116 → 117 not taken.
✗ Branch 116 → 118 not taken.
|
30 | ? Imip::eventsToStore(*m_invitation, QString(), QString(), QString()) |
| 298 |
2/2✓ Branch 28 → 29 taken 2 times.
✓ Branch 31 → 32 taken 12 times.
|
28 | : Imip::eventsToStore(*m_invitation, me, name, partstat); |
| 299 |
2/3✓ Branch 39 → 40 taken 14 times.
✗ Branch 39 → 42 not taken.
✓ Branch 41 → 43 taken 14 times.
|
14 | const QString color = sync->store() ? sync->store()->calendarColor(accountId, path) : QString(); |
| 300 |
4/4✓ Branch 43 → 44 taken 14 times.
✓ Branch 44 → 45 taken 14 times.
✓ Branch 52 → 46 taken 14 times.
✓ Branch 52 → 53 taken 14 times.
|
28 | for (CalendarEvent &row : rows) { |
| 301 | 14 | row.accountId = accountId; | |
| 302 | 14 | row.calendarPath = path; | |
| 303 | 14 | row.color = color; | |
| 304 | } | ||
| 305 |
11/11✓ Branch 53 → 54 taken 14 times.
✓ Branch 57 → 58 taken 14 times.
✓ Branch 58 → 59 taken 14 times.
✓ Branch 60 → 61 taken 14 times.
✓ Branch 61 → 62 taken 14 times.
✓ Branch 63 → 64 taken 2 times.
✓ Branch 63 → 65 taken 12 times.
✓ Branch 64 → 66 taken 2 times.
✓ Branch 66 → 67 taken 14 times.
✓ Branch 76 → 55 taken 14 times.
✓ Branch 76 → 77 taken 14 times.
|
28 | qCInfo(lcInvitation) << "Storing invitation" << m_invitation->method << "as" << (partstat.isEmpty() ? "-" : partstat) |
| 306 |
4/4✓ Branch 67 → 68 taken 14 times.
✓ Branch 68 → 69 taken 14 times.
✓ Branch 69 → 70 taken 14 times.
✓ Branch 71 → 72 taken 14 times.
|
14 | << "in" << path << "rows" << rows.size(); |
| 307 | // F-52: a mail that carries only an occurrence (RECURRENCE-ID) merges | ||
| 308 | // into the stored series — the master row and its other exceptions | ||
| 309 | // survive an update of one date. | ||
| 310 |
2/5✓ Branch 78 → 79 taken 14 times.
✗ Branch 79 → 80 not taken.
✓ Branch 79 → 87 taken 14 times.
✗ Branch 81 → 82 not taken.
✗ Branch 81 → 87 not taken.
|
14 | if (m_invitation->event.recurrenceId.isValid() && rows.size() >= 1 && |
| 311 |
1/5✗ Branch 84 → 85 not taken.
✗ Branch 85 → 86 not taken.
✗ Branch 85 → 87 not taken.
✗ Branch 88 → 89 not taken.
✓ Branch 88 → 92 taken 14 times.
|
14 | rows.cbegin()->recurrenceId.isValid()) |
| 312 | ✗ | return sync->applyOccurrenceUpdate(m_invitation->uid, accountId, path, rows); | |
| 313 |
1/1✓ Branch 93 → 94 taken 14 times.
|
14 | return sync->restoreEventSeries(m_invitation->uid, accountId, path, rows); |
| 314 | 14 | } | |
| 315 | |||
| 316 | 30 | bool QuickInvitation::admitsMutation(bool confirmMismatch) { | |
| 317 |
2/2✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 29 times.
|
30 | if (!m_invitation) return false; |
| 318 | 29 | rebuildCard(); // Re-evaluate if the stored appointment changed since display. | |
| 319 | // S106-342: a newer revision stored since the card was shown (answered | ||
| 320 | // elsewhere, a sync) is never overwritten by this older invitation — the | ||
| 321 | // "outdated" state was a button-visibility rule only. | ||
| 322 |
4/4✓ Branch 11 → 12 taken 29 times.
✓ Branch 12 → 13 taken 29 times.
✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 34 taken 28 times.
|
58 | if (m_card.value(QStringLiteral("state")).toString() == QLatin1String("outdated")) { |
| 323 |
5/5✓ Branch 20 → 21 taken 1 time.
✓ Branch 24 → 25 taken 1 time.
✓ Branch 25 → 26 taken 1 time.
✓ Branch 29 → 22 taken 1 time.
✓ Branch 29 → 30 taken 1 time.
|
2 | qCInfo(lcInvitation) << "Invitation answer refused: a newer revision is stored"; |
| 324 |
2/2✓ Branch 30 → 31 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
|
1 | m_deps.setStatus(tr("A newer version of this invitation is already in the calendar.")); |
| 325 | 1 | return false; | |
| 326 | } | ||
| 327 |
12/24✓ Branch 38 → 39 taken 28 times.
✓ Branch 39 → 40 taken 28 times.
✓ Branch 40 → 41 taken 9 times.
✓ Branch 40 → 42 taken 19 times.
✓ Branch 41 → 42 taken 4 times.
✓ Branch 41 → 43 taken 5 times.
✓ Branch 44 → 45 taken 28 times.
✗ Branch 44 → 46 not taken.
✓ Branch 46 → 47 taken 28 times.
✗ Branch 46 → 48 not taken.
✓ Branch 48 → 49 taken 28 times.
✗ Branch 48 → 50 not taken.
✓ Branch 50 → 51 taken 28 times.
✗ Branch 50 → 52 not taken.
✓ Branch 52 → 53 taken 23 times.
✓ Branch 52 → 54 taken 5 times.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 95 → 96 not taken.
✗ Branch 95 → 97 not taken.
✗ Branch 99 → 100 not taken.
✗ Branch 99 → 101 not taken.
✗ Branch 103 → 104 not taken.
✗ Branch 103 → 105 not taken.
|
56 | if (!m_card.value(QStringLiteral("requiresConfirmation")).toBool() || confirmMismatch) return true; |
| 328 |
5/5✓ Branch 54 → 55 taken 5 times.
✓ Branch 58 → 59 taken 5 times.
✓ Branch 59 → 60 taken 5 times.
✓ Branch 63 → 56 taken 5 times.
✓ Branch 63 → 64 taken 5 times.
|
10 | qCWarning(lcSecurity) << "Calendar mutation requires mismatch confirmation"; |
| 329 |
2/2✓ Branch 64 → 65 taken 5 times.
✓ Branch 65 → 66 taken 5 times.
|
5 | m_deps.setStatus(tr("The invitation does not match the saved appointment. Confirm this change explicitly.")); |
| 330 | 5 | return false; | |
| 331 | } | ||
| 332 | |||
| 333 | 16 | bool QuickInvitation::respond(const QString &partstat, const QString &calendarKey, const QString &comment, bool confirmMismatch) { | |
| 334 |
3/3✓ Branch 2 → 3 taken 16 times.
✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 5 taken 12 times.
|
16 | if (!admitsMutation(confirmMismatch)) return false; |
| 335 |
1/1✓ Branch 5 → 6 taken 12 times.
|
12 | const QString status = partstat.toUpper(); |
| 336 |
8/8✓ Branch 8 → 9 taken 4 times.
✓ Branch 8 → 16 taken 8 times.
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 16 taken 1 time.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 2 times.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 17 → 19 taken 11 times.
|
12 | if (status != QLatin1String("ACCEPTED") && status != QLatin1String("TENTATIVE") && status != QLatin1String("DECLINED")) |
| 337 | 1 | return false; | |
| 338 | 11 | QString accountId, path; | |
| 339 |
1/1✓ Branch 19 → 20 taken 11 times.
|
11 | const auto stored = storedCopy(); |
| 340 |
2/2✓ Branch 21 → 22 taken 3 times.
✓ Branch 21 → 26 taken 8 times.
|
11 | if (stored) { |
| 341 | 3 | accountId = stored->accountId; | |
| 342 | 3 | path = stored->calendarPath; | |
| 343 |
3/3✓ Branch 26 → 27 taken 8 times.
✓ Branch 27 → 28 taken 1 time.
✓ Branch 27 → 32 taken 7 times.
|
8 | } else if (!resolveCalendar(calendarKey, &accountId, &path)) { |
| 344 |
2/2✓ Branch 28 → 29 taken 1 time.
✓ Branch 29 → 30 taken 1 time.
|
1 | m_deps.setStatus(tr("Choose a writable calendar for the invitation.")); |
| 345 | 1 | return false; | |
| 346 | } | ||
| 347 | // A declined invitation that was never stored stays out of the calendar. | ||
| 348 |
4/4✓ Branch 34 → 35 taken 2 times.
✓ Branch 34 → 37 taken 8 times.
✓ Branch 36 → 37 taken 1 time.
✓ Branch 36 → 38 taken 1 time.
|
10 | const bool keep = status != QLatin1String("DECLINED") || stored; |
| 349 |
5/7✓ Branch 39 → 40 taken 9 times.
✓ Branch 39 → 43 taken 1 time.
✓ Branch 40 → 41 taken 9 times.
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 43 taken 9 times.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 49 taken 10 times.
|
10 | if (keep && !storeRows(accountId, path, status)) { |
| 350 | ✗ | m_deps.setStatus(tr("The invitation could not be saved to the calendar.")); | |
| 351 | ✗ | return false; | |
| 352 | } | ||
| 353 |
1/1✓ Branch 49 → 50 taken 10 times.
|
10 | const QString me = ownAddress(); |
| 354 |
10/23✓ Branch 54 → 55 taken 10 times.
✓ Branch 55 → 56 taken 10 times.
✓ Branch 56 → 57 taken 10 times.
✗ Branch 56 → 60 not taken.
✓ Branch 57 → 58 taken 10 times.
✓ Branch 58 → 59 taken 4 times.
✓ Branch 58 → 60 taken 6 times.
✓ Branch 61 → 62 taken 10 times.
✗ Branch 61 → 63 not taken.
✓ Branch 63 → 64 taken 10 times.
✗ Branch 63 → 65 not taken.
✓ Branch 65 → 66 taken 10 times.
✗ Branch 65 → 67 not taken.
✓ Branch 67 → 68 taken 10 times.
✗ Branch 67 → 69 not taken.
✗ Branch 211 → 212 not taken.
✗ Branch 211 → 213 not taken.
✗ Branch 215 → 216 not taken.
✗ Branch 215 → 217 not taken.
✗ Branch 219 → 220 not taken.
✗ Branch 219 → 221 not taken.
✗ Branch 223 → 224 not taken.
✗ Branch 223 → 225 not taken.
|
20 | const bool sendReply = m_card.value(QStringLiteral("canReply")).toBool() && !serverSends(accountId); |
| 355 |
2/2✓ Branch 69 → 70 taken 4 times.
✓ Branch 69 → 189 taken 6 times.
|
10 | if (sendReply) { |
| 356 | 4 | const auto &primary = m_session.accounts()->primary(); | |
| 357 | 4 | Rfc2822Builder builder; | |
| 358 |
1/1✓ Branch 75 → 76 taken 4 times.
|
4 | builder.setFrom(primary->name, primary->email); |
| 359 |
3/5✓ Branch 79 → 80 taken 4 times.
✓ Branch 82 → 83 taken 4 times.
✓ Branch 82 → 84 taken 4 times.
✗ Branch 230 → 231 not taken.
✗ Branch 230 → 232 not taken.
|
8 | builder.setTo({m_invitation->organizerEmail}); |
| 360 |
2/2✓ Branch 86 → 87 taken 2 times.
✓ Branch 86 → 88 taken 2 times.
|
4 | const QString verb = status == QLatin1String("ACCEPTED") ? tr("Accepted") |
| 361 |
5/5✓ Branch 87 → 93 taken 2 times.
✓ Branch 90 → 91 taken 1 time.
✓ Branch 90 → 92 taken 1 time.
✓ Branch 91 → 93 taken 1 time.
✓ Branch 92 → 93 taken 1 time.
|
4 | : status == QLatin1String("TENTATIVE") ? tr("Tentative") : tr("Declined"); |
| 362 |
2/2✓ Branch 97 → 98 taken 4 times.
✓ Branch 98 → 99 taken 4 times.
|
4 | builder.setSubject(QStringLiteral("%1: %2").arg(verb, m_invitation->event.summary)); |
| 363 |
1/1✓ Branch 102 → 103 taken 4 times.
|
8 | QString body = tr("%1 has answered the invitation “%2”: %3.") |
| 364 |
2/3✗ Branch 106 → 107 not taken.
✓ Branch 106 → 108 taken 4 times.
✓ Branch 110 → 111 taken 4 times.
|
4 | .arg(primary->name.isEmpty() ? me : primary->name, m_invitation->event.summary, verb); |
| 365 |
6/6✓ Branch 112 → 113 taken 4 times.
✓ Branch 115 → 116 taken 1 time.
✓ Branch 115 → 127 taken 3 times.
✓ Branch 116 → 117 taken 1 time.
✓ Branch 120 → 121 taken 1 time.
✓ Branch 121 → 122 taken 1 time.
|
5 | if (!comment.trimmed().isEmpty()) body += QStringLiteral("\n\n") + comment.trimmed(); |
| 366 |
1/1✓ Branch 127 → 128 taken 4 times.
|
4 | builder.setBodyText(body); |
| 367 |
3/3✓ Branch 131 → 132 taken 4 times.
✓ Branch 134 → 135 taken 4 times.
✓ Branch 135 → 136 taken 4 times.
|
4 | builder.setCalendarPart(Imip::buildReply(*m_invitation, me, primary->name, status, comment), QStringLiteral("REPLY")); |
| 368 |
1/1✓ Branch 141 → 142 taken 4 times.
|
4 | builder.setMessageId(); |
| 369 |
8/10✓ Branch 143 → 144 taken 4 times.
✓ Branch 146 → 147 taken 4 times.
✓ Branch 147 → 148 taken 4 times.
✓ Branch 151 → 152 taken 4 times.
✓ Branch 154 → 155 taken 4 times.
✓ Branch 154 → 156 taken 4 times.
✓ Branch 159 → 160 taken 1 time.
✓ Branch 159 → 161 taken 3 times.
✗ Branch 285 → 286 not taken.
✗ Branch 285 → 287 not taken.
|
16 | if (!m_deps.send({m_invitation->organizerEmail}, builder.build(Rfc2822Builder::BccHeader::Omit), tr("Reply sent to %1.").arg(m_invitation->organizerEmail))) |
| 370 | 1 | return false; | |
| 371 |
8/8✓ Branch 161 → 162 taken 3 times.
✓ Branch 165 → 166 taken 3 times.
✓ Branch 166 → 167 taken 3 times.
✓ Branch 167 → 168 taken 3 times.
✓ Branch 168 → 169 taken 3 times.
✓ Branch 170 → 171 taken 3 times.
✓ Branch 174 → 163 taken 3 times.
✓ Branch 174 → 175 taken 3 times.
|
6 | qCInfo(lcInvitation) << "Reply" << status << "sent for" << m_invitation->uid; |
| 372 |
6/6✓ Branch 177 → 178 taken 3 times.
✓ Branch 177 → 179 taken 1 time.
✓ Branch 181 → 182 taken 3 times.
✓ Branch 181 → 183 taken 1 time.
✓ Branch 185 → 186 taken 3 times.
✓ Branch 185 → 188 taken 1 time.
|
6 | } else { |
| 373 |
5/5✓ Branch 189 → 190 taken 5 times.
✓ Branch 189 → 191 taken 1 time.
✓ Branch 190 → 192 taken 5 times.
✓ Branch 191 → 192 taken 1 time.
✓ Branch 192 → 193 taken 6 times.
|
6 | m_deps.setStatus(keep ? tr("Saved to the calendar.") : tr("Invitation declined.")); |
| 374 | } | ||
| 375 |
1/1✓ Branch 195 → 196 taken 9 times.
|
9 | rebuildCard(); |
| 376 |
1/1✓ Branch 196 → 197 taken 9 times.
|
9 | emit changed(); |
| 377 | 9 | return true; | |
| 378 | 20 | } | |
| 379 | |||
| 380 | 8 | bool QuickInvitation::addToCalendar(const QString &calendarKey, bool confirmMismatch) { | |
| 381 |
3/3✓ Branch 2 → 3 taken 8 times.
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 6 times.
|
8 | if (!admitsMutation(confirmMismatch)) return false; |
| 382 | 6 | QString accountId, path; | |
| 383 |
1/1✓ Branch 5 → 6 taken 6 times.
|
6 | const auto stored = storedCopy(); |
| 384 |
2/2✓ Branch 7 → 8 taken 3 times.
✓ Branch 7 → 12 taken 3 times.
|
6 | if (stored) { |
| 385 | 3 | accountId = stored->accountId; | |
| 386 | 3 | path = stored->calendarPath; | |
| 387 |
3/3✓ Branch 12 → 13 taken 3 times.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 18 taken 2 times.
|
3 | } else if (!resolveCalendar(calendarKey, &accountId, &path)) { |
| 388 |
2/2✓ Branch 14 → 15 taken 1 time.
✓ Branch 15 → 16 taken 1 time.
|
1 | m_deps.setStatus(tr("Choose a writable calendar for the invitation.")); |
| 389 | 1 | return false; | |
| 390 | } | ||
| 391 | // An update keeps the answer given before. | ||
| 392 |
1/1✓ Branch 18 → 19 taken 5 times.
|
5 | const QString me = ownAddress(); |
| 393 |
4/5✓ Branch 20 → 21 taken 3 times.
✓ Branch 20 → 26 taken 2 times.
✓ Branch 22 → 23 taken 3 times.
✗ Branch 22 → 26 not taken.
✓ Branch 24 → 25 taken 3 times.
|
5 | const QString previous = stored && !me.isEmpty() ? statusIn(stored->master.icalRaw, me) : QString(); |
| 394 |
2/3✓ Branch 27 → 28 taken 5 times.
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 33 taken 5 times.
|
5 | if (!storeRows(accountId, path, previous)) { |
| 395 | ✗ | m_deps.setStatus(tr("The invitation could not be saved to the calendar.")); | |
| 396 | ✗ | return false; | |
| 397 | } | ||
| 398 |
2/2✓ Branch 33 → 34 taken 5 times.
✓ Branch 34 → 35 taken 5 times.
|
5 | m_deps.setStatus(tr("Saved to the calendar.")); |
| 399 |
1/1✓ Branch 36 → 37 taken 5 times.
|
5 | rebuildCard(); |
| 400 |
1/1✓ Branch 37 → 38 taken 5 times.
|
5 | emit changed(); |
| 401 | 5 | return true; | |
| 402 | 6 | } | |
| 403 | |||
| 404 | 8 | bool QuickInvitation::removeFromCalendar(bool confirmMismatch) { | |
| 405 | 8 | auto *sync = m_session.calendarSync(); | |
| 406 |
1/1✓ Branch 3 → 4 taken 8 times.
|
8 | const auto stored = storedCopy(); |
| 407 |
9/10✓ Branch 5 → 6 taken 7 times.
✓ Branch 5 → 15 taken 1 time.
✓ Branch 6 → 7 taken 7 times.
✗ Branch 6 → 15 not taken.
✓ Branch 8 → 9 taken 6 times.
✓ Branch 8 → 15 taken 1 time.
✓ Branch 12 → 13 taken 4 times.
✓ Branch 12 → 15 taken 2 times.
✓ Branch 17 → 18 taken 5 times.
✓ Branch 17 → 19 taken 3 times.
|
12 | if (!m_invitation || !sync || !stored || m_invitation->method != QLatin1String("CANCEL") || |
| 408 |
3/3✓ Branch 13 → 14 taken 4 times.
✓ Branch 14 → 15 taken 1 time.
✓ Branch 14 → 16 taken 3 times.
|
9 | !admitsMutation(confirmMismatch)) return false; |
| 409 | // F-52: a cancelled occurrence leaves the series (its exception row and | ||
| 410 | // an EXDATE on the master); the other dates stay in the calendar. | ||
| 411 |
2/3✓ Branch 20 → 21 taken 3 times.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 54 taken 3 times.
|
3 | if (m_invitation->event.recurrenceId.isValid()) { |
| 412 | ✗ | if (!sync->applyOccurrenceCancel(m_invitation->uid, stored->accountId, stored->calendarPath, | |
| 413 | ✗ | m_invitation->event.recurrenceId)) { | |
| 414 | ✗ | m_deps.setStatus(tr("The appointment could not be removed.")); | |
| 415 | ✗ | return false; | |
| 416 | } | ||
| 417 | ✗ | qCInfo(lcInvitation) << "Cancelled occurrence removed" << m_invitation->uid | |
| 418 | ✗ | << m_invitation->event.recurrenceId.toString(Qt::ISODate); | |
| 419 | ✗ | m_deps.setStatus(tr("Removed this date from the calendar.")); | |
| 420 | ✗ | rebuildCard(); | |
| 421 | ✗ | emit changed(); | |
| 422 | ✗ | return true; | |
| 423 | } | ||
| 424 |
2/3✓ Branch 57 → 58 taken 3 times.
✗ Branch 58 → 59 not taken.
✓ Branch 58 → 63 taken 3 times.
|
3 | if (!sync->removeEvent(m_invitation->uid, stored->accountId, stored->calendarPath)) { |
| 425 | ✗ | m_deps.setStatus(tr("The appointment could not be removed.")); | |
| 426 | ✗ | return false; | |
| 427 | } | ||
| 428 |
6/6✓ Branch 63 → 64 taken 3 times.
✓ Branch 67 → 68 taken 3 times.
✓ Branch 68 → 69 taken 3 times.
✓ Branch 70 → 71 taken 3 times.
✓ Branch 74 → 65 taken 3 times.
✓ Branch 74 → 75 taken 3 times.
|
6 | qCInfo(lcInvitation) << "Cancelled appointment removed" << m_invitation->uid; |
| 429 |
2/2✓ Branch 75 → 76 taken 3 times.
✓ Branch 76 → 77 taken 3 times.
|
3 | m_deps.setStatus(tr("Removed from the calendar.")); |
| 430 |
1/1✓ Branch 78 → 79 taken 3 times.
|
3 | rebuildCard(); |
| 431 |
1/1✓ Branch 79 → 80 taken 3 times.
|
3 | emit changed(); |
| 432 | 3 | return true; | |
| 433 | 8 | } | |
| 434 | |||
| 435 | 3 | bool QuickInvitation::applyReply(bool confirmMismatch) { | |
| 436 | 3 | auto *sync = m_session.calendarSync(); | |
| 437 |
1/1✓ Branch 3 → 4 taken 3 times.
|
3 | const auto stored = storedCopy(); |
| 438 |
3/6✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 18 not taken.
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 18 not taken.
✓ Branch 11 → 12 taken 3 times.
✗ Branch 11 → 18 not taken.
|
6 | if (!m_invitation || !sync || !stored || m_invitation->attendees.isEmpty() || |
| 439 |
7/9✓ Branch 5 → 6 taken 3 times.
✗ Branch 5 → 18 not taken.
✓ Branch 15 → 16 taken 2 times.
✓ Branch 15 → 18 taken 1 time.
✓ Branch 16 → 17 taken 2 times.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 2 times.
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 22 taken 2 times.
|
6 | m_invitation->method != QLatin1String("REPLY") || !admitsMutation(confirmMismatch)) return false; |
| 440 |
1/1✓ Branch 23 → 24 taken 2 times.
|
2 | const Imip::Attendee &replier = m_invitation->attendees.first(); |
| 441 | 2 | CalendarEvent updated = stored->master; | |
| 442 |
1/1✓ Branch 26 → 27 taken 2 times.
|
2 | const QString patched = Imip::withAttendeeStatus(updated.icalRaw, replier.email, replier.partstat); |
| 443 |
2/2✓ Branch 28 → 29 taken 1 time.
✓ Branch 28 → 30 taken 1 time.
|
2 | if (patched.isEmpty()) return false; |
| 444 | 1 | updated.icalRaw = patched; | |
| 445 |
2/3✓ Branch 31 → 32 taken 1 time.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 34 taken 1 time.
|
1 | if (!sync->saveEvent(updated, false)) return false; |
| 446 |
8/8✓ Branch 34 → 35 taken 1 time.
✓ Branch 38 → 39 taken 1 time.
✓ Branch 39 → 40 taken 1 time.
✓ Branch 40 → 41 taken 1 time.
✓ Branch 41 → 42 taken 1 time.
✓ Branch 43 → 44 taken 1 time.
✓ Branch 47 → 36 taken 1 time.
✓ Branch 47 → 48 taken 1 time.
|
2 | qCInfo(lcInvitation) << "Attendee status" << replier.partstat << "applied to" << m_invitation->uid; |
| 447 |
1/1✓ Branch 48 → 49 taken 1 time.
|
1 | rebuildCard(); |
| 448 |
1/1✓ Branch 49 → 50 taken 1 time.
|
1 | emit changed(); |
| 449 | 1 | return true; | |
| 450 | 3 | } | |
| 451 |