presentation/QuickCalendarSync.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "QuickCalendarSync.h" | ||
| 2 | |||
| 3 | #include "DavAccountSettings.h" | ||
| 4 | #include "app/core/CalendarSubscriptions.h" | ||
| 5 | #include "app/core/CalendarSyncCoordinator.h" | ||
| 6 | #include "app/core/CalendarSyncStatus.h" | ||
| 7 | #include "app/core/ContactSyncCoordinator.h" | ||
| 8 | |||
| 9 | #include <QDateTime> | ||
| 10 | #include <QLocale> | ||
| 11 | #include <QLoggingCategory> | ||
| 12 | #include <QUrl> | ||
| 13 | |||
| 14 |
3/7✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 8 not taken.
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 8 not taken.
✓ Branch 5 → 6 taken 1 time.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 12 not taken.
|
1 | Q_LOGGING_CATEGORY(lcQuickSync, "mailjd.quick.sync") |
| 15 | |||
| 16 | 797 | QuickCalendarSync::QuickCalendarSync(CalendarSyncCoordinator *calendars, | |
| 17 | 797 | ContactSyncCoordinator *contacts, QObject *parent) | |
| 18 |
1/1✓ Branch 3 → 4 taken 797 times.
|
797 | : QObject(parent), m_calendars(calendars), m_contacts(contacts) { |
| 19 |
2/2✓ Branch 5 → 6 taken 794 times.
✓ Branch 5 → 15 taken 3 times.
|
797 | if (m_calendars) { |
| 20 |
1/1✓ Branch 7 → 8 taken 794 times.
|
794 | connect(m_calendars->syncStatus(), &CalendarSyncStatus::changed, this, &QuickCalendarSync::changed); |
| 21 |
1/1✓ Branch 9 → 10 taken 794 times.
|
794 | connect(m_calendars, &CalendarSyncCoordinator::syncStateChanged, this, &QuickCalendarSync::changed); |
| 22 |
1/1✓ Branch 12 → 13 taken 794 times.
|
794 | connect(m_calendars->subscriptions(), &CalendarSubscriptions::changed, this, &QuickCalendarSync::changed); |
| 23 | } | ||
| 24 | // "2 min ago" ages while the window is open. | ||
| 25 |
1/1✓ Branch 15 → 16 taken 797 times.
|
797 | m_refresh.setInterval(30000); |
| 26 |
1/1✓ Branch 16 → 17 taken 797 times.
|
797 | connect(&m_refresh, &QTimer::timeout, this, &QuickCalendarSync::changed); |
| 27 |
1/1✓ Branch 18 → 19 taken 797 times.
|
797 | m_refresh.start(); |
| 28 | 797 | } | |
| 29 | |||
| 30 | 48 | qint64 QuickCalendarSync::now() const { | |
| 31 |
2/2✓ Branch 3 → 4 taken 4 times.
✓ Branch 3 → 6 taken 44 times.
|
48 | return m_clock ? m_clock() : QDateTime::currentSecsSinceEpoch(); |
| 32 | } | ||
| 33 | |||
| 34 | 4117 | bool QuickCalendarSync::running() const { | |
| 35 |
3/4✓ Branch 2 → 3 taken 4115 times.
✓ Branch 2 → 6 taken 2 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 4115 times.
|
4117 | return m_calendars && m_calendars->syncRunning(); |
| 36 | } | ||
| 37 | |||
| 38 | 1748 | QString QuickCalendarSync::lastSyncText(qint64 lastSuccess) const { | |
| 39 |
2/2✓ Branch 2 → 3 taken 1700 times.
✓ Branch 2 → 5 taken 48 times.
|
1748 | if (lastSuccess <= 0) |
| 40 |
1/1✓ Branch 3 → 4 taken 1700 times.
|
1700 | return tr("Never synchronized"); |
| 41 |
1/1✓ Branch 5 → 6 taken 48 times.
|
48 | const qint64 age = qMax<qint64>(0, now() - lastSuccess); |
| 42 |
2/2✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 10 taken 47 times.
|
48 | if (age < 60) |
| 43 |
1/1✓ Branch 8 → 9 taken 1 time.
|
1 | return tr("Synchronized just now"); |
| 44 | // English source texts are final (no English catalog): singular and | ||
| 45 | // plural are separate strings, the German catalog adds its numerus forms. | ||
| 46 |
2/2✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 15 taken 46 times.
|
47 | if (age < 3600) { |
| 47 | 1 | const int minutes = int(age / 60); | |
| 48 |
2/4✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 1 time.
✗ Branch 12 → 14 not taken.
✓ Branch 13 → 14 taken 1 time.
|
1 | return minutes == 1 ? tr("Synchronized 1 minute ago") : tr("Synchronized %n minutes ago", "", minutes); |
| 49 | } | ||
| 50 |
2/2✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 20 taken 45 times.
|
46 | if (age < 24 * 3600) { |
| 51 | 1 | const int hours = int(age / 3600); | |
| 52 |
2/4✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 1 time.
✗ Branch 17 → 19 not taken.
✓ Branch 18 → 19 taken 1 time.
|
1 | return hours == 1 ? tr("Synchronized 1 hour ago") : tr("Synchronized %n hours ago", "", hours); |
| 53 | } | ||
| 54 |
1/1✓ Branch 20 → 21 taken 45 times.
|
45 | const QDateTime when = QDateTime::fromSecsSinceEpoch(lastSuccess); |
| 55 |
1/1✓ Branch 21 → 22 taken 45 times.
|
45 | return tr("Last synchronized on %1") |
| 56 |
3/3✓ Branch 23 → 24 taken 45 times.
✓ Branch 24 → 25 taken 45 times.
✓ Branch 25 → 26 taken 45 times.
|
45 | .arg(QLocale().toString(when, QLocale::ShortFormat)); |
| 57 | 45 | } | |
| 58 | |||
| 59 | 6801 | QVariantList QuickCalendarSync::accounts() const { | |
| 60 | 6801 | QVariantList result; | |
| 61 |
1/1✓ Branch 2 → 3 taken 6801 times.
|
6801 | const auto configs = DavAccountSettings::calendarConfigs(); |
| 62 |
5/5✓ Branch 3 → 4 taken 6801 times.
✓ Branch 4 → 5 taken 6801 times.
✓ Branch 5 → 6 taken 6801 times.
✓ Branch 164 → 7 taken 1743 times.
✓ Branch 164 → 165 taken 6801 times.
|
8544 | for (const auto &account : DavAccountSettings::accounts()) { |
| 63 | 1743 | bool calendarsSelected = false; | |
| 64 |
2/2✓ Branch 21 → 10 taken 86 times.
✓ Branch 21 → 22 taken 1743 times.
|
1829 | for (const auto &config : configs) |
| 65 |
3/6✓ Branch 12 → 13 taken 86 times.
✗ Branch 12 → 16 not taken.
✓ Branch 14 → 15 taken 86 times.
✗ Branch 14 → 16 not taken.
✓ Branch 17 → 18 taken 86 times.
✗ Branch 17 → 19 not taken.
|
86 | if (config.accountId == account.id && !config.selectedCalendars.isEmpty()) |
| 66 | 86 | calendarsSelected = true; | |
| 67 | 5223 | const CalendarAccountSyncState state = m_calendars ? m_calendars->syncStatus()->state(account.id) | |
| 68 |
5/15✓ Branch 22 → 23 taken 1740 times.
✓ Branch 22 → 25 taken 3 times.
✓ Branch 24 → 30 taken 1740 times.
✓ Branch 30 → 31 taken 3 times.
✓ Branch 30 → 32 taken 1740 times.
✗ Branch 169 → 170 not taken.
✗ Branch 169 → 172 not taken.
✗ Branch 170 → 171 not taken.
✗ Branch 170 → 172 not taken.
✗ Branch 173 → 174 not taken.
✗ Branch 173 → 175 not taken.
✗ Branch 177 → 178 not taken.
✗ Branch 177 → 180 not taken.
✗ Branch 178 → 179 not taken.
✗ Branch 178 → 180 not taken.
|
1746 | : CalendarAccountSyncState{account.id}; |
| 69 | 1743 | QVariantMap entry; | |
| 70 |
1/1✓ Branch 36 → 37 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("accountId"), account.id); |
| 71 |
2/2✓ Branch 40 → 41 taken 1743 times.
✓ Branch 42 → 43 taken 1743 times.
|
3486 | const QString host = QUrl(account.serverUrl).host(); |
| 72 |
3/4✗ Branch 45 → 46 not taken.
✓ Branch 45 → 47 taken 1743 times.
✓ Branch 51 → 52 taken 1743 times.
✓ Branch 56 → 57 taken 1743 times.
|
5229 | entry.insert(QStringLiteral("label"), host.isEmpty() ? account.username |
| 73 |
4/13✓ Branch 50 → 51 taken 1743 times.
✓ Branch 61 → 62 taken 1743 times.
✗ Branch 61 → 63 not taken.
✓ Branch 63 → 64 taken 1743 times.
✗ Branch 63 → 65 not taken.
✓ Branch 65 → 66 taken 1743 times.
✗ Branch 65 → 67 not taken.
✗ Branch 204 → 205 not taken.
✗ Branch 204 → 206 not taken.
✗ Branch 208 → 209 not taken.
✗ Branch 208 → 210 not taken.
✗ Branch 212 → 213 not taken.
✗ Branch 212 → 214 not taken.
|
3486 | : account.username + QStringLiteral(" @ ") + host); |
| 74 |
1/1✓ Branch 71 → 72 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("calendarsSelected"), calendarsSelected); |
| 75 |
5/7✓ Branch 75 → 76 taken 86 times.
✓ Branch 75 → 77 taken 1657 times.
✓ Branch 84 → 85 taken 1743 times.
✓ Branch 89 → 90 taken 1657 times.
✓ Branch 89 → 91 taken 86 times.
✗ Branch 237 → 238 not taken.
✗ Branch 237 → 239 not taken.
|
5143 | entry.insert(QStringLiteral("state"), calendarsSelected ? state.state : QStringLiteral("unconfigured")); |
| 76 |
2/2✓ Branch 91 → 92 taken 1743 times.
✓ Branch 96 → 97 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("lastSyncText"), lastSyncText(state.lastSuccess)); |
| 77 |
1/1✓ Branch 105 → 106 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("lastSuccess"), state.lastSuccess); |
| 78 |
1/1✓ Branch 113 → 114 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("errorKind"), state.errorKind); |
| 79 |
1/1✓ Branch 124 → 125 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("error"), calendarsSelected |
| 80 |
4/4✓ Branch 117 → 118 taken 86 times.
✓ Branch 117 → 119 taken 1657 times.
✓ Branch 118 → 120 taken 86 times.
✓ Branch 119 → 120 taken 1657 times.
|
3486 | ? CalendarSyncStatus::messageForKind(state.errorKind) |
| 81 | : tr("No calendars are selected for this account. Use Discover to choose them.")); | ||
| 82 |
1/1✓ Branch 133 → 134 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("detail"), state.errorDetail); |
| 83 |
1/2✓ Branch 142 → 143 taken 1699 times.
✗ Branch 142 → 146 not taken.
|
3442 | const bool needsCredentials = state.errorKind == QLatin1String("password") || |
| 84 |
3/4✓ Branch 139 → 140 taken 1699 times.
✓ Branch 139 → 146 taken 44 times.
✗ Branch 145 → 146 not taken.
✓ Branch 145 → 147 taken 1699 times.
|
3442 | state.errorKind == QLatin1String("authorization") || |
| 85 | 1699 | state.errorKind == QLatin1String("authentication"); | |
| 86 |
1/1✓ Branch 152 → 153 taken 1743 times.
|
3486 | entry.insert(QStringLiteral("needsCredentials"), needsCredentials); |
| 87 |
1/1✓ Branch 157 → 158 taken 1743 times.
|
1743 | result.append(entry); |
| 88 | 8544 | } | |
| 89 | 6801 | return result; | |
| 90 | 6801 | } | |
| 91 | |||
| 92 | 2159 | QString QuickCalendarSync::summaryText() const { | |
| 93 |
1/2✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 2159 times.
|
2159 | if (running()) |
| 94 | ✗ | return tr("Synchronizing…"); | |
| 95 |
1/1✓ Branch 6 → 7 taken 2159 times.
|
2159 | const QVariantList list = accounts(); |
| 96 | 2159 | qint64 oldest = 0; | |
| 97 | 2159 | bool any = false; | |
| 98 |
2/2✓ Branch 62 → 9 taken 512 times.
✓ Branch 62 → 63 taken 2156 times.
|
2668 | for (const auto &value : list) { |
| 99 |
1/1✓ Branch 10 → 11 taken 512 times.
|
512 | const QVariantMap entry = value.toMap(); |
| 100 |
4/4✓ Branch 15 → 16 taken 512 times.
✓ Branch 16 → 17 taken 512 times.
✓ Branch 21 → 22 taken 509 times.
✓ Branch 21 → 23 taken 3 times.
|
1024 | if (!entry.value(QStringLiteral("calendarsSelected")).toBool()) |
| 101 | 509 | continue; | |
| 102 |
3/4✓ Branch 28 → 29 taken 3 times.
✓ Branch 29 → 30 taken 3 times.
✓ Branch 36 → 37 taken 3 times.
✗ Branch 36 → 39 not taken.
|
6 | if (entry.value(QStringLiteral("state")).toString() == QLatin1String("error")) |
| 103 |
1/1✓ Branch 37 → 38 taken 3 times.
|
3 | return tr("Synchronization failed"); |
| 104 | ✗ | const qint64 success = entry.value(QStringLiteral("lastSuccess")).toLongLong(); | |
| 105 | ✗ | oldest = any ? qMin(oldest, success) : success; | |
| 106 | ✗ | any = true; | |
| 107 | 512 | } | |
| 108 |
1/3✗ Branch 63 → 64 not taken.
✓ Branch 63 → 65 taken 2156 times.
✗ Branch 64 → 66 not taken.
|
2156 | return any ? lastSyncText(oldest) : QString(); |
| 109 | 2159 | } | |
| 110 | |||
| 111 | 1250 | QVariantMap QuickCalendarSync::problem() const { | |
| 112 |
5/5✓ Branch 2 → 3 taken 1250 times.
✓ Branch 3 → 4 taken 1250 times.
✓ Branch 4 → 5 taken 1250 times.
✓ Branch 53 → 6 taken 320 times.
✓ Branch 53 → 54 taken 1247 times.
|
1567 | for (const auto &value : accounts()) { |
| 113 |
1/3✓ Branch 7 → 8 taken 320 times.
✗ Branch 99 → 100 not taken.
✗ Branch 99 → 101 not taken.
|
320 | const QVariantMap entry = value.toMap(); |
| 114 |
10/22✓ Branch 12 → 13 taken 320 times.
✓ Branch 13 → 14 taken 320 times.
✓ Branch 14 → 15 taken 3 times.
✓ Branch 14 → 25 taken 317 times.
✓ Branch 23 → 24 taken 3 times.
✗ Branch 23 → 25 not taken.
✓ Branch 38 → 39 taken 320 times.
✗ Branch 38 → 40 not taken.
✓ Branch 40 → 41 taken 320 times.
✗ Branch 40 → 42 not taken.
✓ Branch 42 → 43 taken 320 times.
✗ Branch 42 → 44 not taken.
✓ Branch 44 → 45 taken 3 times.
✓ Branch 44 → 46 taken 317 times.
✗ Branch 83 → 84 not taken.
✗ Branch 83 → 85 not taken.
✗ Branch 87 → 88 not taken.
✗ Branch 87 → 89 not taken.
✗ Branch 91 → 92 not taken.
✗ Branch 91 → 93 not taken.
✗ Branch 95 → 96 not taken.
✗ Branch 95 → 97 not taken.
|
963 | if (entry.value(QStringLiteral("calendarsSelected")).toBool() && |
| 115 |
13/24✓ Branch 20 → 21 taken 3 times.
✓ Branch 21 → 22 taken 3 times.
✓ Branch 26 → 27 taken 3 times.
✓ Branch 26 → 28 taken 317 times.
✓ Branch 28 → 29 taken 3 times.
✓ Branch 28 → 30 taken 317 times.
✓ Branch 30 → 31 taken 3 times.
✓ Branch 30 → 32 taken 317 times.
✓ Branch 32 → 33 taken 3 times.
✓ Branch 32 → 34 taken 317 times.
✓ Branch 34 → 35 taken 3 times.
✓ Branch 34 → 36 taken 317 times.
✓ Branch 36 → 37 taken 320 times.
✗ Branch 36 → 38 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
✗ Branch 66 → 67 not taken.
✗ Branch 66 → 68 not taken.
✗ Branch 70 → 71 not taken.
✗ Branch 70 → 72 not taken.
✗ Branch 74 → 75 not taken.
✗ Branch 74 → 76 not taken.
✗ Branch 78 → 79 not taken.
✗ Branch 78 → 80 not taken.
|
326 | entry.value(QStringLiteral("state")).toString() == QLatin1String("error")) |
| 116 | 3 | return entry; | |
| 117 | 1567 | } | |
| 118 | 1247 | return {}; | |
| 119 | } | ||
| 120 | |||
| 121 | ✗ | void QuickCalendarSync::syncNow() { | |
| 122 | ✗ | qCInfo(lcQuickSync) << "Manual synchronization requested"; | |
| 123 | ✗ | if (m_calendars) { | |
| 124 | ✗ | m_calendars->retryPendingWrites(); | |
| 125 | ✗ | m_calendars->triggerSync(); | |
| 126 | } | ||
| 127 | ✗ | if (m_contacts) | |
| 128 | ✗ | m_contacts->triggerSync(); | |
| 129 | ✗ | emit changed(); | |
| 130 | ✗ | } | |
| 131 | |||
| 132 | 62 | QVariantList QuickCalendarSync::subscriptions() const { | |
| 133 | 62 | QVariantList list; | |
| 134 |
4/5✓ Branch 2 → 3 taken 62 times.
✓ Branch 3 → 4 taken 62 times.
✓ Branch 4 → 5 taken 62 times.
✗ Branch 67 → 6 not taken.
✓ Branch 67 → 68 taken 62 times.
|
62 | for (const auto &entry : CalendarSubscriptions::subscriptions()) { |
| 135 | // S106-256: "Downloading…" only while this feed's own download runs — | ||
| 136 | // a feed whose downloads all failed showed it whenever another ran. | ||
| 137 | ✗ | const bool refreshing = m_calendars && m_calendars->subscriptions()->running(entry.id); | |
| 138 | ✗ | list.append(QVariantMap{{QStringLiteral("accountId"), CalendarSubscriptions::accountIdFor(entry.id)}, | |
| 139 | ✗ | {QStringLiteral("name"), entry.name}, | |
| 140 | ✗ | {QStringLiteral("url"), entry.url}, | |
| 141 | ✗ | {QStringLiteral("intervalMinutes"), entry.intervalMinutes}, | |
| 142 | ✗ | {QStringLiteral("stateText"), refreshing && entry.lastRefresh == 0 ? tr("Downloading…") | |
| 143 | ✗ | : lastSyncText(entry.lastRefresh)}, | |
| 144 | ✗ | {QStringLiteral("error"), entry.lastError}}); | |
| 145 | 62 | } | |
| 146 | 62 | return list; | |
| 147 | ✗ | } | |
| 148 | |||
| 149 | 1 | QVariantMap QuickCalendarSync::subscribe(const QString &url, const QString &name, int intervalHours, | |
| 150 | const QString &username, const QString &password) { | ||
| 151 |
1/7✗ Branch 2 → 3 not taken.
✓ Branch 2 → 22 taken 1 time.
✗ Branch 10 → 11 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 16 not taken.
✗ Branch 62 → 63 not taken.
✗ Branch 62 → 64 not taken.
|
1 | if (!m_calendars) return {{QStringLiteral("ok"), false}, {QStringLiteral("error"), tr("Calendar storage not available")}}; |
| 152 | 1 | QString error; | |
| 153 |
1/1✓ Branch 22 → 23 taken 1 time.
|
1 | QByteArray secret = password.toUtf8(); |
| 154 |
1/1✓ Branch 25 → 26 taken 1 time.
|
1 | const QString id = m_calendars->subscriptions()->add(url, name, qMax(1, intervalHours) * 60, &error, username, secret); |
| 155 |
1/1✓ Branch 26 → 27 taken 1 time.
|
1 | secret.fill('\0'); |
| 156 |
6/6✓ Branch 27 → 28 taken 1 time.
✓ Branch 31 → 32 taken 1 time.
✓ Branch 32 → 33 taken 1 time.
✓ Branch 34 → 35 taken 1 time.
✓ Branch 38 → 29 taken 1 time.
✓ Branch 38 → 39 taken 1 time.
|
2 | qCInfo(lcQuickSync) << "Subscribe:" << !id.isEmpty(); |
| 157 |
2/4✓ Branch 50 → 51 taken 2 times.
✓ Branch 50 → 52 taken 1 time.
✗ Branch 94 → 95 not taken.
✗ Branch 94 → 96 not taken.
|
5 | return {{QStringLiteral("ok"), !id.isEmpty()}, {QStringLiteral("error"), error}}; |
| 158 | 4 | } | |
| 159 | |||
| 160 | ✗ | bool QuickCalendarSync::unsubscribe(const QString &accountId) { | |
| 161 | ✗ | if (!m_calendars || !CalendarSubscriptions::isSubscription(accountId)) return false; | |
| 162 | ✗ | return m_calendars->subscriptions()->remove(accountId.mid(QStringLiteral("subscription:").size())); | |
| 163 | } | ||
| 164 | |||
| 165 | ✗ | bool QuickCalendarSync::updateSubscription(const QString &accountId, const QString &name, int intervalMinutes) { | |
| 166 | ✗ | if (!m_calendars || !CalendarSubscriptions::isSubscription(accountId)) return false; | |
| 167 | ✗ | return m_calendars->subscriptions()->update(accountId.mid(QStringLiteral("subscription:").size()), name, | |
| 168 | ✗ | intervalMinutes); | |
| 169 | } | ||
| 170 | |||
| 171 | ✗ | void QuickCalendarSync::refreshSubscription(const QString &accountId) { | |
| 172 | ✗ | if (m_calendars && CalendarSubscriptions::isSubscription(accountId)) | |
| 173 | ✗ | m_calendars->subscriptions()->refresh(accountId.mid(QStringLiteral("subscription:").size())); | |
| 174 | ✗ | } | |
| 175 |