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

KAlarm Library

  • sources
  • kde-4.12
  • kdepimlibs
  • kalarmcal
karecurrence.cpp
1 /*
2  * karecurrence.cpp - recurrence with special yearly February 29th handling
3  * This file is part of kalarmcal library, which provides access to KAlarm
4  * calendar data.
5  * Copyright © 2005-2013 by David Jarvie <djarvie@kde.org>
6  *
7  * This library is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU Library General Public License as published
9  * by the Free Software Foundation; either version 2 of the License, or (at
10  * your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
15  * License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public License
18  * along with this library; see the file COPYING.LIB. If not, write to the
19  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
20  * MA 02110-1301, USA.
21  */
22 
23 #include "karecurrence.h"
24 
25 #ifndef KALARMCAL_USE_KRESOURCES
26 #include <kcalcore/recurrence.h>
27 #include <kcalcore/icalformat.h>
28 #else
29 #include <kcal/recurrence.h>
30 #include <kcal/icalformat.h>
31 #endif
32 #include <kglobal.h>
33 #include <klocale.h>
34 #include <klocalizedstring.h>
35 #include <kdebug.h>
36 
37 #include <QBitArray>
38 #include <QDateTime>
39 
40 #ifndef KALARMCAL_USE_KRESOURCES
41 using namespace KCalCore;
42 #else
43 using namespace KCal;
44 #endif
45 
46 namespace KAlarmCal
47 {
48 
49 class Recurrence_p : public Recurrence
50 {
51  public:
52  using Recurrence::setNewRecurrenceType;
53  Recurrence_p() : Recurrence() {}
54  Recurrence_p(const Recurrence& r) : Recurrence(r) {}
55  Recurrence_p(const Recurrence_p& r) : Recurrence(r) {}
56 };
57 
58 class KARecurrence::Private
59 {
60  public:
61  Private()
62  : mFeb29Type(Feb29_None), mCachedType(-1) {}
63  explicit Private(const Recurrence& r)
64  : mRecurrence(r), mFeb29Type(Feb29_None), mCachedType(-1) {}
65  void clear()
66  {
67  mRecurrence.clear();
68  mFeb29Type = Feb29_None;
69  mCachedType = -1;
70  }
71  bool set(Type, int freq, int count, int f29, const KDateTime& start, const KDateTime& end);
72  bool init(RecurrenceRule::PeriodType, int freq, int count, int feb29Type, const KDateTime& start, const KDateTime& end);
73  void fix();
74  void writeRecurrence(const KARecurrence* q, Recurrence& recur) const;
75  KDateTime endDateTime() const;
76  int combineDurations(const RecurrenceRule*, const RecurrenceRule*, QDate& end) const;
77 
78  static Feb29Type mDefaultFeb29;
79  Recurrence_p mRecurrence;
80  Feb29Type mFeb29Type; // yearly recurrence on Feb 29th (leap years) / Mar 1st (non-leap years)
81  mutable int mCachedType;
82 };
83 
84 /*=============================================================================
85 = Class KARecurrence
86 = The purpose of this class is to represent the restricted range of recurrence
87 = types which are handled by KAlarm, and to translate between these and the
88 = libkcal Recurrence class. In particular, it handles yearly recurrences on
89 = 29th February specially:
90 =
91 = KARecurrence allows annual 29th February recurrences to fall on 28th
92 = February or 1st March, or not at all, in non-leap years. It allows such
93 = 29th February recurrences to be combined with the 29th of other months in
94 = a simple way, represented simply as the 29th of multiple months including
95 = February. For storage in the libkcal calendar, the 29th day of the month
96 = recurrence for other months is combined with a last-day-of-February or a
97 = 60th-day-of-the-year recurrence rule, thereby conforming to RFC2445.
98 =============================================================================*/
99 
100 KARecurrence::Feb29Type KARecurrence::Private::mDefaultFeb29 = KARecurrence::Feb29_None;
101 
102 KARecurrence::KARecurrence()
103  : d(new Private)
104 { }
105 
106 KARecurrence::KARecurrence(const Recurrence& r)
107  : d(new Private(r))
108 {
109  fix();
110 }
111 
112 KARecurrence::KARecurrence(const KARecurrence& r)
113  : d(new Private(*r.d))
114 { }
115 
116 KARecurrence::~KARecurrence()
117 {
118  delete d;
119 }
120 
121 KARecurrence& KARecurrence::operator=(const KARecurrence& r)
122 {
123  if (&r != this)
124  *d = *r.d;
125  return *this;
126 }
127 
128 bool KARecurrence::operator==(const KARecurrence& r) const
129 {
130  return d->mRecurrence == r.d->mRecurrence
131  && d->mFeb29Type == r.d->mFeb29Type;
132 }
133 
134 KARecurrence::Feb29Type KARecurrence::feb29Type() const
135 {
136  return d->mFeb29Type;
137 }
138 
139 KARecurrence::Feb29Type KARecurrence::defaultFeb29Type()
140 {
141  return Private::mDefaultFeb29;
142 }
143 
144 void KARecurrence::setDefaultFeb29Type(Feb29Type t)
145 {
146  Private::mDefaultFeb29 = t;
147 }
148 
149 /******************************************************************************
150 * Set up a KARecurrence from recurrence parameters, using the start date to
151 * determine the recurrence day/month as appropriate.
152 * Only a restricted subset of recurrence types is allowed.
153 * Reply = true if successful.
154 */
155 bool KARecurrence::set(Type t, int freq, int count, const KDateTime& start, const KDateTime& end)
156 {
157  return d->set(t, freq, count, -1, start, end);
158 }
159 
160 bool KARecurrence::set(Type t, int freq, int count, const KDateTime& start, const KDateTime& end, Feb29Type f29)
161 {
162  return d->set(t, freq, count, f29, start, end);
163 }
164 
165 bool KARecurrence::Private::set(Type recurType, int freq, int count, int f29, const KDateTime& start, const KDateTime& end)
166 {
167  mCachedType = -1;
168  RecurrenceRule::PeriodType rrtype;
169  switch (recurType)
170  {
171  case MINUTELY: rrtype = RecurrenceRule::rMinutely; break;
172  case DAILY: rrtype = RecurrenceRule::rDaily; break;
173  case WEEKLY: rrtype = RecurrenceRule::rWeekly; break;
174  case MONTHLY_DAY: rrtype = RecurrenceRule::rMonthly; break;
175  case ANNUAL_DATE: rrtype = RecurrenceRule::rYearly; break;
176  case NO_RECUR: rrtype = RecurrenceRule::rNone; break;
177  default:
178  return false;
179  }
180  if (!init(rrtype, freq, count, f29, start, end))
181  return false;
182  switch (recurType)
183  {
184  case WEEKLY:
185  {
186  QBitArray days(7);
187  days.setBit(start.date().dayOfWeek() - 1);
188  mRecurrence.addWeeklyDays(days);
189  break;
190  }
191  case MONTHLY_DAY:
192  mRecurrence.addMonthlyDate(start.date().day());
193  break;
194  case ANNUAL_DATE:
195  mRecurrence.addYearlyDate(start.date().day());
196  mRecurrence.addYearlyMonth(start.date().month());
197  break;
198  default:
199  break;
200  }
201  return true;
202 }
203 
204 /******************************************************************************
205 * Initialise a KARecurrence from recurrence parameters.
206 * Reply = true if successful.
207 */
208 bool KARecurrence::init(RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end)
209 {
210  return d->init(t, freq, count, -1, start, end);
211 }
212 
213 bool KARecurrence::init(RecurrenceRule::PeriodType t, int freq, int count, const KDateTime& start, const KDateTime& end, Feb29Type f29)
214 {
215  return d->init(t, freq, count, f29, start, end);
216 }
217 
218 bool KARecurrence::Private::init(RecurrenceRule::PeriodType recurType, int freq, int count, int f29, const KDateTime& start,
219  const KDateTime& end)
220 {
221  clear();
222  Feb29Type feb29Type = (f29 == -1) ? mDefaultFeb29 : static_cast<Feb29Type>(f29);
223  if (count < -1)
224  return false;
225  bool dateOnly = start.isDateOnly();
226  if (!count && ((!dateOnly && !end.isValid())
227  || (dateOnly && !end.date().isValid())))
228  return false;
229  switch (recurType)
230  {
231  case RecurrenceRule::rMinutely:
232  case RecurrenceRule::rDaily:
233  case RecurrenceRule::rWeekly:
234  case RecurrenceRule::rMonthly:
235  case RecurrenceRule::rYearly:
236  break;
237  case RecurrenceRule::rNone:
238  return true;
239  default:
240  return false;
241  }
242  mRecurrence.setNewRecurrenceType(recurType, freq);
243  if (count)
244  mRecurrence.setDuration(count);
245  else if (dateOnly)
246  mRecurrence.setEndDate(end.date());
247  else
248  mRecurrence.setEndDateTime(end);
249  KDateTime startdt = start;
250  if (recurType == RecurrenceRule::rYearly
251  && (feb29Type == Feb29_Feb28 || feb29Type == Feb29_Mar1))
252  {
253  int year = startdt.date().year();
254  if (!QDate::isLeapYear(year)
255  && startdt.date().dayOfYear() == (feb29Type == Feb29_Mar1 ? 60 : 59))
256  {
257  /* The event start date is February 28th or March 1st, but it
258  * is a recurrence on February 29th (recurring on February 28th
259  * or March 1st in non-leap years). Adjust the start date to
260  * be on February 29th in the last previous leap year.
261  * This is necessary because KARecurrence represents all types
262  * of 29th February recurrences by a simple 29th February.
263  */
264  while (!QDate::isLeapYear(--year)) ;
265  startdt.setDate(QDate(year, 2, 29));
266  }
267  mFeb29Type = feb29Type;
268  }
269  mRecurrence.setStartDateTime(startdt); // sets recurrence all-day if date-only
270  return true;
271 }
272 
273 /******************************************************************************
274 * Initialise the recurrence from an iCalendar RRULE string.
275 */
276 bool KARecurrence::set(const QString& icalRRULE)
277 {
278  static QString RRULE = QLatin1String("RRULE:");
279  d->clear();
280  if (icalRRULE.isEmpty())
281  return true;
282  ICalFormat format;
283  if (!format.fromString(d->mRecurrence.defaultRRule(true),
284  (icalRRULE.startsWith(RRULE) ? icalRRULE.mid(RRULE.length()) : icalRRULE)))
285  return false;
286  fix();
287  return true;
288 }
289 
290 void KARecurrence::clear()
291 {
292  d->clear();
293 }
294 
295 /******************************************************************************
296 * Must be called after presetting with a KCal::Recurrence, to convert the
297 * recurrence to KARecurrence types:
298 * - Convert hourly recurrences to minutely.
299 * - Remove all but the first day in yearly date recurrences.
300 * - Check for yearly recurrences falling on February 29th and adjust them as
301 * necessary. A 29th of the month rule can be combined with either a 60th day
302 * of the year rule or a last day of February rule.
303 */
304 void KARecurrence::fix()
305 {
306  d->fix();
307 }
308 
309 void KARecurrence::Private::fix()
310 {
311  mCachedType = -1;
312  mFeb29Type = Feb29_None;
313  int convert = 0;
314  int days[2] = { 0, 0 };
315  RecurrenceRule* rrules[2];
316  const RecurrenceRule::List rrulelist = mRecurrence.rRules();
317  int rri = 0;
318  int rrend = rrulelist.count();
319  for (int i = 0; i < 2 && rri < rrend; ++i, ++rri)
320  {
321  RecurrenceRule* rrule = rrulelist[rri];
322  rrules[i] = rrule;
323  bool stop = true;
324  int rtype = mRecurrence.recurrenceType(rrule);
325  switch (rtype)
326  {
327  case Recurrence::rHourly:
328  // Convert an hourly recurrence to a minutely one
329  rrule->setRecurrenceType(RecurrenceRule::rMinutely);
330  rrule->setFrequency(rrule->frequency() * 60);
331  // fall through to rMinutely
332  case Recurrence::rMinutely:
333  case Recurrence::rDaily:
334  case Recurrence::rWeekly:
335  case Recurrence::rMonthlyDay:
336  case Recurrence::rMonthlyPos:
337  case Recurrence::rYearlyPos:
338  if (!convert)
339  ++rri; // remove all rules except the first
340  break;
341  case Recurrence::rOther:
342  if (dailyType(rrule))
343  { // it's a daily rule with BYDAYS
344  if (!convert)
345  ++rri; // remove all rules except the first
346  }
347  break;
348  case Recurrence::rYearlyDay:
349  {
350  // Ensure that the yearly day number is 60 (i.e. Feb 29th/Mar 1st)
351  if (convert)
352  {
353  // This is the second rule.
354  // Ensure that it can be combined with the first one.
355  if (days[0] != 29
356  || rrule->frequency() != rrules[0]->frequency()
357  || rrule->startDt() != rrules[0]->startDt())
358  break;
359  }
360  QList<int> ds = rrule->byYearDays();
361  if (!ds.isEmpty() && ds.first() == 60)
362  {
363  ++convert; // this rule needs to be converted
364  days[i] = 60;
365  stop = false;
366  break;
367  }
368  break; // not day 60, so remove this rule
369  }
370  case Recurrence::rYearlyMonth:
371  {
372  QList<int> ds = rrule->byMonthDays();
373  if (!ds.isEmpty())
374  {
375  int day = ds.first();
376  if (convert)
377  {
378  // This is the second rule.
379  // Ensure that it can be combined with the first one.
380  if (day == days[0] || (day == -1 && days[0] == 60)
381  || rrule->frequency() != rrules[0]->frequency()
382  || rrule->startDt() != rrules[0]->startDt())
383  break;
384  }
385  if (ds.count() > 1)
386  {
387  ds.clear(); // remove all but the first day
388  ds.append(day);
389  rrule->setByMonthDays(ds);
390  }
391  if (day == -1)
392  {
393  // Last day of the month - only combine if it's February
394  QList<int> months = rrule->byMonths();
395  if (months.count() != 1 || months.first() != 2)
396  day = 0;
397  }
398  if (day == 29 || day == -1)
399  {
400  ++convert; // this rule may need to be converted
401  days[i] = day;
402  stop = false;
403  break;
404  }
405  }
406  if (!convert)
407  ++rri;
408  break;
409  }
410  default:
411  break;
412  }
413  if (stop)
414  break;
415  }
416 
417  // Remove surplus rules
418  for ( ; rri < rrend; ++rri)
419  mRecurrence.deleteRRule(rrulelist[rri]);
420 
421  QDate end;
422  int count;
423  QList<int> months;
424  if (convert == 2)
425  {
426  // There are two yearly recurrence rules to combine into a February 29th recurrence.
427  // Combine the two recurrence rules into a single rYearlyMonth rule falling on Feb 29th.
428  // Find the duration of the two RRULEs combined, using the shorter of the two if they differ.
429  if (days[0] != 29)
430  {
431  // Swap the two rules so that the 29th rule is the first
432  RecurrenceRule* rr = rrules[0];
433  rrules[0] = rrules[1]; // the 29th rule
434  rrules[1] = rr;
435  int d = days[0];
436  days[0] = days[1];
437  days[1] = d; // the non-29th day
438  }
439  // If February is included in the 29th rule, remove it to avoid duplication
440  months = rrules[0]->byMonths();
441  if (months.removeAll(2))
442  rrules[0]->setByMonths(months);
443 
444  count = combineDurations(rrules[0], rrules[1], end);
445  mFeb29Type = (days[1] == 60) ? Feb29_Mar1 : Feb29_Feb28;
446  }
447  else if (convert == 1 && days[0] == 60)
448  {
449  // There is a single 60th day of the year rule.
450  // Convert it to a February 29th recurrence.
451  count = mRecurrence.duration();
452  if (!count)
453  end = mRecurrence.endDate();
454  mFeb29Type = Feb29_Mar1;
455  }
456  else
457  return;
458 
459  // Create the new February 29th recurrence
460  mRecurrence.setNewRecurrenceType(RecurrenceRule::rYearly, mRecurrence.frequency());
461  RecurrenceRule* rrule = mRecurrence.defaultRRule();
462  months.append(2);
463  rrule->setByMonths(months);
464  QList<int> ds;
465  ds.append(29);
466  rrule->setByMonthDays(ds);
467  if (count)
468  mRecurrence.setDuration(count);
469  else
470  mRecurrence.setEndDate(end);
471 }
472 
473 /******************************************************************************
474 * Initialise a KCal::Recurrence to be the same as this instance.
475 * Additional recurrence rules are created as necessary if it recurs on Feb 29th.
476 */
477 void KARecurrence::writeRecurrence(Recurrence& recur) const
478 {
479  d->writeRecurrence(this, recur);
480 }
481 
482 void KARecurrence::Private::writeRecurrence(const KARecurrence* q, Recurrence& recur) const
483 {
484  recur.clear();
485  recur.setStartDateTime(mRecurrence.startDateTime());
486  recur.setExDates(mRecurrence.exDates());
487  recur.setExDateTimes(mRecurrence.exDateTimes());
488  const RecurrenceRule* rrule = mRecurrence.defaultRRuleConst();
489  if (!rrule)
490  return;
491  int freq = mRecurrence.frequency();
492  int count = mRecurrence.duration();
493  static_cast<Recurrence_p*>(&recur)->setNewRecurrenceType(rrule->recurrenceType(), freq);
494  if (count)
495  recur.setDuration(count);
496  else
497  recur.setEndDateTime(endDateTime());
498  switch (q->type())
499  {
500  case DAILY:
501  if (rrule->byDays().isEmpty())
502  break;
503  // fall through to rWeekly
504  case WEEKLY:
505  case MONTHLY_POS:
506  recur.defaultRRule(true)->setByDays(rrule->byDays());
507  break;
508  case MONTHLY_DAY:
509  recur.defaultRRule(true)->setByMonthDays(rrule->byMonthDays());
510  break;
511  case ANNUAL_POS:
512  recur.defaultRRule(true)->setByMonths(rrule->byMonths());
513  recur.defaultRRule()->setByDays(rrule->byDays());
514  break;
515  case ANNUAL_DATE:
516  {
517  QList<int> months = rrule->byMonths();
518  QList<int> days = mRecurrence.monthDays();
519  bool special = (mFeb29Type != Feb29_None && !days.isEmpty()
520  && days.first() == 29 && months.removeAll(2));
521  RecurrenceRule* rrule1 = recur.defaultRRule();
522  rrule1->setByMonths(months);
523  rrule1->setByMonthDays(days);
524  if (!special)
525  break;
526 
527  // It recurs on the 29th February.
528  // Create an additional 60th day of the year, or last day of February, rule.
529  RecurrenceRule* rrule2 = new RecurrenceRule();
530  rrule2->setRecurrenceType(RecurrenceRule::rYearly);
531  rrule2->setFrequency(freq);
532  rrule2->setStartDt(mRecurrence.startDateTime());
533  rrule2->setAllDay(mRecurrence.allDay());
534  if (!count)
535  rrule2->setEndDt(endDateTime());
536  if (mFeb29Type == Feb29_Mar1)
537  {
538  QList<int> ds;
539  ds.append(60);
540  rrule2->setByYearDays(ds);
541  }
542  else
543  {
544  QList<int> ds;
545  ds.append(-1);
546  rrule2->setByMonthDays(ds);
547  QList<int> ms;
548  ms.append(2);
549  rrule2->setByMonths(ms);
550  }
551 
552  if (months.isEmpty())
553  {
554  // Only February recurs.
555  // Replace the RRULE and keep the recurrence count the same.
556  if (count)
557  rrule2->setDuration(count);
558  recur.unsetRecurs();
559  }
560  else
561  {
562  // Months other than February also recur on the 29th.
563  // Remove February from the list and add a separate RRULE for February.
564  if (count)
565  {
566  rrule1->setDuration(-1);
567  rrule2->setDuration(-1);
568  if (count > 0)
569  {
570  /* Adjust counts in the two rules to keep the correct occurrence total.
571  * Note that durationTo() always includes the start date. Since for an
572  * individual RRULE the start date may not actually be included, we need
573  * to decrement the count if the start date doesn't actually recur in
574  * this RRULE.
575  * Note that if the count is small, one of the rules may not recur at
576  * all. In that case, retain it so that the February 29th characteristic
577  * is not lost should the user later change the recurrence count.
578  */
579  KDateTime end = endDateTime();
580  int count1 = rrule1->durationTo(end)
581  - (rrule1->recursOn(mRecurrence.startDate(), mRecurrence.startDateTime().timeSpec()) ? 0 : 1);
582  if (count1 > 0)
583  rrule1->setDuration(count1);
584  else
585  rrule1->setEndDt(mRecurrence.startDateTime());
586  int count2 = rrule2->durationTo(end)
587  - (rrule2->recursOn(mRecurrence.startDate(), mRecurrence.startDateTime().timeSpec()) ? 0 : 1);
588  if (count2 > 0)
589  rrule2->setDuration(count2);
590  else
591  rrule2->setEndDt(mRecurrence.startDateTime());
592  }
593  }
594  }
595  recur.addRRule(rrule2);
596  break;
597  }
598  default:
599  break;
600  }
601 }
602 
603 KDateTime KARecurrence::startDateTime() const
604 {
605  return d->mRecurrence.startDateTime();
606 }
607 
608 QDate KARecurrence::startDate() const
609 {
610  return d->mRecurrence.startDate();
611 }
612 
613 void KARecurrence::setStartDateTime(const KDateTime& dt, bool dateOnly)
614 {
615  d->mRecurrence.setStartDateTime(dt);
616  if (dateOnly)
617  d->mRecurrence.setAllDay(true);
618 }
619 
620 /******************************************************************************
621 * Return the date/time of the last recurrence.
622 */
623 KDateTime KARecurrence::endDateTime() const
624 {
625  return d->endDateTime();
626 }
627 
628 KDateTime KARecurrence::Private::endDateTime() const
629 {
630  if (mFeb29Type == Feb29_None || mRecurrence.duration() <= 1)
631  {
632  /* Either it doesn't have any special February 29th treatment,
633  * it's infinite (count = -1), the end date is specified
634  * (count = 0), or it ends on the start date (count = 1).
635  * So just use the normal KCal end date calculation.
636  */
637  return mRecurrence.endDateTime();
638  }
639 
640  /* Create a temporary recurrence rule to find the end date.
641  * In a standard KCal recurrence, the 29th February only occurs once every
642  * 4 years. So shift the temporary recurrence date to the 28th to ensure
643  * that it occurs every year, thus giving the correct occurrence count.
644  */
645  RecurrenceRule* rrule = new RecurrenceRule();
646  rrule->setRecurrenceType(RecurrenceRule::rYearly);
647  KDateTime dt = mRecurrence.startDateTime();
648  QDate da = dt.date();
649  switch (da.day())
650  {
651  case 29:
652  // The start date is definitely a recurrence date, so shift
653  // start date to the temporary recurrence date of the 28th
654  da.setYMD(da.year(), da.month(), 28);
655  break;
656  case 28:
657  if (da.month() != 2 || mFeb29Type != Feb29_Feb28 || QDate::isLeapYear(da.year()))
658  {
659  // Start date is not a recurrence date, so shift it to 27th
660  da.setYMD(da.year(), da.month(), 27);
661  }
662  break;
663  case 1:
664  if (da.month() == 3 && mFeb29Type == Feb29_Mar1 && !QDate::isLeapYear(da.year()))
665  {
666  // Start date is a March 1st recurrence date, so shift
667  // start date to the temporary recurrence date of the 28th
668  da.setYMD(da.year(), 2, 28);
669  }
670  break;
671  default:
672  break;
673  }
674  dt.setDate(da);
675  rrule->setStartDt(dt);
676  rrule->setAllDay(mRecurrence.allDay());
677  rrule->setFrequency(mRecurrence.frequency());
678  rrule->setDuration(mRecurrence.duration());
679  QList<int> ds;
680  ds.append(28);
681  rrule->setByMonthDays(ds);
682  rrule->setByMonths(mRecurrence.defaultRRuleConst()->byMonths());
683  dt = rrule->endDt();
684  delete rrule;
685 
686  // We've found the end date for a recurrence on the 28th. Unless that date
687  // is a real February 28th recurrence, adjust to the actual recurrence date.
688  if (mFeb29Type == Feb29_Feb28 && dt.date().month() == 2 && !QDate::isLeapYear(dt.date().year()))
689  return dt;
690  return dt.addDays(1);
691 }
692 
693 /******************************************************************************
694 * Return the date of the last recurrence.
695 */
696 QDate KARecurrence::endDate() const
697 {
698  KDateTime end = endDateTime();
699  return end.isValid() ? end.date() : QDate();
700 }
701 
702 void KARecurrence::setEndDate(const QDate& endDate)
703 {
704  d->mRecurrence.setEndDate(endDate);
705 }
706 
707 void KARecurrence::setEndDateTime(const KDateTime& endDateTime)
708 {
709  d->mRecurrence.setEndDateTime(endDateTime);
710 }
711 
712 bool KARecurrence::allDay() const
713 {
714  return d->mRecurrence.allDay();
715 }
716 
717 void KARecurrence::setRecurReadOnly(bool readOnly)
718 {
719  d->mRecurrence.setRecurReadOnly(readOnly);
720 }
721 
722 bool KARecurrence::recurReadOnly() const
723 {
724  return d->mRecurrence.recurReadOnly();
725 }
726 
727 bool KARecurrence::recurs() const
728 {
729  return d->mRecurrence.recurs();
730 }
731 
732 QBitArray KARecurrence::days() const
733 {
734  return d->mRecurrence.days();
735 }
736 
737 QList<RecurrenceRule::WDayPos> KARecurrence::monthPositions() const
738 {
739  return d->mRecurrence.monthPositions();
740 }
741 
742 QList<int> KARecurrence::monthDays() const
743 {
744  return d->mRecurrence.monthDays();
745 }
746 
747 QList<int> KARecurrence::yearDays() const
748 {
749  return d->mRecurrence.yearDays();
750 }
751 
752 QList<int> KARecurrence::yearDates() const
753 {
754  return d->mRecurrence.yearDates();
755 }
756 
757 QList<int> KARecurrence::yearMonths() const
758 {
759  return d->mRecurrence.yearMonths();
760 }
761 
762 QList<RecurrenceRule::WDayPos> KARecurrence::yearPositions() const
763 {
764  return d->mRecurrence.yearPositions();
765 }
766 
767 void KARecurrence::addWeeklyDays(const QBitArray& days)
768 {
769  d->mRecurrence.addWeeklyDays(days);
770 }
771 
772 void KARecurrence::addYearlyDay(int day)
773 {
774  d->mRecurrence.addYearlyDay(day);
775 }
776 
777 void KARecurrence::addYearlyDate(int date)
778 {
779  d->mRecurrence.addYearlyDate(date);
780 }
781 
782 void KARecurrence::addYearlyMonth(short month)
783 {
784  d->mRecurrence.addYearlyMonth(month);
785 }
786 
787 void KARecurrence::addYearlyPos(short pos, const QBitArray& days)
788 {
789  d->mRecurrence.addYearlyPos(pos, days);
790 }
791 
792 void KARecurrence::addMonthlyPos(short pos, const QBitArray& days)
793 {
794  d->mRecurrence.addMonthlyPos(pos, days);
795 }
796 
797 void KARecurrence::addMonthlyPos(short pos, ushort day)
798 {
799  d->mRecurrence.addMonthlyPos(pos, day);
800 }
801 
802 void KARecurrence::addMonthlyDate(short day)
803 {
804  d->mRecurrence.addMonthlyDate(day);
805 }
806 
807 /******************************************************************************
808 * Get the next time the recurrence occurs, strictly after a specified time.
809 */
810 KDateTime KARecurrence::getNextDateTime(const KDateTime& preDateTime) const
811 {
812  switch (type())
813  {
814  case ANNUAL_DATE:
815  case ANNUAL_POS:
816  {
817  Recurrence recur;
818  writeRecurrence(recur);
819  return recur.getNextDateTime(preDateTime);
820  }
821  default:
822  return d->mRecurrence.getNextDateTime(preDateTime);
823  }
824 }
825 
826 /******************************************************************************
827 * Get the previous time the recurrence occurred, strictly before a specified time.
828 */
829 KDateTime KARecurrence::getPreviousDateTime(const KDateTime& afterDateTime) const
830 {
831  switch (type())
832  {
833  case ANNUAL_DATE:
834  case ANNUAL_POS:
835  {
836  Recurrence recur;
837  writeRecurrence(recur);
838  return recur.getPreviousDateTime(afterDateTime);
839  }
840  default:
841  return d->mRecurrence.getPreviousDateTime(afterDateTime);
842  }
843 }
844 
845 /******************************************************************************
846 * Return whether the event will recur on the specified date.
847 * The start date only returns true if it matches the recurrence rules.
848 */
849 bool KARecurrence::recursOn(const QDate& dt, const KDateTime::Spec& timeSpec) const
850 {
851  if (!d->mRecurrence.recursOn(dt, timeSpec))
852  return false;
853  if (dt != d->mRecurrence.startDate())
854  return true;
855  // We know now that it isn't in EXDATES or EXRULES,
856  // so we just need to check if it's in RDATES or RRULES
857  if (d->mRecurrence.rDates().contains(dt))
858  return true;
859  const RecurrenceRule::List rulelist = d->mRecurrence.rRules();
860  for (int rri = 0, rrend = rulelist.count(); rri < rrend; ++rri)
861  if (rulelist[rri]->recursOn(dt, timeSpec))
862  return true;
863  const DateTimeList dtlist = d->mRecurrence.rDateTimes();
864  for (int dti = 0, dtend = dtlist.count(); dti < dtend; ++dti)
865  if (dtlist[dti].date() == dt)
866  return true;
867  return false;
868 }
869 
870 bool KARecurrence::recursAt(const KDateTime& dt) const
871 {
872  return d->mRecurrence.recursAt(dt);
873 }
874 
875 TimeList KARecurrence::recurTimesOn(const QDate& date, const KDateTime::Spec& timeSpec) const
876 {
877  return d->mRecurrence.recurTimesOn(date, timeSpec);
878 }
879 
880 DateTimeList KARecurrence::timesInInterval(const KDateTime& start, const KDateTime& end) const
881 {
882  return d->mRecurrence.timesInInterval(start, end);
883 }
884 
885 int KARecurrence::frequency() const
886 {
887  return d->mRecurrence.frequency();
888 }
889 
890 void KARecurrence::setFrequency(int freq)
891 {
892  d->mRecurrence.setFrequency(freq);
893 }
894 
895 int KARecurrence::duration() const
896 {
897  return d->mRecurrence.duration();
898 }
899 
900 void KARecurrence::setDuration(int duration)
901 {
902  d->mRecurrence.setDuration(duration);
903 }
904 
905 int KARecurrence::durationTo(const KDateTime& dt) const
906 {
907  return d->mRecurrence.durationTo(dt);
908 }
909 
910 int KARecurrence::durationTo(const QDate& date) const
911 {
912  return d->mRecurrence.durationTo(date);
913 }
914 
915 /******************************************************************************
916 * Find the duration of two RRULEs combined.
917 * Use the shorter of the two if they differ.
918 */
919 int KARecurrence::Private::combineDurations(const RecurrenceRule* rrule1, const RecurrenceRule* rrule2, QDate& end) const
920 {
921  int count1 = rrule1->duration();
922  int count2 = rrule2->duration();
923  if (count1 == -1 && count2 == -1)
924  return -1;
925 
926  // One of the RRULEs may not recur at all if the recurrence count is small.
927  // In this case, its end date will have been set to the start date.
928  if (count1 && !count2 && rrule2->endDt().date() == mRecurrence.startDateTime().date())
929  return count1;
930  if (count2 && !count1 && rrule1->endDt().date() == mRecurrence.startDateTime().date())
931  return count2;
932 
933  /* The duration counts will be different even for RRULEs of the same length,
934  * because the first RRULE only actually occurs every 4 years. So we need to
935  * compare the end dates.
936  */
937  if (!count1 || !count2)
938  count1 = count2 = 0;
939  // Get the two rules sorted by end date.
940  KDateTime end1 = rrule1->endDt();
941  KDateTime end2 = rrule2->endDt();
942  if (end1.date() == end2.date())
943  {
944  end = end1.date();
945  return count1 + count2;
946  }
947  const RecurrenceRule* rr1; // earlier end date
948  const RecurrenceRule* rr2; // later end date
949  if (end2.isValid()
950  && (!end1.isValid() || end1.date() > end2.date()))
951  {
952  // Swap the two rules to make rr1 have the earlier end date
953  rr1 = rrule2;
954  rr2 = rrule1;
955  KDateTime e = end1;
956  end1 = end2;
957  end2 = e;
958  }
959  else
960  {
961  rr1 = rrule1;
962  rr2 = rrule2;
963  }
964 
965  // Get the date of the next occurrence after the end of the earlier ending rule
966  RecurrenceRule rr(*rr1);
967  rr.setDuration(-1);
968  KDateTime next1(rr.getNextDate(end1));
969  next1.setDateOnly(true);
970  if (!next1.isValid())
971  end = end1.date();
972  else
973  {
974  if (end2.isValid() && next1 > end2)
975  {
976  // The next occurrence after the end of the earlier ending rule
977  // is later than the end of the later ending rule. So simply use
978  // the end date of the later rule.
979  end = end2.date();
980  return count1 + count2;
981  }
982  QDate prev2 = rr2->getPreviousDate(next1).date();
983  end = (prev2 > end1.date()) ? prev2 : end1.date();
984  }
985  if (count2)
986  count2 = rr2->durationTo(end);
987  return count1 + count2;
988 }
989 
990 /******************************************************************************
991 * Return the longest interval between recurrences.
992 * Reply = 0 if it never recurs.
993 */
994 Duration KARecurrence::longestInterval() const
995 {
996  int freq = d->mRecurrence.frequency();
997  switch (type())
998  {
999  case MINUTELY:
1000  return Duration(freq * 60, Duration::Seconds);
1001 
1002  case DAILY:
1003  {
1004  const QList<RecurrenceRule::WDayPos> days = d->mRecurrence.defaultRRuleConst()->byDays();
1005  if (days.isEmpty())
1006  return Duration(freq, Duration::Days);
1007 
1008  // After applying the frequency, the specified days of the week
1009  // further restrict when the recurrence occurs.
1010  // So the maximum interval may be greater than the frequency.
1011  bool ds[7] = { false, false, false, false, false, false, false };
1012  for (int i = 0, end = days.count(); i < end; ++i)
1013  if (days[i].pos() == 0)
1014  ds[days[i].day() - 1] = true;
1015  if (freq % 7)
1016  {
1017  // It will recur on every day of the week in some week or other
1018  // (except for those days which are excluded).
1019  int first = -1;
1020  int last = -1;
1021  int maxgap = 1;
1022  for (int i = 0; i < freq*7; i += freq)
1023  {
1024  if (ds[i % 7])
1025  {
1026  if (first < 0)
1027  first = i;
1028  else if (i - last > maxgap)
1029  maxgap = i - last;
1030  last = i;
1031  }
1032  }
1033  int wrap = freq*7 - last + first;
1034  if (wrap > maxgap)
1035  maxgap = wrap;
1036  return Duration(maxgap, Duration::Days);
1037  }
1038  else
1039  {
1040  // It will recur on the same day of the week every time.
1041  // Ensure that the day is a day which is not excluded.
1042  if (ds[d->mRecurrence.startDate().dayOfWeek() - 1])
1043  return Duration(freq, Duration::Days);
1044  break;
1045  }
1046  }
1047  case WEEKLY:
1048  {
1049  // Find which days of the week it recurs on, and if on more than
1050  // one, reduce the maximum interval accordingly.
1051  QBitArray ds = d->mRecurrence.days();
1052  int first = -1;
1053  int last = -1;
1054  int maxgap = 1;
1055  // Use the user's definition of the week, starting at the
1056  // day of the week specified by the user's locale.
1057  int weekStart = KGlobal::locale()->weekStartDay() - 1; // zero-based
1058  for (int i = 0; i < 7; ++i)
1059  {
1060  // Get the standard KDE day-of-week number (zero-based)
1061  // for the day-of-week number in the user's locale.
1062  if (ds.testBit((i + weekStart) % 7))
1063  {
1064  if (first < 0)
1065  first = i;
1066  else if (i - last > maxgap)
1067  maxgap = i - last;
1068  last = i;
1069  }
1070  }
1071  if (first < 0)
1072  break; // no days recur
1073  int span = last - first;
1074  if (freq > 1)
1075  return Duration(freq*7 - span, Duration::Days);
1076  if (7 - span > maxgap)
1077  return Duration(7 - span, Duration::Days);
1078  return Duration(maxgap, Duration::Days);
1079  }
1080  case MONTHLY_DAY:
1081  case MONTHLY_POS:
1082  return Duration(freq * 31, Duration::Days);
1083 
1084  case ANNUAL_DATE:
1085  case ANNUAL_POS:
1086  {
1087  // Find which months of the year it recurs on, and if on more than
1088  // one, reduce the maximum interval accordingly.
1089  const QList<int> months = d->mRecurrence.yearMonths(); // month list is sorted
1090  if (months.isEmpty())
1091  break; // no months recur
1092  if (months.count() == 1)
1093  return Duration(freq * 365, Duration::Days);
1094  int first = -1;
1095  int last = -1;
1096  int maxgap = 0;
1097  for (int i = 0, end = months.count(); i < end; ++i)
1098  {
1099  if (first < 0)
1100  first = months[i];
1101  else
1102  {
1103  int span = QDate(2001, last, 1).daysTo(QDate(2001, months[i], 1));
1104  if (span > maxgap)
1105  maxgap = span;
1106  }
1107  last = months[i];
1108  }
1109  int span = QDate(2001, first, 1).daysTo(QDate(2001, last, 1));
1110  if (freq > 1)
1111  return Duration(freq*365 - span, Duration::Days);
1112  if (365 - span > maxgap)
1113  return Duration(365 - span, Duration::Days);
1114  return Duration(maxgap, Duration::Days);
1115  }
1116  default:
1117  break;
1118  }
1119  return 0;
1120 }
1121 
1122 /******************************************************************************
1123 * Return the interval between recurrences, if the interval between successive
1124 * occurrences does not vary.
1125 * Reply = 0 if recurrence does not occur at fixed intervals.
1126 */
1127 Duration KARecurrence::regularInterval() const
1128 {
1129  int freq = d->mRecurrence.frequency();
1130  switch (type())
1131  {
1132  case MINUTELY:
1133  return Duration(freq * 60, Duration::Seconds);
1134  case DAILY:
1135  {
1136  const QList<RecurrenceRule::WDayPos> days = d->mRecurrence.defaultRRuleConst()->byDays();
1137  if (days.isEmpty())
1138  return Duration(freq, Duration::Days);
1139  // After applying the frequency, the specified days of the week
1140  // further restrict when the recurrence occurs.
1141  // Find which days occur, and count the number of days which occur.
1142  bool ds[7] = { false, false, false, false, false, false, false };
1143  for (int i = 0, end = days.count(); i < end; ++i)
1144  if (days[i].pos() == 0)
1145  ds[days[i].day() - 1] = true;
1146  if (!(freq % 7))
1147  {
1148  // It will recur on the same day of the week every time.
1149  // Check whether that day is in the list of included days.
1150  if (ds[d->mRecurrence.startDate().dayOfWeek() - 1])
1151  return Duration(freq, Duration::Days);
1152  break;
1153  }
1154  int n = 0; // number of days which occur
1155  for (int i = 0; i < 7; ++i)
1156  if (ds[i])
1157  ++n;
1158  if (n == 7)
1159  return Duration(freq, Duration::Days); // every day is included
1160  if (n == 1)
1161  return Duration(freq * 7, Duration::Days); // only one day of the week is included
1162  break;
1163  }
1164  case WEEKLY:
1165  {
1166  const QList<RecurrenceRule::WDayPos> days = d->mRecurrence.defaultRRuleConst()->byDays();
1167  if (days.isEmpty())
1168  return Duration(freq * 7, Duration::Days);
1169  // The specified days of the week occur every week in which the
1170  // recurrence occurs.
1171  // Find which days occur, and count the number of days which occur.
1172  bool ds[7] = { false, false, false, false, false, false, false };
1173  for (int i = 0, end = days.count(); i < end; ++i)
1174  if (days[i].pos() == 0)
1175  ds[days[i].day() - 1] = true;
1176  int n = 0; // number of days which occur
1177  for (int i = 0; i < 7; ++i)
1178  if (ds[i])
1179  ++n;
1180  if (n == 7)
1181  {
1182  if (freq == 1)
1183  return Duration(freq, Duration::Days); // every day is included
1184  break;
1185  }
1186  if (n == 1)
1187  return Duration(freq * 7, Duration::Days); // only one day of the week is included
1188  break;
1189  }
1190  default:
1191  break;
1192  }
1193  return 0;
1194 }
1195 
1196 DateTimeList KARecurrence::exDateTimes() const
1197 {
1198  return d->mRecurrence.exDateTimes();
1199 }
1200 
1201 DateList KARecurrence::exDates() const
1202 {
1203  return d->mRecurrence.exDates();
1204 }
1205 
1206 void KARecurrence::setExDateTimes(const DateTimeList& exdates)
1207 {
1208  d->mRecurrence.setExDateTimes(exdates);
1209 }
1210 
1211 void KARecurrence::setExDates(const DateList& exdates)
1212 {
1213  d->mRecurrence.setExDates(exdates);
1214 }
1215 
1216 void KARecurrence::addExDateTime(const KDateTime& exdate)
1217 {
1218  d->mRecurrence.addExDateTime(exdate);
1219 }
1220 
1221 void KARecurrence::addExDate(const QDate& exdate)
1222 {
1223  d->mRecurrence.addExDate(exdate);
1224 }
1225 
1226 void KARecurrence::shiftTimes(const KDateTime::Spec& oldSpec, const KDateTime::Spec& newSpec)
1227 {
1228  d->mRecurrence.shiftTimes(oldSpec, newSpec);
1229 }
1230 
1231 RecurrenceRule* KARecurrence::defaultRRuleConst() const
1232 {
1233  return d->mRecurrence.defaultRRuleConst();
1234 }
1235 
1236 /******************************************************************************
1237 * Return the recurrence's period type.
1238 */
1239 KARecurrence::Type KARecurrence::type() const
1240 {
1241  if (d->mCachedType == -1)
1242  d->mCachedType = type(d->mRecurrence.defaultRRuleConst());
1243  return static_cast<Type>(d->mCachedType);
1244 }
1245 
1246 /******************************************************************************
1247 * Return the recurrence rule type.
1248 */
1249 KARecurrence::Type KARecurrence::type(const RecurrenceRule* rrule)
1250 {
1251  switch (Recurrence::recurrenceType(rrule))
1252  {
1253  case Recurrence::rMinutely: return MINUTELY;
1254  case Recurrence::rDaily: return DAILY;
1255  case Recurrence::rWeekly: return WEEKLY;
1256  case Recurrence::rMonthlyDay: return MONTHLY_DAY;
1257  case Recurrence::rMonthlyPos: return MONTHLY_POS;
1258  case Recurrence::rYearlyMonth: return ANNUAL_DATE;
1259  case Recurrence::rYearlyPos: return ANNUAL_POS;
1260  default:
1261  if (dailyType(rrule))
1262  return DAILY;
1263  return NO_RECUR;
1264  }
1265 }
1266 
1267 /******************************************************************************
1268 * Check if the rule is a daily rule with or without BYDAYS specified.
1269 */
1270 bool KARecurrence::dailyType(const RecurrenceRule* rrule)
1271 {
1272  if (rrule->recurrenceType() != RecurrenceRule::rDaily
1273  || !rrule->bySeconds().isEmpty()
1274  || !rrule->byMinutes().isEmpty()
1275  || !rrule->byHours().isEmpty()
1276  || !rrule->byWeekNumbers().isEmpty()
1277  || !rrule->byMonthDays().isEmpty()
1278  || !rrule->byMonths().isEmpty()
1279  || !rrule->bySetPos().isEmpty()
1280  || !rrule->byYearDays().isEmpty())
1281  return false;
1282  const QList<RecurrenceRule::WDayPos> days = rrule->byDays();
1283  if (days.isEmpty())
1284  return true;
1285  // Check that all the positions are zero (i.e. every time)
1286  bool found = false;
1287  for (int i = 0, end = days.count(); i < end; ++i)
1288  {
1289  if (days[i].pos() != 0)
1290  return false;
1291  found = true;
1292  }
1293  return found;
1294 }
1295 
1296 } // namespace KAlarmCal
1297 
1298 // vim: et sw=4:
KAlarmCal::KARecurrence::monthPositions
QList< KCalCore::RecurrenceRule::WDayPos > monthPositions() const
Returns list of day positions in months.
Definition: karecurrence.cpp:737
KCalCore::RecurrenceRule::setFrequency
void setFrequency(int freq)
KAlarmCal::KARecurrence::fix
void fix()
Convert the recurrence to KARecurrence types.
Definition: karecurrence.cpp:304
KAlarmCal::KARecurrence::Type
Type
The recurrence's period type.
Definition: karecurrence.h:67
KCalCore::Duration
KAlarmCal::KARecurrence::durationTo
int durationTo(const KDateTime &dt) const
Returns the number of recurrences up to and including the date/time specified.
Definition: karecurrence.cpp:905
KAlarmCal::KARecurrence::frequency
int frequency() const
Returns frequency of recurrence, in terms of the recurrence time period type.
Definition: karecurrence.cpp:885
KCalCore::Recurrence::setDuration
void setDuration(int duration)
KCalCore::Recurrence::setStartDateTime
void setStartDateTime(const KDateTime &start)
KAlarmCal::KARecurrence::operator=
KARecurrence & operator=(const KARecurrence &r)
Assignment operator.
Definition: karecurrence.cpp:121
KCalCore::RecurrenceRule::setDuration
void setDuration(int duration)
KAlarmCal::KARecurrence::days
QBitArray days() const
Returns week day mask (bit 0 = Monday).
Definition: karecurrence.cpp:732
KAlarmCal::KARecurrence::setRecurReadOnly
void setRecurReadOnly(bool readOnly)
Set if recurrence is read-only or can be changed.
Definition: karecurrence.cpp:717
KAlarmCal::KARecurrence::addWeeklyDays
void addWeeklyDays(const QBitArray &days)
Adds days to the weekly day recurrence list.
Definition: karecurrence.cpp:767
KCalCore::Recurrence::setEndDateTime
void setEndDateTime(const KDateTime &endDateTime)
KAlarmCal::KARecurrence::Feb29Type
Feb29Type
When annual February 29th recurrences should occur in non-leap years.
Definition: karecurrence.h:79
KAlarmCal::KARecurrence::addMonthlyDate
void addMonthlyDate(short day)
Adds a date (e.g.
Definition: karecurrence.cpp:802
KAlarmCal::KARecurrence::endDateTime
KDateTime endDateTime() const
Return the date/time of the last recurrence.
Definition: karecurrence.cpp:623
KAlarmCal::KARecurrence::timesInInterval
KCalCore::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: karecurrence.cpp:880
KAlarmCal::KARecurrence::writeRecurrence
void writeRecurrence(KCalCore::Recurrence &) const
Initialise a KCalCore::Recurrence to be the same as this instance.
Definition: karecurrence.cpp:477
KAlarmCal::KARecurrence::yearDays
QList< int > yearDays() const
Returns the day numbers within a yearly recurrence.
Definition: karecurrence.cpp:747
KCalCore::RecurrenceRule::clear
void clear()
KAlarmCal::KARecurrence
Represents recurrences for KAlarm.
Definition: karecurrence.h:61
KAlarmCal::KARecurrence::getPreviousDateTime
KDateTime getPreviousDateTime(const KDateTime &afterDateTime) const
Get the previous time the recurrence occurred, strictly before a specified time.
Definition: karecurrence.cpp:829
KAlarmCal::KARecurrence::longestInterval
KCalCore::Duration longestInterval() const
Return the longest interval between recurrences.
Definition: karecurrence.cpp:994
KAlarmCal::KARecurrence::recursAt
bool recursAt(const KDateTime &dt) const
Returns true if the date/time specified is one at which the event will recur.
Definition: karecurrence.cpp:870
KCalCore::RecurrenceRule::setEndDt
void setEndDt(const KDateTime &endDateTime)
KAlarmCal::KARecurrence::startDate
QDate startDate() const
Return the start date/time of the recurrence.
Definition: karecurrence.cpp:608
KCalCore::Recurrence
KAlarmCal::KARecurrence::type
Type type() const
Return the recurrence's period type.
Definition: karecurrence.cpp:1239
KAlarmCal::KARecurrence::monthDays
QList< int > monthDays() const
Returns list of day numbers of a month.
Definition: karecurrence.cpp:742
KCalCore::SortableList
KCalCore::ICalFormat
KAlarmCal::KARecurrence::recurs
bool recurs() const
Returns whether the event recurs at all.
Definition: karecurrence.cpp:727
KAlarmCal::KARecurrence::setDuration
void setDuration(int duration)
Sets the total number of times the event is to occur, including both the first and last...
Definition: karecurrence.cpp:900
KAlarmCal::KARecurrence::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: karecurrence.cpp:895
KAlarmCal::KARecurrence::getNextDateTime
KDateTime getNextDateTime(const KDateTime &preDateTime) const
Get the next time the recurrence occurs, strictly after a specified time.
Definition: karecurrence.cpp:810
KAlarmCal::KARecurrence::addYearlyMonth
void addYearlyMonth(short month)
Adds month in yearly recurrence.
Definition: karecurrence.cpp:782
KCalCore::RecurrenceRule::frequency
uint frequency() const
KCalCore::RecurrenceRule::endDt
KDateTime endDt(bool *result=0) const
KCalCore::RecurrenceRule::startDt
KDateTime startDt() const
KCalCore::Recurrence::clear
void clear()
KCalCore::RecurrenceRule::recursOn
bool recursOn(const QDate &date, const KDateTime::Spec &timeSpec) const
KAlarmCal::KARecurrence::yearPositions
QList< KCalCore::RecurrenceRule::WDayPos > yearPositions() const
Returns the positions within a yearly recurrence.
Definition: karecurrence.cpp:762
KAlarmCal::KARecurrence::setDefaultFeb29Type
static void setDefaultFeb29Type(Feb29Type t)
Set the default way that 29th February annual recurrences should occur in non-leap years...
Definition: karecurrence.cpp:144
KAlarmCal::KARecurrence::setEndDateTime
void setEndDateTime(const KDateTime &endDateTime)
Sets the date and time of the last recurrence.
Definition: karecurrence.cpp:707
KCalCore::RecurrenceRule::PeriodType
PeriodType
KAlarmCal::KARecurrence::set
bool set(const QString &icalRRULE)
Initialise the recurrence from an iCalendar RRULE string.
Definition: karecurrence.cpp:276
KCalCore::Recurrence::unsetRecurs
void unsetRecurs()
KCalCore::Recurrence::addRRule
void addRRule(RecurrenceRule *rrule)
KAlarmCal::KARecurrence::endDate
QDate endDate() const
Return the date of the last recurrence.
Definition: karecurrence.cpp:696
KAlarmCal::KARecurrence::yearDates
QList< int > yearDates() const
Returns the dates within a yearly recurrence.
Definition: karecurrence.cpp:752
KAlarmCal::KARecurrence::setFrequency
void setFrequency(int freq)
Sets the frequency of recurrence, in terms of the recurrence time period type.
Definition: karecurrence.cpp:890
KAlarmCal::KARecurrence::setEndDate
void setEndDate(const QDate &endDate)
Sets the date of the last recurrence.
Definition: karecurrence.cpp:702
KCalCore::RecurrenceRule::durationTo
int durationTo(const KDateTime &dt) const
KAlarmCal::KARecurrence::recurReadOnly
bool recurReadOnly() const
Returns true if the recurrence is read-only, or false if it can be changed.
Definition: karecurrence.cpp:722
KAlarmCal::KARecurrence::startDateTime
KDateTime startDateTime() const
Return the start date/time of the recurrence (Time for all-day recurrences will be 0:00)...
Definition: karecurrence.cpp:603
KCalCore::Recurrence::getNextDateTime
KDateTime getNextDateTime(const KDateTime &preDateTime) const
KAlarmCal::KARecurrence::init
bool init(KCalCore::RecurrenceRule::PeriodType t, int freq, int count, const KDateTime &start, const KDateTime &end)
Set up a KARecurrence from recurrence parameters.
Definition: karecurrence.cpp:208
KCalCore::RecurrenceRule::duration
int duration() const
KAlarmCal::KARecurrence::recursOn
bool recursOn(const QDate &, const KDateTime::Spec &) const
Return whether the event will recur on the specified date.
Definition: karecurrence.cpp:849
KAlarmCal::KARecurrence::clear
void clear()
Removes all recurrence and exception rules and dates.
Definition: karecurrence.cpp:290
KCalCore::RecurrenceRule::setAllDay
void setAllDay(bool allDay)
KCalCore::Recurrence::getPreviousDateTime
KDateTime getPreviousDateTime(const KDateTime &afterDateTime) const
KAlarmCal::KARecurrence::addMonthlyPos
void addMonthlyPos(short pos, const QBitArray &days)
Adds a position (e.g.
Definition: karecurrence.cpp:792
KAlarmCal::KARecurrence::recurTimesOn
KCalCore::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: karecurrence.cpp:875
KAlarmCal::KARecurrence::addYearlyPos
void addYearlyPos(short pos, const QBitArray &days)
Adds position within month/year within a yearly recurrence.
Definition: karecurrence.cpp:787
KAlarmCal::KARecurrence::addYearlyDay
void addYearlyDay(int day)
Adds day number of year within a yearly recurrence.
Definition: karecurrence.cpp:772
KAlarmCal::KARecurrence::yearMonths
QList< int > yearMonths() const
Returns the months within a yearly recurrence.
Definition: karecurrence.cpp:757
KCalCore::RecurrenceRule::setStartDt
void setStartDt(const KDateTime &start)
KCalCore::ICalFormat::fromString
bool fromString(const Calendar::Ptr &calendar, const QString &string, bool deleted=false, const QString &notebook=QString())
KAlarmCal::KARecurrence::addYearlyDate
void addYearlyDate(int date)
Adds date within a yearly recurrence.
Definition: karecurrence.cpp:777
KAlarmCal::KARecurrence::allDay
bool allDay() const
Set whether the recurrence has no time, just a date.
Definition: karecurrence.cpp:712
KAlarmCal::KARecurrence::feb29Type
Feb29Type feb29Type() const
Return when 29th February annual recurrences should occur in non-leap years.
Definition: karecurrence.cpp:134
KAlarmCal::KARecurrence::defaultFeb29Type
static Feb29Type defaultFeb29Type()
Return the default way that 29th February annual recurrences should occur in non-leap years...
Definition: karecurrence.cpp:139
icalformat.h
KAlarmCal::KAEvent::recurType
KARecurrence::Type recurType() const
Return the recurrence period type for the event.
Definition: kaevent.cpp:3197
KAlarmCal::KARecurrence::operator==
bool operator==(const KARecurrence &r) const
Comparison operator for equality.
Definition: karecurrence.cpp:128
KAlarmCal::KARecurrence::setStartDateTime
void setStartDateTime(const KDateTime &dt, bool dateOnly)
Set the recurrence start date/time, and optionally set it to all-day.
Definition: karecurrence.cpp:613
KAlarmCal::KARecurrence::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: karecurrence.cpp:1226
KAlarmCal::KARecurrence::dailyType
static bool dailyType(const KCalCore::RecurrenceRule *)
Check if the recurrence rule is a daily rule with or without BYDAYS specified.
Definition: karecurrence.cpp:1270
KCalCore::RecurrenceRule
KAlarmCal::KARecurrence::regularInterval
KCalCore::Duration regularInterval() const
Return the interval between recurrences, if the interval between successive occurrences does not vary...
Definition: karecurrence.cpp:1127
KCalCore::RecurrenceRule::getPreviousDate
KDateTime getPreviousDate(const KDateTime &afterDateTime) const
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:01:14 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KAlarm Library

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

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kldap
  • kmbox
  • kmime
  • kpimidentities
  • kpimtextedit
  • kresources
  • ktnef
  • kxmlrpcclient
  • microblog

Search



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