File indexing completed on 2024-03-24 03:55:37
0001 /* 0002 This file is part of the kcalcore library. 0003 0004 SPDX-FileCopyrightText: 1998 Preston Brown <pbrown@kde.org> 0005 SPDX-FileCopyrightText: 2001, 2003, 2004 Cornelius Schumacher <schumacher@kde.org> 0006 SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 0007 0008 SPDX-License-Identifier: LGPL-2.0-or-later 0009 */ 0010 /** 0011 @file 0012 This file is part of the API for handling calendar data and 0013 defines the MemoryCalendar class. 0014 0015 @brief 0016 This class provides a calendar stored as a local file. 0017 0018 @author Preston Brown \<pbrown@kde.org\> 0019 @author Cornelius Schumacher \<schumacher@kde.org\> 0020 */ 0021 0022 #include "memorycalendar.h" 0023 #include "calformat.h" 0024 #include "kcalendarcore_debug.h" 0025 0026 #include <QDate> 0027 0028 #include <functional> 0029 0030 using namespace KCalendarCore; 0031 0032 /** 0033 Private class that helps to provide binary compatibility between releases. 0034 @internal 0035 */ 0036 //@cond PRIVATE 0037 class Q_DECL_HIDDEN KCalendarCore::MemoryCalendar::Private 0038 { 0039 private: 0040 static constexpr int incidenceTypeCount = 4; 0041 0042 public: 0043 Private(MemoryCalendar *qq) 0044 : q(qq) 0045 , mFormat(nullptr) 0046 , mUpdateLastModified(true) 0047 { 0048 } 0049 ~Private() 0050 { 0051 } 0052 0053 MemoryCalendar *q; 0054 CalFormat *mFormat; // calendar format 0055 QString mIncidenceBeingUpdated; // Instance identifier of Incidence currently being updated 0056 bool mUpdateLastModified; // Call setLastModified() on incidence modific ations 0057 0058 /** 0059 * List of all incidences. 0060 * First indexed by incidence->type(), then by incidence->uid(); 0061 */ 0062 QMultiHash<QString, Incidence::Ptr> mIncidences[incidenceTypeCount]; 0063 0064 /** 0065 * Has all incidences, indexed by identifier. 0066 */ 0067 QHash<QString, KCalendarCore::Incidence::Ptr> mIncidencesByIdentifier; 0068 0069 /** 0070 * Contains incidences ( to-dos; non-recurring, non-multiday events; journals; ) 0071 * indexed by start/due date. 0072 * 0073 * The QMap key is the incidence->type(). 0074 * The QMultiHash key is the dtStart/dtDue() converted to calendar's timezone 0075 * 0076 * Note: We had 3 variables, mJournalsForDate, mTodosForDate and mEventsForDate 0077 * but i merged them into one (indexed by type) because it simplifies code using 0078 * it. No need to if else based on type. 0079 */ 0080 QMultiHash<QDate, Incidence::Ptr> mIncidencesForDate[incidenceTypeCount]; 0081 0082 void insertIncidence(const Incidence::Ptr &incidence); 0083 0084 Incidence::Ptr incidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId = {}) const; 0085 0086 bool deleteIncidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId = {}); 0087 0088 void deleteAllIncidences(IncidenceBase::IncidenceType type); 0089 0090 template<typename IncidenceType, typename Key> 0091 void forIncidences(const QMultiHash<Key, Incidence::Ptr> &incidences, const Key &key, std::function<void(const typename IncidenceType::Ptr &)> &&op) const 0092 { 0093 for (auto it = incidences.constFind(key), end = incidences.cend(); it != end && it.key() == key; ++it) { 0094 op(it.value().template staticCast<IncidenceType>()); 0095 } 0096 } 0097 0098 template<typename IncidenceType, typename Key> 0099 void forIncidences(const QMultiHash<Key, Incidence::Ptr> &incidences, std::function<void(const typename IncidenceType::Ptr &)> &&op) const 0100 { 0101 for (const auto &incidence : incidences) { 0102 op(incidence.template staticCast<IncidenceType>()); 0103 } 0104 } 0105 0106 template<typename IncidenceType> 0107 typename IncidenceType::List castIncidenceList(const QMultiHash<QString, Incidence::Ptr> &incidences) const 0108 { 0109 typename IncidenceType::List list; 0110 list.reserve(incidences.size()); 0111 std::transform(incidences.cbegin(), incidences.cend(), std::back_inserter(list), [](const Incidence::Ptr &inc) { 0112 return inc.staticCast<IncidenceType>(); 0113 }); 0114 return list; 0115 } 0116 0117 template<typename IncidenceType> 0118 typename IncidenceType::List incidenceInstances(IncidenceBase::IncidenceType type, const Incidence::Ptr &incidence) const 0119 { 0120 typename IncidenceType::List list; 0121 forIncidences<IncidenceType, QString>(mIncidences[type], incidence->uid(), [&list](const typename IncidenceType::Ptr &incidence) { 0122 if (incidence->hasRecurrenceId()) { 0123 list.push_back(incidence); 0124 } 0125 }); 0126 return list; 0127 } 0128 0129 Incidence::Ptr findIncidence(const QMultiHash<QString, Incidence::Ptr> &incidences, const QString &uid, const QDateTime &recurrenceId) const 0130 { 0131 for (auto it = incidences.constFind(uid), end = incidences.cend(); it != end && it.key() == uid; ++it) { 0132 const auto &incidence = it.value(); 0133 if (recurrenceId.isNull() && !incidence->hasRecurrenceId()) { 0134 return incidence; 0135 } else if (!recurrenceId.isNull() && incidence->hasRecurrenceId() && recurrenceId == incidence->recurrenceId()) { 0136 return incidence; 0137 } 0138 } 0139 return {}; 0140 } 0141 }; 0142 //@endcond 0143 0144 MemoryCalendar::MemoryCalendar(const QTimeZone &timeZone) 0145 : Calendar(timeZone) 0146 , d(new KCalendarCore::MemoryCalendar::Private(this)) 0147 { 0148 } 0149 0150 MemoryCalendar::MemoryCalendar(const QByteArray &timeZoneId) 0151 : Calendar(timeZoneId) 0152 , d(new KCalendarCore::MemoryCalendar::Private(this)) 0153 { 0154 } 0155 0156 MemoryCalendar::~MemoryCalendar() 0157 { 0158 setObserversEnabled(false); 0159 0160 // Don't call the virtual function deleteEvents() etc, the base class might have 0161 // other ways of deleting the data. 0162 d->deleteAllIncidences(Incidence::TypeEvent); 0163 d->deleteAllIncidences(Incidence::TypeTodo); 0164 d->deleteAllIncidences(Incidence::TypeJournal); 0165 0166 d->mIncidencesByIdentifier.clear(); 0167 0168 setModified(false); 0169 0170 setObserversEnabled(true); 0171 0172 delete d; 0173 } 0174 0175 void MemoryCalendar::doSetTimeZone(const QTimeZone &timeZone) 0176 { 0177 // Reset date based hashes before storing for the new zone. 0178 for (auto &table : d->mIncidencesForDate) { 0179 table.clear(); 0180 } 0181 0182 for (auto &table : d->mIncidences) { 0183 for (const auto &incidence : table) { 0184 const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing); 0185 if (dt.isValid()) { 0186 d->mIncidencesForDate[incidence->type()].insert(dt.toTimeZone(timeZone).date(), incidence); 0187 } 0188 } 0189 } 0190 } 0191 0192 bool MemoryCalendar::deleteIncidence(const Incidence::Ptr &incidence) 0193 { 0194 // Notify while the incidence is still available, 0195 // this is necessary so korganizer still has time to query for exceptions 0196 notifyIncidenceAboutToBeDeleted(incidence); 0197 incidence->unRegisterObserver(this); 0198 const Incidence::IncidenceType type = incidence->type(); 0199 const QString &uid = incidence->uid(); 0200 bool deleted = d->deleteIncidence(uid, type, incidence->recurrenceId()); 0201 if (deleted) { 0202 setModified(true); 0203 0204 // Delete child-incidences. 0205 if (!incidence->hasRecurrenceId() && incidence->recurs()) { 0206 deleteIncidenceInstances(incidence); 0207 } 0208 } else { 0209 qCWarning(KCALCORE_LOG) << incidence->typeStr() << " not found. uid=" << uid; 0210 } 0211 notifyIncidenceDeleted(incidence); 0212 return deleted; 0213 } 0214 0215 bool MemoryCalendar::deleteIncidenceInstances(const Incidence::Ptr &incidence) 0216 { 0217 Incidence::List instances; 0218 for (auto it = d->mIncidences[incidence->type()].constFind(incidence->uid()), end = d->mIncidences[incidence->type()].constEnd(); 0219 it != end && it.key() == incidence->uid(); 0220 ++it) { 0221 if (it.value()->hasRecurrenceId()) { 0222 qCDebug(KCALCORE_LOG) << "deleting child" 0223 << ", type=" << int(incidence->type()) << ", uid=" 0224 << incidence->uid() 0225 // << ", start=" << i->dtStart() 0226 << " from calendar"; 0227 // Don't call deleteIncidence() now since it's modifying the 0228 // mIncidences map we're iterating over. 0229 instances.append(it.value()); 0230 } 0231 } 0232 for (Incidence::Ptr instance : instances) { 0233 deleteIncidence(instance); 0234 } 0235 0236 return true; 0237 } 0238 0239 //@cond PRIVATE 0240 bool MemoryCalendar::Private::deleteIncidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId) 0241 { 0242 for (auto it = mIncidences[type].find(uid), end = mIncidences[type].end(); it != end && it.key() == uid; ++it) { 0243 Incidence::Ptr incidence = it.value(); 0244 if (recurrenceId.isNull() && incidence->hasRecurrenceId()) { 0245 continue; 0246 } else if (!recurrenceId.isNull() && (!incidence->hasRecurrenceId() || recurrenceId != incidence->recurrenceId())) { 0247 continue; 0248 } 0249 mIncidences[type].erase(it); 0250 mIncidencesByIdentifier.remove(incidence->instanceIdentifier()); 0251 const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing); 0252 if (dt.isValid()) { 0253 mIncidencesForDate[type].remove(dt.toTimeZone(q->timeZone()).date(), incidence); 0254 } 0255 return true; 0256 } 0257 return false; 0258 } 0259 0260 void MemoryCalendar::Private::deleteAllIncidences(Incidence::IncidenceType incidenceType) 0261 { 0262 for (auto &incidence : mIncidences[incidenceType]) { 0263 q->notifyIncidenceAboutToBeDeleted(incidence); 0264 incidence->unRegisterObserver(q); 0265 } 0266 mIncidences[incidenceType].clear(); 0267 mIncidencesForDate[incidenceType].clear(); 0268 } 0269 0270 Incidence::Ptr MemoryCalendar::Private::incidence(const QString &uid, Incidence::IncidenceType type, const QDateTime &recurrenceId) const 0271 { 0272 return findIncidence(mIncidences[type], uid, recurrenceId); 0273 } 0274 0275 void MemoryCalendar::Private::insertIncidence(const Incidence::Ptr &incidence) 0276 { 0277 const QString uid = incidence->uid(); 0278 const Incidence::IncidenceType type = incidence->type(); 0279 if (!mIncidences[type].contains(uid, incidence)) { 0280 mIncidences[type].insert(uid, incidence); 0281 mIncidencesByIdentifier.insert(incidence->instanceIdentifier(), incidence); 0282 const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing); 0283 if (dt.isValid()) { 0284 mIncidencesForDate[type].insert(dt.toTimeZone(q->timeZone()).date(), incidence); 0285 } 0286 0287 } else { 0288 #ifndef NDEBUG 0289 // if we already have an to-do with this UID, it must be the same incidence, 0290 // otherwise something's really broken 0291 Q_ASSERT(mIncidences[type].value(uid) == incidence); 0292 #endif 0293 } 0294 } 0295 //@endcond 0296 0297 bool MemoryCalendar::addIncidence(const Incidence::Ptr &incidence) 0298 { 0299 d->insertIncidence(incidence); 0300 0301 notifyIncidenceAdded(incidence); 0302 0303 incidence->registerObserver(this); 0304 0305 setModified(true); 0306 0307 return true; 0308 } 0309 0310 bool MemoryCalendar::addEvent(const Event::Ptr &event) 0311 { 0312 return addIncidence(event); 0313 } 0314 0315 bool MemoryCalendar::deleteEvent(const Event::Ptr &event) 0316 { 0317 return deleteIncidence(event); 0318 } 0319 0320 bool MemoryCalendar::deleteEventInstances(const Event::Ptr &event) 0321 { 0322 return deleteIncidenceInstances(event); 0323 } 0324 0325 Event::Ptr MemoryCalendar::event(const QString &uid, const QDateTime &recurrenceId) const 0326 { 0327 return d->incidence(uid, Incidence::TypeEvent, recurrenceId).staticCast<Event>(); 0328 } 0329 0330 bool MemoryCalendar::addTodo(const Todo::Ptr &todo) 0331 { 0332 return addIncidence(todo); 0333 } 0334 0335 bool MemoryCalendar::deleteTodo(const Todo::Ptr &todo) 0336 { 0337 return deleteIncidence(todo); 0338 } 0339 0340 bool MemoryCalendar::deleteTodoInstances(const Todo::Ptr &todo) 0341 { 0342 return deleteIncidenceInstances(todo); 0343 } 0344 0345 Todo::Ptr MemoryCalendar::todo(const QString &uid, const QDateTime &recurrenceId) const 0346 { 0347 return d->incidence(uid, Incidence::TypeTodo, recurrenceId).staticCast<Todo>(); 0348 } 0349 0350 Todo::List MemoryCalendar::rawTodos(TodoSortField sortField, SortDirection sortDirection) const 0351 { 0352 return Calendar::sortTodos(d->castIncidenceList<Todo>(d->mIncidences[Incidence::TypeTodo]), sortField, sortDirection); 0353 } 0354 0355 Todo::List MemoryCalendar::todoInstances(const Incidence::Ptr &todo, TodoSortField sortField, SortDirection sortDirection) const 0356 { 0357 return Calendar::sortTodos(d->incidenceInstances<Todo>(Incidence::TypeTodo, todo), sortField, sortDirection); 0358 } 0359 0360 Todo::List MemoryCalendar::rawTodosForDate(const QDate &date) const 0361 { 0362 Todo::List todoList; 0363 0364 d->forIncidences<Todo>(d->mIncidencesForDate[Incidence::TypeTodo], date, [&todoList](const Todo::Ptr &todo) { 0365 todoList.append(todo); 0366 }); 0367 0368 // Iterate over all todos. Look for recurring todoss that occur on this date 0369 d->forIncidences<Todo>(d->mIncidences[Incidence::TypeTodo], [this, &todoList, &date](const Todo::Ptr &todo) { 0370 if (todo->recurs() && todo->recursOn(date, timeZone())) { 0371 todoList.append(todo); 0372 } 0373 }); 0374 0375 return todoList; 0376 } 0377 0378 Todo::List MemoryCalendar::rawTodos(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const 0379 { 0380 Q_UNUSED(inclusive); // use only exact dtDue/dtStart, not dtStart and dtEnd 0381 0382 Todo::List todoList; 0383 const auto ts = timeZone.isValid() ? timeZone : this->timeZone(); 0384 QDateTime st(start, QTime(0, 0, 0), ts); 0385 QDateTime nd(end, QTime(23, 59, 59, 999), ts); 0386 0387 // Get todos 0388 for (const auto &incidence : d->mIncidences[Incidence::TypeTodo]) { 0389 const auto todo = incidence.staticCast<Todo>(); 0390 0391 QDateTime rStart = todo->hasDueDate() ? todo->dtDue() : todo->hasStartDate() ? todo->dtStart() : QDateTime(); 0392 if (!rStart.isValid()) { 0393 continue; 0394 } 0395 0396 if (!todo->recurs()) { // non-recurring todos 0397 if (nd.isValid() && nd < rStart) { 0398 continue; 0399 } 0400 if (st.isValid() && rStart < st) { 0401 continue; 0402 } 0403 } else { // recurring events 0404 switch (todo->recurrence()->duration()) { 0405 case -1: // infinite 0406 break; 0407 case 0: // end date given 0408 default: // count given 0409 QDateTime rEnd(todo->recurrence()->endDate(), QTime(23, 59, 59, 999), ts); 0410 if (!rEnd.isValid()) { 0411 continue; 0412 } 0413 if (st.isValid() && rEnd < st) { 0414 continue; 0415 } 0416 break; 0417 } // switch(duration) 0418 } // if(recurs) 0419 0420 todoList.append(todo); 0421 } 0422 0423 return todoList; 0424 } 0425 0426 Alarm::List MemoryCalendar::alarms(const QDateTime &from, const QDateTime &to, bool excludeBlockedAlarms) const 0427 { 0428 Q_UNUSED(excludeBlockedAlarms); 0429 Alarm::List alarmList; 0430 0431 d->forIncidences<Event>(d->mIncidences[Incidence::TypeEvent], [this, &alarmList, &from, &to](const Event::Ptr &e) { 0432 if (e->recurs()) { 0433 appendRecurringAlarms(alarmList, e, from, to); 0434 } else { 0435 appendAlarms(alarmList, e, from, to); 0436 } 0437 }); 0438 0439 d->forIncidences<Todo>(d->mIncidences[IncidenceBase::TypeTodo], [this, &alarmList, &from, &to](const Todo::Ptr &t) { 0440 if (!t->isCompleted()) { 0441 appendAlarms(alarmList, t, from, to); 0442 if (t->recurs()) { 0443 appendRecurringAlarms(alarmList, t, from, to); 0444 } else { 0445 appendAlarms(alarmList, t, from, to); 0446 } 0447 } 0448 }); 0449 0450 return alarmList; 0451 } 0452 0453 bool MemoryCalendar::updateLastModifiedOnChange() const 0454 { 0455 return d->mUpdateLastModified; 0456 } 0457 0458 void MemoryCalendar::setUpdateLastModifiedOnChange(bool update) 0459 { 0460 d->mUpdateLastModified = update; 0461 } 0462 0463 void MemoryCalendar::incidenceUpdate(const QString &uid, const QDateTime &recurrenceId) 0464 { 0465 Incidence::Ptr inc = incidence(uid, recurrenceId); 0466 0467 if (inc) { 0468 if (!d->mIncidenceBeingUpdated.isEmpty()) { 0469 qCWarning(KCALCORE_LOG) << "Incidence::update() called twice without an updated() call in between."; 0470 } 0471 0472 // Save it so we can detect changes to uid or recurringId. 0473 d->mIncidenceBeingUpdated = inc->instanceIdentifier(); 0474 0475 const QDateTime dt = inc->dateTime(Incidence::RoleCalendarHashing); 0476 if (dt.isValid()) { 0477 d->mIncidencesForDate[inc->type()].remove(dt.toTimeZone(timeZone()).date(), inc); 0478 } 0479 } 0480 } 0481 0482 void MemoryCalendar::incidenceUpdated(const QString &uid, const QDateTime &recurrenceId) 0483 { 0484 Incidence::Ptr inc = incidence(uid, recurrenceId); 0485 0486 if (inc) { 0487 if (d->mIncidenceBeingUpdated.isEmpty()) { 0488 qCWarning(KCALCORE_LOG) << "Incidence::updated() called twice without an update() call in between."; 0489 } else if (inc->instanceIdentifier() != d->mIncidenceBeingUpdated) { 0490 // Instance identifier changed, update our hash table 0491 d->mIncidencesByIdentifier.remove(d->mIncidenceBeingUpdated); 0492 d->mIncidencesByIdentifier.insert(inc->instanceIdentifier(), inc); 0493 } 0494 0495 d->mIncidenceBeingUpdated = QString(); 0496 0497 if (d->mUpdateLastModified) { 0498 inc->setLastModified(QDateTime::currentDateTimeUtc()); 0499 } 0500 // we should probably update the revision number here, 0501 // or internally in the Event itself when certain things change. 0502 // need to verify with ical documentation. 0503 0504 const QDateTime dt = inc->dateTime(Incidence::RoleCalendarHashing); 0505 if (dt.isValid()) { 0506 d->mIncidencesForDate[inc->type()].insert(dt.toTimeZone(timeZone()).date(), inc); 0507 } 0508 0509 notifyIncidenceChanged(inc); 0510 0511 setModified(true); 0512 } 0513 } 0514 0515 Event::List MemoryCalendar::rawEventsForDate(const QDate &date, const QTimeZone &timeZone, EventSortField sortField, SortDirection sortDirection) const 0516 { 0517 Event::List eventList; 0518 0519 if (!date.isValid()) { 0520 // There can't be events on invalid dates 0521 return eventList; 0522 } 0523 0524 if (timeZone.isValid() && timeZone != this->timeZone()) { 0525 // We cannot use the hash table on date, since time zone is different. 0526 eventList = rawEvents(date, date, timeZone, false); 0527 return Calendar::sortEvents(std::move(eventList), sortField, sortDirection); 0528 } 0529 0530 // Iterate over all non-recurring, single-day events that start on this date 0531 d->forIncidences<Event>(d->mIncidencesForDate[Incidence::TypeEvent], date, [&eventList](const Event::Ptr &event) { 0532 eventList.append(event); 0533 }); 0534 0535 // Iterate over all events. Look for recurring events that occur on this date 0536 const auto ts = timeZone.isValid() ? timeZone : this->timeZone(); 0537 for (const auto &event : d->mIncidences[Incidence::TypeEvent]) { 0538 const auto ev = event.staticCast<Event>(); 0539 if (ev->recurs()) { 0540 if (ev->isMultiDay()) { 0541 int extraDays = ev->dtStart().date().daysTo(ev->dtEnd().date()); 0542 for (int i = 0; i <= extraDays; ++i) { 0543 if (ev->recursOn(date.addDays(-i), ts)) { 0544 eventList.append(ev); 0545 break; 0546 } 0547 } 0548 } else { 0549 if (ev->recursOn(date, ts)) { 0550 eventList.append(ev); 0551 } 0552 } 0553 } else { 0554 if (ev->isMultiDay()) { 0555 if (ev->dtStart().toTimeZone(ts).date() <= date && ev->dtEnd().toTimeZone(ts).date() >= date) { 0556 eventList.append(ev); 0557 } 0558 } 0559 } 0560 } 0561 0562 return Calendar::sortEvents(std::move(eventList), sortField, sortDirection); 0563 } 0564 0565 Event::List MemoryCalendar::rawEvents(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const 0566 { 0567 Event::List eventList; 0568 const auto ts = timeZone.isValid() ? timeZone : this->timeZone(); 0569 QDateTime st(start, QTime(0, 0, 0), ts); 0570 QDateTime nd(end, QTime(23, 59, 59, 999), ts); 0571 0572 // Get non-recurring events 0573 for (const auto &e : d->mIncidences[Incidence::TypeEvent]) { 0574 const auto event = e.staticCast<Event>(); 0575 QDateTime rStart = event->dtStart(); 0576 if (nd.isValid() && nd < rStart) { 0577 continue; 0578 } 0579 if (inclusive && st.isValid() && rStart < st) { 0580 continue; 0581 } 0582 0583 if (!event->recurs()) { // non-recurring events 0584 QDateTime rEnd = event->dtEnd(); 0585 if (st.isValid() && rEnd < st) { 0586 continue; 0587 } 0588 if (inclusive && nd.isValid() && nd < rEnd) { 0589 continue; 0590 } 0591 } else { // recurring events 0592 switch (event->recurrence()->duration()) { 0593 case -1: // infinite 0594 if (inclusive) { 0595 continue; 0596 } 0597 break; 0598 case 0: // end date given 0599 default: // count given 0600 QDateTime rEnd(event->recurrence()->endDate(), QTime(23, 59, 59, 999), ts); 0601 if (!rEnd.isValid()) { 0602 continue; 0603 } 0604 if (st.isValid() && rEnd < st) { 0605 continue; 0606 } 0607 if (inclusive && nd.isValid() && nd < rEnd) { 0608 continue; 0609 } 0610 break; 0611 } // switch(duration) 0612 } // if(recurs) 0613 0614 eventList.append(event); 0615 } 0616 0617 return eventList; 0618 } 0619 0620 Event::List MemoryCalendar::rawEvents(EventSortField sortField, SortDirection sortDirection) const 0621 { 0622 return Calendar::sortEvents(d->castIncidenceList<Event>(d->mIncidences[Incidence::TypeEvent]), sortField, sortDirection); 0623 } 0624 0625 Event::List MemoryCalendar::eventInstances(const Incidence::Ptr &event, EventSortField sortField, SortDirection sortDirection) const 0626 { 0627 return Calendar::sortEvents(d->incidenceInstances<Event>(Incidence::TypeEvent, event), sortField, sortDirection); 0628 } 0629 0630 bool MemoryCalendar::addJournal(const Journal::Ptr &journal) 0631 { 0632 return addIncidence(journal); 0633 } 0634 0635 bool MemoryCalendar::deleteJournal(const Journal::Ptr &journal) 0636 { 0637 return deleteIncidence(journal); 0638 } 0639 0640 bool MemoryCalendar::deleteJournalInstances(const Journal::Ptr &journal) 0641 { 0642 return deleteIncidenceInstances(journal); 0643 } 0644 0645 Journal::Ptr MemoryCalendar::journal(const QString &uid, const QDateTime &recurrenceId) const 0646 { 0647 return d->incidence(uid, Incidence::TypeJournal, recurrenceId).staticCast<Journal>(); 0648 } 0649 0650 Journal::List MemoryCalendar::rawJournals(JournalSortField sortField, SortDirection sortDirection) const 0651 { 0652 return Calendar::sortJournals(d->castIncidenceList<Journal>(d->mIncidences[Incidence::TypeJournal]), sortField, sortDirection); 0653 } 0654 0655 Journal::List MemoryCalendar::journalInstances(const Incidence::Ptr &journal, JournalSortField sortField, SortDirection sortDirection) const 0656 { 0657 return Calendar::sortJournals(d->incidenceInstances<Journal>(Incidence::TypeJournal, journal), sortField, sortDirection); 0658 } 0659 0660 Journal::List MemoryCalendar::rawJournalsForDate(const QDate &date) const 0661 { 0662 Journal::List journalList; 0663 0664 d->forIncidences<Journal>(d->mIncidencesForDate[Incidence::TypeJournal], date, [&journalList](const Journal::Ptr &journal) { 0665 journalList.append(journal); 0666 }); 0667 0668 return journalList; 0669 } 0670 0671 Incidence::Ptr MemoryCalendar::instance(const QString &identifier) const 0672 { 0673 return d->mIncidencesByIdentifier.value(identifier); 0674 } 0675 0676 void MemoryCalendar::virtual_hook(int id, void *data) 0677 { 0678 Q_UNUSED(id); 0679 Q_UNUSED(data); 0680 Q_ASSERT(false); 0681 } 0682 0683 #include "moc_memorycalendar.cpp"