00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "kalarm.h"
00022 #include "karecurrence.h"
00023
00024 #include "datetime.h"
00025 #include "functions.h"
00026
00027 #include <QBitArray>
00028 #include <kdebug.h>
00029
00030 #include <kcal/icalformat.h>
00031
00032
00033 using namespace KCal;
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 Preferences::Feb29Type KARecurrence::mDefaultFeb29 = Preferences::Feb29_None;
00053
00054
00055
00056
00057
00058
00059
00060
00061 bool KARecurrence::set(Type recurType, int freq, int count, int f29, const KDateTime& start, const KDateTime& end)
00062 {
00063 mCachedType = -1;
00064 RecurrenceRule::PeriodType rrtype;
00065 switch (recurType)
00066 {
00067 case MINUTELY: rrtype = RecurrenceRule::rMinutely; break;
00068 case DAILY: rrtype = RecurrenceRule::rDaily; break;
00069 case WEEKLY: rrtype = RecurrenceRule::rWeekly; break;
00070 case MONTHLY_DAY: rrtype = RecurrenceRule::rMonthly; break;
00071 case ANNUAL_DATE: rrtype = RecurrenceRule::rYearly; break;
00072 case NO_RECUR: rrtype = RecurrenceRule::rNone; break;
00073 default:
00074 return false;
00075 }
00076 if (!init(rrtype, freq, count, f29, start, end))
00077 return false;
00078 switch (recurType)
00079 {
00080 case WEEKLY:
00081 {
00082 QBitArray days(7);
00083 days.setBit(start.date().dayOfWeek() - 1);
00084 addWeeklyDays(days);
00085 break;
00086 }
00087 case MONTHLY_DAY:
00088 addMonthlyDate(start.date().day());
00089 break;
00090 case ANNUAL_DATE:
00091 addYearlyDate(start.date().day());
00092 addYearlyMonth(start.date().month());
00093 break;
00094 default:
00095 break;
00096 }
00097 return true;
00098 }
00099
00100
00101
00102
00103
00104 bool KARecurrence::init(RecurrenceRule::PeriodType recurType, int freq, int count, int f29, const KDateTime& start,
00105 const KDateTime& end)
00106 {
00107 mCachedType = -1;
00108 Preferences::Feb29Type feb29Type = (f29 == -1) ? mDefaultFeb29 : static_cast<Preferences::Feb29Type>(f29);
00109 mFeb29Type = Preferences::Feb29_None;
00110 clear();
00111 if (count < -1)
00112 return false;
00113 bool dateOnly = start.isDateOnly();
00114 if (!count && ((!dateOnly && !end.isValid())
00115 || (dateOnly && !end.date().isValid())))
00116 return false;
00117 switch (recurType)
00118 {
00119 case RecurrenceRule::rMinutely:
00120 case RecurrenceRule::rDaily:
00121 case RecurrenceRule::rWeekly:
00122 case RecurrenceRule::rMonthly:
00123 case RecurrenceRule::rYearly:
00124 break;
00125 case rNone:
00126 return true;
00127 default:
00128 return false;
00129 }
00130 setNewRecurrenceType(recurType, freq);
00131 if (count)
00132 setDuration(count);
00133 else if (dateOnly)
00134 setEndDate(end.date());
00135 else
00136 setEndDateTime(end);
00137 KDateTime startdt = start;
00138 if (recurType == RecurrenceRule::rYearly
00139 && (feb29Type == Preferences::Feb29_Feb28 || feb29Type == Preferences::Feb29_Mar1))
00140 {
00141 int year = startdt.date().year();
00142 if (!QDate::isLeapYear(year)
00143 && startdt.date().dayOfYear() == (feb29Type == Preferences::Feb29_Mar1 ? 60 : 59))
00144 {
00145
00146
00147
00148
00149
00150
00151
00152 while (!QDate::isLeapYear(--year)) ;
00153 startdt.setDate(QDate(year, 2, 29));
00154 }
00155 mFeb29Type = feb29Type;
00156 }
00157 setStartDateTime(startdt);
00158 return true;
00159 }
00160
00161
00162
00163
00164 bool KARecurrence::set(const QString& icalRRULE)
00165 {
00166 static QString RRULE = QLatin1String("RRULE:");
00167 mCachedType = -1;
00168 clear();
00169 if (icalRRULE.isEmpty())
00170 return true;
00171 ICalFormat format;
00172 if (!format.fromString(defaultRRule(true),
00173 (icalRRULE.startsWith(RRULE) ? icalRRULE.mid(RRULE.length()) : icalRRULE)))
00174 return false;
00175 fix();
00176 return true;
00177 }
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 void KARecurrence::fix()
00189 {
00190 mCachedType = -1;
00191 mFeb29Type = Preferences::Feb29_None;
00192 int convert = 0;
00193 int days[2] = { 0, 0 };
00194 RecurrenceRule* rrules[2];
00195 RecurrenceRule::List rrulelist = rRules();
00196 RecurrenceRule::List::ConstIterator rr = rrulelist.begin();
00197 for (int i = 0; i < 2 && rr != rrulelist.end(); ++i, ++rr)
00198 {
00199 RecurrenceRule* rrule = *rr;
00200 rrules[i] = rrule;
00201 bool stop = true;
00202 int rtype = recurrenceType(rrule);
00203 switch (rtype)
00204 {
00205 case rHourly:
00206
00207 rrule->setRecurrenceType(RecurrenceRule::rMinutely);
00208 rrule->setFrequency(rrule->frequency() * 60);
00209
00210 case rMinutely:
00211 case rDaily:
00212 case rWeekly:
00213 case rMonthlyDay:
00214 case rMonthlyPos:
00215 case rYearlyPos:
00216 if (!convert)
00217 ++rr;
00218 break;
00219 case rOther:
00220 if (dailyType(rrule))
00221 {
00222 if (!convert)
00223 ++rr;
00224 }
00225 break;
00226 case rYearlyDay:
00227 {
00228
00229 if (convert)
00230 {
00231
00232
00233 if (days[0] != 29
00234 || rrule->frequency() != rrules[0]->frequency()
00235 || rrule->startDt() != rrules[0]->startDt())
00236 break;
00237 }
00238 QList<int> ds = rrule->byYearDays();
00239 if (!ds.isEmpty() && ds.first() == 60)
00240 {
00241 ++convert;
00242 days[i] = 60;
00243 stop = false;
00244 break;
00245 }
00246 break;
00247 }
00248 case rYearlyMonth:
00249 {
00250 QList<int> ds = rrule->byMonthDays();
00251 if (!ds.isEmpty())
00252 {
00253 int day = ds.first();
00254 if (convert)
00255 {
00256
00257
00258 if (day == days[0] || (day == -1 && days[0] == 60)
00259 || rrule->frequency() != rrules[0]->frequency()
00260 || rrule->startDt() != rrules[0]->startDt())
00261 break;
00262 }
00263 if (ds.count() > 1)
00264 {
00265 ds.clear();
00266 ds.append(day);
00267 rrule->setByMonthDays(ds);
00268 }
00269 if (day == -1)
00270 {
00271
00272 QList<int> months = rrule->byMonths();
00273 if (months.count() != 1 || months.first() != 2)
00274 day = 0;
00275 }
00276 if (day == 29 || day == -1)
00277 {
00278 ++convert;
00279 days[i] = day;
00280 stop = false;
00281 break;
00282 }
00283 }
00284 if (!convert)
00285 ++rr;
00286 break;
00287 }
00288 default:
00289 break;
00290 }
00291 if (stop)
00292 break;
00293 }
00294
00295
00296 for ( ; rr != rrulelist.end(); ++rr)
00297 deleteRRule(*rr);
00298
00299 QDate end;
00300 int count;
00301 QList<int> months;
00302 if (convert == 2)
00303 {
00304
00305
00306
00307 if (days[0] != 29)
00308 {
00309
00310 RecurrenceRule* rr = rrules[0];
00311 rrules[0] = rrules[1];
00312 rrules[1] = rr;
00313 int d = days[0];
00314 days[0] = days[1];
00315 days[1] = d;
00316 }
00317
00318 months = rrules[0]->byMonths();
00319 if (months.removeAll(2))
00320 rrules[0]->setByMonths(months);
00321
00322 count = combineDurations(rrules[0], rrules[1], end);
00323 mFeb29Type = (days[1] == 60) ? Preferences::Feb29_Mar1 : Preferences::Feb29_Feb28;
00324 }
00325 else if (convert == 1 && days[0] == 60)
00326 {
00327
00328
00329 count = duration();
00330 if (!count)
00331 end = endDate();
00332 mFeb29Type = Preferences::Feb29_Mar1;
00333 }
00334 else
00335 return;
00336
00337
00338 setNewRecurrenceType(RecurrenceRule::rYearly, frequency());
00339 RecurrenceRule* rrule = defaultRRule();
00340 months.append(2);
00341 rrule->setByMonths(months);
00342 QList<int> ds;
00343 ds.append(29);
00344 rrule->setByMonthDays(ds);
00345 if (count)
00346 setDuration(count);
00347 else
00348 setEndDate(end);
00349 }
00350
00351
00352
00353
00354 KDateTime KARecurrence::getNextDateTime(const KDateTime& preDateTime) const
00355 {
00356 switch (type())
00357 {
00358 case ANNUAL_DATE:
00359 case ANNUAL_POS:
00360 {
00361 Recurrence recur;
00362 writeRecurrence(recur);
00363 return recur.getNextDateTime(preDateTime);
00364 }
00365 default:
00366 return Recurrence::getNextDateTime(preDateTime);
00367 }
00368 }
00369
00370
00371
00372
00373 KDateTime KARecurrence::getPreviousDateTime(const KDateTime& afterDateTime) const
00374 {
00375 switch (type())
00376 {
00377 case ANNUAL_DATE:
00378 case ANNUAL_POS:
00379 {
00380 Recurrence recur;
00381 writeRecurrence(recur);
00382 return recur.getPreviousDateTime(afterDateTime);
00383 }
00384 default:
00385 return Recurrence::getPreviousDateTime(afterDateTime);
00386 }
00387 }
00388
00389
00390
00391
00392
00393 void KARecurrence::writeRecurrence(KCal::Recurrence& recur) const
00394 {
00395 recur.clear();
00396 recur.setStartDateTime(startDateTime());
00397 recur.setExDates(exDates());
00398 recur.setExDateTimes(exDateTimes());
00399 const RecurrenceRule* rrule = defaultRRuleConst();
00400 if (!rrule)
00401 return;
00402 int freq = frequency();
00403 int count = duration();
00404 static_cast<KARecurrence*>(&recur)->setNewRecurrenceType(rrule->recurrenceType(), freq);
00405 if (count)
00406 recur.setDuration(count);
00407 else
00408 recur.setEndDateTime(endDateTime());
00409 switch (type())
00410 {
00411 case DAILY:
00412 if (rrule->byDays().isEmpty())
00413 break;
00414
00415 case WEEKLY:
00416 case MONTHLY_POS:
00417 recur.defaultRRule(true)->setByDays(rrule->byDays());
00418 break;
00419 case MONTHLY_DAY:
00420 recur.defaultRRule(true)->setByMonthDays(rrule->byMonthDays());
00421 break;
00422 case ANNUAL_POS:
00423 recur.defaultRRule(true)->setByMonths(rrule->byMonths());
00424 recur.defaultRRule()->setByDays(rrule->byDays());
00425 break;
00426 case ANNUAL_DATE:
00427 {
00428 QList<int> months = rrule->byMonths();
00429 QList<int> days = monthDays();
00430 bool special = (mFeb29Type != Preferences::Feb29_None && !days.isEmpty()
00431 && days.first() == 29 && months.removeAll(2));
00432 RecurrenceRule* rrule1 = recur.defaultRRule();
00433 rrule1->setByMonths(months);
00434 rrule1->setByMonthDays(days);
00435 if (!special)
00436 break;
00437
00438
00439
00440 RecurrenceRule* rrule2 = new RecurrenceRule();
00441 rrule2->setRecurrenceType(RecurrenceRule::rYearly);
00442 rrule2->setFrequency(freq);
00443 rrule2->setStartDt(startDateTime());
00444 rrule2->setAllDay(allDay());
00445 if (!count)
00446 rrule2->setEndDt(endDateTime());
00447 if (mFeb29Type == Preferences::Feb29_Mar1)
00448 {
00449 QList<int> ds;
00450 ds.append(60);
00451 rrule2->setByYearDays(ds);
00452 }
00453 else
00454 {
00455 QList<int> ds;
00456 ds.append(-1);
00457 rrule2->setByMonthDays(ds);
00458 QList<int> ms;
00459 ms.append(2);
00460 rrule2->setByMonths(ms);
00461 }
00462
00463 if (months.isEmpty())
00464 {
00465
00466
00467 if (count)
00468 rrule2->setDuration(count);
00469 recur.unsetRecurs();
00470 }
00471 else
00472 {
00473
00474
00475 if (count)
00476 {
00477 rrule1->setDuration(-1);
00478 rrule2->setDuration(-1);
00479 if (count > 0)
00480 {
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 KDateTime end = endDateTime();
00491 kDebug(0)<<"29th recurrence: count="<<count<<", end date="<<end.toString();
00492 int count1 = rrule1->durationTo(end)
00493 - (rrule1->recursOn(startDate(), startDateTime().timeSpec()) ? 0 : 1);
00494 if (count1 > 0)
00495 rrule1->setDuration(count1);
00496 else
00497 rrule1->setEndDt(startDateTime());
00498 int count2 = rrule2->durationTo(end)
00499 - (rrule2->recursOn(startDate(), startDateTime().timeSpec()) ? 0 : 1);
00500 if (count2 > 0)
00501 rrule2->setDuration(count2);
00502 else
00503 rrule2->setEndDt(startDateTime());
00504 }
00505 }
00506 }
00507 recur.addRRule(rrule2);
00508 break;
00509 }
00510 default:
00511 break;
00512 }
00513 }
00514
00515
00516
00517
00518 KDateTime KARecurrence::endDateTime() const
00519 {
00520 if (mFeb29Type == Preferences::Feb29_None || duration() <= 1)
00521 {
00522
00523
00524
00525
00526
00527 return Recurrence::endDateTime();
00528 }
00529
00530
00531
00532
00533
00534
00535 RecurrenceRule* rrule = new RecurrenceRule();
00536 rrule->setRecurrenceType(RecurrenceRule::rYearly);
00537 KDateTime dt = startDateTime();
00538 QDate d = dt.date();
00539 switch (d.day())
00540 {
00541 case 29:
00542
00543
00544 d.setYMD(d.year(), d.month(), 28);
00545 break;
00546 case 28:
00547 if (d.month() != 2 || mFeb29Type != Preferences::Feb29_Feb28 || QDate::isLeapYear(d.year()))
00548 {
00549
00550 d.setYMD(d.year(), d.month(), 27);
00551 }
00552 break;
00553 case 1:
00554 if (d.month() == 3 && mFeb29Type == Preferences::Feb29_Mar1 && !QDate::isLeapYear(d.year()))
00555 {
00556
00557
00558 d.setYMD(d.year(), 2, 28);
00559 }
00560 break;
00561 default:
00562 break;
00563 }
00564 dt.setDate(d);
00565 rrule->setStartDt(dt);
00566 rrule->setAllDay(allDay());
00567 rrule->setFrequency(frequency());
00568 rrule->setDuration(duration());
00569 QList<int> ds;
00570 ds.append(28);
00571 rrule->setByMonthDays(ds);
00572 rrule->setByMonths(defaultRRuleConst()->byMonths());
00573 dt = rrule->endDt();
00574 delete rrule;
00575
00576
00577
00578 if (mFeb29Type == Preferences::Feb29_Feb28 && dt.date().month() == 2 && !QDate::isLeapYear(dt.date().year()))
00579 return dt;
00580 return dt.addDays(1);
00581 }
00582
00583
00584
00585
00586 QDate KARecurrence::endDate() const
00587 {
00588 KDateTime end = endDateTime();
00589 return end.isValid() ? end.date() : QDate();
00590 }
00591
00592
00593
00594
00595
00596 bool KARecurrence::recursOn(const QDate& dt, const KDateTime::Spec& timeSpec) const
00597 {
00598 if (!Recurrence::recursOn(dt, timeSpec))
00599 return false;
00600 if (dt != startDate())
00601 return true;
00602
00603
00604 if (rDates().contains(dt))
00605 return true;
00606 RecurrenceRule::List rulelist = rRules();
00607 for (RecurrenceRule::List::ConstIterator rr = rulelist.begin(); rr != rulelist.end(); ++rr)
00608 if ((*rr)->recursOn(dt, timeSpec))
00609 return true;
00610 DateTimeList dtlist = rDateTimes();
00611 for (DateTimeList::ConstIterator rdt = dtlist.begin(); rdt != dtlist.end(); ++rdt)
00612 if ((*rdt).date() == dt)
00613 return true;
00614 return false;
00615 }
00616
00617
00618
00619
00620
00621 int KARecurrence::combineDurations(const RecurrenceRule* rrule1, const RecurrenceRule* rrule2, QDate& end) const
00622 {
00623 int count1 = rrule1->duration();
00624 int count2 = rrule2->duration();
00625 if (count1 == -1 && count2 == -1)
00626 return -1;
00627
00628
00629
00630 if (count1 && !count2 && rrule2->endDt().date() == startDateTime().date())
00631 return count1;
00632 if (count2 && !count1 && rrule1->endDt().date() == startDateTime().date())
00633 return count2;
00634
00635
00636
00637
00638
00639 if (!count1 || !count2)
00640 count1 = count2 = 0;
00641
00642 KDateTime end1 = rrule1->endDt();
00643 KDateTime end2 = rrule2->endDt();
00644 if (end1.date() == end2.date())
00645 {
00646 end = end1.date();
00647 return count1 + count2;
00648 }
00649 const RecurrenceRule* rr1;
00650 const RecurrenceRule* rr2;
00651 if (end2.isValid()
00652 && (!end1.isValid() || end1.date() > end2.date()))
00653 {
00654
00655 rr1 = rrule2;
00656 rr2 = rrule1;
00657 KDateTime e = end1;
00658 end1 = end2;
00659 end2 = e;
00660 }
00661 else
00662 {
00663 rr1 = rrule1;
00664 rr2 = rrule2;
00665 }
00666
00667
00668 RecurrenceRule rr(*rr1);
00669 rr.setDuration(-1);
00670 KDateTime next1(rr.getNextDate(end1));
00671 next1.setDateOnly(true);
00672 if (!next1.isValid())
00673 end = end1.date();
00674 else
00675 {
00676 if (end2.isValid() && next1 > end2)
00677 {
00678
00679
00680
00681 end = end2.date();
00682 return count1 + count2;
00683 }
00684 QDate prev2 = rr2->getPreviousDate(next1).date();
00685 end = (prev2 > end1.date()) ? prev2 : end1.date();
00686 }
00687 if (count2)
00688 count2 = rr2->durationTo(end);
00689 return count1 + count2;
00690 }
00691
00692
00693
00694
00695
00696 Duration KARecurrence::longestInterval() const
00697 {
00698 int freq = frequency();
00699 switch (type())
00700 {
00701 case MINUTELY:
00702 return Duration(freq * 60, Duration::Seconds);
00703
00704 case DAILY:
00705 {
00706 QList<RecurrenceRule::WDayPos> days = defaultRRuleConst()->byDays();
00707 if (days.isEmpty())
00708 return Duration(freq, Duration::Days);
00709
00710
00711
00712
00713 bool ds[7] = { false, false, false, false, false, false, false };
00714 for (int i = 0, end = days.count(); i < end; ++i)
00715 if (days[i].pos() == 0)
00716 ds[days[i].day() - 1] = true;
00717 if (freq % 7)
00718 {
00719
00720
00721 int first = -1;
00722 int last = -1;
00723 int maxgap = 1;
00724 for (int i = 0; i < freq*7; i += freq)
00725 {
00726 if (ds[i % 7])
00727 {
00728 if (first < 0)
00729 first = i;
00730 else if (i - last > maxgap)
00731 maxgap = i - last;
00732 last = i;
00733 }
00734 }
00735 int wrap = freq*7 - last + first;
00736 if (wrap > maxgap)
00737 maxgap = wrap;
00738 return Duration(maxgap, Duration::Days);
00739 }
00740 else
00741 {
00742
00743
00744 if (ds[startDate().dayOfWeek() - 1])
00745 return Duration(freq, Duration::Days);
00746 break;
00747 }
00748 }
00749 case WEEKLY:
00750 {
00751
00752
00753 QBitArray ds = days();
00754 int first = -1;
00755 int last = -1;
00756 int maxgap = 1;
00757 for (int i = 0; i < 7; ++i)
00758 {
00759 if (ds.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1))
00760 {
00761 if (first < 0)
00762 first = i;
00763 else if (i - last > maxgap)
00764 maxgap = i - last;
00765 last = i;
00766 }
00767 }
00768 if (first < 0)
00769 break;
00770 int span = last - first;
00771 if (freq > 1)
00772 return Duration(freq*7 - span, Duration::Days);
00773 if (7 - span > maxgap)
00774 return Duration(7 - span, Duration::Days);
00775 return Duration(maxgap, Duration::Days);
00776 }
00777 case MONTHLY_DAY:
00778 case MONTHLY_POS:
00779 return Duration(freq * 31, Duration::Days);
00780
00781 case ANNUAL_DATE:
00782 case ANNUAL_POS:
00783 {
00784
00785
00786 const QList<int> months = yearMonths();
00787 if (months.isEmpty())
00788 break;
00789 if (months.count() == 1)
00790 return Duration(freq * 365, Duration::Days);
00791 int first = -1;
00792 int last = -1;
00793 int maxgap = 0;
00794 for (int i = 0, end = months.count(); i < end; ++i)
00795 {
00796 if (first < 0)
00797 first = months[i];
00798 else
00799 {
00800 int span = QDate(2001, last, 1).daysTo(QDate(2001, months[i], 1));
00801 if (span > maxgap)
00802 maxgap = span;
00803 }
00804 last = months[i];
00805 }
00806 int span = QDate(2001, first, 1).daysTo(QDate(2001, last, 1));
00807 if (freq > 1)
00808 return Duration(freq*365 - span, Duration::Days);
00809 if (365 - span > maxgap)
00810 return Duration(365 - span, Duration::Days);
00811 return Duration(maxgap, Duration::Days);
00812 }
00813 default:
00814 break;
00815 }
00816 return 0;
00817 }
00818
00819
00820
00821
00822
00823
00824 Duration KARecurrence::regularInterval() const
00825 {
00826 int freq = frequency();
00827 switch (type())
00828 {
00829 case MINUTELY:
00830 return Duration(freq * 60, Duration::Seconds);
00831 case DAILY:
00832 {
00833 QList<RecurrenceRule::WDayPos> days = defaultRRuleConst()->byDays();
00834 if (days.isEmpty())
00835 return Duration(freq, Duration::Days);
00836
00837
00838
00839 bool ds[7] = { false, false, false, false, false, false, false };
00840 for (int i = 0, end = days.count(); i < end; ++i)
00841 if (days[i].pos() == 0)
00842 ds[days[i].day() - 1] = true;
00843 if (!(freq % 7))
00844 {
00845
00846
00847 if (ds[startDate().dayOfWeek() - 1])
00848 return Duration(freq, Duration::Days);
00849 break;
00850 }
00851 int n = 0;
00852 for (int i = 0; i < 7; ++i)
00853 if (ds[i])
00854 ++n;
00855 if (n == 7)
00856 return Duration(freq, Duration::Days);
00857 if (n == 1)
00858 return Duration(freq * 7, Duration::Days);
00859 break;
00860 }
00861 case WEEKLY:
00862 {
00863 QList<RecurrenceRule::WDayPos> days = defaultRRuleConst()->byDays();
00864 if (days.isEmpty())
00865 return Duration(freq * 7, Duration::Days);
00866
00867
00868
00869 bool ds[7] = { false, false, false, false, false, false, false };
00870 for (int i = 0, end = days.count(); i < end; ++i)
00871 if (days[i].pos() == 0)
00872 ds[days[i].day() - 1] = true;
00873 int n = 0;
00874 for (int i = 0; i < 7; ++i)
00875 if (ds[i])
00876 ++n;
00877 if (n == 7)
00878 {
00879 if (freq == 1)
00880 return Duration(freq, Duration::Days);
00881 break;
00882 }
00883 if (n == 1)
00884 return Duration(freq * 7, Duration::Days);
00885 break;
00886 }
00887 default:
00888 break;
00889 }
00890 return 0;
00891 }
00892
00893
00894
00895
00896 KARecurrence::Type KARecurrence::type() const
00897 {
00898 if (mCachedType == -1)
00899 mCachedType = type(defaultRRuleConst());
00900 return static_cast<Type>(mCachedType);
00901 }
00902
00903 KARecurrence::Type KARecurrence::type(const RecurrenceRule* rrule)
00904 {
00905 switch (recurrenceType(rrule))
00906 {
00907 case rMinutely: return MINUTELY;
00908 case rDaily: return DAILY;
00909 case rWeekly: return WEEKLY;
00910 case rMonthlyDay: return MONTHLY_DAY;
00911 case rMonthlyPos: return MONTHLY_POS;
00912 case rYearlyMonth: return ANNUAL_DATE;
00913 case rYearlyPos: return ANNUAL_POS;
00914 default:
00915 if (dailyType(rrule))
00916 return DAILY;
00917 return NO_RECUR;
00918 }
00919 }
00920
00921
00922
00923
00924 bool KARecurrence::dailyType(const RecurrenceRule* rrule)
00925 {
00926 if (rrule->recurrenceType() != RecurrenceRule::rDaily
00927 || !rrule->bySeconds().isEmpty()
00928 || !rrule->byMinutes().isEmpty()
00929 || !rrule->byHours().isEmpty()
00930 || !rrule->byWeekNumbers().isEmpty()
00931 || !rrule->byMonthDays().isEmpty()
00932 || !rrule->byMonths().isEmpty()
00933 || !rrule->bySetPos().isEmpty()
00934 || !rrule->byYearDays().isEmpty())
00935 return false;
00936 QList<RecurrenceRule::WDayPos> days = rrule->byDays();
00937 if (days.isEmpty())
00938 return true;
00939
00940 bool found = false;
00941 for (int i = 0, end = days.count(); i < end; ++i)
00942 {
00943 if (days[i].pos() != 0)
00944 return false;
00945 found = true;
00946 }
00947 return found;
00948
00949 }