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

KDE's Doxygen guidelines are available online.