KCalendarCore

calendar.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: 2000-2004 Cornelius Schumacher <[email protected]>
6  SPDX-FileCopyrightText: 2003-2004 Reinhold Kainhofer <[email protected]>
7  SPDX-FileCopyrightText: 2006 David Jarvie <[email protected]>
8  SPDX-FileCopyrightText: 2021 Boris Shmarin <[email protected]>
9 
10  SPDX-License-Identifier: LGPL-2.0-or-later
11 */
12 /**
13  @file
14  This file is part of the API for handling calendar data and
15  defines the Calendar class.
16 
17  @brief
18  Represents the main calendar class.
19 
20  @author Preston Brown <[email protected]>
21  @author Cornelius Schumacher <[email protected]>
22  @author Reinhold Kainhofer <[email protected]>
23  @author David Jarvie <[email protected]>
24 */
25 #include "calendar.h"
26 #include "calendar_p.h"
27 #include "calfilter.h"
28 #include "icaltimezones_p.h"
29 #include "sorting.h"
30 #include "visitor.h"
31 
32 #include "kcalendarcore_debug.h"
33 
34 
35 extern "C" {
36 #include <libical/icaltimezone.h>
37 }
38 
39 #include <algorithm>
40 #include <set>
41 
42 using namespace KCalendarCore;
43 
44 /**
45  Make a QHash::value that returns a QVector.
46 */
47 template<typename K, typename V>
49 {
50  QVector<V> v;
51  v.reserve(c.size());
52  for (typename QMultiHash<K, V>::const_iterator it = c.begin(), end = c.end(); it != end; ++it) {
53  v.push_back(it.value());
54  }
55  return v;
56 }
57 
58 template<typename K, typename V>
59 QVector<V> values(const QMultiHash<K, V> &c, const K &x)
60 {
61  QVector<V> v;
62  typename QMultiHash<K, V>::const_iterator it = c.find(x);
63  while (it != c.end() && it.key() == x) {
64  v.push_back(it.value());
65  ++it;
66  }
67  return v;
68 }
69 
70 /**
71  Template for a class that implements a visitor for adding an Incidence
72  to a resource supporting addEvent(), addTodo() and addJournal() calls.
73 */
74 template<class T>
75 class AddVisitor : public Visitor
76 {
77 public:
78  AddVisitor(T *r)
79  : mResource(r)
80  {
81  }
82 
83  bool visit(const Event::Ptr &e) override
84  {
85  return mResource->addEvent(e);
86  }
87  bool visit(const Todo::Ptr &t) override
88  {
89  return mResource->addTodo(t);
90  }
91  bool visit(const Journal::Ptr &j) override
92  {
93  return mResource->addJournal(j);
94  }
95  bool visit(const FreeBusy::Ptr &) override
96  {
97  return false;
98  }
99 
100 private:
101  T *mResource;
102 };
103 
104 /**
105  Template for a class that implements a visitor for deleting an Incidence
106  from a resource supporting deleteEvent(), deleteTodo() and deleteJournal()
107  calls.
108 */
109 template<class T>
110 class DeleteVisitor : public Visitor
111 {
112 public:
113  DeleteVisitor(T *r)
114  : mResource(r)
115  {
116  }
117 
118  bool visit(const Event::Ptr &e) override
119  {
120  mResource->deleteEvent(e);
121  return true;
122  }
123  bool visit(const Todo::Ptr &t) override
124  {
125  mResource->deleteTodo(t);
126  return true;
127  }
128  bool visit(const Journal::Ptr &j) override
129  {
130  mResource->deleteJournal(j);
131  return true;
132  }
133  bool visit(const FreeBusy::Ptr &) override
134  {
135  return false;
136  }
137 
138 private:
139  T *mResource;
140 };
141 //@endcond
142 
144  : d(new KCalendarCore::Calendar::Private)
145 {
146  if (timeZone.isValid()) {
147  d->mTimeZone = timeZone;
148  } else {
149  d->mTimeZone = QTimeZone::systemTimeZone();
150  }
151 }
152 
153 Calendar::Calendar(const QByteArray &timeZoneId)
154  : d(new KCalendarCore::Calendar::Private)
155 {
157 }
158 
160 {
161  delete d;
162 }
163 
164 Person Calendar::owner() const
165 {
166  return d->mOwner;
167 }
168 
169 void Calendar::setOwner(const Person &owner)
170 {
171  if (owner != d->mOwner) {
172  d->mOwner = owner;
173  setModified(true);
175  }
176 }
177 
178 void Calendar::setTimeZone(const QTimeZone &timeZone)
179 {
180  if (timeZone.isValid()) {
181  d->mTimeZone = timeZone;
182  } else {
183  d->mTimeZone = QTimeZone::systemTimeZone();
184  }
185 
186  doSetTimeZone(d->mTimeZone);
187 }
188 
190 {
191  return d->mTimeZone;
192 }
193 
194 void Calendar::setTimeZoneId(const QByteArray &timeZoneId)
195 {
196  d->mTimeZone = d->timeZoneIdSpec(timeZoneId);
197 
198  doSetTimeZone(d->mTimeZone); // NOLINT false clang-analyzer-optin.cplusplus.VirtualCall
199 }
200 
201 //@cond PRIVATE
202 QTimeZone Calendar::Private::timeZoneIdSpec(const QByteArray &timeZoneId)
203 {
204  if (timeZoneId == QByteArrayLiteral("UTC")) {
205  return QTimeZone::utc();
206  }
207  auto tz = QTimeZone(timeZoneId);
208  if (tz.isValid()) {
209  return tz;
210  }
211  return QTimeZone::systemTimeZone();
212 }
213 //@endcond
214 
216 {
217  return d->mTimeZone.id();
218 }
219 
220 void Calendar::shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
221 {
222  setTimeZone(newZone);
223 
224  int i;
225  int end;
226  Event::List ev = events();
227  for (i = 0, end = ev.count(); i < end; ++i) {
228  ev[i]->shiftTimes(oldZone, newZone);
229  }
230 
231  Todo::List to = todos();
232  for (i = 0, end = to.count(); i < end; ++i) {
233  to[i]->shiftTimes(oldZone, newZone);
234  }
235 
236  Journal::List jo = journals();
237  for (i = 0, end = jo.count(); i < end; ++i) {
238  jo[i]->shiftTimes(oldZone, newZone);
239  }
240 }
241 
243 {
244  if (filter) {
245  d->mFilter = filter;
246  } else {
247  d->mFilter = d->mDefaultFilter;
248  }
250 }
251 
253 {
254  return d->mFilter;
255 }
256 
258 {
259  const Incidence::List rawInc = rawIncidences();
260  QStringList uniqueCategories;
261  QStringList thisCats;
262  // @TODO: For now just iterate over all incidences. In the future,
263  // the list of categories should be built when reading the file.
264  for (const Incidence::Ptr &inc : rawInc) {
265  thisCats = inc->categories();
266  for (const auto &cat : std::as_const(thisCats)) {
267  if (!uniqueCategories.contains(cat)) {
268  uniqueCategories.append(cat);
269  }
270  }
271  }
272  return uniqueCategories;
273 }
274 
276 {
277  return mergeIncidenceList(events(date), todos(date), journals(date));
278 }
279 
281 {
282  return mergeIncidenceList(events(), todos(), journals());
283 }
284 
286 {
288 }
289 
291 {
292  if (incidence) {
293  Event::List elist;
294  Todo::List tlist;
295  Journal::List jlist;
296 
297  if (incidence->type() == Incidence::TypeEvent) {
298  elist = eventInstances(incidence);
299  } else if (incidence->type() == Incidence::TypeTodo) {
300  tlist = todoInstances(incidence);
301  } else if (incidence->type() == Incidence::TypeJournal) {
302  jlist = journalInstances(incidence);
303  }
304  return mergeIncidenceList(elist, tlist, jlist);
305  } else {
306  return Incidence::List();
307  }
308 }
309 
311 {
312  if (!incidence) {
313  return {};
314  }
315 
316  Incidence::List list;
317  const Incidence::List vals = values(d->mNotebookIncidences);
318  std::copy_if(vals.cbegin(), vals.cend(), std::back_inserter(list), [&](const Incidence::Ptr &in) {
319  return (incidence->dtStart() == in->dtStart() || (!incidence->dtStart().isValid() && !in->dtStart().isValid()))
320  && incidence->summary() == in->summary();
321  });
322  return list;
323 }
324 
325 bool Calendar::addNotebook(const QString &notebook, bool isVisible)
326 {
327  if (d->mNotebooks.contains(notebook)) {
328  return false;
329  } else {
330  d->mNotebooks.insert(notebook, isVisible);
331  return true;
332  }
333 }
334 
335 bool Calendar::updateNotebook(const QString &notebook, bool isVisible)
336 {
337  if (!d->mNotebooks.contains(notebook)) {
338  return false;
339  } else {
340  d->mNotebooks.insert(notebook, isVisible);
341  for (auto noteIt = d->mNotebookIncidences.cbegin(); noteIt != d->mNotebookIncidences.cend(); ++noteIt) {
342  const Incidence::Ptr &incidence = noteIt.value();
343  auto visibleIt = d->mIncidenceVisibility.find(incidence);
344  if (visibleIt != d->mIncidenceVisibility.end()) {
345  *visibleIt = isVisible;
346  }
347  }
348  return true;
349  }
350 }
351 
352 bool Calendar::deleteNotebook(const QString &notebook)
353 {
354  if (!d->mNotebooks.contains(notebook)) {
355  return false;
356  } else {
357  return d->mNotebooks.remove(notebook);
358  }
359 }
360 
362 {
363  if (!d->mNotebooks.contains(notebook)) {
364  return false;
365  } else {
366  d->mDefaultNotebook = notebook;
367  return true;
368  }
369 }
370 
372 {
373  return d->mDefaultNotebook;
374 }
375 
376 bool Calendar::hasValidNotebook(const QString &notebook) const
377 {
378  return d->mNotebooks.contains(notebook);
379 }
380 
381 bool Calendar::isVisible(const Incidence::Ptr &incidence) const
382 {
383  if (d->mIncidenceVisibility.contains(incidence)) {
384  return d->mIncidenceVisibility[incidence];
385  }
386  const QString nuid = notebook(incidence);
387  bool rv;
388  if (d->mNotebooks.contains(nuid)) {
389  rv = d->mNotebooks.value(nuid);
390  } else {
391  // NOTE returns true also for nonexisting notebooks for compatibility
392  rv = true;
393  }
394  d->mIncidenceVisibility[incidence] = rv;
395  return rv;
396 }
397 
398 bool Calendar::isVisible(const QString &notebook) const
399 {
400  QHash<QString, bool>::ConstIterator it = d->mNotebooks.constFind(notebook);
401  return (it != d->mNotebooks.constEnd()) ? *it : true;
402 }
403 
405 {
406  d->mNotebookIncidences.clear();
407  d->mUidToNotebook.clear();
408  d->mIncidenceVisibility.clear();
409 }
410 
411 bool Calendar::setNotebook(const Incidence::Ptr &inc, const QString &notebook)
412 {
413  if (!inc) {
414  return false;
415  }
416 
417  if (!notebook.isEmpty() && !incidence(inc->uid(), inc->recurrenceId())) {
418  qCWarning(KCALCORE_LOG) << "cannot set notebook until incidence has been added";
419  return false;
420  }
421 
422  if (d->mUidToNotebook.contains(inc->uid())) {
423  QString old = d->mUidToNotebook.value(inc->uid());
424  if (!old.isEmpty() && notebook != old) {
425  if (inc->hasRecurrenceId()) {
426  qCWarning(KCALCORE_LOG) << "cannot set notebook for child incidences";
427  return false;
428  }
429  // Move all possible children also.
430  const Incidence::List list = instances(inc);
431  for (const auto &incidence : list) {
432  d->mNotebookIncidences.remove(old, incidence);
433  d->mNotebookIncidences.insert(notebook, incidence);
434  }
435  notifyIncidenceChanged(inc); // for removing from old notebook
436  // do not remove from mUidToNotebook to keep deleted incidences
437  d->mNotebookIncidences.remove(old, inc);
438  }
439  }
440  if (!notebook.isEmpty()) {
441  d->mUidToNotebook.insert(inc->uid(), notebook);
442  d->mNotebookIncidences.insert(notebook, inc);
443  qCDebug(KCALCORE_LOG) << "setting notebook" << notebook << "for" << inc->uid();
444  notifyIncidenceChanged(inc); // for inserting into new notebook
445  const Incidence::List list = instances(inc);
446  for (const auto &incidence : list) {
448  }
449  }
450 
451  return true;
452 }
453 
455 {
456  if (incidence) {
457  return d->mUidToNotebook.value(incidence->uid());
458  } else {
459  return QString();
460  }
461 }
462 
464 {
465  return d->mUidToNotebook.value(uid);
466 }
467 
469 {
470  return d->mNotebookIncidences.uniqueKeys();
471 }
472 
474 {
475  if (notebook.isEmpty()) {
476  return values(d->mNotebookIncidences);
477  } else {
478  return values(d->mNotebookIncidences, notebook);
479  }
480 }
481 
482 #if KCALENDARCORE_BUILD_DEPRECATED_SINCE(5, 95)
483 /** static */
484 Event::List Calendar::sortEvents(const Event::List &eventList, EventSortField sortField, SortDirection sortDirection)
485 {
486  Event::List eventListSorted(eventList);
487  return sortEvents(std::move(eventListSorted), sortField, sortDirection);
488 }
489 #endif
490 
492 {
493  switch (sortField) {
494  case EventSortUnsorted:
495  break;
496 
497  case EventSortStartDate:
498  if (sortDirection == SortDirectionAscending) {
499  std::sort(eventList.begin(), eventList.end(), Events::startDateLessThan);
500  } else {
501  std::sort(eventList.begin(), eventList.end(), Events::startDateMoreThan);
502  }
503  break;
504 
505  case EventSortEndDate:
506  if (sortDirection == SortDirectionAscending) {
507  std::sort(eventList.begin(), eventList.end(), Events::endDateLessThan);
508  } else {
509  std::sort(eventList.begin(), eventList.end(), Events::endDateMoreThan);
510  }
511  break;
512 
513  case EventSortSummary:
514  if (sortDirection == SortDirectionAscending) {
515  std::sort(eventList.begin(), eventList.end(), Events::summaryLessThan);
516  } else {
517  std::sort(eventList.begin(), eventList.end(), Events::summaryMoreThan);
518  }
519  break;
520  }
521 
522  return eventList;
523 }
524 
525 Event::List Calendar::events(const QDate &date, const QTimeZone &timeZone, EventSortField sortField, SortDirection sortDirection) const
526 {
527  Event::List el = rawEventsForDate(date, timeZone, sortField, sortDirection);
528  d->mFilter->apply(&el);
529  return el;
530 }
531 
533 {
534  Event::List el = rawEventsForDate(dt.date(), dt.timeZone());
535  d->mFilter->apply(&el);
536  return el;
537 }
538 
539 Event::List Calendar::events(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const
540 {
541  Event::List el = rawEvents(start, end, timeZone, inclusive);
542  d->mFilter->apply(&el);
543  return el;
544 }
545 
547 {
548  Event::List el = rawEvents(sortField, sortDirection);
549  d->mFilter->apply(&el);
550  return el;
551 }
552 
554 {
555  if (!incidence) {
556  return false;
557  }
558 
559  AddVisitor<Calendar> v(this);
560  return incidence->accept(v, incidence);
561 }
562 
564 {
565  if (!incidence) {
566  return false;
567  }
568 
569  if (beginChange(incidence)) {
570  DeleteVisitor<Calendar> v(this);
571  const bool result = incidence->accept(v, incidence);
573  return result;
574  } else {
575  return false;
576  }
577 }
578 
579 Incidence::Ptr Calendar::createException(const Incidence::Ptr &incidence, const QDateTime &recurrenceId, bool thisAndFuture)
580 {
581  Q_ASSERT(recurrenceId.isValid());
582  if (!incidence || !incidence->recurs() || !recurrenceId.isValid()) {
583  return Incidence::Ptr();
584  }
585 
586  Incidence::Ptr newInc(incidence->clone());
587  const QDateTime current = QDateTime::currentDateTimeUtc();
588  newInc->setCreated(current);
589  newInc->setLastModified(current);
590  newInc->setRevision(0);
591  // Recurring exceptions are not support for now
592  newInc->clearRecurrence();
593 
594  newInc->setRecurrenceId(recurrenceId);
595  newInc->setThisAndFuture(thisAndFuture);
596  newInc->setDtStart(recurrenceId);
597 
598  // Calculate and set the new end of the incidence
599  QDateTime end = incidence->dateTime(IncidenceBase::RoleEnd);
600 
601  if (end.isValid()) {
602  if (incidence->allDay()) {
603  qint64 offset = incidence->dtStart().daysTo(recurrenceId);
604  end = end.addDays(offset);
605  } else {
606  qint64 offset = incidence->dtStart().secsTo(recurrenceId);
607  end = end.addSecs(offset);
608  }
609  newInc->setDateTime(end, IncidenceBase::RoleEnd);
610  }
611  return newInc;
612 }
613 
614 Incidence::Ptr Calendar::incidence(const QString &uid, const QDateTime &recurrenceId) const
615 {
616  Incidence::Ptr i = event(uid, recurrenceId);
617  if (i) {
618  return i;
619  }
620 
621  i = todo(uid, recurrenceId);
622  if (i) {
623  return i;
624  }
625 
626  i = journal(uid, recurrenceId);
627  return i;
628 }
629 
630 Incidence::Ptr Calendar::deleted(const QString &uid, const QDateTime &recurrenceId) const
631 {
632  Incidence::Ptr i = deletedEvent(uid, recurrenceId);
633  if (i) {
634  return i;
635  }
636 
637  i = deletedTodo(uid, recurrenceId);
638  if (i) {
639  return i;
640  }
641 
642  i = deletedJournal(uid, recurrenceId);
643  return i;
644 }
645 
647 {
648  Incidence::List result;
650  std::copy_if(incidences.cbegin(), incidences.cend(), std::back_inserter(result), [&sid](const Incidence::Ptr &in) {
651  return in->schedulingID() == sid;
652  });
653  return result;
654 }
655 
657 {
659  const auto itEnd = incidences.cend();
660  auto it = std::find_if(incidences.cbegin(), itEnd, [&uid](const Incidence::Ptr &in) {
661  return in->schedulingID() == uid;
662  });
663 
664  return it != itEnd ? *it : Incidence::Ptr();
665 }
666 
667 #if KCALENDARCORE_BUILD_DEPRECATED_SINCE(5, 95)
668 /** static */
669 Todo::List Calendar::sortTodos(const Todo::List &todoList, TodoSortField sortField, SortDirection sortDirection)
670 {
671  Todo::List todoListSorted(todoList);
672  return sortTodos(std::move(todoListSorted), sortField, sortDirection);
673 }
674 #endif
675 
677 {
678  // Note that To-dos may not have Start DateTimes nor due DateTimes.
679  switch (sortField) {
680  case TodoSortUnsorted:
681  break;
682 
683  case TodoSortStartDate:
684  if (sortDirection == SortDirectionAscending) {
685  std::sort(todoList.begin(), todoList.end(), Todos::startDateLessThan);
686  } else {
687  std::sort(todoList.begin(), todoList.end(), Todos::startDateMoreThan);
688  }
689  break;
690 
691  case TodoSortDueDate:
692  if (sortDirection == SortDirectionAscending) {
693  std::sort(todoList.begin(), todoList.end(), Todos::dueDateLessThan);
694  } else {
695  std::sort(todoList.begin(), todoList.end(), Todos::dueDateMoreThan);
696  }
697  break;
698 
699  case TodoSortPriority:
700  if (sortDirection == SortDirectionAscending) {
701  std::sort(todoList.begin(), todoList.end(), Todos::priorityLessThan);
702  } else {
703  std::sort(todoList.begin(), todoList.end(), Todos::priorityMoreThan);
704  }
705  break;
706 
708  if (sortDirection == SortDirectionAscending) {
709  std::sort(todoList.begin(), todoList.end(), Todos::percentLessThan);
710  } else {
711  std::sort(todoList.begin(), todoList.end(), Todos::percentMoreThan);
712  }
713  break;
714 
715  case TodoSortSummary:
716  if (sortDirection == SortDirectionAscending) {
717  std::sort(todoList.begin(), todoList.end(), Todos::summaryLessThan);
718  } else {
719  std::sort(todoList.begin(), todoList.end(), Todos::summaryMoreThan);
720  }
721  break;
722 
723  case TodoSortCreated:
724  if (sortDirection == SortDirectionAscending) {
725  std::sort(todoList.begin(), todoList.end(), Todos::createdLessThan);
726  } else {
727  std::sort(todoList.begin(), todoList.end(), Todos::createdMoreThan);
728  }
729  break;
730 
731  case TodoSortCategories:
732  if (sortDirection == SortDirectionAscending) {
733  std::sort(todoList.begin(), todoList.end(), Incidences::categoriesLessThan);
734  } else {
735  std::sort(todoList.begin(), todoList.end(), Incidences::categoriesMoreThan);
736  }
737  break;
738  }
739 
740  return todoList;
741 }
742 
743 Todo::List Calendar::todos(TodoSortField sortField, SortDirection sortDirection) const
744 {
745  Todo::List tl = rawTodos(sortField, sortDirection);
746  d->mFilter->apply(&tl);
747  return tl;
748 }
749 
750 Todo::List Calendar::todos(const QDate &date) const
751 {
752  Todo::List el = rawTodosForDate(date);
753  d->mFilter->apply(&el);
754  return el;
755 }
756 
757 Todo::List Calendar::todos(const QDate &start, const QDate &end, const QTimeZone &timeZone, bool inclusive) const
758 {
759  Todo::List tl = rawTodos(start, end, timeZone, inclusive);
760  d->mFilter->apply(&tl);
761  return tl;
762 }
763 
764 #if KCALENDARCORE_BUILD_DEPRECATED_SINCE(5, 95)
765 /** static */
767 {
768  Journal::List journalListSorted = journalList;
769  return sortJournals(std::move(journalListSorted), sortField, sortDirection);
770 }
771 #endif
772 
774 {
775  switch (sortField) {
776  case JournalSortUnsorted:
777  break;
778 
779  case JournalSortDate:
780  if (sortDirection == SortDirectionAscending) {
781  std::sort(journalList.begin(), journalList.end(), Journals::dateLessThan);
782  } else {
783  std::sort(journalList.begin(), journalList.end(), Journals::dateMoreThan);
784  }
785  break;
786 
787  case JournalSortSummary:
788  if (sortDirection == SortDirectionAscending) {
789  std::sort(journalList.begin(), journalList.end(), Journals::summaryLessThan);
790  } else {
791  std::sort(journalList.begin(), journalList.end(), Journals::summaryMoreThan);
792  }
793  break;
794  }
795 
796  return journalList;
797 }
798 
800 {
801  Journal::List jl = rawJournals(sortField, sortDirection);
802  d->mFilter->apply(&jl);
803  return jl;
804 }
805 
807 {
809  d->mFilter->apply(&el);
810  return el;
811 }
812 
813 // When this is called, the to-dos have already been added to the calendar.
814 // This method is only about linking related to-dos.
815 void Calendar::setupRelations(const Incidence::Ptr &forincidence)
816 {
817  if (!forincidence) {
818  return;
819  }
820 
821  const QString uid = forincidence->uid();
822 
823  // First, go over the list of orphans and see if this is their parent
824  Incidence::List l = values(d->mOrphans, uid);
825  d->mOrphans.remove(uid);
826  if (!l.isEmpty()) {
827  Incidence::List &relations = d->mIncidenceRelations[uid];
829  for (int i = 0, end = l.count(); i < end; ++i) {
830  relations.append(l[i]);
831  d->mOrphanUids.remove(l[i]->uid());
832  }
833  }
834 
835  // Now see about this incidences parent
836  if (!forincidence->relatedTo().isEmpty()) {
837  // Incidence has a uid it is related to but is not registered to it yet.
838  // Try to find it
839  Incidence::Ptr parent = incidence(forincidence->relatedTo());
840  if (parent) {
841  // Found it
842 
843  // look for hierarchy loops
844  if (isAncestorOf(forincidence, parent)) {
845  forincidence->setRelatedTo(QString());
846  qCWarning(KCALCORE_LOG) << "hierarchy loop between " << forincidence->uid() << " and " << parent->uid();
847  } else {
848  d->mIncidenceRelations[parent->uid()].append(forincidence);
849  }
850  } else {
851  // Not found, put this in the mOrphans list
852  // Note that the mOrphans dict might contain multiple entries with the
853  // same key! which are multiple children that wait for the parent
854  // incidence to be inserted.
855  d->mOrphans.insert(forincidence->relatedTo(), forincidence);
856  d->mOrphanUids.insert(forincidence->uid(), forincidence);
857  }
858  }
859 }
860 
861 // If a to-do with sub-to-dos is deleted, move it's sub-to-dos to the orphan list
863 {
864  if (!incidence) {
865  qCDebug(KCALCORE_LOG) << "Warning: incidence is 0";
866  return;
867  }
868 
869  const QString uid = incidence->uid();
870 
871  for (const Incidence::Ptr &i : qAsConst(d->mIncidenceRelations[uid])) {
872  if (!d->mOrphanUids.contains(i->uid())) {
873  d->mOrphans.insert(uid, i);
874  d->mOrphanUids.insert(i->uid(), i);
875  i->setRelatedTo(uid);
876  }
877  }
878 
879  const QString parentUid = incidence->relatedTo();
880 
881  // If this incidence is related to something else, tell that about it
882  if (!parentUid.isEmpty()) {
883  Incidence::List &relations = d->mIncidenceRelations[parentUid];
885  }
886 
887  // Remove this one from the orphans list
888  if (d->mOrphanUids.remove(uid)) {
889  // This incidence is located in the orphans list - it should be removed
890  // Since the mOrphans dict might contain the same key (with different
891  // child incidence pointers!) multiple times, take care that we remove
892  // the correct one. So we need to remove all items with the given
893  // parent UID, and re-add those that are not for this item. Also, there
894  // might be other entries with different UID that point to this
895  // incidence (this might happen when the relatedTo of the item is
896  // changed before its parent is inserted. This might happen with
897  // groupware servers....). Remove them, too
898  QStringList relatedToUids;
899 
900  // First, create a list of all keys in the mOrphans list which point
901  // to the removed item
902  relatedToUids << incidence->relatedTo();
903  for (auto it = d->mOrphans.cbegin(); it != d->mOrphans.cend(); ++it) {
904  if (it.value()->uid() == uid) {
905  relatedToUids << it.key();
906  }
907  }
908 
909  // now go through all uids that have one entry that point to the incidence
910  for (const auto &relUid : std::as_const(relatedToUids)) {
911  // Remove all to get access to the remaining entries
912  Incidence::List lst = values(d->mOrphans, relUid);
913  d->mOrphans.remove(relUid);
914  lst.erase(std::remove(lst.begin(), lst.end(), incidence), lst.end());
915 
916  // Re-add those that point to a different orphan incidence
917  for (const auto &in : std::as_const(lst)) {
918  d->mOrphans.insert(relUid, in);
919  }
920  }
921  }
922 
923  // Make sure the deleted incidence doesn't relate to a non-deleted incidence,
924  // since that would cause trouble in MemoryCalendar::close(), as the deleted
925  // incidences are destroyed after the non-deleted incidences. The destructor
926  // of the deleted incidences would then try to access the already destroyed
927  // non-deleted incidence, which would segfault.
928  //
929  // So in short: Make sure dead incidences don't point to alive incidences
930  // via the relation.
931  //
932  // This crash is tested in MemoryCalendarTest::testRelationsCrash().
933  // incidence->setRelatedTo( Incidence::Ptr() );
934 }
935 
936 bool Calendar::isAncestorOf(const Incidence::Ptr &ancestor, const Incidence::Ptr &incidence) const
937 {
938  if (!incidence || incidence->relatedTo().isEmpty()) {
939  return false;
940  } else if (incidence->relatedTo() == ancestor->uid()) {
941  return true;
942  } else {
943  return isAncestorOf(ancestor, this->incidence(incidence->relatedTo()));
944  }
945 }
946 
948 {
949  return d->mIncidenceRelations[uid];
950 }
951 
953 {
954 }
955 
957 {
958  Q_UNUSED(modified);
959  Q_UNUSED(calendar);
960 }
961 
963 {
964  Q_UNUSED(incidence);
965 }
966 
968 {
969  Q_UNUSED(incidence);
970 }
971 
973 {
974  Q_UNUSED(incidence);
975 }
976 
978 {
979  Q_UNUSED(incidence);
980  Q_UNUSED(calendar);
981 }
982 
984 {
985  Q_UNUSED(incidence);
986 }
987 
989 {
990  if (!observer) {
991  return;
992  }
993 
994  if (!d->mObservers.contains(observer)) {
995  d->mObservers.append(observer);
996  } else {
997  d->mNewObserver = true;
998  }
999 }
1000 
1002 {
1003  if (!observer) {
1004  return;
1005  } else {
1006  d->mObservers.removeAll(observer);
1007  }
1008 }
1009 
1011 {
1012  return false;
1013 }
1014 
1015 void Calendar::setModified(bool modified)
1016 {
1017  if (modified != d->mModified || d->mNewObserver) {
1018  d->mNewObserver = false;
1019  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1020  observer->calendarModified(modified, this);
1021  }
1022  d->mModified = modified;
1023  }
1024 }
1025 
1027 {
1028  return d->mModified;
1029 }
1030 
1032 {
1033  return true;
1034 }
1035 
1037 {
1038  return true;
1039 }
1040 
1041 void Calendar::incidenceUpdated(const QString &uid, const QDateTime &recurrenceId)
1042 {
1043  Incidence::Ptr inc = incidence(uid, recurrenceId);
1044 
1045  if (!inc) {
1046  return;
1047  }
1048 
1049  inc->setLastModified(QDateTime::currentDateTimeUtc());
1050  // we should probably update the revision number here,
1051  // or internally in the Event itself when certain things change.
1052  // need to verify with ical documentation.
1053 
1055 
1056  setModified(true);
1057 }
1058 
1060 {
1061  Q_UNUSED(timeZone);
1062 }
1063 
1065 {
1066  if (!incidence) {
1067  return;
1068  }
1069 
1070  if (!d->mObserversEnabled) {
1071  return;
1072  }
1073 
1074  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1075  observer->calendarIncidenceAdded(incidence);
1076  }
1077 
1079  const auto dt = incidence->dateTime(role);
1080  if (dt.isValid() && dt.timeZone() != QTimeZone::utc()) {
1081  if (!d->mTimeZones.contains(dt.timeZone())) {
1082  d->mTimeZones.push_back(dt.timeZone());
1083  }
1084  }
1085  }
1086 }
1087 
1089 {
1090  if (!incidence) {
1091  return;
1092  }
1093 
1094  if (!d->mObserversEnabled) {
1095  return;
1096  }
1097 
1098  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1099  observer->calendarIncidenceChanged(incidence);
1100  }
1101 }
1102 
1104 {
1105  if (!incidence) {
1106  return;
1107  }
1108 
1109  if (!d->mObserversEnabled) {
1110  return;
1111  }
1112 
1113  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1114  observer->calendarIncidenceAboutToBeDeleted(incidence);
1115  }
1116 }
1117 
1119 {
1120  if (!incidence) {
1121  return;
1122  }
1123 
1124  if (!d->mObserversEnabled) {
1125  return;
1126  }
1127 
1128  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1129  observer->calendarIncidenceDeleted(incidence, this);
1130  }
1131 }
1132 
1134 {
1135  if (!incidence) {
1136  return;
1137  }
1138 
1139  if (!d->mObserversEnabled) {
1140  return;
1141  }
1142 
1143  for (CalendarObserver *observer : qAsConst(d->mObservers)) {
1144  observer->calendarIncidenceAdditionCanceled(incidence);
1145  }
1146 }
1147 
1149 {
1150  setModified(true);
1151 }
1152 
1154 {
1155  d->mProductId = id;
1156 }
1157 
1158 QString Calendar::productId() const
1159 {
1160  return d->mProductId;
1161 }
1162 
1163 /** static */
1165 {
1168 
1169  int i;
1170  int end;
1171  for (i = 0, end = events.count(); i < end; ++i) {
1172  incidences.append(events[i]);
1173  }
1174 
1175  for (i = 0, end = todos.count(); i < end; ++i) {
1176  incidences.append(todos[i]);
1177  }
1178 
1179  for (i = 0, end = journals.count(); i < end; ++i) {
1181  }
1182 
1183  return incidences;
1184 }
1185 
1187 {
1188  Q_UNUSED(incidence);
1189  return true;
1190 }
1191 
1193 {
1194  Q_UNUSED(incidence);
1195  return true;
1196 }
1197 
1199 {
1200  d->mObserversEnabled = enabled;
1201 }
1202 
1204 {
1205  QDateTime preTime = from.addSecs(-1);
1206 
1207  Alarm::List alarmlist = incidence->alarms();
1208  for (int i = 0, iend = alarmlist.count(); i < iend; ++i) {
1209  if (alarmlist[i]->enabled()) {
1210  QDateTime dt = alarmlist[i]->nextRepetition(preTime);
1211  if (dt.isValid() && dt <= to) {
1212  qCDebug(KCALCORE_LOG) << incidence->summary() << "':" << dt.toString();
1213  alarms.append(alarmlist[i]);
1214  }
1215  }
1216  }
1217 }
1218 
1220 {
1221  QDateTime dt;
1222  bool endOffsetValid = false;
1223  Duration endOffset(0);
1224  Duration period(from, to);
1225 
1226  Alarm::List alarmlist = incidence->alarms();
1227  for (int i = 0, iend = alarmlist.count(); i < iend; ++i) {
1228  Alarm::Ptr a = alarmlist[i];
1229  if (a->enabled()) {
1230  if (a->hasTime()) {
1231  // The alarm time is defined as an absolute date/time
1232  dt = a->nextRepetition(from.addSecs(-1));
1233  if (!dt.isValid() || dt > to) {
1234  continue;
1235  }
1236  } else {
1237  // Alarm time is defined by an offset from the event start or end time.
1238  // Find the offset from the event start time, which is also used as the
1239  // offset from the recurrence time.
1240  Duration offset(0);
1241  if (a->hasStartOffset()) {
1242  offset = a->startOffset();
1243  } else if (a->hasEndOffset()) {
1244  offset = a->endOffset();
1245  if (!endOffsetValid) {
1246  endOffset = Duration(incidence->dtStart(), incidence->dateTime(Incidence::RoleAlarmEndOffset));
1247  endOffsetValid = true;
1248  }
1249  }
1250 
1251  // Find the incidence's earliest alarm
1252  QDateTime alarmStart = offset.end(a->hasEndOffset() ? incidence->dateTime(Incidence::RoleAlarmEndOffset) : incidence->dtStart());
1253  if (alarmStart > to) {
1254  continue;
1255  }
1256  QDateTime baseStart = incidence->dtStart();
1257  if (from > alarmStart) {
1258  alarmStart = from; // don't look earlier than the earliest alarm
1259  baseStart = (-offset).end((-endOffset).end(alarmStart));
1260  }
1261 
1262  // Adjust the 'alarmStart' date/time and find the next recurrence at or after it.
1263  // Treat the two offsets separately in case one is daily and the other not.
1264  dt = incidence->recurrence()->getNextDateTime(baseStart.addSecs(-1));
1265  if (!dt.isValid() || (dt = endOffset.end(offset.end(dt))) > to) { // adjust 'dt' to get the alarm time
1266  // The next recurrence is too late.
1267  if (!a->repeatCount()) {
1268  continue;
1269  }
1270 
1271  // The alarm has repetitions, so check whether repetitions of previous
1272  // recurrences fall within the time period.
1273  bool found = false;
1274  Duration alarmDuration = a->duration();
1275  for (QDateTime base = baseStart; (dt = incidence->recurrence()->getPreviousDateTime(base)).isValid(); base = dt) {
1276  if (a->duration().end(dt) < base) {
1277  break; // this recurrence's last repetition is too early, so give up
1278  }
1279 
1280  // The last repetition of this recurrence is at or after 'alarmStart' time.
1281  // Check if a repetition occurs between 'alarmStart' and 'to'.
1282  int snooze = a->snoozeTime().value(); // in seconds or days
1283  if (a->snoozeTime().isDaily()) {
1284  Duration toFromDuration(dt, base);
1285  int toFrom = toFromDuration.asDays();
1286  if (a->snoozeTime().end(from) <= to || (toFromDuration.isDaily() && toFrom % snooze == 0)
1287  || (toFrom / snooze + 1) * snooze <= toFrom + period.asDays()) {
1288  found = true;
1289 #ifndef NDEBUG
1290  // for debug output
1291  dt = offset.end(dt).addDays(((toFrom - 1) / snooze + 1) * snooze);
1292 #endif
1293  break;
1294  }
1295  } else {
1296  int toFrom = dt.secsTo(base);
1297  if (period.asSeconds() >= snooze || toFrom % snooze == 0 || (toFrom / snooze + 1) * snooze <= toFrom + period.asSeconds()) {
1298  found = true;
1299 #ifndef NDEBUG
1300  // for debug output
1301  dt = offset.end(dt).addSecs(((toFrom - 1) / snooze + 1) * snooze);
1302 #endif
1303  break;
1304  }
1305  }
1306  }
1307  if (!found) {
1308  continue;
1309  }
1310  }
1311  }
1312  qCDebug(KCALCORE_LOG) << incidence->summary() << "':" << dt.toString();
1313  alarms.append(a);
1314  }
1315  }
1316 }
1317 
1319 {
1320  d->batchAddingInProgress = true;
1321 }
1322 
1324 {
1325  d->batchAddingInProgress = false;
1326 }
1327 
1329 {
1330  return d->batchAddingInProgress;
1331 }
1332 
1334 {
1335  d->mDeletionTracking = enable;
1336 }
1337 
1339 {
1340  return d->mDeletionTracking;
1341 }
1342 
1344 {
1345  return alarms(QDateTime(QDate(1900, 1, 1), QTime(0, 0, 0)), to);
1346 }
1347 
1348 void Calendar::virtual_hook(int id, void *data)
1349 {
1350  Q_UNUSED(id);
1351  Q_UNUSED(data);
1352  Q_ASSERT(false);
1353 }
1354 
1355 QString Calendar::id() const
1356 {
1357  return d->mId;
1358 }
1359 
1360 void Calendar::setId(const QString &id)
1361 {
1362  if (d->mId != id) {
1363  d->mId = id;
1364  Q_EMIT idChanged();
1365  }
1366 }
1367 
1368 QString Calendar::name() const
1369 {
1370  return d->mName;
1371 }
1372 
1373 void Calendar::setName(const QString &name)
1374 {
1375  if (d->mName != name) {
1376  d->mName = name;
1377  Q_EMIT nameChanged();
1378  }
1379 }
1380 
1381 QIcon Calendar::icon() const
1382 {
1383  return d->mIcon;
1384 }
1385 
1386 void Calendar::setIcon(const QIcon &icon)
1387 {
1388  d->mIcon = icon;
1389  Q_EMIT iconChanged();
1390 }
1391 
1392 AccessMode Calendar::accessMode() const
1393 {
1394  return d->mAccessMode;
1395 }
1396 
1398 {
1399  if (d->mAccessMode != mode) {
1400  d->mAccessMode = mode;
1402  }
1403 }
1404 
1405 bool Calendar::isLoading() const
1406 {
1407  return d->mIsLoading;
1408 }
1409 
1410 void Calendar::setIsLoading(bool isLoading)
1411 {
1412  if (d->mIsLoading == isLoading) {
1413  return;
1414  }
1415 
1416  d->mIsLoading = isLoading;
1418 }
Incidence::Ptr incidence(const QString &uid, const QDateTime &recurrenceId={}) const
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:614
QTimeZone utc()
void append(const T &value)
virtual void calendarIncidenceAboutToBeDeleted(const Incidence::Ptr &incidence)
Notify the Observer that an Incidence will be removed.
Definition: calendar.cpp:972
void appendAlarms(Alarm::List &alarms, const Incidence::Ptr &incidence, const QDateTime &from, const QDateTime &to) const
Appends alarms of incidence in interval to list of alarms.
Definition: calendar.cpp:1203
virtual void calendarIncidenceAdded(const Incidence::Ptr &incidence)
Notify the Observer that an Incidence has been inserted.
Definition: calendar.cpp:962
QDateTime addSecs(qint64 s) const const
void notifyIncidenceChanged(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they modified an Incidence.
Definition: calendar.cpp:1088
bool isEmpty() const const
@ TodoSortUnsorted
Do not sort Todos.
Definition: calendar.h:81
@ JournalSortDate
Sort Journals chronologically by date.
Definition: calendar.h:96
void accessModeChanged()
Emitted when the AccessMode changes.
Represents a span of time measured in seconds or days.
Definition: duration.h:43
QTimeZone timeZone() const const
TodoSortField
Calendar Todo sort keys.
Definition: calendar.h:80
virtual Event::List events(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const
Returns a sorted, filtered list of all Events for this Calendar.
Definition: calendar.cpp:546
void unregisterObserver(CalendarObserver *observer)
Unregisters an Observer for this Calendar.
Definition: calendar.cpp:1001
Q_EMITQ_EMIT
virtual bool setNotebook(const Incidence::Ptr &incidence, const QString &notebook)
Associate notebook for an incidence.
Definition: calendar.cpp:411
@ RoleStartTimeZone
Role for determining an incidence's starting timezone.
QVector::iterator begin()
QVector::const_iterator cend() const const
virtual Journal::List journalInstances(const Incidence::Ptr &journal, JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all instances for this recurring Journal.
void setId(const QString &id)
set a unique identifier for this calendar.
Definition: calendar.cpp:1360
void idChanged()
Emitted when the id changes.
bool isModified() const
Determine the calendar's modification status.
Definition: calendar.cpp:1026
JournalSortField
Calendar Journal sort keys.
Definition: calendar.h:94
QDateTime addDays(qint64 ndays) const const
virtual Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Todos for this Calendar.
Namespace for all KCalendarCore types.
Definition: alarm.h:36
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
QHash::iterator begin()
@ TodoSortCategories
Sort Todos by categories (tags)
Definition: calendar.h:88
void append(const T &value)
virtual void doSetTimeZone(const QTimeZone &timeZone)
Let Calendar subclasses set the time specification.
Definition: calendar.cpp:1059
Q_SCRIPTABLE Q_NOREPLY void start()
bool isVisible(const Incidence::Ptr &incidence) const
Check if incidence is visible.
Definition: calendar.cpp:381
virtual Incidence::List incidencesFromSchedulingID(const QString &sid) const
Searches all events and todos for an incidence with this scheduling identifier.
Definition: calendar.cpp:646
void push_back(const T &value)
void setIcon(const QIcon &icon)
Set this calendar's icon.
Definition: calendar.cpp:1386
virtual bool isSaving() const
Determine if the calendar is currently being saved.
Definition: calendar.cpp:1010
virtual bool deleteIncidence(const Incidence::Ptr &incidence)
Removes an Incidence from the calendar.
Definition: calendar.cpp:563
void incidenceUpdated(const QString &uid, const QDateTime &recurrenceId) override
The Observer interface.
Definition: calendar.cpp:1041
static Journal::List sortJournals(const Journal::List &journalList, JournalSortField sortField, SortDirection sortDirection)
Sort a list of Journals.
Definition: calendar.cpp:766
virtual bool addIncidence(const Incidence::Ptr &incidence)
Inserts an Incidence into the calendar.
Definition: calendar.cpp:553
static Todo::List sortTodos(const Todo::List &todoList, TodoSortField sortField, SortDirection sortDirection)
Sort a list of Todos.
Definition: calendar.cpp:669
QDateTime currentDateTimeUtc()
@ TypeTodo
Type is a to-do.
virtual bool beginChange(const Incidence::Ptr &incidence)
Flag that a change to a Calendar Incidence is starting.
Definition: calendar.cpp:1186
virtual Todo::List todos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const
Returns a sorted, filtered list of all Todos for this Calendar.
Definition: calendar.cpp:743
@ TodoSortPercentComplete
Sort Todos by percentage completed.
Definition: calendar.h:85
virtual Event::List eventInstances(const Incidence::Ptr &event, EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all possible instances for this recurring Event.
AccessMode
The calendar's access mode, i.e.
Definition: calendar.h:104
bool updateNotebook(const QString &notebook, bool isVisible)
Update notebook information in calendar.
Definition: calendar.cpp:335
@ EventSortStartDate
Sort Events chronologically, by start date.
Definition: calendar.h:72
QDateTime end(const QDateTime &start) const
Computes a duration end time by adding the number of seconds or days in the duration to the specified...
Definition: duration.cpp:171
void nameChanged()
Emitted when the name changes.
void setTimeZone(const QTimeZone &timeZone)
Sets the default time specification zone used for creating or modifying incidences in the Calendar.
Definition: calendar.cpp:178
@ TodoSortSummary
Sort Todos alphabetically, by summary.
Definition: calendar.h:86
virtual Todo::List todoInstances(const Incidence::Ptr &todo, TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all possible instances for this recurring Todo.
CalFilter * filter() const
Returns the calendar filter.
Definition: calendar.cpp:252
virtual void calendarModified(bool modified, Calendar *calendar)
Notify the Observer that a Calendar has been modified.
Definition: calendar.cpp:956
virtual bool save()
Syncs changes in memory to persistent storage.
Definition: calendar.cpp:1031
bool setDefaultNotebook(const QString &notebook)
set DefaultNotebook information to calendar.
Definition: calendar.cpp:361
void setOwner(const Person &owner)
Sets the owner of the calendar to owner.
Definition: calendar.cpp:169
virtual void removeRelations(const Incidence::Ptr &incidence)
Removes all Relations from an Incidence.
Definition: calendar.cpp:862
Represents the main calendar class.
Definition: calendar.h:132
int asSeconds() const
Returns the length of the duration in seconds.
Definition: duration.cpp:186
void setObserversEnabled(bool enabled)
Let Calendar subclasses notify that they enabled an Observer.
Definition: calendar.cpp:1198
Provides a filter for calendars.
Definition: calfilter.h:42
EventSortField
Calendar Event sort keys.
Definition: calendar.h:70
virtual Event::Ptr deletedEvent(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the deleted Event associated with the given unique identifier.
int size() const const
static Incidence::List mergeIncidenceList(const Event::List &events, const Todo::List &todos, const Journal::List &journals)
Create a merged list of Events, Todos, and Journals.
Definition: calendar.cpp:1164
qint64 secsTo(const QDateTime &other) const const
static Incidence::Ptr createException(const Incidence::Ptr &incidence, const QDateTime &recurrenceId, bool thisAndFuture=false)
Creates an exception for an occurrence from a recurring Incidence.
Definition: calendar.cpp:579
QHash::const_iterator constEnd() const const
QSharedPointer< Incidence > Ptr
A shared pointer to an Incidence.
Definition: incidence.h:121
virtual QStringList notebooks() const
List all uids of notebooks currently in the memory.
Definition: calendar.cpp:468
QVector::const_iterator cbegin() const const
virtual bool reload()
Loads the calendar contents from storage.
Definition: calendar.cpp:1036
@ EventSortUnsorted
Do not sort Events.
Definition: calendar.h:71
@ TodoSortStartDate
Sort Todos chronologically, by start date.
Definition: calendar.h:82
bool deletionTracking() const
Returns if deletion tracking is enabled.
Definition: calendar.cpp:1338
bool isEmpty() const const
Incidence::List relations(const QString &uid) const
Returns a list of incidences that have a relation of RELTYPE parent to incidence uid.
Definition: calendar.cpp:947
virtual void calendarIncidenceDeleted(const Incidence::Ptr &incidence, const Calendar *calendar)
Notify the Observer that an Incidence has been removed.
Definition: calendar.cpp:977
bool isValid() const const
void appendRecurringAlarms(Alarm::List &alarms, const Incidence::Ptr &incidence, const QDateTime &from, const QDateTime &to) const
Appends alarms of recurring events in interval to list of alarms.
Definition: calendar.cpp:1219
bool deleteNotebook(const QString &notebook)
Delete notebook information from calendar.
Definition: calendar.cpp:352
virtual Incidence::Ptr incidenceFromSchedulingID(const QString &sid) const
Returns the Incidence associated with the given scheduling identifier.
Definition: calendar.cpp:656
void setProductId(const QString &id)
Sets the calendar Product ID to id.
Definition: calendar.cpp:1153
void setName(const QString &name)
Set the user-visible name for this calendar.
Definition: calendar.cpp:1373
virtual Todo::Ptr deletedTodo(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the deleted Todo associated with the given unique identifier.
@ JournalSortUnsorted
Do not sort Journals.
Definition: calendar.h:95
Calendar(const QTimeZone &timeZone)
Constructs a calendar with a specified time zone timeZone.
Definition: calendar.cpp:143
virtual Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Events for this Calendar.
int asDays() const
Returns the length of the duration in days.
Definition: duration.cpp:191
virtual Journal::List journals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const
Returns a sorted, filtered list of all Journals for this Calendar.
Definition: calendar.cpp:799
SortDirection
Calendar Incidence sort directions.
Definition: calendar.h:62
This class provides the interface for a visitor of calendar components.
Definition: visitor.h:30
virtual Journal::Ptr deletedJournal(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the deleted Journal associated with the given unique identifier.
@ TodoSortDueDate
Sort Todos chronologically, by due date.
Definition: calendar.h:83
void reserve(int size)
virtual Incidence::List rawIncidences() const
Returns an unfiltered list of all Incidences for this Calendar.
Definition: calendar.cpp:285
void notifyIncidenceAboutToBeDeleted(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they will remove an Incidence.
Definition: calendar.cpp:1103
virtual Incidence::List incidences() const
Returns a filtered list of all Incidences for this Calendar.
Definition: calendar.cpp:280
virtual QString notebook(const Incidence::Ptr &incidence) const
Get incidence's notebook.
Definition: calendar.cpp:454
void customPropertyUpdated() override
Definition: calendar.cpp:1148
@ RoleEnd
Role for determining an incidence's dtEnd, will return an invalid QDateTime if the incidence does not...
virtual void clearNotebookAssociations()
Clears notebook associations from hash-tables for incidences.
Definition: calendar.cpp:404
Alarm::List alarmsTo(const QDateTime &to) const
Return a list of Alarms that occur before the specified timestamp.
Definition: calendar.cpp:1343
virtual void calendarIncidenceAdditionCanceled(const Incidence::Ptr &incidence)
Notify the Observer that an addition of Incidence has been canceled.
Definition: calendar.cpp:983
QVector< Ptr > List
List of incidences.
Definition: incidence.h:126
QVector::iterator end()
typename QHash< Key, T >::iterator find(const Key &key, const T &value)
virtual Alarm::List alarms(const QDateTime &from, const QDateTime &to, bool excludeBlockedAlarms=false) const =0
Returns a list of Alarms within a time range for this Calendar.
void setDeletionTracking(bool enable)
Enables or disabled deletion tracking.
Definition: calendar.cpp:1333
QString defaultNotebook() const
Get uid of default notebook.
Definition: calendar.cpp:371
bool batchAdding() const
Definition: calendar.cpp:1328
bool addNotebook(const QString &notebook, bool isVisible)
Add notebook information into calendar.
Definition: calendar.cpp:325
void ownerChanged()
Emitted when the owner changes.
void notifyIncidenceAdditionCanceled(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they canceled addition of an Incidence.
Definition: calendar.cpp:1133
void setFilter(CalFilter *filter)
Sets the calendar filter.
Definition: calendar.cpp:242
virtual void virtual_hook(int id, void *data)
Definition: calendar.cpp:1348
QTimeZone systemTimeZone()
virtual bool endChange(const Incidence::Ptr &incidence)
Flag that a change to a Calendar Incidence has completed.
Definition: calendar.cpp:1192
@ EventSortEndDate
Sort Events chronologically, by end date.
Definition: calendar.h:73
@ RoleEndTimeZone
Role for determining an incidence's ending timezone.
QTimeZone timeZone() const
Get the time zone used for creating or modifying incidences in the Calendar.
Definition: calendar.cpp:189
QDate date() const const
@ EventSortSummary
Sort Events alphabetically, by summary.
Definition: calendar.h:74
void registerObserver(CalendarObserver *observer)
Registers an Observer for this Calendar.
Definition: calendar.cpp:988
bool isValid() const const
bool hasValidNotebook(const QString &notebook) const
Check if calendar knows about the given notebook.
Definition: calendar.cpp:376
void setModified(bool modified)
Sets if the calendar has been modified.
Definition: calendar.cpp:1015
QVector::iterator erase(QVector::iterator begin, QVector::iterator end)
void setTimeZoneId(const QByteArray &timeZoneId)
Sets the time zone ID used for creating or modifying incidences in the Calendar.
Definition: calendar.cpp:194
@ TypeEvent
Type is an event.
bool isAncestorOf(const Incidence::Ptr &ancestor, const Incidence::Ptr &incidence) const
Checks if ancestor is an ancestor of incidence.
Definition: calendar.cpp:936
@ JournalSortSummary
Sort Journals alphabetically, by summary.
Definition: calendar.h:97
@ TypeJournal
Type is a journal.
int count(const T &value) const const
virtual Incidence::List instances(const Incidence::Ptr &incidence) const
Returns an unfiltered list of all exceptions of this recurring incidence.
Definition: calendar.cpp:290
@ TodoSortCreated
Sort Todos chronologically, by creation date.
Definition: calendar.h:87
@ SortDirectionAscending
Sort in ascending order (first to last)
Definition: calendar.h:63
void filterChanged()
Emitted when setFilter() is called.
Represents a person, by name and email address.
Definition: person.h:37
QByteArray timeZoneId() const
Returns the time zone ID used for creating or modifying incidences in the calendar.
Definition: calendar.cpp:215
@ RoleAlarmEndOffset
Role for an incidence alarm's ending offset date/time.
virtual Journal::Ptr journal(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the Journal associated with the given unique identifier.
void setIsLoading(bool isLoading)
Sets the loading state of this calendar.
Definition: calendar.cpp:1410
QString toString(Qt::DateFormat format) const const
void notifyIncidenceAdded(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they inserted an Incidence.
Definition: calendar.cpp:1064
virtual Todo::Ptr todo(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the Todo associated with the given unique identifier.
virtual Incidence::List duplicates(const Incidence::Ptr &incidence)
List all possible duplicate incidences.
Definition: calendar.cpp:310
bool isDaily() const
Returns whether the duration is specified in terms of days rather than seconds.
Definition: duration.cpp:181
void iconChanged()
Emitted when the icon name changes.
virtual Journal::List rawJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Journals for this Calendar.
@ TodoSortPriority
Sort Todos by priority.
Definition: calendar.h:84
Incidence::Ptr deleted(const QString &uid, const QDateTime &recurrenceId={}) const
Returns the deleted Incidence associated with the given unique identifier.
Definition: calendar.cpp:630
virtual Journal::List rawJournalsForDate(const QDate &date) const =0
Returns an unfiltered list of all Journals for on the specified date.
virtual void endBatchAdding()
Tells the Calendar that you stopped adding a batch of incidences.
Definition: calendar.cpp:1323
virtual Event::Ptr event(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the Event associated with the given unique identifier.
void isLoadingChanged()
Emitted when the loading state changed.
QVector< V > values(const QMultiHash< K, V > &c)
Make a QHash::value that returns a QVector.
Definition: calendar.cpp:48
void shiftTimes(const QTimeZone &oldZone, const QTimeZone &newZone)
Shifts the times of all incidences so that they appear at the same clock time as before but in a new ...
Definition: calendar.cpp:220
QObject * parent() const const
virtual Event::List rawEventsForDate(const QDateTime &dt) const =0
Returns an unfiltered list of all Events which occur on the given timestamp.
static Event::List sortEvents(const Event::List &eventList, EventSortField sortField, SortDirection sortDirection)
Sort a list of Events.
Definition: calendar.cpp:484
virtual void setupRelations(const Incidence::Ptr &incidence)
Setup Relations for an Incidence.
Definition: calendar.cpp:815
virtual Todo::List rawTodosForDate(const QDate &date) const =0
Returns an unfiltered list of all Todos which due on the specified date.
void notifyIncidenceDeleted(const Incidence::Ptr &incidence)
Let Calendar subclasses notify that they removed an Incidence.
Definition: calendar.cpp:1118
QHash::iterator end()
void setAccessMode(const AccessMode mode)
Set this calendar's AccessMode, i.e.
Definition: calendar.cpp:1397
virtual void calendarIncidenceChanged(const Incidence::Ptr &incidence)
Notify the Observer that an Incidence has been modified.
Definition: calendar.cpp:967
virtual void startBatchAdding()
Call this to tell the calendar that you're adding a batch of incidences.
Definition: calendar.cpp:1318
QStringList categories() const
Returns a list of all categories used by Incidences in this Calendar.
Definition: calendar.cpp:257
~Calendar() override
Destroys the calendar.
Definition: calendar.cpp:159
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Wed Jun 29 2022 04:02:26 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.