diff options
Diffstat (limited to 'libkcal/recurrence.cpp')
-rw-r--r-- | libkcal/recurrence.cpp | 177 |
1 files changed, 128 insertions, 49 deletions
diff --git a/libkcal/recurrence.cpp b/libkcal/recurrence.cpp index c2d7897a0..ae47db326 100644 --- a/libkcal/recurrence.cpp +++ b/libkcal/recurrence.cpp @@ -34,7 +34,6 @@ using namespace KCal; - Recurrence::Recurrence() : mFloating( false ), mRecurReadOnly(false), @@ -282,9 +281,8 @@ bool Recurrence::recursOn(const TQDate &qd) const if ( mRDates.contains( qd ) ) return true; - // Check if it might recur today at all. bool recurs = false; - if ( startDate() == qd ) recurs = true; + for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) { recurs = recurs || (*rr)->recursOn( qd ); } @@ -770,10 +768,74 @@ TimeList Recurrence::recurTimesOn( const TQDate &date ) const return times; } +DateTimeList Recurrence::timesInInterval( const TQDateTime &start, const TQDateTime &end ) const +{ + int i, count; + DateTimeList times; + for ( i = 0, count = mRRules.count(); i < count; ++i ) { + times += mRRules[i]->timesInInterval( start, end ); + } + + // add rdatetimes that fit in the interval + for ( i = 0, count = mRDateTimes.count(); i < count; ++i ) { + if ( mRDateTimes[i] >= start && mRDateTimes[i] <= end ) { + times += mRDateTimes[i]; + } + } + + // add rdates that fit in the interval + TQDateTime qdt( mStartDateTime ); + for ( i = 0, count = mRDates.count(); i < count; ++i ) { + qdt.setDate( mRDates[i] ); + if ( qdt >= start && qdt <= end ) { + times += qdt; + } + } + + // Recurrence::timesInInterval(...) doesn't explicitly add mStartDateTime to the list + // of times to be returned. It calls mRRules[i]->timesInInterval(...) which include + // mStartDateTime. + // So, If we have rdates/rdatetimes but don't have any rrule we must explicitly + // add mStartDateTime to the list, otherwise we won't see the first occurrence. + if ( ( !mRDates.isEmpty() || !mRDateTimes.isEmpty() ) && + mRRules.isEmpty() && + start <= mStartDateTime && + end >= mStartDateTime ) { + times += mStartDateTime; + } + + qSortUnique( times ); + + // Remove excluded times + int idt = 0; + int enddt = times.count(); + for ( i = 0, count = mExDates.count(); i < count && idt < enddt; ++i ) { + while ( idt < enddt && times[idt].date() < mExDates[i] ) ++idt; + while ( idt < enddt && times[idt].date() == mExDates[i] ) { + times.remove( times.at( idt ) ); + --enddt; + } + } + DateTimeList extimes; + for ( i = 0, count = mExRules.count(); i < count; ++i ) { + extimes += mExRules[i]->timesInInterval( start, end ); + } + extimes += mExDateTimes; + qSortUnique( extimes ); + + int st = 0; + for ( i = 0, count = extimes.count(); i < count; ++i ) { + int j = removeSorted( times, extimes[i], st ); + if ( j >= 0 ) { + st = j; + } + } + + return times; +} TQDateTime Recurrence::getNextDateTime( const TQDateTime &preDateTime ) const { -//kdDebug(5800) << " Recurrence::getNextDateTime after " << preDateTime << endl; TQDateTime nextDT = preDateTime; // prevent infinite loops, e.g. when an exrule extinguishes an rrule (e.g. // the exrule is identical to the rrule). If an occurrence is found, break @@ -795,40 +857,51 @@ TQDateTime Recurrence::getNextDateTime( const TQDateTime &preDateTime ) const ++loop; // First, get the next recurrence from the RDate lists DateTimeList dates; - if ( nextDT < startDateTime() ) dates << startDateTime(); - DateTimeList::ConstIterator it = mRDateTimes.begin(); + if ( nextDT < startDateTime() ) { + dates << startDateTime(); + } + + int end; // Assume that the rdatetime list is sorted - while ( it != mRDateTimes.end() && (*it) <= nextDT ) ++it; - if ( it != mRDateTimes.end() ) dates << (*it); + int i = findGT( mRDateTimes, nextDT, 0 ); + if ( i >= 0 ) { + dates << mRDateTimes[i]; + } -/*kdDebug(5800) << " nextDT: " << nextDT << ", startDT: " << startDateTime() << endl; -kdDebug(5800) << " getNextDateTime: found " << dates.count() << " RDATES and DTSTART in loop " << loop << endl;*/ - DateList::ConstIterator dit = mRDates.begin(); - while ( dit != mRDates.end() && TQDateTime( (*dit), startDateTime().time() ) <= nextDT ) ++dit; - if ( dit != mRDates.end() ) dates << TQDateTime( (*dit), startDateTime().time() ); + TQDateTime qdt( startDateTime() ); + for ( i = 0, end = mRDates.count(); i < end; ++i ) { + qdt.setDate( mRDates[i] ); + if ( qdt > nextDT ) { + dates << qdt; + break; + } + } // Add the next occurrences from all RRULEs. - for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) { - TQDateTime dt = (*rr)->getNextDate( nextDT ); - if ( dt.isValid() ) dates << dt; + for ( i = 0, end = mRRules.count(); i < end; ++i ) { + TQDateTime dt = mRRules[i]->getNextDate( nextDT ); + if ( dt.isValid() ) { + dates << dt; + } } // Take the first of these (all others can't be used later on) qSortUnique( dates ); -// kdDebug(5800) << " getNextDateTime: found " << dates.count() << " dates in loop " << loop << endl; - - if ( dates.isEmpty() ) return TQDateTime(); + if ( dates.isEmpty() ) { + return TQDateTime(); + } nextDT = dates.first(); // Check if that date/time is excluded explicitly or by an exrule: - if ( !mExDates.contains( nextDT.date() ) && !mExDateTimes.contains( nextDT ) ) { -// kdDebug(5800) << " NextDT" << nextDT << " not excluded by EXDATE " << endl; + if ( !containsSorted( mExDates, nextDT.date() ) && + !containsSorted( mExDateTimes, nextDT ) ) { bool allowed = true; - for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) { - allowed = allowed && !( (*rr)->recursAt( nextDT ) ); + for ( i = 0, end = mExRules.count(); i < end; ++i ) { + allowed = allowed && !( mExRules[i]->recursAt( nextDT ) ); + } + if ( allowed ) { + return nextDT; } -// kdDebug(5800) << " NextDT " << nextDT << ", allowed=" << allowed << endl; - if ( allowed ) return nextDT; } } @@ -856,44 +929,50 @@ TQDateTime Recurrence::getPreviousDateTime( const TQDateTime &afterDateTime ) co ++loop; // First, get the next recurrence from the RDate lists DateTimeList dates; - if ( prevDT > startDateTime() ) dates << startDateTime(); - - DateTimeList::ConstIterator dtit = mRDateTimes.end(); - if ( dtit != mRDateTimes.begin() ) { - do { - --dtit; - } while ( dtit != mRDateTimes.begin() && (*dtit) >= prevDT ); - if ( (*dtit) < prevDT ) dates << (*dtit); + if ( prevDT > startDateTime() ) { + dates << startDateTime(); + } + + int i = findLT( mRDateTimes, prevDT, 0 ); + if ( i >= 0 ) { + dates << mRDateTimes[i]; } - DateList::ConstIterator dit = mRDates.end(); - if ( dit != mRDates.begin() ) { - do { - --dit; - } while ( dit != mRDates.begin() && TQDateTime((*dit), startDateTime().time()) >= prevDT ); - if ( TQDateTime((*dit), startDateTime().time()) < prevDT ) - dates << TQDateTime( (*dit), startDateTime().time() ); + TQDateTime qdt( startDateTime() ); + for ( i = mRDates.count(); --i >= 0; ) { + qdt.setDate( mRDates[i] ); + if ( qdt < prevDT ) { + dates << qdt; + break; + } } // Add the previous occurrences from all RRULEs. - for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) { - TQDateTime dt = (*rr)->getPreviousDate( prevDT ); - if ( dt.isValid() ) dates << dt; + int end; + for ( i = 0, end = mRRules.count(); i < end; ++i ) { + TQDateTime dt = mRRules[i]->getPreviousDate( prevDT ); + if ( dt.isValid() ) { + dates << dt; + } } -//kdDebug(5800) << " getPreviousDateTime: found " << dates.count() << " dates in loop " << loop << endl; // Take the last of these (all others can't be used later on) qSortUnique( dates ); - if ( dates.isEmpty() ) return TQDateTime(); + if ( dates.isEmpty() ) { + return TQDateTime(); + } prevDT = dates.last(); // Check if that date/time is excluded explicitly or by an exrule: - if ( !mExDates.contains( prevDT.date() ) && !mExDateTimes.contains( prevDT ) ) { + if ( !containsSorted( mExDates, prevDT.date() ) && + !containsSorted( mExDateTimes, prevDT ) ) { bool allowed = true; - for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) { - allowed = allowed && !( (*rr)->recursAt( prevDT ) ); + for ( i = 0, end = mExRules.count(); i < end; ++i ) { + allowed = allowed && !( mExRules[i]->recursAt( prevDT ) ); + } + if ( allowed ) { + return prevDT; } - if ( allowed ) return prevDT; } } |