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

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