summaryrefslogtreecommitdiffstats
path: root/src/calendarstore.cpp
diff options
context:
space:
mode:
authorDanilo M. <danix@danix.xyz>2026-09-24 17:50:47 +0200
committerDanilo M. <danix@danix.xyz>2026-09-24 17:50:47 +0200
commitff40d2a6dffdf234ade8bc4a5faa7624e58d5379 (patch)
treecf7b2469957db7d6d602cd4532263750eecdb9c4 /src/calendarstore.cpp
parent7494ce76f1eefc2a9a2112d2f2ffec4709d90e08 (diff)
downloadqtmaildir-ff40d2a6dffdf234ade8bc4a5faa7624e58d5379.tar.gz
qtmaildir-ff40d2a6dffdf234ade8bc4a5faa7624e58d5379.zip
fix: drop orphaned overrides when a series stops, plus review minors
Diffstat (limited to 'src/calendarstore.cpp')
-rw-r--r--src/calendarstore.cpp26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/calendarstore.cpp b/src/calendarstore.cpp
index ef67eba..619ffb9 100644
--- a/src/calendarstore.cpp
+++ b/src/calendarstore.cpp
@@ -363,8 +363,25 @@ void writeFields(icalcomponent *root, icalcomponent *c, const EventEdit &edit, b
if (!master || edit.repeat.custom)
return; // a custom RRULE is never rewritten (spec, repeat control)
removeAll(c, ICAL_RRULE_PROPERTY);
- if (edit.repeat.freq == RepeatRule::Freq::None)
+ if (edit.repeat.freq == RepeatRule::Freq::None) {
+ // Stopping a series orphans its RECURRENCE-ID overrides: occurrences()
+ // skips the override loop for a non-repeating event, so they would
+ // vanish from every view while staying in the synced file, ready to
+ // spring back if a repeat is re-enabled. EXDATEs are inert once the
+ // series does not repeat, and removing them would drop data, so they
+ // stay. Collect first: removing a component mid-walk invalidates it.
+ QList<icalcomponent *> doomed;
+ for (icalcomponent *v = icalcomponent_get_first_component(root, ICAL_VEVENT_COMPONENT);
+ v; v = icalcomponent_get_next_component(root, ICAL_VEVENT_COMPONENT)) {
+ if (v != c && icalcomponent_get_first_property(v, ICAL_RECURRENCEID_PROPERTY))
+ doomed.append(v);
+ }
+ for (icalcomponent *v : doomed) {
+ icalcomponent_remove_component(root, v);
+ icalcomponent_free(v);
+ }
return;
+ }
// UNTIL follows DTSTART's type: a DATE for all-day, else UTC (RFC 5545).
QString until;
if (edit.repeat.end == RepeatRule::End::Until) {
@@ -667,8 +684,13 @@ bool sameMeaning(const QByteArray &a, const QByteArray &b)
|| p.end != q.end || p.summary != q.summary || p.cancelled != q.cancelled)
return false;
}
+ // EXDATE properties are a SET: a server may reorder them, so compare
+ // sorted copies rather than the lists as read.
+ QList<QDateTime> xd = x.exdates, yd = y.exdates;
+ std::sort(xd.begin(), xd.end());
+ std::sort(yd.begin(), yd.end());
return x.summary == y.summary && x.start == y.start && x.end == y.end
- && x.allDay == y.allDay && x.repeat == y.repeat && x.exdates == y.exdates;
+ && x.allDay == y.allDay && x.repeat == y.repeat && xd == yd;
}
} // namespace CalendarStore