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: 88.9% 8 / 0 / 9
Functions: 83.3% 5 / 0 / 6
Branches: -% 0 / 0 / 0

app/core/CalendarSubscriptions.h
Line Branch Exec Source
1 #pragma once
2
3 #include <QDateTime>
4 #include <QList>
5 #include <QObject>
6 #include <QSet>
7 #include <QString>
8 #include <QTimer>
9 #include <functional>
10
11 class CalendarStore;
12 class QNetworkAccessManager;
13
14 // Sprint 93 S93.5.4 (CAL-SUBSCRIBE): read-only calendars from an ICS URL
15 // (holidays, team feeds, webcal:// links).
16 //
17 // A subscription is a local read-only calendar in the same store and
18 // sidebar (accountId "subscription:<id>", path = the URL). refreshDue()
19 // downloads every subscription whose interval has passed (GET with the
20 // DAV size and timeout limits, no redirect to a less safe scheme, no
21 // credentials), reads it with IcsFile and replaces the calendar's
22 // appointments; a failed download keeps the last copy and records the
23 // error. The list lives in QSettings "calendar/subscriptions".
24 class CalendarSubscriptions final : public QObject {
25 10 Q_OBJECT
26 public:
27 struct Subscription {
28 QString id;
29 QString url; // https:// (webcal:// is stored as https://)
30 QString name;
31 int intervalMinutes = 360;
32 QString username; // CAL-SUBSCRIBE-AUTH: "" = public feed; the password is in the keyring
33 qint64 lastRefresh = 0; // epoch seconds of the last successful download
34 QString lastError;
35 };
36 using NamFactory = std::function<QNetworkAccessManager *(QObject *parent)>;
37 // Reads the keyring password of a protected feed (tests inject one).
38 using PasswordReader = std::function<void(QObject *owner, const Subscription &,
39 std::function<void(QByteArray, QString)>)>;
40 using PasswordWriter = std::function<bool(const Subscription &, const QByteArray &)>;
41
42 CalendarSubscriptions(CalendarStore *store, QObject *parent = nullptr);
43 2 void setNetworkAccessManagerFactory(NamFactory factory) { m_namFactory = std::move(factory); }
44 946 void setNetworkGate(std::function<bool()> gate) { m_networkGate = std::move(gate); }
45 1 void setClock(std::function<qint64()> clock) { m_clock = std::move(clock); }
46 1 void setPasswordStore(PasswordReader reader, PasswordWriter writer) {
47 1 m_passwordReader = std::move(reader);
48 1 m_passwordWriter = std::move(writer);
49 1 }
50
51 static QList<Subscription> subscriptions();
52 static QString accountIdFor(const QString &subscriptionId);
53 static bool isSubscription(const QString &accountId);
54 // Returns the new id, or "" (with *error) for an invalid URL or a
55 // duplicate. The first download starts at once.
56 // A username makes it a protected feed: https only, the password goes to
57 // the keyring (never into QSettings or logs).
58 QString add(const QString &url, const QString &name, int intervalMinutes, QString *error = nullptr,
59 const QString &username = {}, const QByteArray &password = {});
60 bool remove(const QString &id);
61 // Sprint 100 S100.1.14 (D-23): rename a subscription or change how often
62 // it is downloaded; the calendar in the store gets the new name at once.
63 bool update(const QString &id, const QString &name, int intervalMinutes);
64 // Downloads the due subscriptions (all with `force`).
65 void refreshDue(bool force = false);
66 void refresh(const QString &id);
67 bool busy() const { return !m_running.isEmpty(); }
68 // S106-256: whether this subscription's own download runs now.
69 ✗ bool running(const QString &id) const { return m_running.contains(id); }
70
71 signals:
72 void storeChanged();
73 void changed(); // list, refresh state or errors
74
75 private:
76 static void save(const QList<Subscription> &list);
77 void storeCalendar(const Subscription &entry);
78 void finished(const QString &id, const QByteArray &body, const QString &error);
79 void download(const Subscription &subscription, const QByteArray &password);
80 qint64 now() const;
81
82 CalendarStore *m_store = nullptr;
83 NamFactory m_namFactory;
84 std::function<bool()> m_networkGate;
85 std::function<qint64()> m_clock;
86 PasswordReader m_passwordReader;
87 PasswordWriter m_passwordWriter;
88 QSet<QString> m_running;
89 QTimer m_timer;
90 };
91