00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <limits.h>
00026
00027 #include <kdebug.h>
00028 #include <kglobal.h>
00029 #include <klocale.h>
00030 #include <qbitarray.h>
00031
00032 #include "recurrence.h"
00033 #include "recurrencerule.h"
00034
00035 using namespace KCal;
00036
00037
00038 Recurrence::Recurrence()
00039 : mFloating( false ),
00040 mRecurReadOnly(false),
00041 mCachedType(rMax)
00042 {
00043 mExRules.setAutoDelete( true );
00044 mRRules.setAutoDelete( true );
00045 }
00046
00047 Recurrence::Recurrence( const Recurrence &r )
00048 : RecurrenceRule::Observer(),
00049 mRDateTimes( r.mRDateTimes ), mRDates( r.mRDates ),
00050 mExDateTimes( r.mExDateTimes ), mExDates( r.mExDates ),
00051 mStartDateTime( r.mStartDateTime ),
00052 mFloating( r.mFloating ),
00053 mRecurReadOnly(r.mRecurReadOnly),
00054 mCachedType( r.mCachedType )
00055 {
00056 mExRules.setAutoDelete( true );
00057 mRRules.setAutoDelete( true );
00058 RecurrenceRule::List::ConstIterator rr;
00059 for ( rr = r.mRRules.begin(); rr != r.mRRules.end(); ++rr ) {
00060 RecurrenceRule *rule = new RecurrenceRule( *(*rr) );
00061 mRRules.append( rule );
00062 rule->addObserver( this );
00063 }
00064 for ( rr = r.mExRules.begin(); rr != r.mExRules.end(); ++rr ) {
00065 RecurrenceRule *rule = new RecurrenceRule( *(*rr) );
00066 mExRules.append( rule );
00067 rule->addObserver( this );
00068 }
00069 }
00070
00071 Recurrence::~Recurrence()
00072 {
00073 }
00074
00075
00076
00077 bool Recurrence::operator==( const Recurrence& r2 ) const
00078 {
00079 if ( mStartDateTime != r2.mStartDateTime
00080 || mFloating != r2.mFloating
00081 || mRecurReadOnly != r2.mRecurReadOnly )
00082 return false;
00083 if ( mExDates != r2.mExDates ) return false;
00084 if ( mExDateTimes != r2.mExDateTimes ) return false;
00085 if ( mRDates != r2.mRDates ) return false;
00086 if ( mRDateTimes != r2.mRDateTimes ) return false;
00087
00088
00089
00090 if ( mRRules.count() != r2.mRRules.count() ) return false;
00091 RecurrenceRule::List::ConstIterator rit1 = mRRules.begin();
00092 RecurrenceRule::List::ConstIterator rit2 = r2.mRRules.begin();
00093
00094 while ( rit1 != mRRules.end() && rit2 != r2.mRRules.end() ) {
00095
00096
00097 if ( *(*rit1) != *(*rit2) ) return false;
00098 ++rit1;
00099 ++rit2;
00100 }
00101 RecurrenceRule::List::ConstIterator exit1 = mExRules.begin();
00102 RecurrenceRule::List::ConstIterator exit2 = r2.mExRules.begin();
00103
00104 while ( exit1 != mExRules.end() && exit2 != r2.mExRules.end() ) {
00105
00106
00107 if ( *(*exit1) != *(*exit2) ) return false;
00108 ++exit1;
00109 ++exit2;
00110 }
00111 return true;
00112 }
00113
00114 void Recurrence::addObserver( Observer *observer )
00115 {
00116 if ( !mObservers.contains( observer ) )
00117 mObservers.append( observer );
00118 }
00119
00120 void Recurrence::removeObserver( Observer *observer )
00121 {
00122 if ( mObservers.contains( observer ) )
00123 mObservers.remove( observer );
00124 }
00125
00126
00127 QDateTime Recurrence::startDateTime() const
00128 {
00129 if ( mFloating )
00130 return QDateTime( mStartDateTime.date(), QTime( 0, 0, 0 ) );
00131 else return mStartDateTime;
00132 }
00133
00134 void Recurrence::setFloats( bool floats )
00135 {
00136 if ( mRecurReadOnly ) return;
00137 if ( floats == mFloating ) return;
00138 mFloating = floats;
00139
00140
00141 RecurrenceRule::List::ConstIterator it;
00142 for ( it = mRRules.begin(); it != mRRules.end(); ++it ) {
00143 (*it)->setFloats( floats );
00144 }
00145
00146 RecurrenceRule::List::ConstIterator it1;
00147 for ( it1 = mExRules.begin(); it1 != mExRules.end(); ++it1 ) {
00148 (*it1)->setFloats( floats );
00149 }
00150 updated();
00151 }
00152
00153 RecurrenceRule *Recurrence::defaultRRule( bool create ) const
00154 {
00155 if ( mRRules.isEmpty() ) {
00156 if ( !create || mRecurReadOnly ) return 0;
00157 RecurrenceRule *rrule = new RecurrenceRule();
00158 rrule->setStartDt( startDateTime() );
00159 const_cast<KCal::Recurrence*>(this)->addRRule( rrule );
00160 return rrule;
00161 } else {
00162 return mRRules.first();
00163 }
00164 }
00165
00166 RecurrenceRule *Recurrence::defaultRRuleConst() const
00167 {
00168 if ( mRRules.isEmpty() ) {
00169 return 0;
00170 } else {
00171 return mRRules.first();
00172 }
00173 }
00174
00175 void Recurrence::updated()
00176 {
00177
00178 mCachedType = rMax;
00179 for ( QValueList<Observer*>::ConstIterator it = mObservers.begin();
00180 it != mObservers.end(); ++it ) {
00181 if ( (*it) ) (*it)->recurrenceUpdated( this );
00182 }
00183 }
00184
00185 bool Recurrence::doesRecur() const
00186 {
00187 return !mRRules.isEmpty() || !mRDates.isEmpty() || !mRDateTimes.isEmpty();
00188 }
00189
00190 ushort Recurrence::recurrenceType() const
00191 {
00192 if ( mCachedType == rMax ) {
00193 mCachedType = recurrenceType( defaultRRuleConst() );
00194 }
00195 return mCachedType;
00196 }
00197
00198 ushort Recurrence::recurrenceType( const RecurrenceRule *rrule )
00199 {
00200 if ( !rrule ) return rNone;
00201 RecurrenceRule::PeriodType type = rrule->recurrenceType();
00202
00203
00204 if ( !rrule->bySetPos().isEmpty() )
00205 return rOther;
00206 if ( !rrule->bySeconds().isEmpty() )
00207 return rOther;
00208 if ( !rrule->byWeekNumbers().isEmpty() )
00209 return rOther;
00210
00211
00212
00213 if ( !rrule->byMinutes().isEmpty() )
00214 return rOther;
00215 if ( !rrule->byHours().isEmpty() )
00216 return rOther;
00217
00218
00219
00220
00221
00222
00223 if ( !rrule->byYearDays().isEmpty() && type != RecurrenceRule::rYearly )
00224 return rOther;
00225 if ( !rrule->byMonths().isEmpty() && type != RecurrenceRule::rYearly )
00226 return rOther;
00227 if ( !rrule->byDays().isEmpty() ) {
00228 if ( type != RecurrenceRule::rYearly && type != RecurrenceRule::rMonthly &&
00229 type != RecurrenceRule::rWeekly )
00230 return rOther;
00231 }
00232
00233 switch ( type ) {
00234 case RecurrenceRule::rNone: return rNone;
00235 case RecurrenceRule::rMinutely: return rMinutely;
00236 case RecurrenceRule::rHourly: return rHourly;
00237 case RecurrenceRule::rDaily: return rDaily;
00238 case RecurrenceRule::rWeekly: return rWeekly;
00239 case RecurrenceRule::rMonthly: {
00240 if ( rrule->byDays().isEmpty() ) return rMonthlyDay;
00241 else if ( rrule->byMonthDays().isEmpty() ) return rMonthlyPos;
00242 else return rOther;
00243 }
00244 case RecurrenceRule::rYearly: {
00245
00246
00247
00248
00249 if ( !rrule->byDays().isEmpty() ) {
00250
00251 if ( rrule->byMonthDays().isEmpty() && rrule->byYearDays().isEmpty() )
00252 return rYearlyPos;
00253 else return rOther;
00254 } else if ( !rrule->byYearDays().isEmpty() ) {
00255
00256 if ( rrule->byMonths().isEmpty() && rrule->byMonthDays().isEmpty() )
00257 return rYearlyDay;
00258 else return rOther;
00259 } else {
00260 return rYearlyMonth;
00261 }
00262 break;
00263 }
00264 default: return rOther;
00265 }
00266 return rOther;
00267 }
00268
00269 bool Recurrence::recursOn(const QDate &qd) const
00270 {
00271 TimeList tms;
00272
00273 if ( mExDates.contains( qd ) ) return false;
00274
00275
00276 if ( doesFloat() ) {
00277 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00278 if ( (*rr)->recursOn( qd ) )
00279 return false;
00280 }
00281 }
00282
00283 if ( mRDates.contains( qd ) ) return true;
00284
00285 bool recurs = false;
00286
00287 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00288 recurs = recurs || (*rr)->recursOn( qd );
00289 }
00290
00291 if ( !recurs ) {
00292 for ( DateTimeList::ConstIterator rit = mRDateTimes.begin();
00293 rit != mRDateTimes.end(); ++rit ) {
00294 if ( (*rit).date() == qd ) {
00295 recurs = true;
00296 break;
00297 }
00298 }
00299 }
00300
00301 if ( !recurs ) return false;
00302
00303
00304 bool exon = false;
00305 for ( DateTimeList::ConstIterator exit = mExDateTimes.begin();
00306 exit != mExDateTimes.end(); ++exit ) {
00307 if ( (*exit).date() == qd ) {
00308 exon = true;
00309 break;
00310 }
00311 }
00312 if ( !doesFloat() ) {
00313 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00314 exon = exon || (*rr)->recursOn( qd );
00315 }
00316 }
00317
00318 if ( !exon ) {
00319
00320 return recurs;
00321 } else {
00322
00323
00324 TimeList timesForDay( recurTimesOn( qd ) );
00325 return !timesForDay.isEmpty();
00326 }
00327 }
00328
00329 bool Recurrence::recursAt( const QDateTime &dt ) const
00330 {
00331
00332 if ( mExDateTimes.contains( dt )) return false;
00333 if ( mExDates.contains( dt.date() )) return false;
00334 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00335 if ( (*rr)->recursAt( dt ) ) return false;
00336 }
00337
00338
00339 bool occurs = ( startDateTime() == dt ) || mRDateTimes.contains( dt );
00340 if ( occurs )
00341 return true;
00342 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00343 if ( (*rr)->recursAt( dt ) ) return true;
00344 }
00345
00346 return false;
00347 }
00348
00352 QDateTime Recurrence::endDateTime() const
00353 {
00354 DateTimeList dts;
00355 dts << startDateTime();
00356 if ( !mRDates.isEmpty() ) dts << QDateTime( mRDates.last(), QTime( 0, 0, 0 ) );
00357 if ( !mRDateTimes.isEmpty() ) dts << mRDateTimes.last();
00358 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00359 QDateTime rl( (*rr)->endDt() );
00360
00361 if ( !rl.isValid() ) return QDateTime();
00362 dts << rl;
00363 }
00364 qSortUnique( dts );
00365 if ( dts.isEmpty() ) return QDateTime();
00366 else return dts.last();
00367 }
00368
00372 QDate Recurrence::endDate() const
00373 {
00374 QDateTime end( endDateTime() );
00375 if ( end.isValid() ) { return end.date(); }
00376 else return QDate();
00377 }
00378
00379 void Recurrence::setEndDate( const QDate &date )
00380 {
00381 if ( doesFloat() )
00382 setEndDateTime( QDateTime( date, QTime( 23, 59, 59 ) ) );
00383 else
00384 setEndDateTime( QDateTime( date, mStartDateTime.time() ) );
00385 }
00386
00387 void Recurrence::setEndDateTime( const QDateTime &dateTime )
00388 {
00389 if ( mRecurReadOnly ) return;
00390 RecurrenceRule *rrule = defaultRRule( true );
00391 if ( !rrule ) return;
00392 rrule->setEndDt( dateTime );
00393 updated();
00394 }
00395
00396 int Recurrence::duration() const
00397 {
00398 RecurrenceRule *rrule = defaultRRuleConst();
00399 if ( rrule ) return rrule->duration();
00400 else return 0;
00401 }
00402
00403
00404
00405
00406
00407
00408 int Recurrence::durationTo( const QDateTime &datetime ) const
00409 {
00410
00411 RecurrenceRule *rrule = defaultRRuleConst();
00412 if ( !rrule ) return 0;
00413 else return rrule->durationTo( datetime );
00414 }
00415
00416 void Recurrence::setDuration( int duration )
00417 {
00418 if ( mRecurReadOnly ) return;
00419 RecurrenceRule *rrule = defaultRRule( true );
00420 if ( !rrule ) return;
00421 rrule->setDuration( duration );
00422 updated();
00423 }
00424
00425 void Recurrence::unsetRecurs()
00426 {
00427 if ( mRecurReadOnly ) return;
00428 mRRules.clearAll();
00429 updated();
00430 }
00431
00432 void Recurrence::clear()
00433 {
00434 if ( mRecurReadOnly ) return;
00435 mRRules.clearAll();
00436 mExRules.clearAll();
00437 mRDates.clear();
00438 mRDateTimes.clear();
00439 mExDates.clear();
00440 mExDateTimes.clear();
00441 mCachedType = rMax;
00442 updated();
00443 }
00444
00445 void Recurrence::setStartDateTime( const QDateTime &start )
00446 {
00447 if ( mRecurReadOnly ) return;
00448 mStartDateTime = start;
00449 setFloats( false );
00450
00451 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00452 (*rr)->setStartDt( start );
00453 }
00454 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00455 (*rr)->setStartDt( start );
00456 }
00457 updated();
00458 }
00459
00460 void Recurrence::setStartDate( const QDate &start )
00461 {
00462 setStartDateTime( QDateTime( start, QTime(0,0,0) ) );
00463 setFloats( true );
00464 }
00465
00466 int Recurrence::frequency() const
00467 {
00468 RecurrenceRule *rrule = defaultRRuleConst();
00469 if ( rrule ) return rrule->frequency();
00470 else return 0;
00471 }
00472
00473
00474
00475 void Recurrence::setFrequency( int freq )
00476 {
00477 if ( mRecurReadOnly || freq <= 0 ) return;
00478 RecurrenceRule *rrule = defaultRRule( true );
00479 if ( rrule )
00480 rrule->setFrequency( freq );
00481 updated();
00482 }
00483
00484
00485
00486
00487 int Recurrence::weekStart() const
00488 {
00489 RecurrenceRule *rrule = defaultRRuleConst();
00490 if ( rrule ) return rrule->weekStart();
00491 else return 1;
00492 }
00493
00494
00495 QBitArray Recurrence::days() const
00496 {
00497 QBitArray days( 7 );
00498 days.fill( 0 );
00499 RecurrenceRule *rrule = defaultRRuleConst();
00500 if ( rrule ) {
00501 QValueList<RecurrenceRule::WDayPos> bydays = rrule->byDays();
00502 for ( QValueListConstIterator<RecurrenceRule::WDayPos> it = bydays.begin();
00503 it != bydays.end(); ++it ) {
00504 if ( (*it).pos() == 0 ) {
00505 days.setBit( (*it).day() - 1 );
00506 }
00507 }
00508 }
00509 return days;
00510 }
00511
00512
00513
00514
00515
00516 QValueList<int> Recurrence::monthDays() const
00517 {
00518 RecurrenceRule *rrule = defaultRRuleConst();
00519 if ( rrule ) return rrule->byMonthDays();
00520 else return QValueList<int>();
00521 }
00522
00523
00524 QValueList<RecurrenceRule::WDayPos> Recurrence::monthPositions() const
00525 {
00526 RecurrenceRule *rrule = defaultRRuleConst();
00527 if ( rrule ) return rrule->byDays();
00528 else return QValueList<RecurrenceRule::WDayPos>();
00529 }
00530
00531
00532
00533
00534 QValueList<int> Recurrence::yearDays() const
00535 {
00536 RecurrenceRule *rrule = defaultRRuleConst();
00537 if ( rrule ) return rrule->byYearDays();
00538 else return QValueList<int>();
00539 }
00540
00541 QValueList<int> Recurrence::yearDates() const
00542 {
00543 return monthDays();
00544 }
00545
00546 QValueList<int> Recurrence::yearMonths() const
00547 {
00548 RecurrenceRule *rrule = defaultRRuleConst();
00549 if ( rrule ) return rrule->byMonths();
00550 else return QValueList<int>();
00551 }
00552
00553 QValueList<RecurrenceRule::WDayPos> Recurrence::yearPositions() const
00554 {
00555 return monthPositions();
00556 }
00557
00558
00559
00560 RecurrenceRule *Recurrence::setNewRecurrenceType( RecurrenceRule::PeriodType type, int freq )
00561 {
00562 if ( mRecurReadOnly || freq <= 0 ) return 0;
00563 mRRules.clearAll();
00564 updated();
00565 RecurrenceRule *rrule = defaultRRule( true );
00566 if ( !rrule ) return 0;
00567 rrule->setRecurrenceType( type );
00568 rrule->setFrequency( freq );
00569 rrule->setDuration( -1 );
00570 return rrule;
00571 }
00572
00573 void Recurrence::setMinutely( int _rFreq )
00574 {
00575 if ( setNewRecurrenceType( RecurrenceRule::rMinutely, _rFreq ) )
00576 updated();
00577 }
00578
00579 void Recurrence::setHourly( int _rFreq )
00580 {
00581 if ( setNewRecurrenceType( RecurrenceRule::rHourly, _rFreq ) )
00582 updated();
00583 }
00584
00585 void Recurrence::setDaily( int _rFreq )
00586 {
00587 if ( setNewRecurrenceType( RecurrenceRule::rDaily, _rFreq ) )
00588 updated();
00589 }
00590
00591 void Recurrence::setWeekly( int freq, int weekStart )
00592 {
00593 RecurrenceRule *rrule = setNewRecurrenceType( RecurrenceRule::rWeekly, freq );
00594 if ( !rrule ) return;
00595 rrule->setWeekStart( weekStart );
00596 updated();
00597 }
00598
00599 void Recurrence::setWeekly( int freq, const QBitArray &days, int weekStart )
00600 {
00601 setWeekly( freq, weekStart );
00602 addMonthlyPos( 0, days );
00603 }
00604
00605 void Recurrence::addWeeklyDays( const QBitArray &days )
00606 {
00607 addMonthlyPos( 0, days );
00608 }
00609
00610 void Recurrence::setMonthly( int freq )
00611 {
00612 if ( setNewRecurrenceType( RecurrenceRule::rMonthly, freq ) )
00613 updated();
00614 }
00615
00616 void Recurrence::addMonthlyPos( short pos, const QBitArray &days )
00617 {
00618
00619 if ( mRecurReadOnly || pos > 53 || pos < -53 ) return;
00620 RecurrenceRule *rrule = defaultRRule( false );
00621 if ( !rrule ) return;
00622 bool changed = false;
00623 QValueList<RecurrenceRule::WDayPos> positions = rrule->byDays();
00624
00625 for ( int i = 0; i < 7; ++i ) {
00626 if ( days.testBit(i) ) {
00627 RecurrenceRule::WDayPos p( pos, i + 1 );
00628 if ( !positions.contains( p ) ) {
00629 changed = true;
00630 positions.append( p );
00631 }
00632 }
00633 }
00634 if ( changed ) {
00635 rrule->setByDays( positions );
00636 updated();
00637 }
00638 }
00639
00640
00641 void Recurrence::addMonthlyPos( short pos, ushort day )
00642 {
00643
00644 if ( mRecurReadOnly || pos > 53 || pos < -53 ) return;
00645 RecurrenceRule *rrule = defaultRRule( false );
00646 if ( !rrule ) return;
00647 QValueList<RecurrenceRule::WDayPos> positions = rrule->byDays();
00648
00649 RecurrenceRule::WDayPos p( pos, day );
00650 if ( !positions.contains( p ) ) {
00651 positions.append( p );
00652 rrule->setByDays( positions );
00653 updated();
00654 }
00655 }
00656
00657
00658 void Recurrence::addMonthlyDate( short day )
00659 {
00660 if ( mRecurReadOnly || day > 31 || day < -31 ) return;
00661 RecurrenceRule *rrule = defaultRRule( true );
00662 if ( !rrule ) return;
00663
00664 QValueList<int> monthDays = rrule->byMonthDays();
00665 if ( !monthDays.contains( day ) ) {
00666 monthDays.append( day );
00667 rrule->setByMonthDays( monthDays );
00668 updated();
00669 }
00670 }
00671
00672 void Recurrence::setYearly( int freq )
00673 {
00674 if ( setNewRecurrenceType( RecurrenceRule::rYearly, freq ) )
00675 updated();
00676 }
00677
00678
00679
00680 void Recurrence::addYearlyDay( int day )
00681 {
00682 RecurrenceRule *rrule = defaultRRule( false );
00683 if ( !rrule ) return;
00684
00685 QValueList<int> days = rrule->byYearDays();
00686 if ( !days.contains( day ) ) {
00687 days << day;
00688 rrule->setByYearDays( days );
00689 updated();
00690 }
00691 }
00692
00693
00694 void Recurrence::addYearlyDate( int day )
00695 {
00696 addMonthlyDate( day );
00697 }
00698
00699
00700 void Recurrence::addYearlyPos( short pos, const QBitArray &days )
00701 {
00702 addMonthlyPos( pos, days );
00703 }
00704
00705
00706
00707 void Recurrence::addYearlyMonth( short month )
00708 {
00709 if ( mRecurReadOnly || month < 1 || month > 12 ) return;
00710 RecurrenceRule *rrule = defaultRRule( false );
00711 if ( !rrule ) return;
00712
00713 QValueList<int> months = rrule->byMonths();
00714 if ( !months.contains(month) ) {
00715 months << month;
00716 rrule->setByMonths( months );
00717 updated();
00718 }
00719 }
00720
00721
00722 TimeList Recurrence::recurTimesOn( const QDate &date ) const
00723 {
00724 TimeList times;
00725
00726 if ( mExDates.contains( date ) ) return times;
00727
00728
00729 if ( doesFloat() ) {
00730 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00731 if ( (*rr)->recursOn( date ) )
00732 return times;
00733 }
00734 }
00735
00736 if ( startDate() == date ) times << startDateTime().time();
00737 bool foundDate = false;
00738 for ( DateTimeList::ConstIterator it = mRDateTimes.begin();
00739 it != mRDateTimes.end(); ++it ) {
00740 if ( (*it).date() == date ) {
00741 times << (*it).time();
00742 foundDate = true;
00743 } else if (foundDate) break;
00744 }
00745 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00746 times += (*rr)->recurTimesOn( date );
00747 }
00748 qSortUnique( times );
00749
00750 foundDate = false;
00751 TimeList extimes;
00752 for ( DateTimeList::ConstIterator it = mExDateTimes.begin();
00753 it != mExDateTimes.end(); ++it ) {
00754 if ( (*it).date() == date ) {
00755 extimes << (*it).time();
00756 foundDate = true;
00757 } else if (foundDate) break;
00758 }
00759 if ( !doesFloat() ) {
00760 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00761 extimes += (*rr)->recurTimesOn( date );
00762 }
00763 }
00764 qSortUnique( extimes );
00765
00766 for ( TimeList::Iterator it = extimes.begin(); it != extimes.end(); ++it ) {
00767 times.remove( (*it) );
00768 }
00769 return times;
00770 }
00771
00772 DateTimeList Recurrence::timesInInterval( const QDateTime &start, const QDateTime &end ) const
00773 {
00774 int i, count;
00775 DateTimeList times;
00776 for ( i = 0, count = mRRules.count(); i < count; ++i ) {
00777 times += mRRules[i]->timesInInterval( start, end );
00778 }
00779
00780
00781 for ( i = 0, count = mRDateTimes.count(); i < count; ++i ) {
00782 if ( mRDateTimes[i] >= start && mRDateTimes[i] <= end ) {
00783 times += mRDateTimes[i];
00784 }
00785 }
00786
00787
00788 QDateTime qdt( mStartDateTime );
00789 for ( i = 0, count = mRDates.count(); i < count; ++i ) {
00790 qdt.setDate( mRDates[i] );
00791 if ( qdt >= start && qdt <= end ) {
00792 times += qdt;
00793 }
00794 }
00795
00796
00797
00798
00799
00800
00801 if ( ( !mRDates.isEmpty() || !mRDateTimes.isEmpty() ) &&
00802 mRRules.isEmpty() &&
00803 start <= mStartDateTime &&
00804 end >= mStartDateTime ) {
00805 times += mStartDateTime;
00806 }
00807
00808 qSortUnique( times );
00809
00810
00811 int idt = 0;
00812 int enddt = times.count();
00813 for ( i = 0, count = mExDates.count(); i < count && idt < enddt; ++i ) {
00814 while ( idt < enddt && times[idt].date() < mExDates[i] ) ++idt;
00815 while ( idt < enddt && times[idt].date() == mExDates[i] ) {
00816 times.remove( times.at( idt ) );
00817 --enddt;
00818 }
00819 }
00820 DateTimeList extimes;
00821 for ( i = 0, count = mExRules.count(); i < count; ++i ) {
00822 extimes += mExRules[i]->timesInInterval( start, end );
00823 }
00824 extimes += mExDateTimes;
00825 qSortUnique( extimes );
00826
00827 int st = 0;
00828 for ( i = 0, count = extimes.count(); i < count; ++i ) {
00829 int j = removeSorted( times, extimes[i], st );
00830 if ( j >= 0 ) {
00831 st = j;
00832 }
00833 }
00834
00835 return times;
00836 }
00837
00838 QDateTime Recurrence::getNextDateTime( const QDateTime &preDateTime ) const
00839 {
00840
00841 QDateTime nextDT = preDateTime;
00842
00843
00844
00845
00846
00847 int loop = 0;
00848 while ( loop < 1000 ) {
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 ++loop;
00860
00861 DateTimeList dates;
00862 if ( nextDT < startDateTime() ) dates << startDateTime();
00863 DateTimeList::ConstIterator it = mRDateTimes.begin();
00864
00865 while ( it != mRDateTimes.end() && (*it) <= nextDT ) ++it;
00866 if ( it != mRDateTimes.end() ) dates << (*it);
00867
00868
00869
00870 DateList::ConstIterator dit = mRDates.begin();
00871 while ( dit != mRDates.end() && QDateTime( (*dit), startDateTime().time() ) <= nextDT ) ++dit;
00872 if ( dit != mRDates.end() ) dates << QDateTime( (*dit), startDateTime().time() );
00873
00874
00875 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00876 QDateTime dt = (*rr)->getNextDate( nextDT );
00877 if ( dt.isValid() ) dates << dt;
00878 }
00879
00880
00881 qSortUnique( dates );
00882
00883
00884 if ( dates.isEmpty() ) return QDateTime();
00885 nextDT = dates.first();
00886
00887
00888 if ( !mExDates.contains( nextDT.date() ) && !mExDateTimes.contains( nextDT ) ) {
00889
00890 bool allowed = true;
00891 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00892 allowed = allowed && !( (*rr)->recursAt( nextDT ) );
00893 }
00894
00895 if ( allowed ) return nextDT;
00896 }
00897 }
00898
00899
00900 return QDateTime();
00901 }
00902
00903 QDateTime Recurrence::getPreviousDateTime( const QDateTime &afterDateTime ) const
00904 {
00905 QDateTime prevDT = afterDateTime;
00906
00907
00908
00909 int loop = 0;
00910 while ( loop < 1000 ) {
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920 ++loop;
00921
00922 DateTimeList dates;
00923 if ( prevDT > startDateTime() ) dates << startDateTime();
00924
00925 DateTimeList::ConstIterator dtit = mRDateTimes.end();
00926 if ( dtit != mRDateTimes.begin() ) {
00927 do {
00928 --dtit;
00929 } while ( dtit != mRDateTimes.begin() && (*dtit) >= prevDT );
00930 if ( (*dtit) < prevDT ) dates << (*dtit);
00931 }
00932
00933 DateList::ConstIterator dit = mRDates.end();
00934 if ( dit != mRDates.begin() ) {
00935 do {
00936 --dit;
00937 } while ( dit != mRDates.begin() && QDateTime((*dit), startDateTime().time()) >= prevDT );
00938 if ( QDateTime((*dit), startDateTime().time()) < prevDT )
00939 dates << QDateTime( (*dit), startDateTime().time() );
00940 }
00941
00942
00943 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00944 QDateTime dt = (*rr)->getPreviousDate( prevDT );
00945 if ( dt.isValid() ) dates << dt;
00946 }
00947
00948
00949
00950 qSortUnique( dates );
00951 if ( dates.isEmpty() ) return QDateTime();
00952 prevDT = dates.last();
00953
00954
00955 if ( !mExDates.contains( prevDT.date() ) && !mExDateTimes.contains( prevDT ) ) {
00956 bool allowed = true;
00957 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00958 allowed = allowed && !( (*rr)->recursAt( prevDT ) );
00959 }
00960 if ( allowed ) return prevDT;
00961 }
00962 }
00963
00964
00965 return QDateTime();
00966 }
00967
00968
00969
00970
00971
00972 RecurrenceRule::List Recurrence::rRules() const
00973 {
00974 return mRRules;
00975 }
00976
00977 void Recurrence::addRRule( RecurrenceRule *rrule )
00978 {
00979 if ( mRecurReadOnly || !rrule ) return;
00980 rrule->setFloats( mFloating );
00981 mRRules.append( rrule );
00982 rrule->addObserver( this );
00983 updated();
00984 }
00985
00986 void Recurrence::removeRRule( RecurrenceRule *rrule )
00987 {
00988 if (mRecurReadOnly) return;
00989 mRRules.remove( rrule );
00990 rrule->removeObserver( this );
00991 updated();
00992 }
00993
00994 RecurrenceRule::List Recurrence::exRules() const
00995 {
00996 return mExRules;
00997 }
00998
00999 void Recurrence::addExRule( RecurrenceRule *exrule )
01000 {
01001 if ( mRecurReadOnly || !exrule ) return;
01002 exrule->setFloats( mFloating );
01003 mExRules.append( exrule );
01004 exrule->addObserver( this );
01005 updated();
01006 }
01007
01008 void Recurrence::removeExRule( RecurrenceRule *exrule )
01009 {
01010 if (mRecurReadOnly) return;
01011 mExRules.remove( exrule );
01012 exrule->removeObserver( this );
01013 updated();
01014 }
01015
01016
01017 DateTimeList Recurrence::rDateTimes() const
01018 {
01019 return mRDateTimes;
01020 }
01021
01022 void Recurrence::setRDateTimes( const DateTimeList &rdates )
01023 {
01024 if ( mRecurReadOnly ) return;
01025 mRDateTimes = rdates;
01026 qSortUnique( mRDateTimes );
01027 updated();
01028 }
01029
01030 void Recurrence::addRDateTime( const QDateTime &rdate )
01031 {
01032 if ( mRecurReadOnly ) return;
01033 mRDateTimes.append( rdate );
01034 qSortUnique( mRDateTimes );
01035 updated();
01036 }
01037
01038
01039 DateList Recurrence::rDates() const
01040 {
01041 return mRDates;
01042 }
01043
01044 void Recurrence::setRDates( const DateList &rdates )
01045 {
01046 if ( mRecurReadOnly ) return;
01047 mRDates = rdates;
01048 qSortUnique( mRDates );
01049 updated();
01050 }
01051
01052 void Recurrence::addRDate( const QDate &rdate )
01053 {
01054 if ( mRecurReadOnly ) return;
01055 mRDates.append( rdate );
01056 qSortUnique( mRDates );
01057 updated();
01058 }
01059
01060
01061 DateTimeList Recurrence::exDateTimes() const
01062 {
01063 return mExDateTimes;
01064 }
01065
01066 void Recurrence::setExDateTimes( const DateTimeList &exdates )
01067 {
01068 if ( mRecurReadOnly ) return;
01069 mExDateTimes = exdates;
01070 qSortUnique( mExDateTimes );
01071 }
01072
01073 void Recurrence::addExDateTime( const QDateTime &exdate )
01074 {
01075 if ( mRecurReadOnly ) return;
01076 mExDateTimes.append( exdate );
01077 qSortUnique( mExDateTimes );
01078 updated();
01079 }
01080
01081
01082 DateList Recurrence::exDates() const
01083 {
01084 return mExDates;
01085 }
01086
01087 void Recurrence::setExDates( const DateList &exdates )
01088 {
01089 if ( mRecurReadOnly ) return;
01090 mExDates = exdates;
01091 qSortUnique( mExDates );
01092 updated();
01093 }
01094
01095 void Recurrence::addExDate( const QDate &exdate )
01096 {
01097 if ( mRecurReadOnly ) return;
01098 mExDates.append( exdate );
01099 qSortUnique( mExDates );
01100 updated();
01101 }
01102
01103 void Recurrence::recurrenceChanged( RecurrenceRule * )
01104 {
01105 updated();
01106 }
01107
01108
01109
01110
01111 void Recurrence::dump() const
01112 {
01113 kdDebug(5800) << "Recurrence::dump():" << endl;
01114
01115 kdDebug(5800) << " -) " << mRRules.count() << " RRULEs: " << endl;
01116 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
01117 kdDebug(5800) << " -) RecurrenceRule : " << endl;
01118 (*rr)->dump();
01119 }
01120 kdDebug(5800) << " -) " << mExRules.count() << " EXRULEs: " << endl;
01121 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
01122 kdDebug(5800) << " -) ExceptionRule : " << endl;
01123 (*rr)->dump();
01124 }
01125
01126
01127 kdDebug(5800) << endl << " -) " << mRDates.count() << " Recurrence Dates: " << endl;
01128 for ( DateList::ConstIterator it = mRDates.begin(); it != mRDates.end(); ++it ) {
01129 kdDebug(5800) << " " << (*it) << endl;
01130 }
01131 kdDebug(5800) << endl << " -) " << mRDateTimes.count() << " Recurrence Date/Times: " << endl;
01132 for ( DateTimeList::ConstIterator it = mRDateTimes.begin(); it != mRDateTimes.end(); ++it ) {
01133 kdDebug(5800) << " " << (*it) << endl;
01134 }
01135 kdDebug(5800) << endl << " -) " << mExDates.count() << " Exceptions Dates: " << endl;
01136 for ( DateList::ConstIterator it = mExDates.begin(); it != mExDates.end(); ++it ) {
01137 kdDebug(5800) << " " << (*it) << endl;
01138 }
01139 kdDebug(5800) << endl << " -) " << mExDateTimes.count() << " Exception Date/Times: " << endl;
01140 for ( DateTimeList::ConstIterator it = mExDateTimes.begin(); it != mExDateTimes.end(); ++it ) {
01141 kdDebug(5800) << " " << (*it) << endl;
01142 }
01143 }