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

KAlarm Library

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

Skip menu "kdepimlibs-4.11.3 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