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

KAlarm Library

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

KDE's Doxygen guidelines are available online.

KAlarm Library

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

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

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