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