Commit d2a82eae authored by Damien Caliste's avatar Damien Caliste

Use the recurrenceId to delete the right occurrence.

parent 27f6d544
...@@ -404,3 +404,47 @@ void MemoryCalendarTest::testRawEvents() ...@@ -404,3 +404,47 @@ void MemoryCalendarTest::testRawEvents()
cal->close(); cal->close();
} }
void MemoryCalendarTest::testDeleteIncidence()
{
MemoryCalendar::Ptr cal(new MemoryCalendar(QTimeZone::utc()));
Event::Ptr event = Event::Ptr(new Event());
event->setDtStart(QDateTime(QDate(2021, 1, 4), QTime(10, 13),
QTimeZone("Europe/Paris")));
QVERIFY(cal->addEvent(event));
QVERIFY(cal->instance(event->instanceIdentifier()));
QVERIFY(cal->deleteIncidence(event));
QVERIFY(cal->instance(event->instanceIdentifier()).isNull());
event->recurrence()->setDaily(1);
event->recurrence()->setDuration(3);
QVERIFY(cal->addEvent(event));
QVERIFY(cal->instance(event->instanceIdentifier()));
Event::Ptr exception = Event::Ptr(event->clone());
exception->recurrence()->clear();
exception->setRecurrenceId(event->dtStart().addDays(1));
exception->setDtStart(event->dtStart().addDays(1).addSecs(3600));
QVERIFY(cal->addEvent(exception));
QVERIFY(cal->instance(exception->instanceIdentifier()));
Event::Ptr exception2 = Event::Ptr(event->clone());
exception2->recurrence()->clear();
exception2->setRecurrenceId(event->dtStart().addDays(2));
exception2->setDtStart(event->dtStart().addDays(2).addSecs(-3600));
QVERIFY(cal->addEvent(exception2));
QVERIFY(cal->instance(exception2->instanceIdentifier()));
QVERIFY(cal->deleteIncidence(exception));
QVERIFY(cal->incidence(event->uid(), exception->recurrenceId()).isNull());
QVERIFY(!cal->deleteIncidence(exception));
QVERIFY(cal->incidence(event->uid(), exception2->recurrenceId()));
QVERIFY(cal->incidence(event->uid()));
QVERIFY(cal->deleteIncidence(event));
QVERIFY(cal->incidence(event->uid(), exception2->recurrenceId()).isNull());
QVERIFY(cal->incidence(event->uid()).isNull());
}
...@@ -26,6 +26,7 @@ private Q_SLOTS: ...@@ -26,6 +26,7 @@ private Q_SLOTS:
void testRawEvents(); void testRawEvents();
void testRawEventsForDate(); void testRawEventsForDate();
void testVisibility(); void testVisibility();
void testDeleteIncidence();
}; };
#endif #endif
...@@ -89,6 +89,10 @@ public: ...@@ -89,6 +89,10 @@ public:
IncidenceBase::IncidenceType type, IncidenceBase::IncidenceType type,
const QDateTime &recurrenceId = {}) const; const QDateTime &recurrenceId = {}) const;
bool deleteIncidence(const QString &uid,
IncidenceBase::IncidenceType type,
const QDateTime &recurrenceId = {});
Incidence::Ptr deletedIncidence(const QString &uid, Incidence::Ptr deletedIncidence(const QString &uid,
const QDateTime &recurrenceId, const QDateTime &recurrenceId,
IncidenceBase::IncidenceType type) const; IncidenceBase::IncidenceType type) const;
...@@ -209,54 +213,74 @@ bool MemoryCalendar::deleteIncidence(const Incidence::Ptr &incidence) ...@@ -209,54 +213,74 @@ bool MemoryCalendar::deleteIncidence(const Incidence::Ptr &incidence)
// relations is an Incidence's property, not a Todo's, so // relations is an Incidence's property, not a Todo's, so
// we remove relations in deleteIncidence, not in deleteTodo. // we remove relations in deleteIncidence, not in deleteTodo.
removeRelations(incidence); removeRelations(incidence);
// Notify while the incidence is still available,
// this is necessary so korganizer still has time to query for exceptions
notifyIncidenceAboutToBeDeleted(incidence);
const Incidence::IncidenceType type = incidence->type(); const Incidence::IncidenceType type = incidence->type();
const QString uid = incidence->uid(); const QString &uid = incidence->uid();
auto incidenceIt = d->mIncidences[type].constFind(uid); bool deleted = d->deleteIncidence(uid, type, incidence->recurrenceId());
if (incidenceIt != d->mIncidences[type].cend()) { if (deleted) {
// Notify while the incidence is still available,
// this is necessary so korganizer still has time to query for exceptions
notifyIncidenceAboutToBeDeleted(incidence);
d->mIncidences[type].erase(incidenceIt);
d->mIncidencesByIdentifier.remove(incidence->instanceIdentifier());
setModified(true); setModified(true);
if (deletionTracking()) { if (deletionTracking()) {
d->mDeletedIncidences[type].insert(uid, incidence); d->mDeletedIncidences[type].insert(uid, incidence);
} }
const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing);
if (dt.isValid()) {
d->mIncidencesForDate[type].remove(dt.toTimeZone(timeZone()).date(), incidence);
}
// Delete child-incidences. // Delete child-incidences.
if (!incidence->hasRecurrenceId()) { if (!incidence->hasRecurrenceId() && incidence->recurs()) {
deleteIncidenceInstances(incidence); deleteIncidenceInstances(incidence);
} }
notifyIncidenceDeleted(incidence);
return true;
} else { } else {
qCWarning(KCALCORE_LOG) << incidence->typeStr() << " not found. uid=" << uid; qCWarning(KCALCORE_LOG) << incidence->typeStr() << " not found. uid=" << uid;
return false;
} }
notifyIncidenceDeleted(incidence);
return deleted;
} }
bool MemoryCalendar::deleteIncidenceInstances(const Incidence::Ptr &incidence) bool MemoryCalendar::deleteIncidenceInstances(const Incidence::Ptr &incidence)
{ {
d->forIncidences<Incidence>(d->mIncidences[incidence->type()], incidence->uid(), [this](const Incidence::Ptr &incidence) { Incidence::List instances;
if (incidence->hasRecurrenceId()) { for (auto it = d->mIncidences[incidence->type()].constFind(incidence->uid()), end = d->mIncidences[incidence->type()].constEnd(); it != end && it.key() == incidence->uid(); ++it) {
if (it.value()->hasRecurrenceId()) {
qCDebug(KCALCORE_LOG) << "deleting child" qCDebug(KCALCORE_LOG) << "deleting child"
<< ", type=" << int(incidence->type()) << ", type=" << int(incidence->type())
<< ", uid=" << incidence->uid() << ", uid=" << incidence->uid()
// << ", start=" << i->dtStart() // << ", start=" << i->dtStart()
<< " from calendar"; << " from calendar";
deleteIncidence(incidence); // Don't call deleteIncidence() now since it's modifying the
// mIncidences map we're iterating over.
instances.append(it.value());
} }
}); }
for (Incidence::Ptr instance : instances) {
deleteIncidence(instance);
}
return true; return true;
} }
//@cond PRIVATE //@cond PRIVATE
bool MemoryCalendar::Private::deleteIncidence(const QString &uid,
IncidenceBase::IncidenceType type,
const QDateTime &recurrenceId)
{
for (auto it = mIncidences[type].find(uid), end = mIncidences[type].end(); it != end && it.key() == uid; ++it) {
Incidence::Ptr incidence = it.value();
if (recurrenceId.isNull() && incidence->hasRecurrenceId()) {
continue;
} else if (!recurrenceId.isNull() && (!incidence->hasRecurrenceId() || recurrenceId != incidence->recurrenceId())) {
continue;
}
mIncidences[type].erase(it);
mIncidencesByIdentifier.remove(incidence->instanceIdentifier());
const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing);
if (dt.isValid()) {
mIncidencesForDate[type].remove(dt.toTimeZone(q->timeZone()).date(), incidence);
}
return true;
}
return false;
}
void MemoryCalendar::Private::deleteAllIncidences(Incidence::IncidenceType incidenceType) void MemoryCalendar::Private::deleteAllIncidences(Incidence::IncidenceType incidenceType)
{ {
for (auto &incidence : mIncidences[incidenceType]) { for (auto &incidence : mIncidences[incidenceType]) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment