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: 100.0% 11 / 0 / 11
Functions: 100.0% 6 / 0 / 6
Branches: 88.0% 22 / 0 / 25

data/CalendarModels.h
Line Branch Exec Source
1 #pragma once
2
3 #include <QDateTime>
4 #include <QString>
5 #include <QStringList>
6
7 #include "DavPushModels.h"
8
9 // DAV paths are only unique within their account. Length-prefix the account
10 // so even unusual account/path separators cannot alias another collection.
11 1291281 inline QString calendarSelectionKey(const QString &accountId, const QString &path) {
12
4/4
✓ Branch 5 → 6 taken 1291281 times.
✓ Branch 6 → 7 taken 1291281 times.
✓ Branch 7 → 8 taken 1291281 times.
✓ Branch 8 → 9 taken 1291281 times.
1291281 return QString::number(accountId.size()) + QLatin1Char(':') + accountId + path;
13 }
14
15 // ═══════════════════════════════════════════════════════
16 // CalDAV data models (Sprint 32 – T-330)
17 // ═══════════════════════════════════════════════════════
18
19 /// Info about a discovered CalDAV calendar (PROPFIND result)
20 struct CalendarInfo {
21 QString path; ///< DAV href path (unique per server)
22 QString accountId; ///< Owning DAV account id; path is only unique per account
23 QString displayName; ///< Human-readable name, e.g. "Persönlich"
24 QString color; ///< Hex color from APPLE:calendar-color, e.g. "#FF6600"
25 QString ctag; ///< Calendar CTag for sync change detection
26 bool readOnly = false; ///< User-marked as read-only (no write ops)
27 QStringList supportedComponents; ///< Empty = server did not restrict components
28 DavPushOffer push; ///< Sprint 96: WebDAV-Push offer of this collection (discovery only, not stored)
29
8/8
✓ Branch 3 → 4 taken 4298 times.
✓ Branch 3 → 9 taken 20552 times.
✓ Branch 8 → 9 taken 3701 times.
✓ Branch 8 → 10 taken 597 times.
✓ Branch 12 → 13 taken 4298 times.
✓ Branch 12 → 14 taken 20552 times.
✓ Branch 14 → 15 taken 4298 times.
✓ Branch 14 → 16 taken 20552 times.
29148 bool supportsTasks() const { return supportedComponents.isEmpty() || supportedComponents.contains(QStringLiteral("VTODO")); }
30 };
31
32 /// Sprint 103 (S103.1.10, D-14): a person named in an event with the
33 /// iCalendar CONTACT property — never an ATTENDEE, so no server sends an
34 /// invitation. `uri` is the ALTREP ("urn:uuid:<UID>" of a contact card).
35 struct EventPerson {
36 31 QString uri;
37 30 QString uid; ///< UID from an urn:uuid ALTREP, else empty
38 30 QString name; ///< the CONTACT text value
39
4/6
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 30 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 30 times.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 30 times.
31 bool operator==(const EventPerson &) const = default;
40 };
41
42 /// Sprint 103: ATTENDEE / ORGANIZER written by other clients (read-only).
43 struct EventAttendee {
44 QString address; ///< mailto: address without the scheme
45 QString name; ///< CN
46 QString role; ///< ROLE (REQ-PARTICIPANT, …), "ORGANIZER" for the organizer
47 QString partstat; ///< PARTSTAT (ACCEPTED, …)
48 QString cutype; ///< CUTYPE (INDIVIDUAL, ROOM, …)
49 bool organizer = false;
50 bool operator==(const EventAttendee &) const = default;
51 };
52
53 /// Single calendar event parsed from VEVENT (RFC 5545)
54 struct CalendarEvent {
55 qint64 id = 0; ///< Database primary key
56 QString uid; ///< iCal UID (unique within calendar)
57 QString calendarPath; ///< DAV path of parent calendar
58 QString accountId; ///< Owning DAV account id
59 QString resourceHref; ///< DAV href of the VEVENT resource
60 QString summary; ///< Event title (SUMMARY)
61 QString description; ///< Event description (DESCRIPTION)
62 QString location; ///< Event location (LOCATION)
63 // Invalid server rows remain lossless in storage, but have no occurrences.
64 78228 bool isSchedulable() const { return dtStart.isValid(); }
65 QDateTime dtStart; ///< Start date/time (DTSTART)
66 QDateTime dtEnd; ///< End date/time (DTEND)
67 bool allDay = false; ///< True if VALUE=DATE (no time component)
68 QString rrule; ///< Recurrence rule string (RRULE), stored as-is
69 QDateTime recurrenceId; ///< RECURRENCE-ID: set for exceptions (moved
70 ///< occurrences); invalid for masters (Q11)
71 QList<QDateTime> exdates; ///< Deleted occurrences (EXDATE, T-79.C1/H3)
72 QString etag; ///< DAV ETag for incremental sync
73 QString color; ///< Inherited from parent calendar
74 QDateTime lastModified; ///< LAST-MODIFIED timestamp
75 // Sprint 93 S93.1.1–S93.1.4 (lossless round trip, zones, full RRULE).
76 // dtStart/dtEnd carry their zone: UTC, local time (floating) or the
77 // resolved IANA zone (see ICalTime.h).
78 QList<QDateTime> rdates; ///< Extra occurrences (RDATE)
79 QString icalRaw; ///< The VEVENT as last read from / written to the
80 ///< server; the serializer patches it (S93.1.1)
81 QString resourceIcal; ///< The whole VCALENDAR resource (VTIMEZONE,
82 ///< calendar properties); filled for write-back
83 bool partialRecurrence = false; ///< Display only: the RRULE could not be
84 ///< expanded completely (S93.1.4)
85 bool occurrencesLimited = false; ///< Display only: the series has more
86 ///< occurrences in the range than the
87 ///< display limit (Sprint 102, DisplayLimit)
88 QString syncState; ///< "" synced, "pending", "conflict" (outbox, S93.1.6)
89 QList<int> reminders; ///< Sprint 93 S93.5.1: display/audio VALARMs as
90 ///< minutes before the start (negative = after),
91 ///< sorted ascending, unique
92 // Sprint 103 (S103.1.10): people named in the event (CONTACT) and the
93 // read-only attendees/organizer. The writer applies `people` only when
94 // `peopleSet` is true (the list was read from the component or edited);
95 // rows loaded without it keep their CONTACT lines untouched.
96 QList<EventPerson> people;
97 bool peopleSet = false;
98 QList<EventAttendee> attendees;
99 };
100
101 /// A DAV resource whose local state still has to reach the server
102 /// (calendar_outbox, Sprint 93 S93.1.6). The payload is not stored: a put
103 /// pushes the current local rows of `uid`, patched onto the stored resource.
104 struct CalendarOutboxEntry {
105 QString accountId;
106 QString calendarPath;
107 QString uid;
108 QString operation; ///< "put" or "delete"
109 QString href; ///< resource URL ("" = <calendar>/<uid>.ics)
110 QString baseEtag; ///< server ETag the change is based on; "" = create
111 int revision = 0; ///< incremented by every local change
112 int attempts = 0;
113 qint64 nextAttempt = 0; ///< epoch seconds; 0 = now
114 QString lastError; ///< technical detail (log/"Details" only)
115 QString state; ///< "pending" or "conflict"
116 QStringList conflictFields;
117 QString serverIcal; ///< conflict: the server version ("" = deleted there)
118 QString serverEtag;
119 qint64 created = 0;
120 QString componentType = QStringLiteral("VEVENT");
121 QString dependencyKey; ///< Move: source DELETE waits for the destination PUT
122 };
123
124 // S106-351: the bound of a stored task sort order (see CalendarTask::sortOrder).
125 inline constexpr qint64 kTaskSortOrderLimit = qint64(1) << 52;
126
127 /// Single TODO/task parsed from VTODO (RFC 5545)
128 struct CalendarTask {
129 qint64 id = 0; ///< Database primary key
130 QString uid; ///< iCal UID
131 QString calendarPath; ///< DAV path of parent calendar
132 QString accountId; ///< Owning DAV account id
133 QString resourceHref; ///< DAV href of the VTODO resource
134 QString summary; ///< Task title (SUMMARY)
135 QString description; ///< Task description (DESCRIPTION)
136 QDateTime dtStart; ///< Start date (DTSTART)
137 QDateTime due; ///< Due date (DUE)
138 bool dueAllDay = false; ///< DUE was encoded as VALUE=DATE
139 int percentComplete = 0; ///< 0–100 (PERCENT-COMPLETE)
140 int priority = 0; ///< 0–9 (PRIORITY, 0 = undefined, 1 = starred/important)
141 QString status; ///< NEEDS-ACTION | COMPLETED | IN-PROCESS | CANCELLED
142 QDateTime completedAt; ///< Completion timestamp (COMPLETED)
143 QDateTime created; ///< Creation timestamp (CREATED)
144 QString organizer; ///< Creator/organizer (ORGANIZER CN or mailto)
145 QString relatedMessageId; ///< Canonical Message-ID of the linked mail
146 QString etag; ///< DAV ETag
147 QDateTime lastModified; ///< LAST-MODIFIED timestamp
148 QString color; ///< Inherited from parent calendar
149 QString calendarDisplayName; ///< Display name of parent calendar
150 bool startAllDay = false;
151 QString icalRaw;
152 QString resourceIcal;
153 QString syncState;
154 QString parentUid;
155 QString rrule;
156 QStringList tags;
157 QList<QDateTime> alarmTimes;
158 // S106-351: X-APPLE-SORT-ORDER is server text; stored values stay within
159 // ±kTaskSortOrderLimit so order arithmetic never overflows.
160 qint64 sortOrder = 0;
161 bool readOnly = false;
162 QString previousStatus;
163 int previousPercent = 0;
164
165 /// Nextcloud Tasks: priority 1 = starred/important
166
3/4
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 5 not taken.
3 bool isStarred() const { return priority >= 1 && priority <= 4; }
167 };
168
169 779698 inline QString taskSelectionKey(const CalendarTask &task) {
170
3/3
✓ Branch 4 → 5 taken 779698 times.
✓ Branch 5 → 6 taken 779698 times.
✓ Branch 6 → 7 taken 779698 times.
779698 return calendarSelectionKey(task.accountId, task.calendarPath) + QLatin1Char('\n') + task.uid;
171 }
172