KCalendarCore

memorycalendar.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  SPDX-FileCopyrightText: 1998 Preston Brown <[email protected]>
5  SPDX-FileCopyrightText: 2001, 2003, 2004 Cornelius Schumacher <[email protected]>
6  SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.0-or-later
9 */
10 /**
11  @file
12  This file is part of the API for handling calendar data and
13  defines the MemoryCalendar class.
14 
15  @brief
16  This class provides a calendar stored as a local file.
17 
18  @author Preston Brown <[email protected]>
19  @author Cornelius Schumacher <[email protected]>
20  */
21 
22 #include "memorycalendar.h"
23 #include "calformat.h"
24 #include "kcalendarcore_debug.h"
25 
26 #include <QDate>
27 
28 #include <functional>
29 
30 using namespace KCalendarCore;
31 
32 /**
33  Private class that helps to provide binary compatibility between releases.
34  @internal
35 */
36 //@cond PRIVATE
37 class Q_DECL_HIDDEN KCalendarCore::MemoryCalendar::Private
38 {
39 private:
40  static constexpr int incidenceTypeCount = 4;
41 
42 public:
43  Private(MemoryCalendar *qq)
44  : q(qq)
45  , mFormat(nullptr)
46  , mUpdateLastModified(true)
47  {
48  }
49  ~Private()
50  {
51  }
52 
53  MemoryCalendar *q;
54  CalFormat *mFormat; // calendar format
55  QString mIncidenceBeingUpdated; // Instance identifier of Incidence currently being updated
56  bool mUpdateLastModified; // Call setLastModified() on incidence modific ations
57 
58  /**
59  * List of all incidences.
60  * First indexed by incidence->type(), then by incidence->uid();
61  */
62  QMultiHash<QString, Incidence::Ptr> mIncidences[incidenceTypeCount];
63 
64  /**
65  * Has all incidences, indexed by identifier.
66  */
67  QHash<QString, KCalendarCore::Incidence::Ptr> mIncidencesByIdentifier;
68 
69  /**
70  * List of all deleted incidences.
71  * First indexed by incidence->type(), then by incidence->uid();
72  */
73  QMultiHash<QString, Incidence::Ptr> mDeletedIncidences[incidenceTypeCount];
74 
75  /**
76  * Contains incidences ( to-dos; non-recurring, non-multiday events; journals; )
77  * indexed by start/due date.
78  *
79  * The QMap key is the incidence->type().
80  * The QMultiHash key is the dtStart/dtDue() converted to calendar's timezone
81  *
82  * Note: We had 3 variables, mJournalsForDate, mTodosForDate and mEventsForDate
83  * but i merged them into one (indexed by type) because it simplifies code using
84  * it. No need to if else based on type.
85  */
86  QMultiHash<QDate, Incidence::Ptr> mIncidencesForDate[incidenceTypeCount];
87 
88  void insertIncidence(const Incidence::Ptr &incidence);
89 
90  Incidence::Ptr incidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId = {}) const;
91 
92  bool deleteIncidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId = {});
93 
94  Incidence::Ptr deletedIncidence(const QString &uid, const QDateTime &recurrenceId, IncidenceBase::IncidenceType type) const;
95 
96  void deleteAllIncidences(IncidenceBase::IncidenceType type);
97 
98  template<typename IncidenceType, typename Key>
99  void forIncidences(const QMultiHash<Key, Incidence::Ptr> &incidences, const Key &key, std::function<void(const typename IncidenceType::Ptr &)> &&op) const
100  {
101  for (auto it = incidences.constFind(key), end = incidences.cend(); it != end && it.key() == key; ++it) {
102  op(it.value().template staticCast<IncidenceType>());
103  }
104  }
105 
106  template<typename IncidenceType, typename Key>
107  void forIncidences(const QMultiHash<Key, Incidence::Ptr> &incidences, std::function<void(const typename IncidenceType::Ptr &)> &&op) const
108  {
109  for (const auto &incidence : incidences) {
110  op(incidence.template staticCast<IncidenceType>());
111  }
112  }
113 
114  template<typename IncidenceType>
115  typename IncidenceType::List castIncidenceList(const QMultiHash<QString, Incidence::Ptr> &incidences) const
116  {
117  typename IncidenceType::List list;
118  list.reserve(incidences.size());
119  std::transform(incidences.cbegin(), incidences.cend(), std::back_inserter(list), [](const Incidence::Ptr &inc) {
120  return inc.staticCast<IncidenceType>();
121  });
122  return list;
123  }
124 
125  template<typename IncidenceType>
126  typename IncidenceType::List incidenceInstances(IncidenceBase::IncidenceType type, const Incidence::Ptr &incidence) const
127  {
128  typename IncidenceType::List list;
129  forIncidences<IncidenceType, QString>(mIncidences[type], incidence->uid(), [&list](const typename IncidenceType::Ptr &incidence) {
130  if (incidence->hasRecurrenceId()) {
131  list.push_back(incidence);
132  }
133  });
134  return list;
135  }
136 
137  Incidence::Ptr findIncidence(const QMultiHash<QString, Incidence::Ptr> &incidences, const QString &uid, const QDateTime &recurrenceId) const
138  {
139  for (auto it = incidences.constFind(uid), end = incidences.cend(); it != end && it.key() == uid; ++it) {
140  const auto &incidence = it.value();
141  if (recurrenceId.isNull() && !incidence->hasRecurrenceId()) {
142  return incidence;
143  } else if (!recurrenceId.isNull() && incidence->hasRecurrenceId() && recurrenceId == incidence->recurrenceId()) {
144  return incidence;
145  }
146  }
147  return {};
148  }
149 };
150 //@endcond
151 
153  : Calendar(timeZone)
154  , d(new KCalendarCore::MemoryCalendar::Private(this))
155 {
156 }
157 
159  : Calendar(timeZoneId)
160  , d(new KCalendarCore::MemoryCalendar::Private(this))
161 {
162 }
163 
165 {
166  close(); // NOLINT false clang-analyzer-optin.cplusplus.VirtualCall
167  delete d;
168 }
169 
170 void MemoryCalendar::doSetTimeZone(const QTimeZone &timeZone)
171 {
172  // Reset date based hashes before storing for the new zone.
173  for (auto &table : d->mIncidencesForDate) {
174  table.clear();
175  }
176 
177  for (auto &table : d->mIncidences) {
178  for (const auto &incidence : table) {
179  const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing);
180  if (dt.isValid()) {
181  d->mIncidencesForDate[incidence->type()].insert(dt.toTimeZone(timeZone).date(), incidence);
182  }
183  }
184  }
185 }
186 
188 {
189  setObserversEnabled(false);
190 
191  // Don't call the virtual function deleteEvents() etc, the base class might have
192  // other ways of deleting the data.
193  d->deleteAllIncidences(Incidence::TypeEvent);
194  d->deleteAllIncidences(Incidence::TypeTodo);
195  d->deleteAllIncidences(Incidence::TypeJournal);
196 
197  d->mIncidencesByIdentifier.clear();
198  for (auto &table : d->mDeletedIncidences) {
199  table.clear();
200  }
201 
202  clearNotebookAssociations();
203 
204  setModified(false);
205 
206  setObserversEnabled(true);
207 }
208 
209 bool MemoryCalendar::deleteIncidence(const Incidence::Ptr &incidence)
210 {
211  // Handle orphaned children
212  // relations is an Incidence's property, not a Todo's, so
213  // we remove relations in deleteIncidence, not in deleteTodo.
214  removeRelations(incidence);
215  // Notify while the incidence is still available,
216  // this is necessary so korganizer still has time to query for exceptions
217  notifyIncidenceAboutToBeDeleted(incidence);
218  incidence->unRegisterObserver(this);
219  const Incidence::IncidenceType type = incidence->type();
220  const QString &uid = incidence->uid();
221  bool deleted = d->deleteIncidence(uid, type, incidence->recurrenceId());
222  if (deleted) {
223  setModified(true);
224  if (deletionTracking()) {
225  d->mDeletedIncidences[type].insert(uid, incidence);
226  }
227 
228  // Delete child-incidences.
229  if (!incidence->hasRecurrenceId() && incidence->recurs()) {
230  deleteIncidenceInstances(incidence);
231  }
232  } else {
233  qCWarning(KCALCORE_LOG) << incidence->typeStr() << " not found. uid=" << uid;
234  }
235  notifyIncidenceDeleted(incidence);
236  return deleted;
237 }
238 
240 {
241  Incidence::List instances;
242  for (auto it = d->mIncidences[incidence->type()].constFind(incidence->uid()), end = d->mIncidences[incidence->type()].constEnd();
243  it != end && it.key() == incidence->uid();
244  ++it) {
245  if (it.value()->hasRecurrenceId()) {
246  qCDebug(KCALCORE_LOG) << "deleting child"
247  << ", type=" << int(incidence->type()) << ", uid="
248  << incidence->uid()
249  // << ", start=" << i->dtStart()
250  << " from calendar";
251  // Don't call deleteIncidence() now since it's modifying the
252  // mIncidences map we're iterating over.
253  instances.append(it.value());
254  }
255  }
256  for (Incidence::Ptr instance : instances) {
257  deleteIncidence(instance);
258  }
259 
260  return true;
261 }
262 
263 //@cond PRIVATE
264 bool MemoryCalendar::Private::deleteIncidence(const QString &uid, IncidenceBase::IncidenceType type, const QDateTime &recurrenceId)
265 {
266  for (auto it = mIncidences[type].find(uid), end = mIncidences[type].end(); it != end && it.key() == uid; ++it) {
267  Incidence::Ptr incidence = it.value();
268  if (recurrenceId.isNull() && incidence->hasRecurrenceId()) {
269  continue;
270  } else if (!recurrenceId.isNull() && (!incidence->hasRecurrenceId() || recurrenceId != incidence->recurrenceId())) {
271  continue;
272  }
273  mIncidences[type].erase(it);
274  mIncidencesByIdentifier.remove(incidence->instanceIdentifier());
275  const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing);
276  if (dt.isValid()) {
277  mIncidencesForDate[type].remove(dt.toTimeZone(q->timeZone()).date(), incidence);
278  }
279  return true;
280  }
281  return false;
282 }
283 
284 void MemoryCalendar::Private::deleteAllIncidences(Incidence::IncidenceType incidenceType)
285 {
286  for (auto &incidence : mIncidences[incidenceType]) {
287  q->notifyIncidenceAboutToBeDeleted(incidence);
288  incidence->unRegisterObserver(q);
289  }
290  mIncidences[incidenceType].clear();
291  mIncidencesForDate[incidenceType].clear();
292 }
293 
294 Incidence::Ptr MemoryCalendar::Private::incidence(const QString &uid, Incidence::IncidenceType type, const QDateTime &recurrenceId) const
295 {
296  return findIncidence(mIncidences[type], uid, recurrenceId);
297 }
298 
299 Incidence::Ptr MemoryCalendar::Private::deletedIncidence(const QString &uid, const QDateTime &recurrenceId, IncidenceBase::IncidenceType type) const
300 {
301  if (!q->deletionTracking()) {
302  return Incidence::Ptr();
303  }
304 
305  return findIncidence(mDeletedIncidences[type], uid, recurrenceId);
306 }
307 
308 void MemoryCalendar::Private::insertIncidence(const Incidence::Ptr &incidence)
309 {
310  const QString uid = incidence->uid();
311  const Incidence::IncidenceType type = incidence->type();
312  if (!mIncidences[type].contains(uid, incidence)) {
313  mIncidences[type].insert(uid, incidence);
314  mIncidencesByIdentifier.insert(incidence->instanceIdentifier(), incidence);
315  const QDateTime dt = incidence->dateTime(Incidence::RoleCalendarHashing);
316  if (dt.isValid()) {
317  mIncidencesForDate[type].insert(dt.toTimeZone(q->timeZone()).date(), incidence);
318  }
319 
320  } else {
321 #ifndef NDEBUG
322  // if we already have an to-do with this UID, it must be the same incidence,
323  // otherwise something's really broken
324  Q_ASSERT(mIncidences[type].value(uid) == incidence);
325 #endif
326  }
327 }
328 //@endcond
329 
330 bool MemoryCalendar::addIncidence(const Incidence::Ptr &incidence)
331 {
332  d->insertIncidence(incidence);
333 
334  notifyIncidenceAdded(incidence);
335 
336  incidence->registerObserver(this);
337 
338  setupRelations(incidence);
339 
340  setModified(true);
341 
342  return true;
343 }
344 
345 bool MemoryCalendar::addEvent(const Event::Ptr &event)
346 {
347  return addIncidence(event);
348 }
349 
350 bool MemoryCalendar::deleteEvent(const Event::Ptr &event)
351 {
352  return deleteIncidence(event);
353 }
354 
356 {
357  return deleteIncidenceInstances(event);
358 }
359 
360 Event::Ptr MemoryCalendar::event(const QString &uid, const QDateTime &recurrenceId) const
361 {
362  return d->incidence(uid, Incidence::TypeEvent, recurrenceId).staticCast<Event>();
363 }
364 
365 Event::Ptr MemoryCalendar::deletedEvent(const QString &uid, const QDateTime &recurrenceId) const
366 {
367  return d->deletedIncidence(uid, recurrenceId, Incidence::TypeEvent).staticCast<Event>();
368 }
369 
370 bool MemoryCalendar::addTodo(const Todo::Ptr &todo)
371 {
372  return addIncidence(todo);
373 }
374 
375 bool MemoryCalendar::deleteTodo(const Todo::Ptr &todo)
376 {
377  return deleteIncidence(todo);
378 }
379 
381 {
382  return deleteIncidenceInstances(todo);
383 }
384 
385 Todo::Ptr MemoryCalendar::todo(const QString &uid, const QDateTime &recurrenceId) const
386 {
387  return d->incidence(uid, Incidence::TypeTodo, recurrenceId).staticCast<Todo>();
388 }
389 
390 Todo::Ptr MemoryCalendar::deletedTodo(const QString &uid, const QDateTime &recurrenceId) const
391 {
392  return d->deletedIncidence(uid, recurrenceId, Incidence::TypeTodo).staticCast<Todo>();
393 }
394 
395 Todo::List MemoryCalendar::rawTodos(TodoSortField sortField, SortDirection sortDirection) const
396 {
397  return Calendar::sortTodos(d->castIncidenceList<Todo>(d->mIncidences[Incidence::TypeTodo]), sortField, sortDirection);
398 }
399 
401 {
402  if (!deletionTracking()) {
403  return Todo::List();
404  }
405 
406  return Calendar::sortTodos(d->castIncidenceList<Todo>(d->mDeletedIncidences[Incidence::TypeTodo]), sortField, sortDirection);
407 }
408 
409 Todo::List MemoryCalendar::todoInstances(const Incidence::Ptr &todo, TodoSortField sortField, SortDirection sortDirection) const
410 {
411  return Calendar::sortTodos(d->incidenceInstances<Todo>(Incidence::TypeTodo, todo), sortField, sortDirection);
412 }
413 
415 {
416  Todo::List todoList;
417 
418  d->forIncidences<Todo>(d->mIncidencesForDate[Incidence::TypeTodo], date, [&todoList](const Todo::Ptr &todo) {
419  todoList.append(todo);
420  });
421 
422  // Iterate over all todos. Look for recurring todoss that occur on this date
423  d->forIncidences<Todo>(d->mIncidences[Incidence::TypeTodo], [this, &todoList, &date](const Todo::Ptr &todo) {
424  if (todo->recurs() && todo->recursOn(date, timeZone())) {
425  todoList.append(todo);
426  }
427  });
428 
429  return todoList;
430 }
431 
432 Todo::List MemoryCalendar::rawTodos(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const
433 {
434  Q_UNUSED(inclusive); // use only exact dtDue/dtStart, not dtStart and dtEnd
435 
436  Todo::List todoList;
437  const auto ts = timeZone.isValid() ? timeZone : this->timeZone();
438  QDateTime st(start, QTime(0, 0, 0), ts);
439  QDateTime nd(end, QTime(23, 59, 59, 999), ts);
440 
441  // Get todos
442  for (const auto &incidence : d->mIncidences[Incidence::TypeTodo]) {
443  const auto todo = incidence.staticCast<Todo>();
444  if (!isVisible(todo)) {
445  continue;
446  }
447 
448  QDateTime rStart = todo->hasDueDate() ? todo->dtDue() : todo->hasStartDate() ? todo->dtStart() : QDateTime();
449  if (!rStart.isValid()) {
450  continue;
451  }
452 
453  if (!todo->recurs()) { // non-recurring todos
454  if (nd.isValid() && nd < rStart) {
455  continue;
456  }
457  if (st.isValid() && rStart < st) {
458  continue;
459  }
460  } else { // recurring events
461  switch (todo->recurrence()->duration()) {
462  case -1: // infinite
463  break;
464  case 0: // end date given
465  default: // count given
466  QDateTime rEnd(todo->recurrence()->endDate(), QTime(23, 59, 59, 999), ts);
467  if (!rEnd.isValid()) {
468  continue;
469  }
470  if (st.isValid() && rEnd < st) {
471  continue;
472  }
473  break;
474  } // switch(duration)
475  } // if(recurs)
476 
477  todoList.append(todo);
478  }
479 
480  return todoList;
481 }
482 
484 {
485  return alarms(QDateTime(QDate(1900, 1, 1), QTime(0, 0, 0)), to);
486 }
487 
488 Alarm::List MemoryCalendar::alarms(const QDateTime &from, const QDateTime &to, bool excludeBlockedAlarms) const
489 {
490  Q_UNUSED(excludeBlockedAlarms);
491  Alarm::List alarmList;
492 
493  d->forIncidences<Event>(d->mIncidences[Incidence::TypeEvent], [this, &alarmList, &from, &to](const Event::Ptr &e) {
494  if (e->recurs()) {
495  appendRecurringAlarms(alarmList, e, from, to);
496  } else {
497  appendAlarms(alarmList, e, from, to);
498  }
499  });
500 
501  d->forIncidences<Todo>(d->mIncidences[IncidenceBase::TypeTodo], [this, &alarmList, &from, &to](const Todo::Ptr &t) {
502  if (!t->isCompleted()) {
503  appendAlarms(alarmList, t, from, to);
504  if (t->recurs()) {
505  appendRecurringAlarms(alarmList, t, from, to);
506  } else {
507  appendAlarms(alarmList, t, from, to);
508  }
509  }
510  });
511 
512  return alarmList;
513 }
514 
516 {
517  return d->mUpdateLastModified;
518 }
519 
521 {
522  d->mUpdateLastModified = update;
523 }
524 
525 void MemoryCalendar::incidenceUpdate(const QString &uid, const QDateTime &recurrenceId)
526 {
527  Incidence::Ptr inc = incidence(uid, recurrenceId);
528 
529  if (inc) {
530  if (!d->mIncidenceBeingUpdated.isEmpty()) {
531  qCWarning(KCALCORE_LOG) << "Incidence::update() called twice without an updated() call in between.";
532  }
533 
534  // Save it so we can detect changes to uid or recurringId.
535  d->mIncidenceBeingUpdated = inc->instanceIdentifier();
536 
537  const QDateTime dt = inc->dateTime(Incidence::RoleCalendarHashing);
538  if (dt.isValid()) {
539  d->mIncidencesForDate[inc->type()].remove(dt.toTimeZone(timeZone()).date(), inc);
540  }
541  }
542 }
543 
544 void MemoryCalendar::incidenceUpdated(const QString &uid, const QDateTime &recurrenceId)
545 {
546  Incidence::Ptr inc = incidence(uid, recurrenceId);
547 
548  if (inc) {
549  if (d->mIncidenceBeingUpdated.isEmpty()) {
550  qCWarning(KCALCORE_LOG) << "Incidence::updated() called twice without an update() call in between.";
551  } else if (inc->instanceIdentifier() != d->mIncidenceBeingUpdated) {
552  // Instance identifier changed, update our hash table
553  d->mIncidencesByIdentifier.remove(d->mIncidenceBeingUpdated);
554  d->mIncidencesByIdentifier.insert(inc->instanceIdentifier(), inc);
555  }
556 
557  d->mIncidenceBeingUpdated = QString();
558 
559  if (d->mUpdateLastModified) {
560  inc->setLastModified(QDateTime::currentDateTimeUtc());
561  }
562  // we should probably update the revision number here,
563  // or internally in the Event itself when certain things change.
564  // need to verify with ical documentation.
565 
566  const QDateTime dt = inc->dateTime(Incidence::RoleCalendarHashing);
567  if (dt.isValid()) {
568  d->mIncidencesForDate[inc->type()].insert(dt.toTimeZone(timeZone()).date(), inc);
569  }
570 
571  notifyIncidenceChanged(inc);
572 
573  setModified(true);
574  }
575 }
576 
577 Event::List MemoryCalendar::rawEventsForDate(const QDate &date, const QTimeZone &timeZone, EventSortField sortField, SortDirection sortDirection) const
578 {
579  Event::List eventList;
580 
581  if (!date.isValid()) {
582  // There can't be events on invalid dates
583  return eventList;
584  }
585 
586  if (timeZone.isValid() && timeZone != this->timeZone()) {
587  // We cannot use the hash table on date, since time zone is different.
588  eventList = rawEvents(date, date, timeZone, false);
589  return Calendar::sortEvents(eventList, sortField, sortDirection);
590  }
591 
592  // Iterate over all non-recurring, single-day events that start on this date
593  d->forIncidences<Event>(d->mIncidencesForDate[Incidence::TypeEvent], date, [&eventList](const Event::Ptr &event) {
594  eventList.append(event);
595  });
596 
597  // Iterate over all events. Look for recurring events that occur on this date
598  const auto ts = timeZone.isValid() ? timeZone : this->timeZone();
599  for (const auto &event : d->mIncidences[Incidence::TypeEvent]) {
600  const auto ev = event.staticCast<Event>();
601  if (ev->recurs()) {
602  if (ev->isMultiDay()) {
603  int extraDays = ev->dtStart().date().daysTo(ev->dtEnd().date());
604  for (int i = 0; i <= extraDays; ++i) {
605  if (ev->recursOn(date.addDays(-i), ts)) {
606  eventList.append(ev);
607  break;
608  }
609  }
610  } else {
611  if (ev->recursOn(date, ts)) {
612  eventList.append(ev);
613  }
614  }
615  } else {
616  if (ev->isMultiDay()) {
617  if (ev->dtStart().toTimeZone(ts).date() <= date && ev->dtEnd().toTimeZone(ts).date() >= date) {
618  eventList.append(ev);
619  }
620  }
621  }
622  }
623 
624  return Calendar::sortEvents(eventList, sortField, sortDirection);
625 }
626 
627 Event::List MemoryCalendar::rawEvents(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const
628 {
629  Event::List eventList;
630  const auto ts = timeZone.isValid() ? timeZone : this->timeZone();
631  QDateTime st(start, QTime(0, 0, 0), ts);
632  QDateTime nd(end, QTime(23, 59, 59, 999), ts);
633 
634  // Get non-recurring events
635  for (const auto &e : d->mIncidences[Incidence::TypeEvent]) {
636  const auto event = e.staticCast<Event>();
637  QDateTime rStart = event->dtStart();
638  if (nd.isValid() && nd < rStart) {
639  continue;
640  }
641  if (inclusive && st.isValid() && rStart < st) {
642  continue;
643  }
644 
645  if (!event->recurs()) { // non-recurring events
646  QDateTime rEnd = event->dtEnd();
647  if (st.isValid() && rEnd < st) {
648  continue;
649  }
650  if (inclusive && nd.isValid() && nd < rEnd) {
651  continue;
652  }
653  } else { // recurring events
654  switch (event->recurrence()->duration()) {
655  case -1: // infinite
656  if (inclusive) {
657  continue;
658  }
659  break;
660  case 0: // end date given
661  default: // count given
662  QDateTime rEnd(event->recurrence()->endDate(), QTime(23, 59, 59, 999), ts);
663  if (!rEnd.isValid()) {
664  continue;
665  }
666  if (st.isValid() && rEnd < st) {
667  continue;
668  }
669  if (inclusive && nd.isValid() && nd < rEnd) {
670  continue;
671  }
672  break;
673  } // switch(duration)
674  } // if(recurs)
675 
676  eventList.append(event);
677  }
678 
679  return eventList;
680 }
681 
683 {
684  return rawEventsForDate(kdt.date(), kdt.timeZone());
685 }
686 
688 {
689  return Calendar::sortEvents(d->castIncidenceList<Event>(d->mIncidences[Incidence::TypeEvent]), sortField, sortDirection);
690 }
691 
693 {
694  if (!deletionTracking()) {
695  return Event::List();
696  }
697 
698  return Calendar::sortEvents(d->castIncidenceList<Event>(d->mDeletedIncidences[Incidence::TypeEvent]), sortField, sortDirection);
699 }
700 
701 Event::List MemoryCalendar::eventInstances(const Incidence::Ptr &event, EventSortField sortField, SortDirection sortDirection) const
702 {
703  return Calendar::sortEvents(d->incidenceInstances<Event>(Incidence::TypeEvent, event), sortField, sortDirection);
704 }
705 
706 bool MemoryCalendar::addJournal(const Journal::Ptr &journal)
707 {
708  return addIncidence(journal);
709 }
710 
711 bool MemoryCalendar::deleteJournal(const Journal::Ptr &journal)
712 {
713  return deleteIncidence(journal);
714 }
715 
717 {
718  return deleteIncidenceInstances(journal);
719 }
720 
721 Journal::Ptr MemoryCalendar::journal(const QString &uid, const QDateTime &recurrenceId) const
722 {
723  return d->incidence(uid, Incidence::TypeJournal, recurrenceId).staticCast<Journal>();
724 }
725 
726 Journal::Ptr MemoryCalendar::deletedJournal(const QString &uid, const QDateTime &recurrenceId) const
727 {
728  return d->deletedIncidence(uid, recurrenceId, Incidence::TypeJournal).staticCast<Journal>();
729 }
730 
732 {
733  return Calendar::sortJournals(d->castIncidenceList<Journal>(d->mIncidences[Incidence::TypeJournal]), sortField, sortDirection);
734 }
735 
737 {
738  if (!deletionTracking()) {
739  return Journal::List();
740  }
741 
742  return Calendar::sortJournals(d->castIncidenceList<Journal>(d->mDeletedIncidences[Incidence::TypeJournal]), sortField, sortDirection);
743 }
744 
746 {
747  return Calendar::sortJournals(d->incidenceInstances<Journal>(Incidence::TypeJournal, journal), sortField, sortDirection);
748 }
749 
751 {
752  Journal::List journalList;
753 
754  d->forIncidences<Journal>(d->mIncidencesForDate[Incidence::TypeJournal], date, [&journalList](const Journal::Ptr &journal) {
755  journalList.append(journal);
756  });
757 
758  return journalList;
759 }
760 
761 Incidence::Ptr MemoryCalendar::instance(const QString &identifier) const
762 {
763  return d->mIncidencesByIdentifier.value(identifier);
764 }
765 
766 void MemoryCalendar::virtual_hook(int id, void *data)
767 {
768  Q_UNUSED(id);
769  Q_UNUSED(data);
770  Q_ASSERT(false);
771 }
qint64 daysTo(const QDate &d) const const
JournalSortField
Calendar Journal sort keys.
Definition: calendar.h:92
TodoSortField
Calendar Todo sort keys.
Definition: calendar.h:78
QHash::iterator insert(const Key &key, const T &value)
Alarm::List alarms() const
Returns a list of all incidence alarms.
Definition: incidence.cpp:857
Event::List rawEventsForDate(const QDate &date, const QTimeZone &timeZone={}, EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns an unfiltered list of all Events which occur on the given date.
Represents the main calendar class.
Definition: calendar.h:129
bool deleteTodoInstances(const Todo::Ptr &todo) override
Delete all to-dos that are instances of recurring to-do todo.
void update()
Call this to notify the observers after the IncidenceBase object will be changed. ...
static Event::List sortEvents(const Event::List &eventList, EventSortField sortField, SortDirection sortDirection)
Sort a list of Events.
Definition: calendar.cpp:481
Journal::List rawJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all Journals for this Calendar.
Alarm::List alarmsTo(const QDateTime &to) const
Return a list of Alarms that occur before the specified timestamp.
bool addJournal(const Journal::Ptr &journal) override
Inserts a Journal into the calendar.
void append(const T &value)
This file is part of the API for handling calendar data and defines the MemoryCalendar class...
void reserve(int alloc)
bool addEvent(const Event::Ptr &event) override
Inserts an Event into the calendar.
bool deleteJournal(const Journal::Ptr &journal) override
Removes a Journal from the calendar.
Provides a Journal in the sense of RFC2445.
Definition: journal.h:29
int size() const const
An abstract base class that provides an interface to various calendar formats.
Definition: calformat.h:35
bool deleteEventInstances(const Event::Ptr &event) override
Delete all events that are instances of recurring event event.
Journal::Ptr deletedJournal(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the deleted Journal associated with the given unique identifier.
QSharedPointer< Incidence > Ptr
A shared pointer to an Incidence.
Definition: incidence.h:114
Todo::List todoInstances(const Incidence::Ptr &todo, TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all possible instances for this recurring Todo.
Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all Todos for this Calendar.
StandardShortcut find(const QKeySequence &keySeq)
const QList< QKeySequence > & close()
Journal::List rawJournalsForDate(const QDate &date) const override
Returns an unfiltered list of all Journals for on the specified date.
QHash::const_iterator cend() const const
bool deleteJournalInstances(const Journal::Ptr &journal) override
Delete all journals that are instances of recurring journal journal.
bool deleteTodo(const Todo::Ptr &todo) override
Removes a Todo from the calendar.
Todo::Ptr todo(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the Todo associated with the given unique identifier.
void setUpdateLastModifiedOnChange(bool update)
Govern if the memory calendar is changing the lastModified field of incidence it owns, on incidence updates.
void notifyIncidenceAboutToBeDeleted(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they will remove an Incidence.
Definition: calendar.cpp:1111
This file is part of the API for handling calendar data and defines the CalFormat abstract base class...
QDateTime toTimeZone(const QTimeZone &timeZone) const const
QTimeZone timeZone() const
Get the time zone used for creating or modifying incidences in the Calendar.
Definition: calendar.cpp:187
bool addTodo(const Todo::Ptr &todo) override
Inserts a Todo into the calendar.
Event::Ptr deletedEvent(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the deleted Event associated with the given unique identifier.
~MemoryCalendar() override
Destroys the calendar.
bool updateLastModifiedOnChange() const
Return true if the memory calendar is updating the lastModified field of incidence owned by the calen...
Journal::List deletedJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all deleted Journals for this Calendar.
QHash::const_iterator cbegin() const const
This class provides an Event in the sense of RFC2445.
Definition: event.h:29
MemoryCalendar(const QTimeZone &timeZone)
Constructs a calendar with a specified time zone timeZone.
bool deletionTracking() const
Returns if deletion tracking is enabled.
Definition: calendar.cpp:1346
int remove(const Key &key, const T &value)
EventSortField
Calendar Event sort keys.
Definition: calendar.h:68
Role for looking up an incidence in a Calendar.
Journal::Ptr journal(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the Journal associated with the given unique identifier.
bool isValid() const const
Todo::List rawTodosForDate(const QDate &date) const override
Returns an unfiltered list of all Todos which due on the specified date.
Event::Ptr event(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the Event associated with the given unique identifier.
Provides a To-do in the sense of RFC2445.
Definition: todo.h:30
void incidenceUpdate(const QString &uid, const QDateTime &recurrenceId) override
The IncidenceObserver interface.
IncidenceType
The different types of incidences, per RFC2445.
int remove(const Key &key)
typename QHash< Key, T >::iterator insert(const Key &key, const T &value)
Incidence::Ptr instance(const QString &identifier) const
Returns an incidence by identifier.
void doSetTimeZone(const QTimeZone &timeZone) override
Let Calendar subclasses set the time specification.
bool deleteIncidence(const Incidence::Ptr &incidence) override
Removes an Incidence from the calendar.
void close() override
Clears out the current calendar, freeing all used memory etc.
QVector< Ptr > List
List of events.
Definition: event.h:52
void clear()
void incidenceUpdated(const QString &uid, const QDateTime &recurrenceId) override
The Observer interface.
QVector< Ptr > List
List of to-dos.
Definition: todo.h:41
IncidenceType type() const override
Definition: journal.cpp:34
Journal::List journalInstances(const Incidence::Ptr &journal, JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
bool addIncidence(const Incidence::Ptr &incidence) override
Inserts an Incidence into the calendar.
bool isValid() const const
Event::List deletedEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all deleted Events for this Calendar.
const QList< QKeySequence > & end()
Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all Events for this Calendar.
typename QHash< Key, T >::const_iterator constFind(const Key &key, const T &value) const const
bool isNull() const const
QDate date() const const
static Journal::List sortJournals(const Journal::List &journalList, JournalSortField sortField, SortDirection sortDirection)
Sort a list of Journals.
Definition: calendar.cpp:771
static Todo::List sortTodos(const Todo::List &todoList, TodoSortField sortField, SortDirection sortDirection)
Sort a list of Todos.
Definition: calendar.cpp:671
SortDirection
Calendar Incidence sort directions.
Definition: calendar.h:60
QVector< Ptr > List
List of journals.
Definition: journal.h:40
This class provides a calendar stored in memory.
void virtual_hook(int id, void *data) override
Standard trick to add virtuals later.
bool isValid() const const
Todo::List deletedTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all deleted Todos for this Calendar.
Todo::Ptr deletedTodo(const QString &uid, const QDateTime &recurrenceId={}) const override
Returns the deleted Todo associated with the given unique identifier.
QDate addDays(qint64 ndays) const const
bool deleteEvent(const Event::Ptr &event) override
Removes an Event from the calendar.
QSharedPointer< X > staticCast() const const
Event::List eventInstances(const Incidence::Ptr &event, EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const override
Returns a sorted, unfiltered list of all possible instances for this recurring Event.
QDateTime currentDateTimeUtc()
Alarm::List alarms(const QDateTime &from, const QDateTime &to, bool excludeBlockedAlarms=false) const override
Returns a list of Alarms within a time range for this Calendar.
Namespace for all KCalendarCore types.
Definition: alarm.h:36
QString uid() const
Returns the unique id (uid) for the incidence.
QTimeZone timeZone() const const
KIOFILEWIDGETS_EXPORT QStringList list(const QString &fileClass)
bool deleteIncidenceInstances(const Incidence::Ptr &incidence) override
Delete all incidences that are instances of recurring incidence incidence.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Sep 18 2021 22:51:44 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.