KCalendarCore

occurrenceiterator.cpp
Go to the documentation of this file.
1 /*
2  This file is part of the kcalcore library.
3 
4  SPDX-FileCopyrightText: 2013 Christian Mollekopf <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
19 #include "occurrenceiterator.h"
20 #include "calendar.h"
21 #include "calfilter.h"
22 
23 #include <QDate>
24 
25 using namespace KCalendarCore;
26 
31 //@cond PRIVATE
32 class Q_DECL_HIDDEN KCalendarCore::OccurrenceIterator::Private
33 {
34 public:
35  Private(OccurrenceIterator *qq)
36  : q(qq),
37  occurrenceIt(occurrenceList)
38  {
39  }
40 
42  QDateTime start;
43  QDateTime end;
44 
45  struct Occurrence {
46  Occurrence()
47  {
48  }
49 
50  Occurrence(const Incidence::Ptr &i, const QDateTime &recurrenceId, const QDateTime &startDate)
51  : incidence(i), recurrenceId(recurrenceId), startDate(startDate)
52  {
53  }
54 
55  Incidence::Ptr incidence;
56  QDateTime recurrenceId;
57  QDateTime startDate;
58  };
59  QList<Occurrence> occurrenceList;
60  QListIterator<Occurrence> occurrenceIt;
61  Occurrence current;
62 
63  /*
64  * KCalendarCore::CalFilter can't handle individual occurrences.
65  * When filtering completed to-dos, the CalFilter doesn't hide
66  * them if it's a recurring to-do.
67  */
68  bool occurrenceIsHidden(const Calendar &calendar,
69  const Incidence::Ptr &inc,
70  const QDateTime &occurrenceDate)
71  {
72  if ((inc->type() == Incidence::TypeTodo) &&
73  calendar.filter() &&
75  if (inc->recurs()) {
76  const Todo::Ptr todo = inc.staticCast<Todo>();
77  if (todo && (occurrenceDate < todo->dtDue())) {
78  return true;
79  }
80  } else if (inc->hasRecurrenceId()) {
81  const Todo::Ptr mainTodo = calendar.todo(inc->uid());
82  if (mainTodo && mainTodo->isCompleted()) {
83  return true;
84  }
85  }
86  }
87  return false;
88  }
89 
90  void setupIterator(const Calendar &calendar, const Incidence::List &incidences)
91  {
92  for (const Incidence::Ptr &inc : qAsConst(incidences)) {
93  if (inc->hasRecurrenceId()) {
94  continue;
95  }
96  if (inc->recurs()) {
98  QDateTime incidenceRecStart = inc->dateTime(Incidence::RoleRecurrenceStart);
99  //const bool isAllDay = inc->allDay();
100  const auto lstInstances = calendar.instances(inc);
101  for (const Incidence::Ptr &exception : lstInstances) {
102  if (incidenceRecStart.isValid()) {
103  recurrenceIds.insert(
104  exception->recurrenceId().toTimeZone(incidenceRecStart.timeZone()),
105  exception);
106  }
107  }
108  const auto occurrences = inc->recurrence()->timesInInterval(start, end);
109  Incidence::Ptr incidence(inc), lastInc(inc);
110  qint64 offset(0), lastOffset(0);
111  QDateTime occurrenceStartDate;
112  for (const auto &recurrenceId : qAsConst(occurrences)) {
113  occurrenceStartDate = recurrenceId;
114 
115  bool resetIncidence = false;
116  if (recurrenceIds.contains(recurrenceId)) {
117  // TODO: exclude exceptions where the start/end is not within
118  // (so the occurrence of the recurrence is omitted, but no exception is added)
119  if (recurrenceIds.value(recurrenceId)->status() == Incidence::StatusCanceled) {
120  continue;
121  }
122 
123  incidence = recurrenceIds.value(recurrenceId);
124  occurrenceStartDate = incidence->dtStart();
125  resetIncidence = !incidence->thisAndFuture();
126  offset = incidence->recurrenceId().secsTo(incidence->dtStart());
127  if (incidence->thisAndFuture()) {
128  lastInc = incidence;
129  lastOffset = offset;
130  }
131  } else if (inc != incidence) { //thisAndFuture exception is active
132  occurrenceStartDate = occurrenceStartDate.addSecs(offset);
133  }
134 
135  if (!occurrenceIsHidden(calendar, incidence, occurrenceStartDate)) {
136  occurrenceList << Private::Occurrence(incidence, recurrenceId, occurrenceStartDate);
137  }
138 
139  if (resetIncidence) {
140  incidence = lastInc;
141  offset = lastOffset;
142  }
143  }
144  } else {
145  occurrenceList << Private::Occurrence(inc, {}, inc->dtStart());
146  }
147  }
148  occurrenceIt = QListIterator<Private::Occurrence>(occurrenceList);
149  }
150 };
151 //@endcond
152 
165  const QDateTime &start,
166  const QDateTime &end)
167  : d(new KCalendarCore::OccurrenceIterator::Private(this))
168 {
169  d->start = start;
170  d->end = end;
171 
172  Event::List events = calendar.rawEvents(start.date(), end.date(), start.timeZone());
173  if (calendar.filter()) {
174  calendar.filter()->apply(&events);
175  }
176 
177  Todo::List todos = calendar.rawTodos(start.date(), end.date(), start.timeZone());
178  if (calendar.filter()) {
179  calendar.filter()->apply(&todos);
180  }
181 
182  Journal::List journals;
183  const Journal::List allJournals = calendar.rawJournals();
184  for (const KCalendarCore::Journal::Ptr &journal : allJournals) {
185  const QDate journalStart = journal->dtStart().toTimeZone(start.timeZone()).date();
186  if (journal->dtStart().isValid() &&
187  journalStart >= start.date() &&
188  journalStart <= end.date()) {
189  journals << journal;
190  }
191  }
192 
193  if (calendar.filter()) {
194  calendar.filter()->apply(&journals);
195  }
196 
197  const Incidence::List incidences =
198  KCalendarCore::Calendar::mergeIncidenceList(events, todos, journals);
199  d->setupIterator(calendar, incidences);
200 }
201 
203  const Incidence::Ptr &incidence,
204  const QDateTime &start,
205  const QDateTime &end)
206  : d(new KCalendarCore::OccurrenceIterator::Private(this))
207 {
208  Q_ASSERT(incidence);
209  d->start = start;
210  d->end = end;
211  d->setupIterator(calendar, Incidence::List() << incidence);
212 }
213 
214 OccurrenceIterator::~OccurrenceIterator()
215 {
216 }
217 
218 bool OccurrenceIterator::hasNext() const
219 {
220  return d->occurrenceIt.hasNext();
221 }
222 
224 {
225  d->current = d->occurrenceIt.next();
226 }
227 
229 {
230  return d->current.incidence;
231 }
232 
234 {
235  return d->current.startDate;
236 }
237 
239 {
240  return d->current.recurrenceId;
241 }
int criteria() const
Returns the inclusive filter criteria.
Definition: calfilter.cpp:222
QHash::iterator insert(const Key &key, const T &value)
QDateTime recurrenceId() const
Returns the recurrence Id.
Represents the main calendar class.
Definition: calendar.h:119
This file is part of the API for handling calendar data and defines the OccurrenceIterator class...
CalFilter * filter() const
Returns the calendar filter.
Definition: calendar.cpp:233
virtual Todo::Ptr todo(const QString &uid, const QDateTime &recurrenceId={}) const =0
Returns the Todo associated with the given unique identifier.
OccurrenceIterator(const Calendar &calendar, const QDateTime &start=QDateTime(), const QDateTime &end=QDateTime())
Creates iterator that iterates over all occurrences of all incidences between.
virtual Todo::List rawTodos(TodoSortField sortField=TodoSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Todos for this Calendar.
Role for determining the start of the recurrence.
Incidence::Ptr incidence() const
Returns either main incidence or exception, depending on occurrence.
This file is part of the API for handling calendar data and defines the Calendar class.
QDateTime occurrenceStartDate() const
Returns the start date of the occurrence.
Provides a To-do in the sense of RFC2445.
Definition: todo.h:31
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:1176
void apply(Event::List *eventList) const
Applies the filter to a list of Events.
Definition: calfilter.cpp:71
const T value(const Key &key) const const
bool isValid() const const
const QList< QKeySequence > & end()
Iterate over calendar items in a calendar.
QDate date() const const
event or to-do canceled; journal removed
Definition: incidence.h:84
qint64 secsTo(const QDateTime &other) 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:272
bool contains(const Key &key) const const
virtual Event::List rawEvents(EventSortField sortField=EventSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Events for this Calendar.
This file is part of the API for handling calendar data and defines the CalFilter class...
QDateTime addSecs(qint64 s) const const
QSharedPointer< X > staticCast() const const
virtual Journal::List rawJournals(JournalSortField sortField=JournalSortUnsorted, SortDirection sortDirection=SortDirectionAscending) const =0
Returns a sorted, unfiltered list of all Journals for this Calendar.
void next()
Advance iterator to the next occurrence.
Namespace for all KCalendarCore types.
Definition: alarm.h:36
QTimeZone timeZone() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Sep 21 2020 22:51:27 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.