app/core/CalendarSyncStatus.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <QList> | ||
| 4 | #include <QNetworkReply> | ||
| 5 | #include <QObject> | ||
| 6 | #include <QString> | ||
| 7 | #include <functional> | ||
| 8 | #include <optional> | ||
| 9 | |||
| 10 | // Sprint 93 S93.6.3 (F-14): per-account calendar sync status. Before this, | ||
| 11 | // a failed sync only produced a transient status-bar message — a missing | ||
| 12 | // DAV password silently stopped every calendar update for days. | ||
| 13 | // | ||
| 14 | // The coordinator reports each run (started → failed* → finished); the | ||
| 15 | // status keeps, per DAV account, the last attempt, the last success, and | ||
| 16 | // the last error with a kind the UI can act on ("password" offers "Enter | ||
| 17 | // password"). lastSuccess and the last error persist in QSettings | ||
| 18 | // ("caldav/status/<accountId>/…") so "Synced 2 min ago" survives a restart. | ||
| 19 | struct CalendarAccountSyncState { | ||
| 20 | QString accountId; | ||
| 21 | // "never" (no run recorded), "running", "ok" or "error". | ||
| 22 | QString state = QStringLiteral("never"); | ||
| 23 | qint64 lastAttempt = 0; // epoch seconds, 0 = never | ||
| 24 | qint64 lastSuccess = 0; | ||
| 25 | // Kind of the last error: "password", "authorization", "authentication", | ||
| 26 | // "network", "tls", "timeout" or "server"; empty when the last run | ||
| 27 | // succeeded. | ||
| 28 | QString errorKind; | ||
| 29 | // Technical detail (server/transport message), shown under "Details". | ||
| 30 | QString errorDetail; | ||
| 31 | }; | ||
| 32 | |||
| 33 | class CalendarSyncStatus final : public QObject { | ||
| 34 | 67 | Q_OBJECT | |
| 35 | public: | ||
| 36 | explicit CalendarSyncStatus(QObject *parent = nullptr); | ||
| 37 | |||
| 38 | // Error kind for a transport error of a failed DAV request. | ||
| 39 | static QString kindForNetworkError(QNetworkReply::NetworkError error); | ||
| 40 | // The user-facing sentence for an error kind, each with a next step. | ||
| 41 | static QString messageForKind(const QString &kind); | ||
| 42 | |||
| 43 | 1 | void setClock(std::function<qint64()> clock) { m_clock = std::move(clock); } | |
| 44 | |||
| 45 | // One sync run of an account. failed() may be called several times per | ||
| 46 | // run (one per collection); the first error is kept. finished() records | ||
| 47 | // a success unless the run failed. | ||
| 48 | void started(const QString &accountId); | ||
| 49 | void failed(const QString &accountId, const QString &kind, const QString &detail); | ||
| 50 | void finished(const QString &accountId); | ||
| 51 | // S106-053: a run that ends without a verdict (cancelled). | ||
| 52 | void cancelled(const QString &accountId); | ||
| 53 | // S106-056: forgets the persisted status of every account not listed | ||
| 54 | // (removed accounts); called when the coordinator starts syncing. | ||
| 55 | void forgetAllExcept(const QStringList &accountIds); | ||
| 56 | // The account was removed: forget its persisted status. | ||
| 57 | void forget(const QString &accountId); | ||
| 58 | |||
| 59 | // Sprint 93 S93.5.2: the account's server does CalDAV scheduling | ||
| 60 | // (RFC 6638 schedule-outbox-URL found during discovery) and sends iMIP | ||
| 61 | // replies itself. QSettings "caldav/scheduling/<accountId>". | ||
| 62 | static void setServerScheduling(const QString &accountId, bool scheduling); | ||
| 63 | static bool serverScheduling(const QString &accountId); | ||
| 64 | // Sprint 108 S108.8.4/8.5 (D-24, D-25): the schedule-outbox URL (free/ | ||
| 65 | // busy) and calendar-user-address-set of the account's principal, and | ||
| 66 | // whether OPTIONS announced calendar-auto-schedule (unset: not checked | ||
| 67 | // yet). QSettings "caldav/scheduleOutbox|scheduleAddresses|autoSchedule/<id>". | ||
| 68 | static void setScheduling(const QString &accountId, const QString &outboxUrl, const QStringList &addresses); | ||
| 69 | static QString scheduleOutbox(const QString &accountId); | ||
| 70 | static QStringList schedulingAddresses(const QString &accountId); | ||
| 71 | static void setAutoSchedule(const QString &accountId, bool autoSchedule); | ||
| 72 | static std::optional<bool> autoSchedule(const QString &accountId); | ||
| 73 | |||
| 74 | CalendarAccountSyncState state(const QString &accountId) const; | ||
| 75 | bool running() const; | ||
| 76 | |||
| 77 | signals: | ||
| 78 | void changed(); | ||
| 79 | |||
| 80 | private: | ||
| 81 | qint64 now() const; | ||
| 82 | void store(const CalendarAccountSyncState &state) const; | ||
| 83 | |||
| 84 | std::function<qint64()> m_clock; | ||
| 85 | QList<CalendarAccountSyncState> m_running; // states of the current runs | ||
| 86 | }; | ||
| 87 |