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
00286 bool recurs = false;
00287 if ( startDate() == qd ) recurs = true;
00288 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00289 recurs = recurs || (*rr)->recursOn( qd );
00290 }
00291
00292 if ( !recurs ) {
00293 for ( DateTimeList::ConstIterator rit = mRDateTimes.begin();
00294 rit != mRDateTimes.end(); ++rit ) {
00295 if ( (*rit).date() == qd ) {
00296 recurs = true;
00297 break;
00298 }
00299 }
00300 }
00301
00302 if ( !recurs ) return false;
00303
00304
00305 bool exon = false;
00306 for ( DateTimeList::ConstIterator exit = mExDateTimes.begin();
00307 exit != mExDateTimes.end(); ++exit ) {
00308 if ( (*exit).date() == qd ) {
00309 exon = true;
00310 break;
00311 }
00312 }
00313 if ( !doesFloat() ) {
00314 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00315 exon = exon || (*rr)->recursOn( qd );
00316 }
00317 }
00318
00319 if ( !exon ) {
00320
00321 return recurs;
00322 } else {
00323
00324
00325 TimeList timesForDay( recurTimesOn( qd ) );
00326 return !timesForDay.isEmpty();
00327 }
00328 }
00329
00330 bool Recurrence::recursAt( const QDateTime &dt ) const
00331 {
00332
00333 if ( mExDateTimes.contains( dt )) return false;
00334 if ( mExDates.contains( dt.date() )) return false;
00335 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00336 if ( (*rr)->recursAt( dt ) ) return false;
00337 }
00338
00339
00340 bool occurs = ( startDateTime() == dt ) || mRDateTimes.contains( dt );
00341 if ( occurs )
00342 return true;
00343 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00344 if ( (*rr)->recursAt( dt ) ) return true;
00345 }
00346
00347 return false;
00348 }
00349
00353 QDateTime Recurrence::endDateTime() const
00354 {
00355 DateTimeList dts;
00356 dts << startDateTime();
00357 if ( !mRDates.isEmpty() ) dts << QDateTime( mRDates.last(), QTime( 0, 0, 0 ) );
00358 if ( !mRDateTimes.isEmpty() ) dts << mRDateTimes.last();
00359 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00360 QDateTime rl( (*rr)->endDt() );
00361
00362 if ( !rl.isValid() ) return QDateTime();
00363 dts << rl;
00364 }
00365 qSortUnique( dts );
00366 if ( dts.isEmpty() ) return QDateTime();
00367 else return dts.last();
00368 }
00369
00373 QDate Recurrence::endDate() const
00374 {
00375 QDateTime end( endDateTime() );
00376 if ( end.isValid() ) { return end.date(); }
00377 else return QDate();
00378 }
00379
00380 void Recurrence::setEndDate( const QDate &date )
00381 {
00382 if ( doesFloat() )
00383 setEndDateTime( QDateTime( date, QTime( 23, 59, 59 ) ) );
00384 else
00385 setEndDateTime( QDateTime( date, mStartDateTime.time() ) );
00386 }
00387
00388 void Recurrence::setEndDateTime( const QDateTime &dateTime )
00389 {
00390 if ( mRecurReadOnly ) return;
00391 RecurrenceRule *rrule = defaultRRule( true );
00392 if ( !rrule ) return;
00393 rrule->setEndDt( dateTime );
00394 updated();
00395 }
00396
00397 int Recurrence::duration() const
00398 {
00399 RecurrenceRule *rrule = defaultRRuleConst();
00400 if ( rrule ) return rrule->duration();
00401 else return 0;
00402 }
00403
00404
00405
00406
00407
00408
00409 int Recurrence::durationTo( const QDateTime &datetime ) const
00410 {
00411
00412 RecurrenceRule *rrule = defaultRRuleConst();
00413 if ( !rrule ) return 0;
00414 else return rrule->durationTo( datetime );
00415 }
00416
00417 void Recurrence::setDuration( int duration )
00418 {
00419 if ( mRecurReadOnly ) return;
00420 RecurrenceRule *rrule = defaultRRule( true );
00421 if ( !rrule ) return;
00422 rrule->setDuration( duration );
00423 updated();
00424 }
00425
00426 void Recurrence::unsetRecurs()
00427 {
00428 if ( mRecurReadOnly ) return;
00429 mRRules.clearAll();
00430 updated();
00431 }
00432
00433 void Recurrence::clear()
00434 {
00435 if ( mRecurReadOnly ) return;
00436 mRRules.clearAll();
00437 mExRules.clearAll();
00438 mRDates.clear();
00439 mRDateTimes.clear();
00440 mExDates.clear();
00441 mExDateTimes.clear();
00442 mCachedType = rMax;
00443 updated();
00444 }
00445
00446 void Recurrence::setStartDateTime( const QDateTime &start )
00447 {
00448 if ( mRecurReadOnly ) return;
00449 mStartDateTime = start;
00450 setFloats( false );
00451
00452 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00453 (*rr)->setStartDt( start );
00454 }
00455 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00456 (*rr)->setStartDt( start );
00457 }
00458 updated();
00459 }
00460
00461 void Recurrence::setStartDate( const QDate &start )
00462 {
00463 setStartDateTime( QDateTime( start, QTime(0,0,0) ) );
00464 setFloats( true );
00465 }
00466
00467 int Recurrence::frequency() const
00468 {
00469 RecurrenceRule *rrule = defaultRRuleConst();
00470 if ( rrule ) return rrule->frequency();
00471 else return 0;
00472 }
00473
00474
00475
00476 void Recurrence::setFrequency( int freq )
00477 {
00478 if ( mRecurReadOnly || freq <= 0 ) return;
00479 RecurrenceRule *rrule = defaultRRule( true );
00480 if ( rrule )
00481 rrule->setFrequency( freq );
00482 updated();
00483 }
00484
00485
00486
00487
00488 int Recurrence::weekStart() const
00489 {
00490 RecurrenceRule *rrule = defaultRRuleConst();
00491 if ( rrule ) return rrule->weekStart();
00492 else return 1;
00493 }
00494
00495
00496 QBitArray Recurrence::days() const
00497 {
00498 QBitArray days( 7 );
00499 days.fill( 0 );
00500 RecurrenceRule *rrule = defaultRRuleConst();
00501 if ( rrule ) {
00502 QValueList<RecurrenceRule::WDayPos> bydays = rrule->byDays();
00503 for ( QValueListConstIterator<RecurrenceRule::WDayPos> it = bydays.begin();
00504 it != bydays.end(); ++it ) {
00505 if ( (*it).pos() == 0 ) {
00506 days.setBit( (*it).day() - 1 );
00507 }
00508 }
00509 }
00510 return days;
00511 }
00512
00513
00514
00515
00516
00517 QValueList<int> Recurrence::monthDays() const
00518 {
00519 RecurrenceRule *rrule = defaultRRuleConst();
00520 if ( rrule ) return rrule->byMonthDays();
00521 else return QValueList<int>();
00522 }
00523
00524
00525 QValueList<RecurrenceRule::WDayPos> Recurrence::monthPositions() const
00526 {
00527 RecurrenceRule *rrule = defaultRRuleConst();
00528 if ( rrule ) return rrule->byDays();
00529 else return QValueList<RecurrenceRule::WDayPos>();
00530 }
00531
00532
00533
00534
00535 QValueList<int> Recurrence::yearDays() const
00536 {
00537 RecurrenceRule *rrule = defaultRRuleConst();
00538 if ( rrule ) return rrule->byYearDays();
00539 else return QValueList<int>();
00540 }
00541
00542 QValueList<int> Recurrence::yearDates() const
00543 {
00544 return monthDays();
00545 }
00546
00547 QValueList<int> Recurrence::yearMonths() const
00548 {
00549 RecurrenceRule *rrule = defaultRRuleConst();
00550 if ( rrule ) return rrule->byMonths();
00551 else return QValueList<int>();
00552 }
00553
00554 QValueList<RecurrenceRule::WDayPos> Recurrence::yearPositions() const
00555 {
00556 return monthPositions();
00557 }
00558
00559
00560
00561 RecurrenceRule *Recurrence::setNewRecurrenceType( RecurrenceRule::PeriodType type, int freq )
00562 {
00563 if ( mRecurReadOnly || freq <= 0 ) return 0;
00564 mRRules.clearAll();
00565 updated();
00566 RecurrenceRule *rrule = defaultRRule( true );
00567 if ( !rrule ) return 0;
00568 rrule->setRecurrenceType( type );
00569 rrule->setFrequency( freq );
00570 rrule->setDuration( -1 );
00571 return rrule;
00572 }
00573
00574 void Recurrence::setMinutely( int _rFreq )
00575 {
00576 if ( setNewRecurrenceType( RecurrenceRule::rMinutely, _rFreq ) )
00577 updated();
00578 }
00579
00580 void Recurrence::setHourly( int _rFreq )
00581 {
00582 if ( setNewRecurrenceType( RecurrenceRule::rHourly, _rFreq ) )
00583 updated();
00584 }
00585
00586 void Recurrence::setDaily( int _rFreq )
00587 {
00588 if ( setNewRecurrenceType( RecurrenceRule::rDaily, _rFreq ) )
00589 updated();
00590 }
00591
00592 void Recurrence::setWeekly( int freq, int weekStart )
00593 {
00594 RecurrenceRule *rrule = setNewRecurrenceType( RecurrenceRule::rWeekly, freq );
00595 if ( !rrule ) return;
00596 rrule->setWeekStart( weekStart );
00597 updated();
00598 }
00599
00600 void Recurrence::setWeekly( int freq, const QBitArray &days, int weekStart )
00601 {
00602 setWeekly( freq, weekStart );
00603 addMonthlyPos( 0, days );
00604 }
00605
00606 void Recurrence::addWeeklyDays( const QBitArray &days )
00607 {
00608 addMonthlyPos( 0, days );
00609 }
00610
00611 void Recurrence::setMonthly( int freq )
00612 {
00613 if ( setNewRecurrenceType( RecurrenceRule::rMonthly, freq ) )
00614 updated();
00615 }
00616
00617 void Recurrence::addMonthlyPos( short pos, const QBitArray &days )
00618 {
00619
00620 if ( mRecurReadOnly || pos > 53 || pos < -53 ) return;
00621 RecurrenceRule *rrule = defaultRRule( false );
00622 if ( !rrule ) return;
00623 bool changed = false;
00624 QValueList<RecurrenceRule::WDayPos> positions = rrule->byDays();
00625
00626 for ( int i = 0; i < 7; ++i ) {
00627 if ( days.testBit(i) ) {
00628 RecurrenceRule::WDayPos p( pos, i + 1 );
00629 if ( !positions.contains( p ) ) {
00630 changed = true;
00631 positions.append( p );
00632 }
00633 }
00634 }
00635 if ( changed ) {
00636 rrule->setByDays( positions );
00637 updated();
00638 }
00639 }
00640
00641
00642 void Recurrence::addMonthlyPos( short pos, ushort day )
00643 {
00644
00645 if ( mRecurReadOnly || pos > 53 || pos < -53 ) return;
00646 RecurrenceRule *rrule = defaultRRule( false );
00647 if ( !rrule ) return;
00648 QValueList<RecurrenceRule::WDayPos> positions = rrule->byDays();
00649
00650 RecurrenceRule::WDayPos p( pos, day );
00651 if ( !positions.contains( p ) ) {
00652 positions.append( p );
00653 rrule->setByDays( positions );
00654 updated();
00655 }
00656 }
00657
00658
00659 void Recurrence::addMonthlyDate( short day )
00660 {
00661 if ( mRecurReadOnly || day > 31 || day < -31 ) return;
00662 RecurrenceRule *rrule = defaultRRule( true );
00663 if ( !rrule ) return;
00664
00665 QValueList<int> monthDays = rrule->byMonthDays();
00666 if ( !monthDays.contains( day ) ) {
00667 monthDays.append( day );
00668 rrule->setByMonthDays( monthDays );
00669 updated();
00670 }
00671 }
00672
00673 void Recurrence::setYearly( int freq )
00674 {
00675 if ( setNewRecurrenceType( RecurrenceRule::rYearly, freq ) )
00676 updated();
00677 }
00678
00679
00680
00681 void Recurrence::addYearlyDay( int day )
00682 {
00683 RecurrenceRule *rrule = defaultRRule( false );
00684 if ( !rrule ) return;
00685
00686 QValueList<int> days = rrule->byYearDays();
00687 if ( !days.contains( day ) ) {
00688 days << day;
00689 rrule->setByYearDays( days );
00690 updated();
00691 }
00692 }
00693
00694
00695 void Recurrence::addYearlyDate( int day )
00696 {
00697 addMonthlyDate( day );
00698 }
00699
00700
00701 void Recurrence::addYearlyPos( short pos, const QBitArray &days )
00702 {
00703 addMonthlyPos( pos, days );
00704 }
00705
00706
00707
00708 void Recurrence::addYearlyMonth( short month )
00709 {
00710 if ( mRecurReadOnly || month < 1 || month > 12 ) return;
00711 RecurrenceRule *rrule = defaultRRule( false );
00712 if ( !rrule ) return;
00713
00714 QValueList<int> months = rrule->byMonths();
00715 if ( !months.contains(month) ) {
00716 months << month;
00717 rrule->setByMonths( months );
00718 updated();
00719 }
00720 }
00721
00722
00723 TimeList Recurrence::recurTimesOn( const QDate &date ) const
00724 {
00725 TimeList times;
00726
00727 if ( mExDates.contains( date ) ) return times;
00728
00729
00730 if ( doesFloat() ) {
00731 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00732 if ( (*rr)->recursOn( date ) )
00733 return times;
00734 }
00735 }
00736
00737 if ( startDate() == date ) times << startDateTime().time();
00738 bool foundDate = false;
00739 for ( DateTimeList::ConstIterator it = mRDateTimes.begin();
00740 it != mRDateTimes.end(); ++it ) {
00741 if ( (*it).date() == date ) {
00742 times << (*it).time();
00743 foundDate = true;
00744 } else if (foundDate) break;
00745 }
00746 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00747 times += (*rr)->recurTimesOn( date );
00748 }
00749 qSortUnique( times );
00750
00751 foundDate = false;
00752 TimeList extimes;
00753 for ( DateTimeList::ConstIterator it = mExDateTimes.begin();
00754 it != mExDateTimes.end(); ++it ) {
00755 if ( (*it).date() == date ) {
00756 extimes << (*it).time();
00757 foundDate = true;
00758 } else if (foundDate) break;
00759 }
00760 if ( !doesFloat() ) {
00761 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00762 extimes += (*rr)->recurTimesOn( date );
00763 }
00764 }
00765 qSortUnique( extimes );
00766
00767 for ( TimeList::Iterator it = extimes.begin(); it != extimes.end(); ++it ) {
00768 times.remove( (*it) );
00769 }
00770 return times;
00771 }
00772
00773
00774 QDateTime Recurrence::getNextDateTime( const QDateTime &preDateTime ) const
00775 {
00776
00777 QDateTime nextDT = preDateTime;
00778
00779
00780
00781
00782
00783 int loop = 0;
00784 while ( loop < 1000 ) {
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795 ++loop;
00796
00797 DateTimeList dates;
00798 if ( nextDT < startDateTime() ) dates << startDateTime();
00799 DateTimeList::ConstIterator it = mRDateTimes.begin();
00800
00801 while ( it != mRDateTimes.end() && (*it) <= nextDT ) ++it;
00802 if ( it != mRDateTimes.end() ) dates << (*it);
00803
00804
00805
00806 DateList::ConstIterator dit = mRDates.begin();
00807 while ( dit != mRDates.end() && QDateTime( (*dit), startDateTime().time() ) <= nextDT ) ++dit;
00808 if ( dit != mRDates.end() ) dates << QDateTime( (*dit), startDateTime().time() );
00809
00810
00811 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00812 QDateTime dt = (*rr)->getNextDate( nextDT );
00813 if ( dt.isValid() ) dates << dt;
00814 }
00815
00816
00817 qSortUnique( dates );
00818
00819
00820 if ( dates.isEmpty() ) return QDateTime();
00821 nextDT = dates.first();
00822
00823
00824 if ( !mExDates.contains( nextDT.date() ) && !mExDateTimes.contains( nextDT ) ) {
00825
00826 bool allowed = true;
00827 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00828 allowed = allowed && !( (*rr)->recursAt( nextDT ) );
00829 }
00830
00831 if ( allowed ) return nextDT;
00832 }
00833 }
00834
00835
00836 return QDateTime();
00837 }
00838
00839 QDateTime Recurrence::getPreviousDateTime( const QDateTime &afterDateTime ) const
00840 {
00841 QDateTime prevDT = afterDateTime;
00842
00843
00844
00845 int loop = 0;
00846 while ( loop < 1000 ) {
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856 ++loop;
00857
00858 DateTimeList dates;
00859 if ( prevDT > startDateTime() ) dates << startDateTime();
00860
00861 DateTimeList::ConstIterator dtit = mRDateTimes.end();
00862 if ( dtit != mRDateTimes.begin() ) {
00863 do {
00864 --dtit;
00865 } while ( dtit != mRDateTimes.begin() && (*dtit) >= prevDT );
00866 if ( (*dtit) < prevDT ) dates << (*dtit);
00867 }
00868
00869 DateList::ConstIterator dit = mRDates.end();
00870 if ( dit != mRDates.begin() ) {
00871 do {
00872 --dit;
00873 } while ( dit != mRDates.begin() && QDateTime((*dit), startDateTime().time()) >= prevDT );
00874 if ( QDateTime((*dit), startDateTime().time()) < prevDT )
00875 dates << QDateTime( (*dit), startDateTime().time() );
00876 }
00877
00878
00879 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
00880 QDateTime dt = (*rr)->getPreviousDate( prevDT );
00881 if ( dt.isValid() ) dates << dt;
00882 }
00883
00884
00885
00886 qSortUnique( dates );
00887 if ( dates.isEmpty() ) return QDateTime();
00888 prevDT = dates.last();
00889
00890
00891 if ( !mExDates.contains( prevDT.date() ) && !mExDateTimes.contains( prevDT ) ) {
00892 bool allowed = true;
00893 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
00894 allowed = allowed && !( (*rr)->recursAt( prevDT ) );
00895 }
00896 if ( allowed ) return prevDT;
00897 }
00898 }
00899
00900
00901 return QDateTime();
00902 }
00903
00904
00905
00906
00907
00908 RecurrenceRule::List Recurrence::rRules() const
00909 {
00910 return mRRules;
00911 }
00912
00913 void Recurrence::addRRule( RecurrenceRule *rrule )
00914 {
00915 if ( mRecurReadOnly || !rrule ) return;
00916 rrule->setFloats( mFloating );
00917 mRRules.append( rrule );
00918 rrule->addObserver( this );
00919 updated();
00920 }
00921
00922 void Recurrence::removeRRule( RecurrenceRule *rrule )
00923 {
00924 if (mRecurReadOnly) return;
00925 mRRules.remove( rrule );
00926 rrule->removeObserver( this );
00927 updated();
00928 }
00929
00930 RecurrenceRule::List Recurrence::exRules() const
00931 {
00932 return mExRules;
00933 }
00934
00935 void Recurrence::addExRule( RecurrenceRule *exrule )
00936 {
00937 if ( mRecurReadOnly || !exrule ) return;
00938 exrule->setFloats( mFloating );
00939 mExRules.append( exrule );
00940 exrule->addObserver( this );
00941 updated();
00942 }
00943
00944 void Recurrence::removeExRule( RecurrenceRule *exrule )
00945 {
00946 if (mRecurReadOnly) return;
00947 mExRules.remove( exrule );
00948 exrule->removeObserver( this );
00949 updated();
00950 }
00951
00952
00953 DateTimeList Recurrence::rDateTimes() const
00954 {
00955 return mRDateTimes;
00956 }
00957
00958 void Recurrence::setRDateTimes( const DateTimeList &rdates )
00959 {
00960 if ( mRecurReadOnly ) return;
00961 mRDateTimes = rdates;
00962 qSortUnique( mRDateTimes );
00963 updated();
00964 }
00965
00966 void Recurrence::addRDateTime( const QDateTime &rdate )
00967 {
00968 if ( mRecurReadOnly ) return;
00969 mRDateTimes.append( rdate );
00970 qSortUnique( mRDateTimes );
00971 updated();
00972 }
00973
00974
00975 DateList Recurrence::rDates() const
00976 {
00977 return mRDates;
00978 }
00979
00980 void Recurrence::setRDates( const DateList &rdates )
00981 {
00982 if ( mRecurReadOnly ) return;
00983 mRDates = rdates;
00984 qSortUnique( mRDates );
00985 updated();
00986 }
00987
00988 void Recurrence::addRDate( const QDate &rdate )
00989 {
00990 if ( mRecurReadOnly ) return;
00991 mRDates.append( rdate );
00992 qSortUnique( mRDates );
00993 updated();
00994 }
00995
00996
00997 DateTimeList Recurrence::exDateTimes() const
00998 {
00999 return mExDateTimes;
01000 }
01001
01002 void Recurrence::setExDateTimes( const DateTimeList &exdates )
01003 {
01004 if ( mRecurReadOnly ) return;
01005 mExDateTimes = exdates;
01006 qSortUnique( mExDateTimes );
01007 }
01008
01009 void Recurrence::addExDateTime( const QDateTime &exdate )
01010 {
01011 if ( mRecurReadOnly ) return;
01012 mExDateTimes.append( exdate );
01013 qSortUnique( mExDateTimes );
01014 updated();
01015 }
01016
01017
01018 DateList Recurrence::exDates() const
01019 {
01020 return mExDates;
01021 }
01022
01023 void Recurrence::setExDates( const DateList &exdates )
01024 {
01025 if ( mRecurReadOnly ) return;
01026 mExDates = exdates;
01027 qSortUnique( mExDates );
01028 updated();
01029 }
01030
01031 void Recurrence::addExDate( const QDate &exdate )
01032 {
01033 if ( mRecurReadOnly ) return;
01034 mExDates.append( exdate );
01035 qSortUnique( mExDates );
01036 updated();
01037 }
01038
01039 void Recurrence::recurrenceChanged( RecurrenceRule * )
01040 {
01041 updated();
01042 }
01043
01044
01045
01046
01047 void Recurrence::dump() const
01048 {
01049 kdDebug(5800) << "Recurrence::dump():" << endl;
01050
01051 kdDebug(5800) << " -) " << mRRules.count() << " RRULEs: " << endl;
01052 for ( RecurrenceRule::List::ConstIterator rr = mRRules.begin(); rr != mRRules.end(); ++rr ) {
01053 kdDebug(5800) << " -) RecurrenceRule : " << endl;
01054 (*rr)->dump();
01055 }
01056 kdDebug(5800) << " -) " << mExRules.count() << " EXRULEs: " << endl;
01057 for ( RecurrenceRule::List::ConstIterator rr = mExRules.begin(); rr != mExRules.end(); ++rr ) {
01058 kdDebug(5800) << " -) ExceptionRule : " << endl;
01059 (*rr)->dump();
01060 }
01061
01062
01063 kdDebug(5800) << endl << " -) " << mRDates.count() << " Recurrence Dates: " << endl;
01064 for ( DateList::ConstIterator it = mRDates.begin(); it != mRDates.end(); ++it ) {
01065 kdDebug(5800) << " " << (*it) << endl;
01066 }
01067 kdDebug(5800) << endl << " -) " << mRDateTimes.count() << " Recurrence Date/Times: " << endl;
01068 for ( DateTimeList::ConstIterator it = mRDateTimes.begin(); it != mRDateTimes.end(); ++it ) {
01069 kdDebug(5800) << " " << (*it) << endl;
01070 }
01071 kdDebug(5800) << endl << " -) " << mExDates.count() << " Exceptions Dates: " << endl;
01072 for ( DateList::ConstIterator it = mExDates.begin(); it != mExDates.end(); ++it ) {
01073 kdDebug(5800) << " " << (*it) << endl;
01074 }
01075 kdDebug(5800) << endl << " -) " << mExDateTimes.count() << " Exception Date/Times: " << endl;
01076 for ( DateTimeList::ConstIterator it = mExDateTimes.begin(); it != mExDateTimes.end(); ++it ) {
01077 kdDebug(5800) << " " << (*it) << endl;
01078 }
01079 }