// Emulate the old behavior QList<int> Recurrence::monthDays() const { RecurrenceRule *rrule = defaultRRuleConst(); if ( rrule ) { return rrule->byMonthDays(); } else { return QList<int>(); } }
void Recurrence::addMonthlyDate( short day ) { if ( d->mRecurReadOnly || day > 31 || day < -31 ) { return; } RecurrenceRule *rrule = defaultRRule( true ); if ( !rrule ) { return; } QList<int> monthDays = rrule->byMonthDays(); if ( !monthDays.contains( day ) ) { monthDays.append( day ); rrule->setByMonthDays( monthDays ); updated(); } }
/****************************************************************************** * Must be called after presetting with a KCal::Recurrence, to convert the * recurrence to KARecurrence types: * - Convert hourly recurrences to minutely. * - Remove all but the first day in yearly date recurrences. * - Check for yearly recurrences falling on February 29th and adjust them as * necessary. A 29th of the month rule can be combined with either a 60th day * of the year rule or a last day of February rule. */ void KARecurrence::fix() { mCachedType = -1; mFeb29Type = FEB29_FEB29; int convert = 0; int days[2] = { 0, 0 }; RecurrenceRule *rrules[2]; RecurrenceRule::List rrulelist = rRules(); RecurrenceRule::List::ConstIterator rr = rrulelist.begin(); for(int i = 0; i < 2 && rr != rrulelist.end(); ++i, ++rr) { RecurrenceRule *rrule = *rr; rrules[i] = rrule; bool stop = true; int rtype = recurrenceType(rrule); switch(rtype) { case rHourly: // Convert an hourly recurrence to a minutely one rrule->setRecurrenceType(RecurrenceRule::rMinutely); rrule->setFrequency(rrule->frequency() * 60); // fall through to rMinutely case rMinutely: case rDaily: case rWeekly: case rMonthlyDay: case rMonthlyPos: case rYearlyPos: if(!convert) ++rr; // remove all rules except the first break; case rOther: if(dailyType(rrule)) { // it's a daily rule with BYDAYS if(!convert) ++rr; // remove all rules except the first } break; case rYearlyDay: { // Ensure that the yearly day number is 60 (i.e. Feb 29th/Mar 1st) if(convert) { // This is the second rule. // Ensure that it can be combined with the first one. if(days[0] != 29 || rrule->frequency() != rrules[0]->frequency() || rrule->startDt() != rrules[0]->startDt()) break; } QValueList<int> ds = rrule->byYearDays(); if(!ds.isEmpty() && ds.first() == 60) { ++convert; // this rule needs to be converted days[i] = 60; stop = false; break; } break; // not day 60, so remove this rule } case rYearlyMonth: { QValueList<int> ds = rrule->byMonthDays(); if(!ds.isEmpty()) { int day = ds.first(); if(convert) { // This is the second rule. // Ensure that it can be combined with the first one. if(day == days[0] || day == -1 && days[0] == 60 || rrule->frequency() != rrules[0]->frequency() || rrule->startDt() != rrules[0]->startDt()) break; } if(ds.count() > 1) { ds.clear(); // remove all but the first day ds.append(day); rrule->setByMonthDays(ds); } if(day == -1) { // Last day of the month - only combine if it's February QValueList<int> months = rrule->byMonths(); if(months.count() != 1 || months.first() != 2) day = 0; } if(day == 29 || day == -1) { ++convert; // this rule may need to be converted days[i] = day; stop = false; break; } } if(!convert) ++rr; break; } default: break; } if(stop) break; } // Remove surplus rules for(; rr != rrulelist.end(); ++rr) { removeRRule(*rr); delete *rr; } QDate end; int count; QValueList<int> months; if(convert == 2) { // There are two yearly recurrence rules to combine into a February 29th recurrence. // Combine the two recurrence rules into a single rYearlyMonth rule falling on Feb 29th. // Find the duration of the two RRULEs combined, using the shorter of the two if they differ. if(days[0] != 29) { // Swap the two rules so that the 29th rule is the first RecurrenceRule *rr = rrules[0]; rrules[0] = rrules[1]; // the 29th rule rrules[1] = rr; int d = days[0]; days[0] = days[1]; days[1] = d; // the non-29th day } // If February is included in the 29th rule, remove it to avoid duplication months = rrules[0]->byMonths(); if(months.remove(2)) rrules[0]->setByMonths(months); count = combineDurations(rrules[0], rrules[1], end); mFeb29Type = (days[1] == 60) ? FEB29_MAR1 : FEB29_FEB28; } else if(convert == 1 && days[0] == 60) { // There is a single 60th day of the year rule. // Convert it to a February 29th recurrence. count = duration(); if(!count) end = endDate(); mFeb29Type = FEB29_MAR1; } else return; // Create the new February 29th recurrence setNewRecurrenceType(RecurrenceRule::rYearly, frequency()); RecurrenceRule *rrule = defaultRRule(); months.append(2); rrule->setByMonths(months); QValueList<int> ds; ds.append(29); rrule->setByMonthDays(ds); if(count) setDuration(count); else setEndDate(end); }