summaryrefslogtreecommitdiffstats
path: root/libkcal/recurrence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkcal/recurrence.cpp')
-rw-r--r--libkcal/recurrence.cpp177
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;
}
}