• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

KCalCore Library

  • kcalcore
recurrence.cpp
1/*
2 This file is part of kcalcore library.
3
4 Copyright (c) 1998 Preston Brown <pbrown@kde.org>
5 Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
6 Copyright (c) 2002,2006 David Jarvie <software@astrojar.org.uk>
7 Copyright (C) 2005 Reinhold Kainhofer <kainhofer@kde.org>
8
9 This library is free software; you can redistribute it and/or
10 modify it under the terms of the GNU Library General Public
11 License as published by the Free Software Foundation; either
12 version 2 of the License, or (at your option) any later version.
13
14 This library is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 Library General Public License for more details.
18
19 You should have received a copy of the GNU Library General Public License
20 along with this library; see the file COPYING.LIB. If not, write to
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA.
23*/
24#include "recurrence.h"
25
26#include <KDebug>
27
28#include <QtCore/QBitArray>
29#include <QtCore/QTime>
30
31using namespace KCalCore;
32
33//@cond PRIVATE
34class KCalCore::Recurrence::Private
35{
36public:
37 Private()
38 : mCachedType(rMax),
39 mAllDay(false),
40 mRecurReadOnly(false)
41 {
42 }
43
44 Private(const Private &p)
45 : mRDateTimes(p.mRDateTimes),
46 mRDates(p.mRDates),
47 mExDateTimes(p.mExDateTimes),
48 mExDates(p.mExDates),
49 mStartDateTime(p.mStartDateTime),
50 mCachedType(p.mCachedType),
51 mAllDay(p.mAllDay),
52 mRecurReadOnly(p.mRecurReadOnly)
53 {
54 }
55
56 bool operator==(const Private &p) const;
57
58 RecurrenceRule::List mExRules;
59 RecurrenceRule::List mRRules;
60 DateTimeList mRDateTimes;
61 DateList mRDates;
62 DateTimeList mExDateTimes;
63 DateList mExDates;
64 KDateTime mStartDateTime; // date/time of first recurrence
65 QList<RecurrenceObserver*> mObservers;
66
67 // Cache the type of the recurrence with the old system (e.g. MonthlyPos)
68 mutable ushort mCachedType;
69
70 bool mAllDay; // the recurrence has no time, just a date
71 bool mRecurReadOnly;
72};
73
74bool Recurrence::Private::operator==(const Recurrence::Private &p) const
75{
76 if ((mStartDateTime != p.mStartDateTime &&
77 (mStartDateTime.isValid() || p.mStartDateTime.isValid())) ||
78 mAllDay != p.mAllDay ||
79 mRecurReadOnly != p.mRecurReadOnly ||
80 mExDates != p.mExDates ||
81 mExDateTimes != p.mExDateTimes ||
82 mRDates != p.mRDates ||
83 mRDateTimes != p.mRDateTimes) {
84 return false;
85 }
86
87// Compare the rrules, exrules! Assume they have the same order... This only
88// matters if we have more than one rule (which shouldn't be the default anyway)
89 int i;
90 int end = mRRules.count();
91 if (end != p.mRRules.count()) {
92 return false;
93 }
94 for (i = 0; i < end; ++i) {
95 if (*mRRules[i] != *p.mRRules[i]) {
96 return false;
97 }
98 }
99 end = mExRules.count();
100 if (end != p.mExRules.count()) {
101 return false;
102 }
103 for (i = 0; i < end; ++i) {
104 if (*mExRules[i] != *p.mExRules[i]) {
105 return false;
106 }
107 }
108 return true;
109}
110//@endcond
111
112Recurrence::Recurrence()
113 : d(new KCalCore::Recurrence::Private())
114{
115}
116
117Recurrence::Recurrence(const Recurrence &r)
118 : RecurrenceRule::RuleObserver(),
119 d(new KCalCore::Recurrence::Private(*r.d))
120{
121 int i, end;
122 for (i = 0, end = r.d->mRRules.count(); i < end; ++i) {
123 RecurrenceRule *rule = new RecurrenceRule(*r.d->mRRules[i]);
124 d->mRRules.append(rule);
125 rule->addObserver(this);
126 }
127 for (i = 0, end = r.d->mExRules.count(); i < end; ++i) {
128 RecurrenceRule *rule = new RecurrenceRule(*r.d->mExRules[i]);
129 d->mExRules.append(rule);
130 rule->addObserver(this);
131 }
132}
133
134Recurrence::~Recurrence()
135{
136 qDeleteAll(d->mExRules);
137 qDeleteAll(d->mRRules);
138 delete d;
139}
140
141bool Recurrence::operator==(const Recurrence &recurrence) const
142{
143 return *d == *recurrence.d;
144}
145
146Recurrence &Recurrence::operator=(const Recurrence &recurrence)
147{
148 // check for self assignment
149 if (&recurrence == this) {
150 return *this;
151 }
152
153 *d = *recurrence.d;
154 return *this;
155}
156
157void Recurrence::addObserver(RecurrenceObserver *observer)
158{
159 if (!d->mObservers.contains(observer)) {
160 d->mObservers.append(observer);
161 }
162}
163
164void Recurrence::removeObserver(RecurrenceObserver *observer)
165{
166 if (d->mObservers.contains(observer)) {
167 d->mObservers.removeAll(observer);
168 }
169}
170
171KDateTime Recurrence::startDateTime() const
172{
173 return d->mStartDateTime;
174}
175
176bool Recurrence::allDay() const
177{
178 return d->mAllDay;
179}
180
181void Recurrence::setAllDay(bool allDay)
182{
183 if (d->mRecurReadOnly || allDay == d->mAllDay) {
184 return;
185 }
186
187 d->mAllDay = allDay;
188 for (int i = 0, end = d->mRRules.count(); i < end; ++i) {
189 d->mRRules[i]->setAllDay(allDay);
190 }
191 for (int i = 0, end = d->mExRules.count(); i < end; ++i) {
192 d->mExRules[i]->setAllDay(allDay);
193 }
194 updated();
195}
196
197RecurrenceRule *Recurrence::defaultRRule(bool create) const
198{
199 if (d->mRRules.isEmpty()) {
200 if (!create || d->mRecurReadOnly) {
201 return 0;
202 }
203 RecurrenceRule *rrule = new RecurrenceRule();
204 rrule->setStartDt(startDateTime());
205 const_cast<KCalCore::Recurrence*>(this)->addRRule(rrule);
206 return rrule;
207 } else {
208 return d->mRRules[0];
209 }
210}
211
212RecurrenceRule *Recurrence::defaultRRuleConst() const
213{
214 return d->mRRules.isEmpty() ? 0 : d->mRRules[0];
215}
216
217void Recurrence::updated()
218{
219 // recurrenceType() re-calculates the type if it's rMax
220 d->mCachedType = rMax;
221 for (int i = 0, end = d->mObservers.count(); i < end; ++i) {
222 if (d->mObservers[i]) {
223 d->mObservers[i]->recurrenceUpdated(this);
224 }
225 }
226}
227
228bool Recurrence::recurs() const
229{
230 return !d->mRRules.isEmpty() || !d->mRDates.isEmpty() || !d->mRDateTimes.isEmpty();
231}
232
233ushort Recurrence::recurrenceType() const
234{
235 if (d->mCachedType == rMax) {
236 d->mCachedType = recurrenceType(defaultRRuleConst());
237 }
238 return d->mCachedType;
239}
240
241ushort Recurrence::recurrenceType(const RecurrenceRule *rrule)
242{
243 if (!rrule) {
244 return rNone;
245 }
246 RecurrenceRule::PeriodType type = rrule->recurrenceType();
247
248 // BYSETPOS, BYWEEKNUMBER and BYSECOND were not supported in old versions
249 if (!rrule->bySetPos().isEmpty() ||
250 !rrule->bySeconds().isEmpty() ||
251 !rrule->byWeekNumbers().isEmpty()) {
252 return rOther;
253 }
254
255 // It wasn't possible to set BYMINUTES, BYHOUR etc. by the old code. So if
256 // it's set, it's none of the old types
257 if (!rrule->byMinutes().isEmpty() || !rrule->byHours().isEmpty()) {
258 return rOther;
259 }
260
261 // Possible combinations were:
262 // BYDAY: with WEEKLY, MONTHLY, YEARLY
263 // BYMONTHDAY: with MONTHLY, YEARLY
264 // BYMONTH: with YEARLY
265 // BYYEARDAY: with YEARLY
266 if ((!rrule->byYearDays().isEmpty() && type != RecurrenceRule::rYearly) ||
267 (!rrule->byMonths().isEmpty() && type != RecurrenceRule::rYearly)) {
268 return rOther;
269 }
270 if (!rrule->byDays().isEmpty()) {
271 if (type != RecurrenceRule::rYearly &&
272 type != RecurrenceRule::rMonthly &&
273 type != RecurrenceRule::rWeekly) {
274 return rOther;
275 }
276 }
277
278 switch (type) {
279 case RecurrenceRule::rNone:
280 return rNone;
281 case RecurrenceRule::rMinutely:
282 return rMinutely;
283 case RecurrenceRule::rHourly:
284 return rHourly;
285 case RecurrenceRule::rDaily:
286 return rDaily;
287 case RecurrenceRule::rWeekly:
288 return rWeekly;
289 case RecurrenceRule::rMonthly:
290 {
291 if (rrule->byDays().isEmpty()) {
292 return rMonthlyDay;
293 } else if (rrule->byMonthDays().isEmpty()) {
294 return rMonthlyPos;
295 } else {
296 return rOther; // both position and date specified
297 }
298 }
299 case RecurrenceRule::rYearly:
300 {
301 // Possible combinations:
302 // rYearlyMonth: [BYMONTH &] BYMONTHDAY
303 // rYearlyDay: BYYEARDAY
304 // rYearlyPos: [BYMONTH &] BYDAY
305 if (!rrule->byDays().isEmpty()) {
306 // can only by rYearlyPos
307 if (rrule->byMonthDays().isEmpty() && rrule->byYearDays().isEmpty()) {
308 return rYearlyPos;
309 } else {
310 return rOther;
311 }
312 } else if (!rrule->byYearDays().isEmpty()) {
313 // Can only be rYearlyDay
314 if (rrule->byMonths().isEmpty() && rrule->byMonthDays().isEmpty()) {
315 return rYearlyDay;
316 } else {
317 return rOther;
318 }
319 } else {
320 return rYearlyMonth;
321 }
322 break;
323 }
324 default:
325 return rOther;
326 }
327 return rOther;
328}
329
330bool Recurrence::recursOn(const QDate &qd, const KDateTime::Spec &timeSpec) const
331{
332 // Don't waste time if date is before the start of the recurrence
333 if (KDateTime(qd, QTime(23, 59, 59), timeSpec) < d->mStartDateTime) {
334 return false;
335 }
336
337 // First handle dates. Exrules override
338 if (d->mExDates.containsSorted(qd)) {
339 return false;
340 }
341
342 int i, end;
343 TimeList tms;
344 // For all-day events a matching exrule excludes the whole day
345 // since exclusions take precedence over inclusions, we know it can't occur on that day.
346 if (allDay()) {
347 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
348 if (d->mExRules[i]->recursOn(qd, timeSpec)) {
349 return false;
350 }
351 }
352 }
353
354 if (d->mRDates.containsSorted(qd)) {
355 return true;
356 }
357
358 // Check if it might recur today at all.
359 bool recurs = (startDate() == qd);
360 for (i = 0, end = d->mRDateTimes.count(); i < end && !recurs; ++i) {
361 recurs = (d->mRDateTimes[i].toTimeSpec(timeSpec).date() == qd);
362 }
363 for (i = 0, end = d->mRRules.count(); i < end && !recurs; ++i) {
364 recurs = d->mRRules[i]->recursOn(qd, timeSpec);
365 }
366 // If the event wouldn't recur at all, simply return false, don't check ex*
367 if (!recurs) {
368 return false;
369 }
370
371 // Check if there are any times for this day excluded, either by exdate or exrule:
372 bool exon = false;
373 for (i = 0, end = d->mExDateTimes.count(); i < end && !exon; ++i) {
374 exon = (d->mExDateTimes[i].toTimeSpec(timeSpec).date() == qd);
375 }
376 if (!allDay()) { // we have already checked all-day times above
377 for (i = 0, end = d->mExRules.count(); i < end && !exon; ++i) {
378 exon = d->mExRules[i]->recursOn(qd, timeSpec);
379 }
380 }
381
382 if (!exon) {
383 // Simple case, nothing on that day excluded, return the value from before
384 return recurs;
385 } else {
386 // Harder part: I don't think there is any way other than to calculate the
387 // whole list of items for that day.
388//TODO: consider whether it would be more efficient to call
389// Rule::recurTimesOn() instead of Rule::recursOn() from the start
390 TimeList timesForDay(recurTimesOn(qd, timeSpec));
391 return !timesForDay.isEmpty();
392 }
393}
394
395bool Recurrence::recursAt(const KDateTime &dt) const
396{
397 // Convert to recurrence's time zone for date comparisons, and for more efficient time comparisons
398 KDateTime dtrecur = dt.toTimeSpec(d->mStartDateTime.timeSpec());
399
400 // if it's excluded anyway, don't bother to check if it recurs at all.
401 if (d->mExDateTimes.containsSorted(dtrecur) ||
402 d->mExDates.containsSorted(dtrecur.date())) {
403 return false;
404 }
405 int i, end;
406 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
407 if (d->mExRules[i]->recursAt(dtrecur)) {
408 return false;
409 }
410 }
411
412 // Check explicit recurrences, then rrules.
413 if (startDateTime() == dtrecur || d->mRDateTimes.containsSorted(dtrecur)) {
414 return true;
415 }
416 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
417 if (d->mRRules[i]->recursAt(dtrecur)) {
418 return true;
419 }
420 }
421
422 return false;
423}
424
428KDateTime Recurrence::endDateTime() const
429{
430 DateTimeList dts;
431 dts << startDateTime();
432 if (!d->mRDates.isEmpty()) {
433 dts << KDateTime(d->mRDates.last(), QTime(0, 0, 0), d->mStartDateTime.timeSpec());
434 }
435 if (!d->mRDateTimes.isEmpty()) {
436 dts << d->mRDateTimes.last();
437 }
438 for (int i = 0, end = d->mRRules.count(); i < end; ++i) {
439 KDateTime rl(d->mRRules[i]->endDt());
440 // if any of the rules is infinite, the whole recurrence is
441 if (!rl.isValid()) {
442 return KDateTime();
443 }
444 dts << rl;
445 }
446 dts.sortUnique();
447 return dts.isEmpty() ? KDateTime() : dts.last();
448}
449
453QDate Recurrence::endDate() const
454{
455 KDateTime end(endDateTime());
456 return end.isValid() ? end.date() : QDate();
457}
458
459void Recurrence::setEndDate(const QDate &date)
460{
461 KDateTime dt(date, d->mStartDateTime.time(), d->mStartDateTime.timeSpec());
462 if (allDay()) {
463 dt.setTime(QTime(23, 59, 59));
464 }
465 setEndDateTime(dt);
466}
467
468void Recurrence::setEndDateTime(const KDateTime &dateTime)
469{
470 if (d->mRecurReadOnly) {
471 return;
472 }
473 RecurrenceRule *rrule = defaultRRule(true);
474 if (!rrule) {
475 return;
476 }
477 rrule->setEndDt(dateTime);
478 updated();
479}
480
481int Recurrence::duration() const
482{
483 RecurrenceRule *rrule = defaultRRuleConst();
484 return rrule ? rrule->duration() : 0;
485}
486
487int Recurrence::durationTo(const KDateTime &datetime) const
488{
489 // Emulate old behavior: This is just an interface to the first rule!
490 RecurrenceRule *rrule = defaultRRuleConst();
491 return rrule ? rrule->durationTo(datetime) : 0;
492}
493
494int Recurrence::durationTo(const QDate &date) const
495{
496 return durationTo(KDateTime(date, QTime(23, 59, 59), d->mStartDateTime.timeSpec()));
497}
498
499void Recurrence::setDuration(int duration)
500{
501 if (d->mRecurReadOnly) {
502 return;
503 }
504
505 RecurrenceRule *rrule = defaultRRule(true);
506 if (!rrule) {
507 return;
508 }
509 rrule->setDuration(duration);
510 updated();
511}
512
513void Recurrence::shiftTimes(const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec)
514{
515 if (d->mRecurReadOnly) {
516 return;
517 }
518
519 d->mStartDateTime = d->mStartDateTime.toTimeSpec(oldSpec);
520 d->mStartDateTime.setTimeSpec(newSpec);
521
522 int i, end;
523 for (i = 0, end = d->mRDateTimes.count(); i < end; ++i) {
524 d->mRDateTimes[i] = d->mRDateTimes[i].toTimeSpec(oldSpec);
525 d->mRDateTimes[i].setTimeSpec(newSpec);
526 }
527 for (i = 0, end = d->mExDateTimes.count(); i < end; ++i) {
528 d->mExDateTimes[i] = d->mExDateTimes[i].toTimeSpec(oldSpec);
529 d->mExDateTimes[i].setTimeSpec(newSpec);
530 }
531 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
532 d->mRRules[i]->shiftTimes(oldSpec, newSpec);
533 }
534 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
535 d->mExRules[i]->shiftTimes(oldSpec, newSpec);
536 }
537}
538
539void Recurrence::unsetRecurs()
540{
541 if (d->mRecurReadOnly) {
542 return;
543 }
544 qDeleteAll(d->mRRules);
545 d->mRRules.clear();
546 updated();
547}
548
549void Recurrence::clear()
550{
551 if (d->mRecurReadOnly) {
552 return;
553 }
554 qDeleteAll(d->mRRules);
555 d->mRRules.clear();
556 qDeleteAll(d->mExRules);
557 d->mExRules.clear();
558 d->mRDates.clear();
559 d->mRDateTimes.clear();
560 d->mExDates.clear();
561 d->mExDateTimes.clear();
562 d->mCachedType = rMax;
563 updated();
564}
565
566void Recurrence::setRecurReadOnly(bool readOnly)
567{
568 d->mRecurReadOnly = readOnly;
569}
570
571bool Recurrence::recurReadOnly() const
572{
573 return d->mRecurReadOnly;
574}
575
576QDate Recurrence::startDate() const
577{
578 return d->mStartDateTime.date();
579}
580
581void Recurrence::setStartDateTime(const KDateTime &start)
582{
583 if (d->mRecurReadOnly) {
584 return;
585 }
586 d->mStartDateTime = start;
587 setAllDay(start.isDateOnly()); // set all RRULEs and EXRULEs
588
589 int i, end;
590 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
591 d->mRRules[i]->setStartDt(start);
592 }
593 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
594 d->mExRules[i]->setStartDt(start);
595 }
596 updated();
597}
598
599int Recurrence::frequency() const
600{
601 RecurrenceRule *rrule = defaultRRuleConst();
602 return rrule ? rrule->frequency() : 0;
603}
604
605// Emulate the old behaviour. Make this methods just an interface to the
606// first rrule
607void Recurrence::setFrequency(int freq)
608{
609 if (d->mRecurReadOnly || freq <= 0) {
610 return;
611 }
612
613 RecurrenceRule *rrule = defaultRRule(true);
614 if (rrule) {
615 rrule->setFrequency(freq);
616 }
617 updated();
618}
619
620// WEEKLY
621
622int Recurrence::weekStart() const
623{
624 RecurrenceRule *rrule = defaultRRuleConst();
625 return rrule ? rrule->weekStart() : 1;
626}
627
628// Emulate the old behavior
629QBitArray Recurrence::days() const
630{
631 QBitArray days(7);
632 days.fill(0);
633 RecurrenceRule *rrule = defaultRRuleConst();
634 if (rrule) {
635 QList<RecurrenceRule::WDayPos> bydays = rrule->byDays();
636 for (int i = 0; i < bydays.size(); ++i) {
637 if (bydays.at(i).pos() == 0) {
638 days.setBit(bydays.at(i).day() - 1);
639 }
640 }
641 }
642 return days;
643}
644
645// MONTHLY
646
647// Emulate the old behavior
648QList<int> Recurrence::monthDays() const
649{
650 RecurrenceRule *rrule = defaultRRuleConst();
651 if (rrule) {
652 return rrule->byMonthDays();
653 } else {
654 return QList<int>();
655 }
656}
657
658// Emulate the old behavior
659QList<RecurrenceRule::WDayPos> Recurrence::monthPositions() const
660{
661 RecurrenceRule *rrule = defaultRRuleConst();
662 return rrule ? rrule->byDays() : QList<RecurrenceRule::WDayPos>();
663}
664
665// YEARLY
666
667QList<int> Recurrence::yearDays() const
668{
669 RecurrenceRule *rrule = defaultRRuleConst();
670 return rrule ? rrule->byYearDays() : QList<int>();
671}
672
673QList<int> Recurrence::yearDates() const
674{
675 return monthDays();
676}
677
678QList<int> Recurrence::yearMonths() const
679{
680 RecurrenceRule *rrule = defaultRRuleConst();
681 return rrule ? rrule->byMonths() : QList<int>();
682}
683
684QList<RecurrenceRule::WDayPos> Recurrence::yearPositions() const
685{
686 return monthPositions();
687}
688
689RecurrenceRule *Recurrence::setNewRecurrenceType(RecurrenceRule::PeriodType type, int freq)
690{
691 if (d->mRecurReadOnly || freq <= 0) {
692 return 0;
693 }
694
695 qDeleteAll(d->mRRules);
696 d->mRRules.clear();
697 updated();
698 RecurrenceRule *rrule = defaultRRule(true);
699 if (!rrule) {
700 return 0;
701 }
702 rrule->setRecurrenceType(type);
703 rrule->setFrequency(freq);
704 rrule->setDuration(-1);
705 return rrule;
706}
707
708void Recurrence::setMinutely(int _rFreq)
709{
710 if (setNewRecurrenceType(RecurrenceRule::rMinutely, _rFreq)) {
711 updated();
712 }
713}
714
715void Recurrence::setHourly(int _rFreq)
716{
717 if (setNewRecurrenceType(RecurrenceRule::rHourly, _rFreq)) {
718 updated();
719 }
720}
721
722void Recurrence::setDaily(int _rFreq)
723{
724 if (setNewRecurrenceType(RecurrenceRule::rDaily, _rFreq)) {
725 updated();
726 }
727}
728
729void Recurrence::setWeekly(int freq, int weekStart)
730{
731 RecurrenceRule *rrule = setNewRecurrenceType(RecurrenceRule::rWeekly, freq);
732 if (!rrule) {
733 return;
734 }
735 rrule->setWeekStart(weekStart);
736 updated();
737}
738
739void Recurrence::setWeekly(int freq, const QBitArray &days, int weekStart)
740{
741 setWeekly(freq, weekStart);
742 addMonthlyPos(0, days);
743}
744
745void Recurrence::addWeeklyDays(const QBitArray &days)
746{
747 addMonthlyPos(0, days);
748}
749
750void Recurrence::setMonthly(int freq)
751{
752 if (setNewRecurrenceType(RecurrenceRule::rMonthly, freq)) {
753 updated();
754 }
755}
756
757void Recurrence::addMonthlyPos(short pos, const QBitArray &days)
758{
759 // Allow 53 for yearly!
760 if (d->mRecurReadOnly || pos > 53 || pos < -53) {
761 return;
762 }
763
764 RecurrenceRule *rrule = defaultRRule(false);
765 if (!rrule) {
766 return;
767 }
768 bool changed = false;
769 QList<RecurrenceRule::WDayPos> positions = rrule->byDays();
770
771 for (int i = 0; i < 7; ++i) {
772 if (days.testBit(i)) {
773 RecurrenceRule::WDayPos p(pos, i + 1);
774 if (!positions.contains(p)) {
775 changed = true;
776 positions.append(p);
777 }
778 }
779 }
780 if (changed) {
781 rrule->setByDays(positions);
782 updated();
783 }
784}
785
786void Recurrence::addMonthlyPos(short pos, ushort day)
787{
788 // Allow 53 for yearly!
789 if (d->mRecurReadOnly || pos > 53 || pos < -53) {
790 return;
791 }
792
793 RecurrenceRule *rrule = defaultRRule(false);
794 if (!rrule) {
795 return;
796 }
797 QList<RecurrenceRule::WDayPos> positions = rrule->byDays();
798
799 RecurrenceRule::WDayPos p(pos, day);
800 if (!positions.contains(p)) {
801 positions.append(p);
802 rrule->setByDays(positions);
803 updated();
804 }
805}
806
807void Recurrence::addMonthlyDate(short day)
808{
809 if (d->mRecurReadOnly || day > 31 || day < -31) {
810 return;
811 }
812
813 RecurrenceRule *rrule = defaultRRule(true);
814 if (!rrule) {
815 return;
816 }
817
818 QList<int> monthDays = rrule->byMonthDays();
819 if (!monthDays.contains(day)) {
820 monthDays.append(day);
821 rrule->setByMonthDays(monthDays);
822 updated();
823 }
824}
825
826void Recurrence::setYearly(int freq)
827{
828 if (setNewRecurrenceType(RecurrenceRule::rYearly, freq)) {
829 updated();
830 }
831}
832
833// Daynumber within year
834void Recurrence::addYearlyDay(int day)
835{
836 RecurrenceRule *rrule = defaultRRule(false); // It must already exist!
837 if (!rrule) {
838 return;
839 }
840
841 QList<int> days = rrule->byYearDays();
842 if (!days.contains(day)) {
843 days << day;
844 rrule->setByYearDays(days);
845 updated();
846 }
847}
848
849// day part of date within year
850void Recurrence::addYearlyDate(int day)
851{
852 addMonthlyDate(day);
853}
854
855// day part of date within year, given as position (n-th weekday)
856void Recurrence::addYearlyPos(short pos, const QBitArray &days)
857{
858 addMonthlyPos(pos, days);
859}
860
861// month part of date within year
862void Recurrence::addYearlyMonth(short month)
863{
864 if (d->mRecurReadOnly || month < 1 || month > 12) {
865 return;
866 }
867
868 RecurrenceRule *rrule = defaultRRule(false);
869 if (!rrule) {
870 return;
871 }
872
873 QList<int> months = rrule->byMonths();
874 if (!months.contains(month)) {
875 months << month;
876 rrule->setByMonths(months);
877 updated();
878 }
879}
880
881TimeList Recurrence::recurTimesOn(const QDate &date, const KDateTime::Spec &timeSpec) const
882{
883// kDebug() << "recurTimesOn(" << date << ")";
884 int i, end;
885 TimeList times;
886
887 // The whole day is excepted
888 if (d->mExDates.containsSorted(date)) {
889 return times;
890 }
891
892 // EXRULE takes precedence over RDATE entries, so for all-day events,
893 // a matching excule also excludes the whole day automatically
894 if (allDay()) {
895 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
896 if (d->mExRules[i]->recursOn(date, timeSpec)) {
897 return times;
898 }
899 }
900 }
901
902 KDateTime dt = startDateTime().toTimeSpec(timeSpec);
903 if (dt.date() == date) {
904 times << dt.time();
905 }
906
907 bool foundDate = false;
908 for (i = 0, end = d->mRDateTimes.count(); i < end; ++i) {
909 dt = d->mRDateTimes[i].toTimeSpec(timeSpec);
910 if (dt.date() == date) {
911 times << dt.time();
912 foundDate = true;
913 } else if (foundDate) {
914 break; // <= Assume that the rdatetime list is sorted
915 }
916 }
917 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
918 times += d->mRRules[i]->recurTimesOn(date, timeSpec);
919 }
920 times.sortUnique();
921
922 foundDate = false;
923 TimeList extimes;
924 for (i = 0, end = d->mExDateTimes.count(); i < end; ++i) {
925 dt = d->mExDateTimes[i].toTimeSpec(timeSpec);
926 if (dt.date() == date) {
927 extimes << dt.time();
928 foundDate = true;
929 } else if (foundDate) {
930 break;
931 }
932 }
933 if (!allDay()) { // we have already checked all-day times above
934 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
935 extimes += d->mExRules[i]->recurTimesOn(date, timeSpec);
936 }
937 }
938 extimes.sortUnique();
939
940 int st = 0;
941 for (i = 0, end = extimes.count(); i < end; ++i) {
942 int j = times.removeSorted(extimes[i], st);
943 if (j >= 0) {
944 st = j;
945 }
946 }
947 return times;
948}
949
950DateTimeList Recurrence::timesInInterval(const KDateTime &start, const KDateTime &end) const
951{
952 int i, count;
953 DateTimeList times;
954 for (i = 0, count = d->mRRules.count(); i < count; ++i) {
955 times += d->mRRules[i]->timesInInterval(start, end);
956 }
957
958 // add rdatetimes that fit in the interval
959 for (i = 0, count = d->mRDateTimes.count(); i < count; ++i) {
960 if (d->mRDateTimes[i] >= start && d->mRDateTimes[i] <= end) {
961 times += d->mRDateTimes[i];
962 }
963 }
964
965 // add rdates that fit in the interval
966 KDateTime kdt(d->mStartDateTime);
967 for (i = 0, count = d->mRDates.count(); i < count; ++i) {
968 kdt.setDate(d->mRDates[i]);
969 if (kdt >= start && kdt <= end) {
970 times += kdt;
971 }
972 }
973
974 // Recurrence::timesInInterval(...) doesn't explicitly add mStartDateTime to the list
975 // of times to be returned. It calls mRRules[i]->timesInInterval(...) which include
976 // mStartDateTime.
977 // So, If we have rdates/rdatetimes but don't have any rrule we must explicitly
978 // add mStartDateTime to the list, otherwise we won't see the first occurrence.
979 if ((!d->mRDates.isEmpty() || !d->mRDateTimes.isEmpty()) &&
980 d->mRRules.isEmpty() &&
981 start <= d->mStartDateTime &&
982 end >= d->mStartDateTime) {
983 times += d->mStartDateTime;
984 }
985
986 times.sortUnique();
987
988 // Remove excluded times
989 int idt = 0;
990 int enddt = times.count();
991 for (i = 0, count = d->mExDates.count(); i < count && idt < enddt; ++i) {
992 while (idt < enddt && times[idt].date() < d->mExDates[i]) {
993 ++idt;
994 }
995 while (idt < enddt && times[idt].date() == d->mExDates[i]) {
996 times.removeAt(idt);
997 --enddt;
998 }
999 }
1000 DateTimeList extimes;
1001 for (i = 0, count = d->mExRules.count(); i < count; ++i) {
1002 extimes += d->mExRules[i]->timesInInterval(start, end);
1003 }
1004 extimes += d->mExDateTimes;
1005 extimes.sortUnique();
1006
1007 int st = 0;
1008 for (i = 0, count = extimes.count(); i < count; ++i) {
1009 int j = times.removeSorted(extimes[i], st);
1010 if (j >= 0) {
1011 st = j;
1012 }
1013 }
1014
1015 return times;
1016}
1017
1018KDateTime Recurrence::getNextDateTime(const KDateTime &preDateTime) const
1019{
1020 KDateTime nextDT = preDateTime;
1021 // prevent infinite loops, e.g. when an exrule extinguishes an rrule (e.g.
1022 // the exrule is identical to the rrule). If an occurrence is found, break
1023 // out of the loop by returning that KDateTime
1024// TODO_Recurrence: Is a loop counter of 1000 really okay? I mean for secondly
1025// recurrence, an exdate might exclude more than 1000 intervals!
1026 int loop = 0;
1027 while (loop < 1000) {
1028 // Outline of the algo:
1029 // 1) Find the next date/time after preDateTime when the event could recur
1030 // 1.0) Add the start date if it's after preDateTime
1031 // 1.1) Use the next occurrence from the explicit RDATE lists
1032 // 1.2) Add the next recurrence for each of the RRULEs
1033 // 2) Take the earliest recurrence of these = KDateTime nextDT
1034 // 3) If that date/time is not excluded, either explicitly by an EXDATE or
1035 // by an EXRULE, return nextDT as the next date/time of the recurrence
1036 // 4) If it's excluded, start all at 1), but starting at nextDT (instead
1037 // of preDateTime). Loop at most 1000 times.
1038 ++loop;
1039 // First, get the next recurrence from the RDate lists
1040 DateTimeList dates;
1041 if (nextDT < startDateTime()) {
1042 dates << startDateTime();
1043 }
1044
1045 int end;
1046 // Assume that the rdatetime list is sorted
1047 int i = d->mRDateTimes.findGT(nextDT);
1048 if (i >= 0) {
1049 dates << d->mRDateTimes[i];
1050 }
1051
1052 KDateTime kdt(startDateTime());
1053 for (i = 0, end = d->mRDates.count(); i < end; ++i) {
1054 kdt.setDate(d->mRDates[i]);
1055 if (kdt > nextDT) {
1056 dates << kdt;
1057 break;
1058 }
1059 }
1060
1061 // Add the next occurrences from all RRULEs.
1062 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
1063 KDateTime dt = d->mRRules[i]->getNextDate(nextDT);
1064 if (dt.isValid()) {
1065 dates << dt;
1066 }
1067 }
1068
1069 // Take the first of these (all others can't be used later on)
1070 dates.sortUnique();
1071 if (dates.isEmpty()) {
1072 return KDateTime();
1073 }
1074 nextDT = dates.first();
1075
1076 // Check if that date/time is excluded explicitly or by an exrule:
1077 if (!d->mExDates.containsSorted(nextDT.date()) &&
1078 !d->mExDateTimes.containsSorted(nextDT)) {
1079 bool allowed = true;
1080 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
1081 allowed = allowed && !(d->mExRules[i]->recursAt(nextDT));
1082 }
1083 if (allowed) {
1084 return nextDT;
1085 }
1086 }
1087 }
1088
1089 // Couldn't find a valid occurrences in 1000 loops, something is wrong!
1090 return KDateTime();
1091}
1092
1093KDateTime Recurrence::getPreviousDateTime(const KDateTime &afterDateTime) const
1094{
1095 KDateTime prevDT = afterDateTime;
1096 // prevent infinite loops, e.g. when an exrule extinguishes an rrule (e.g.
1097 // the exrule is identical to the rrule). If an occurrence is found, break
1098 // out of the loop by returning that KDateTime
1099 int loop = 0;
1100 while (loop < 1000) {
1101 // Outline of the algo:
1102 // 1) Find the next date/time after preDateTime when the event could recur
1103 // 1.1) Use the next occurrence from the explicit RDATE lists
1104 // 1.2) Add the next recurrence for each of the RRULEs
1105 // 2) Take the earliest recurrence of these = KDateTime nextDT
1106 // 3) If that date/time is not excluded, either explicitly by an EXDATE or
1107 // by an EXRULE, return nextDT as the next date/time of the recurrence
1108 // 4) If it's excluded, start all at 1), but starting at nextDT (instead
1109 // of preDateTime). Loop at most 1000 times.
1110 ++loop;
1111 // First, get the next recurrence from the RDate lists
1112 DateTimeList dates;
1113 if (prevDT > startDateTime()) {
1114 dates << startDateTime();
1115 }
1116
1117 int i = d->mRDateTimes.findLT(prevDT);
1118 if (i >= 0) {
1119 dates << d->mRDateTimes[i];
1120 }
1121
1122 KDateTime kdt(startDateTime());
1123 for (i = d->mRDates.count(); --i >= 0;) {
1124 kdt.setDate(d->mRDates[i]);
1125 if (kdt < prevDT) {
1126 dates << kdt;
1127 break;
1128 }
1129 }
1130
1131 // Add the previous occurrences from all RRULEs.
1132 int end;
1133 for (i = 0, end = d->mRRules.count(); i < end; ++i) {
1134 KDateTime dt = d->mRRules[i]->getPreviousDate(prevDT);
1135 if (dt.isValid()) {
1136 dates << dt;
1137 }
1138 }
1139
1140 // Take the last of these (all others can't be used later on)
1141 dates.sortUnique();
1142 if (dates.isEmpty()) {
1143 return KDateTime();
1144 }
1145 prevDT = dates.last();
1146
1147 // Check if that date/time is excluded explicitly or by an exrule:
1148 if (!d->mExDates.containsSorted(prevDT.date()) &&
1149 !d->mExDateTimes.containsSorted(prevDT)) {
1150 bool allowed = true;
1151 for (i = 0, end = d->mExRules.count(); i < end; ++i) {
1152 allowed = allowed && !(d->mExRules[i]->recursAt(prevDT));
1153 }
1154 if (allowed) {
1155 return prevDT;
1156 }
1157 }
1158 }
1159
1160 // Couldn't find a valid occurrences in 1000 loops, something is wrong!
1161 return KDateTime();
1162}
1163
1164/***************************** PROTECTED FUNCTIONS ***************************/
1165
1166RecurrenceRule::List Recurrence::rRules() const
1167{
1168 return d->mRRules;
1169}
1170
1171void Recurrence::addRRule(RecurrenceRule *rrule)
1172{
1173 if (d->mRecurReadOnly || !rrule) {
1174 return;
1175 }
1176
1177 rrule->setAllDay(d->mAllDay);
1178 d->mRRules.append(rrule);
1179 rrule->addObserver(this);
1180 updated();
1181}
1182
1183void Recurrence::removeRRule(RecurrenceRule *rrule)
1184{
1185 if (d->mRecurReadOnly) {
1186 return;
1187 }
1188
1189 d->mRRules.removeAll(rrule);
1190 rrule->removeObserver(this);
1191 updated();
1192}
1193
1194void Recurrence::deleteRRule(RecurrenceRule *rrule)
1195{
1196 if (d->mRecurReadOnly) {
1197 return;
1198 }
1199
1200 d->mRRules.removeAll(rrule);
1201 delete rrule;
1202 updated();
1203}
1204
1205RecurrenceRule::List Recurrence::exRules() const
1206{
1207 return d->mExRules;
1208}
1209
1210void Recurrence::addExRule(RecurrenceRule *exrule)
1211{
1212 if (d->mRecurReadOnly || !exrule) {
1213 return;
1214 }
1215
1216 exrule->setAllDay(d->mAllDay);
1217 d->mExRules.append(exrule);
1218 exrule->addObserver(this);
1219 updated();
1220}
1221
1222void Recurrence::removeExRule(RecurrenceRule *exrule)
1223{
1224 if (d->mRecurReadOnly) {
1225 return;
1226 }
1227
1228 d->mExRules.removeAll(exrule);
1229 exrule->removeObserver(this);
1230 updated();
1231}
1232
1233void Recurrence::deleteExRule(RecurrenceRule *exrule)
1234{
1235 if (d->mRecurReadOnly) {
1236 return;
1237 }
1238
1239 d->mExRules.removeAll(exrule);
1240 delete exrule;
1241 updated();
1242}
1243
1244DateTimeList Recurrence::rDateTimes() const
1245{
1246 return d->mRDateTimes;
1247}
1248
1249void Recurrence::setRDateTimes(const DateTimeList &rdates)
1250{
1251 if (d->mRecurReadOnly) {
1252 return;
1253 }
1254
1255 d->mRDateTimes = rdates;
1256 d->mRDateTimes.sortUnique();
1257 updated();
1258}
1259
1260void Recurrence::addRDateTime(const KDateTime &rdate)
1261{
1262 if (d->mRecurReadOnly) {
1263 return;
1264 }
1265
1266 d->mRDateTimes.insertSorted(rdate);
1267 updated();
1268}
1269
1270DateList Recurrence::rDates() const
1271{
1272 return d->mRDates;
1273}
1274
1275void Recurrence::setRDates(const DateList &rdates)
1276{
1277 if (d->mRecurReadOnly) {
1278 return;
1279 }
1280
1281 d->mRDates = rdates;
1282 d->mRDates.sortUnique();
1283 updated();
1284}
1285
1286void Recurrence::addRDate(const QDate &rdate)
1287{
1288 if (d->mRecurReadOnly) {
1289 return;
1290 }
1291
1292 d->mRDates.insertSorted(rdate);
1293 updated();
1294}
1295
1296DateTimeList Recurrence::exDateTimes() const
1297{
1298 return d->mExDateTimes;
1299}
1300
1301void Recurrence::setExDateTimes(const DateTimeList &exdates)
1302{
1303 if (d->mRecurReadOnly) {
1304 return;
1305 }
1306
1307 d->mExDateTimes = exdates;
1308 d->mExDateTimes.sortUnique();
1309}
1310
1311void Recurrence::addExDateTime(const KDateTime &exdate)
1312{
1313 if (d->mRecurReadOnly) {
1314 return;
1315 }
1316
1317 d->mExDateTimes.insertSorted(exdate);
1318 updated();
1319}
1320
1321DateList Recurrence::exDates() const
1322{
1323 return d->mExDates;
1324}
1325
1326void Recurrence::setExDates(const DateList &exdates)
1327{
1328 if (d->mRecurReadOnly) {
1329 return;
1330 }
1331
1332 d->mExDates = exdates;
1333 d->mExDates.sortUnique();
1334 updated();
1335}
1336
1337void Recurrence::addExDate(const QDate &exdate)
1338{
1339 if (d->mRecurReadOnly) {
1340 return;
1341 }
1342
1343 d->mExDates.insertSorted(exdate);
1344 updated();
1345}
1346
1347void Recurrence::recurrenceChanged(RecurrenceRule *)
1348{
1349 updated();
1350}
1351
1352// %%%%%%%%%%%%%%%%%% end:Recurrencerule %%%%%%%%%%%%%%%%%%
1353
1354void Recurrence::dump() const
1355{
1356 kDebug();
1357
1358 int i;
1359 int count = d->mRRules.count();
1360 kDebug() << " -)" << count << "RRULEs:";
1361 for (i = 0; i < count; ++i) {
1362 kDebug() << " -) RecurrenceRule: ";
1363 d->mRRules[i]->dump();
1364 }
1365 count = d->mExRules.count();
1366 kDebug() << " -)" << count << "EXRULEs:";
1367 for (i = 0; i < count; ++i) {
1368 kDebug() << " -) ExceptionRule :";
1369 d->mExRules[i]->dump();
1370 }
1371
1372 count = d->mRDates.count();
1373 kDebug() << endl << " -)" << count << "Recurrence Dates:";
1374 for (i = 0; i < count; ++i) {
1375 kDebug() << " " << d->mRDates[i];
1376 }
1377 count = d->mRDateTimes.count();
1378 kDebug() << endl << " -)" << count << "Recurrence Date/Times:";
1379 for (i = 0; i < count; ++i) {
1380 kDebug() << " " << d->mRDateTimes[i].dateTime();
1381 }
1382 count = d->mExDates.count();
1383 kDebug() << endl << " -)" << count << "Exceptions Dates:";
1384 for (i = 0; i < count; ++i) {
1385 kDebug() << " " << d->mExDates[i];
1386 }
1387 count = d->mExDateTimes.count();
1388 kDebug() << endl << " -)" << count << "Exception Date/Times:";
1389 for (i = 0; i < count; ++i) {
1390 kDebug() << " " << d->mExDateTimes[i].dateTime();
1391 }
1392}
1393
1394Recurrence::RecurrenceObserver::~RecurrenceObserver()
1395{
1396}
1397
1398KCALCORE_EXPORT QDataStream& KCalCore::operator<<(QDataStream &out, KCalCore::Recurrence *r)
1399{
1400 if (!r)
1401 return out;
1402
1403 out << r->d->mRDateTimes << r->d->mExDateTimes
1404 << r->d->mRDates << r->d->mStartDateTime << r->d->mCachedType
1405 << r->d->mAllDay << r->d->mRecurReadOnly << r->d->mExDates
1406 << r->d->mExRules.count() << r->d->mRRules.count();
1407
1408 foreach(RecurrenceRule *rule, r->d->mExRules) {
1409 out << rule;
1410 }
1411
1412 foreach(RecurrenceRule *rule, r->d->mRRules) {
1413 out << rule;
1414 }
1415
1416 return out;
1417}
1418
1419
1420KCALCORE_EXPORT QDataStream& KCalCore::operator>>(QDataStream &in, KCalCore::Recurrence *r)
1421{
1422 if (!r)
1423 return in;
1424
1425 int rruleCount, exruleCount;
1426
1427 in >> r->d->mRDateTimes >> r->d->mExDateTimes
1428 >> r->d->mRDates >> r->d->mStartDateTime >> r->d->mCachedType
1429 >> r->d->mAllDay >> r->d->mRecurReadOnly >> r->d->mExDates
1430 >> exruleCount >> rruleCount;
1431
1432 r->d->mExRules.clear();
1433 r->d->mRRules.clear();
1434
1435 for (int i=0; i<exruleCount; ++i) {
1436 RecurrenceRule *rule = new RecurrenceRule();
1437 rule->addObserver(r);
1438 in >> rule;
1439 r->d->mExRules.append(rule);
1440 }
1441
1442 for (int i=0; i<rruleCount; ++i) {
1443 RecurrenceRule *rule = new RecurrenceRule();
1444 rule->addObserver(r);
1445 in >> rule;
1446 r->d->mRRules.append(rule);
1447 }
1448
1449 return in;
1450}
KCalCore::RecurrenceRule::WDayPos
structure for describing the n-th weekday of the month/year.
Definition: recurrencerule.h:69
KCalCore::RecurrenceRule
This class represents a recurrence rule for a calendar incidence.
Definition: recurrencerule.h:44
KCalCore::RecurrenceRule::setAllDay
void setAllDay(bool allDay)
Sets whether the dtstart is all-day (i.e.
Definition: recurrencerule.cpp:1005
KCalCore::RecurrenceRule::PeriodType
PeriodType
enum for describing the frequency how an event recurs, if at all.
Definition: recurrencerule.h:56
KCalCore::RecurrenceRule::setDuration
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last.
Definition: recurrencerule.cpp:996
KCalCore::RecurrenceRule::setFrequency
void setFrequency(int freq)
Sets the recurrence frequency, in terms of the recurrence time period type.
Definition: recurrencerule.cpp:1033
KCalCore::RecurrenceRule::frequency
uint frequency() const
Returns the recurrence frequency, in terms of the recurrence time period type.
Definition: recurrencerule.cpp:2152
KCalCore::RecurrenceRule::duration
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
Definition: recurrencerule.cpp:2157
KCalCore::RecurrenceRule::durationTo
int durationTo(const KDateTime &dt) const
Returns the number of recurrences up to and including the date/time specified.
Definition: recurrencerule.cpp:1582
KCalCore::RecurrenceRule::setEndDt
void setEndDt(const KDateTime &endDateTime)
Sets the date and time of the last recurrence.
Definition: recurrencerule.cpp:986
KCalCore::RecurrenceRule::addObserver
void addObserver(RuleObserver *observer)
Installs an observer.
Definition: recurrencerule.cpp:932
KCalCore::RecurrenceRule::setStartDt
void setStartDt(const KDateTime &start)
Sets the recurrence start date/time.
Definition: recurrencerule.cpp:1024
KCalCore::RecurrenceRule::removeObserver
void removeObserver(RuleObserver *observer)
Removes an observer that was added with addObserver.
Definition: recurrencerule.cpp:939
KCalCore::Recurrence
This class represents a recurrence rule for a calendar incidence.
Definition: recurrence.h:88
KCalCore::Recurrence::recurrenceType
ushort recurrenceType() const
Returns the event's recurrence status.
Definition: recurrence.cpp:233
KCalCore::Recurrence::removeRRule
void removeRRule(RecurrenceRule *rrule)
Remove a recurrence rule from the recurrence.
Definition: recurrence.cpp:1183
KCalCore::Recurrence::setEndDateTime
void setEndDateTime(const KDateTime &endDateTime)
Sets the date and time of the last recurrence.
Definition: recurrence.cpp:468
KCalCore::Recurrence::yearPositions
QList< RecurrenceRule::WDayPos > yearPositions() const
Returns the positions within a yearly recurrence.
Definition: recurrence.cpp:684
KCalCore::Recurrence::setRecurReadOnly
void setRecurReadOnly(bool readOnly)
Set if recurrence is read-only or can be changed.
Definition: recurrence.cpp:566
KCalCore::Recurrence::yearDates
QList< int > yearDates() const
Returns the dates within a yearly recurrence.
Definition: recurrence.cpp:673
KCalCore::Recurrence::shiftTimes
void shiftTimes(const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec)
Shift the times of the recurrence so that they appear at the same clock time as before but in a new t...
Definition: recurrence.cpp:513
KCalCore::Recurrence::frequency
int frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
Definition: recurrence.cpp:599
KCalCore::Recurrence::addYearlyDay
void addYearlyDay(int day)
Adds day number of year within a yearly recurrence.
Definition: recurrence.cpp:834
KCalCore::Recurrence::setYearly
void setYearly(int freq)
Sets an event to recur yearly.
Definition: recurrence.cpp:826
KCalCore::Recurrence::setWeekly
void setWeekly(int freq, int weekStart=1)
Sets an event to recur weekly.
Definition: recurrence.cpp:729
KCalCore::Recurrence::recurs
bool recurs() const
Returns whether the event recurs at all.
Definition: recurrence.cpp:228
KCalCore::Recurrence::setStartDateTime
void setStartDateTime(const KDateTime &start)
Set start of recurrence.
Definition: recurrence.cpp:581
KCalCore::Recurrence::operator=
Recurrence & operator=(const Recurrence &r)
Assignment operator.
Definition: recurrence.cpp:146
KCalCore::Recurrence::~Recurrence
~Recurrence()
Destructor.
Definition: recurrence.cpp:134
KCalCore::Recurrence::setMinutely
void setMinutely(int freq)
Sets an event to recur minutely.
Definition: recurrence.cpp:708
KCalCore::Recurrence::setMonthly
void setMonthly(int freq)
Sets an event to recur monthly.
Definition: recurrence.cpp:750
KCalCore::Recurrence::recursAt
bool recursAt(const KDateTime &dt) const
Returns true if the date/time specified is one at which the event will recur.
Definition: recurrence.cpp:395
KCalCore::Recurrence::getPreviousDateTime
KDateTime getPreviousDateTime(const KDateTime &afterDateTime) const
Returns the date and time of the last previous recurrence, before the specified date/time.
Definition: recurrence.cpp:1093
KCalCore::Recurrence::recursOn
bool recursOn(const QDate &date, const KDateTime::Spec &timeSpec) const
Returns true if the date specified is one on which the event will recur.
Definition: recurrence.cpp:330
KCalCore::Recurrence::setFrequency
void setFrequency(int freq)
Sets the frequency of recurrence, in terms of the recurrence time period type.
Definition: recurrence.cpp:607
KCalCore::Recurrence::monthDays
QList< int > monthDays() const
Returns list of day numbers of a month.
Definition: recurrence.cpp:648
KCalCore::Recurrence::endDateTime
KDateTime endDateTime() const
Returns the date/time of the last recurrence.
Definition: recurrence.cpp:428
KCalCore::Recurrence::deleteExRule
void deleteExRule(RecurrenceRule *exrule)
Remove an exception rule from the recurrence and delete it.
Definition: recurrence.cpp:1233
KCalCore::Recurrence::addYearlyMonth
void addYearlyMonth(short _rNum)
Adds month in yearly recurrence.
Definition: recurrence.cpp:862
KCalCore::Recurrence::deleteRRule
void deleteRRule(RecurrenceRule *rrule)
Remove a recurrence rule from the recurrence and delete it.
Definition: recurrence.cpp:1194
KCalCore::Recurrence::recurReadOnly
bool recurReadOnly() const
Returns true if the recurrence is read-only, or false if it can be changed.
Definition: recurrence.cpp:571
KCalCore::Recurrence::removeObserver
void removeObserver(RecurrenceObserver *observer)
Removes an observer that was added with addObserver.
Definition: recurrence.cpp:164
KCalCore::Recurrence::allDay
bool allDay() const
Set whether the recurrence has no time, just a date.
Definition: recurrence.cpp:176
KCalCore::Recurrence::startDate
QDate startDate() const
Return the start date/time of the recurrence.
Definition: recurrence.cpp:576
KCalCore::Recurrence::addMonthlyPos
void addMonthlyPos(short pos, const QBitArray &days)
Adds a position (e.g.
Definition: recurrence.cpp:757
KCalCore::Recurrence::addObserver
void addObserver(RecurrenceObserver *observer)
Installs an observer.
Definition: recurrence.cpp:157
KCalCore::Recurrence::addYearlyDate
void addYearlyDate(int date)
Adds date within a yearly recurrence.
Definition: recurrence.cpp:850
KCalCore::Recurrence::days
QBitArray days() const
Returns week day mask (bit 0 = Monday).
Definition: recurrence.cpp:629
KCalCore::Recurrence::removeExRule
void removeExRule(RecurrenceRule *exrule)
Remove an exception rule from the recurrence.
Definition: recurrence.cpp:1222
KCalCore::Recurrence::addYearlyPos
void addYearlyPos(short pos, const QBitArray &days)
Adds position within month/year within a yearly recurrence.
Definition: recurrence.cpp:856
KCalCore::Recurrence::setAllDay
void setAllDay(bool allDay)
Sets whether the dtstart is a all-day (i.e.
Definition: recurrence.cpp:181
KCalCore::Recurrence::addRRule
void addRRule(RecurrenceRule *rrule)
Add a recurrence rule to the recurrence.
Definition: recurrence.cpp:1171
KCalCore::Recurrence::setDaily
void setDaily(int freq)
Sets an event to recur daily.
Definition: recurrence.cpp:722
KCalCore::Recurrence::unsetRecurs
void unsetRecurs()
Removes all recurrence rules.
Definition: recurrence.cpp:539
KCalCore::Recurrence::startDateTime
KDateTime startDateTime() const
Return the start date/time of the recurrence (Time for all-day recurrences will be 0:00).
Definition: recurrence.cpp:171
KCalCore::Recurrence::dump
void dump() const
Debug output.
Definition: recurrence.cpp:1354
KCalCore::Recurrence::addExRule
void addExRule(RecurrenceRule *exrule)
Add an exception rule to the recurrence.
Definition: recurrence.cpp:1210
KCalCore::Recurrence::setEndDate
void setEndDate(const QDate &endDate)
Sets the date of the last recurrence.
Definition: recurrence.cpp:459
KCalCore::Recurrence::weekStart
int weekStart() const
Returns the first day of the week.
Definition: recurrence.cpp:622
KCalCore::Recurrence::yearMonths
QList< int > yearMonths() const
Returns the months within a yearly recurrence.
Definition: recurrence.cpp:678
KCalCore::Recurrence::durationTo
int durationTo(const KDateTime &dt) const
Returns the number of recurrences up to and including the date/time specified.
Definition: recurrence.cpp:487
KCalCore::Recurrence::duration
int duration() const
Returns -1 if the event recurs infinitely, 0 if the end date is set, otherwise the total number of re...
Definition: recurrence.cpp:481
KCalCore::Recurrence::setHourly
void setHourly(int freq)
Sets an event to recur hourly.
Definition: recurrence.cpp:715
KCalCore::Recurrence::clear
void clear()
Removes all recurrence and exception rules and dates.
Definition: recurrence.cpp:549
KCalCore::Recurrence::addMonthlyDate
void addMonthlyDate(short day)
Adds a date (e.g.
Definition: recurrence.cpp:807
KCalCore::Recurrence::timesInInterval
DateTimeList timesInInterval(const KDateTime &start, const KDateTime &end) const
Returns a list of all the times at which the recurrence will occur between two specified times.
Definition: recurrence.cpp:950
KCalCore::Recurrence::getNextDateTime
KDateTime getNextDateTime(const KDateTime &preDateTime) const
Returns the date and time of the next recurrence, after the specified date/time.
Definition: recurrence.cpp:1018
KCalCore::Recurrence::yearDays
QList< int > yearDays() const
Returns the day numbers within a yearly recurrence.
Definition: recurrence.cpp:667
KCalCore::Recurrence::operator==
bool operator==(const Recurrence &r) const
Comparison operator for equality.
Definition: recurrence.cpp:141
KCalCore::Recurrence::addWeeklyDays
void addWeeklyDays(const QBitArray &days)
Adds days to the weekly day recurrence list.
Definition: recurrence.cpp:745
KCalCore::Recurrence::monthPositions
QList< RecurrenceRule::WDayPos > monthPositions() const
Returns list of day positions in months.
Definition: recurrence.cpp:659
KCalCore::Recurrence::endDate
QDate endDate() const
Returns the date of the last recurrence.
Definition: recurrence.cpp:453
KCalCore::Recurrence::recurTimesOn
TimeList recurTimesOn(const QDate &date, const KDateTime::Spec &timeSpec) const
Returns a list of the times on the specified date at which the recurrence will occur.
Definition: recurrence.cpp:881
KCalCore::Recurrence::setDuration
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last.
Definition: recurrence.cpp:499
KCalCore::Recurrence::Recurrence
Recurrence()
Constructs an empty recurrence.
Definition: recurrence.cpp:112
KCalCore::SortableList
A QList which can be sorted.
Definition: sortablelist.h:87
KCalCore::SortableList::sortUnique
void sortUnique()
Sort the list.
Definition: sortablelist.h:193
KCalCore::SortableList::removeSorted
int removeSorted(const T &value, int start=0)
Remove value value from the list.
Definition: sortablelist.h:296
KCalCore
TODO: KDE5:
Definition: alarm.h:47
KCalCore::operator>>
KCALCORE_EXPORT QDataStream & operator>>(QDataStream &in, const KCalCore::Alarm::Ptr &)
Alarm deserializer.
Definition: alarm.cpp:863
KCalCore::operator<<
KCALCORE_EXPORT QDataStream & operator<<(QDataStream &out, const KCalCore::Alarm::Ptr &)
Alarm serializer.
Definition: alarm.cpp:853
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jul 21 2022 00:00:00 by doxygen 1.9.5 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCalCore Library

Skip menu "KCalCore Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal