00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00038 #include "calendar.h"
00039 #include "exceptions.h"
00040 #include "calfilter.h"
00041 #include "icaltimezones.h"
00042 #include <kdebug.h>
00043 #include <klocale.h>
00044
00045 extern "C" {
00046 #include <icaltimezone.h>
00047 }
00048
00049 using namespace KCal;
00050
00055
00056 class KCal::Calendar::Private
00057 {
00058 public:
00059 Private()
00060 : mTimeZones( new ICalTimeZones ),
00061 mModified( false ),
00062 mNewObserver( false ),
00063 mObserversEnabled( true ),
00064 mDefaultFilter( new CalFilter )
00065 {
00066
00067 mFilter = mDefaultFilter;
00068 mFilter->setEnabled( false );
00069
00070
00071 mOwner.setName( i18n( "Unknown Name" ) );
00072 mOwner.setEmail( i18n( "unknown@nowhere" ) );
00073 }
00074
00075 ~Private()
00076 {
00077 delete mTimeZones;
00078 if ( mFilter != mDefaultFilter ) {
00079 delete mFilter;
00080 }
00081 delete mDefaultFilter;
00082 }
00083 KDateTime::Spec timeZoneIdSpec( const QString &timeZoneId, bool view );
00084
00085 QString mProductId;
00086 Person mOwner;
00087 ICalTimeZones *mTimeZones;
00088 ICalTimeZone mBuiltInTimeZone;
00089 ICalTimeZone mBuiltInViewTimeZone;
00090 KDateTime::Spec mTimeSpec;
00091 mutable KDateTime::Spec mViewTimeSpec;
00092 bool mModified;
00093 bool mNewObserver;
00094 bool mObserversEnabled;
00095 QList<CalendarObserver*> mObservers;
00096
00097 CalFilter *mDefaultFilter;
00098 CalFilter *mFilter;
00099
00100
00101 QMultiHash<QString, Incidence*> mOrphans;
00102 QMultiHash<QString, Incidence*> mOrphanUids;
00103 };
00104
00105
00106 Calendar::Calendar( const KDateTime::Spec &timeSpec )
00107 : d( new KCal::Calendar::Private )
00108 {
00109 d->mTimeSpec = timeSpec;
00110 d->mViewTimeSpec = timeSpec;
00111 }
00112
00113 Calendar::Calendar( const QString &timeZoneId )
00114 : d( new KCal::Calendar::Private )
00115 {
00116 setTimeZoneId( timeZoneId );
00117 }
00118
00119 Calendar::~Calendar()
00120 {
00121 delete d;
00122 }
00123
00124 Person Calendar::owner() const
00125 {
00126 return d->mOwner;
00127 }
00128
00129 void Calendar::setOwner( const Person &owner )
00130 {
00131 d->mOwner = owner;
00132
00133 setModified( true );
00134 }
00135
00136 void Calendar::setTimeSpec( const KDateTime::Spec &timeSpec )
00137 {
00138 d->mTimeSpec = timeSpec;
00139 d->mBuiltInTimeZone = ICalTimeZone();
00140 setViewTimeSpec( timeSpec );
00141
00142 doSetTimeSpec( d->mTimeSpec );
00143 }
00144
00145 KDateTime::Spec Calendar::timeSpec() const
00146 {
00147 return d->mTimeSpec;
00148 }
00149
00150 void Calendar::setTimeZoneId( const QString &timeZoneId )
00151 {
00152 d->mTimeSpec = d->timeZoneIdSpec( timeZoneId, false );
00153 d->mViewTimeSpec = d->mTimeSpec;
00154 d->mBuiltInViewTimeZone = d->mBuiltInTimeZone;
00155
00156 doSetTimeSpec( d->mTimeSpec );
00157 }
00158
00159
00160 KDateTime::Spec Calendar::Private::timeZoneIdSpec( const QString &timeZoneId,
00161 bool view )
00162 {
00163 if ( view ) {
00164 mBuiltInViewTimeZone = ICalTimeZone();
00165 } else {
00166 mBuiltInTimeZone = ICalTimeZone();
00167 }
00168 if ( timeZoneId == QLatin1String( "UTC" ) ) {
00169 return KDateTime::UTC;
00170 }
00171 ICalTimeZone tz = mTimeZones->zone( timeZoneId );
00172 if ( !tz.isValid() ) {
00173 ICalTimeZoneSource tzsrc;
00174 tz = tzsrc.parse( icaltimezone_get_builtin_timezone( timeZoneId.toLatin1() ) );
00175 if ( view ) {
00176 mBuiltInViewTimeZone = tz;
00177 } else {
00178 mBuiltInTimeZone = tz;
00179 }
00180 }
00181 if ( tz.isValid() ) {
00182 return tz;
00183 } else {
00184 return KDateTime::ClockTime;
00185 }
00186 }
00187
00188
00189 QString Calendar::timeZoneId() const
00190 {
00191 KTimeZone tz = d->mTimeSpec.timeZone();
00192 return tz.isValid() ? tz.name() : QString();
00193 }
00194
00195 void Calendar::setViewTimeSpec( const KDateTime::Spec &timeSpec ) const
00196 {
00197 d->mViewTimeSpec = timeSpec;
00198 d->mBuiltInViewTimeZone = ICalTimeZone();
00199 }
00200
00201 void Calendar::setViewTimeZoneId( const QString &timeZoneId ) const
00202 {
00203 d->mViewTimeSpec = d->timeZoneIdSpec( timeZoneId, true );
00204 }
00205
00206 KDateTime::Spec Calendar::viewTimeSpec() const
00207 {
00208 return d->mViewTimeSpec;
00209 }
00210
00211 QString Calendar::viewTimeZoneId() const
00212 {
00213 KTimeZone tz = d->mViewTimeSpec.timeZone();
00214 return tz.isValid() ? tz.name() : QString();
00215 }
00216
00217 ICalTimeZones *Calendar::timeZones() const
00218 {
00219 return d->mTimeZones;
00220 }
00221
00222 void Calendar::shiftTimes( const KDateTime::Spec &oldSpec,
00223 const KDateTime::Spec &newSpec )
00224 {
00225 setTimeSpec( newSpec );
00226
00227 int i, end;
00228 Event::List ev = events();
00229 for ( i = 0, end = ev.count(); i < end; ++i ) {
00230 ev[i]->shiftTimes( oldSpec, newSpec );
00231 }
00232
00233 Todo::List to = todos();
00234 for ( i = 0, end = to.count(); i < end; ++i ) {
00235 to[i]->shiftTimes( oldSpec, newSpec );
00236 }
00237
00238 Journal::List jo = journals();
00239 for ( i = 0, end = jo.count(); i < end; ++i ) {
00240 jo[i]->shiftTimes( oldSpec, newSpec );
00241 }
00242 }
00243
00244 void Calendar::setFilter( CalFilter *filter )
00245 {
00246 if ( filter ) {
00247 d->mFilter = filter;
00248 } else {
00249 d->mFilter = d->mDefaultFilter;
00250 }
00251 }
00252
00253 CalFilter *Calendar::filter()
00254 {
00255 return d->mFilter;
00256 }
00257
00258 QStringList Calendar::categories()
00259 {
00260 Incidence::List rawInc( rawIncidences() );
00261 QStringList cats, thisCats;
00262
00263
00264 for ( Incidence::List::ConstIterator i = rawInc.constBegin();
00265 i != rawInc.constEnd(); ++i ) {
00266 thisCats = (*i)->categories();
00267 for ( QStringList::ConstIterator si = thisCats.constBegin();
00268 si != thisCats.constEnd(); ++si ) {
00269 if ( !cats.contains( *si ) ) {
00270 cats.append( *si );
00271 }
00272 }
00273 }
00274 return cats;
00275 }
00276
00277 Incidence::List Calendar::incidences( const QDate &date )
00278 {
00279 return mergeIncidenceList( events( date ), todos( date ), journals( date ) );
00280 }
00281
00282 Incidence::List Calendar::incidences()
00283 {
00284 return mergeIncidenceList( events(), todos(), journals() );
00285 }
00286
00287 Incidence::List Calendar::rawIncidences()
00288 {
00289 return mergeIncidenceList( rawEvents(), rawTodos(), rawJournals() );
00290 }
00291
00292 Event::List Calendar::sortEvents( Event::List *eventList,
00293 EventSortField sortField,
00294 SortDirection sortDirection )
00295 {
00296 Event::List eventListSorted;
00297 Event::List tempList, t;
00298 Event::List alphaList;
00299 Event::List::Iterator sortIt;
00300 Event::List::Iterator eit;
00301
00302
00303
00304
00305 switch( sortField ) {
00306 case EventSortUnsorted:
00307 eventListSorted = *eventList;
00308 break;
00309
00310 case EventSortStartDate:
00311 alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
00312 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00313 if ( (*eit)->dtStart().isDateOnly() ) {
00314 tempList.append( *eit );
00315 continue;
00316 }
00317 sortIt = eventListSorted.begin();
00318 if ( sortDirection == SortDirectionAscending ) {
00319 while ( sortIt != eventListSorted.end() &&
00320 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00321 ++sortIt;
00322 }
00323 } else {
00324 while ( sortIt != eventListSorted.end() &&
00325 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00326 ++sortIt;
00327 }
00328 }
00329 eventListSorted.insert( sortIt, *eit );
00330 }
00331 if ( sortDirection == SortDirectionAscending ) {
00332
00333 tempList += eventListSorted;
00334 eventListSorted = tempList;
00335 } else {
00336
00337 eventListSorted += tempList;
00338 }
00339 break;
00340
00341 case EventSortEndDate:
00342 alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
00343 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00344 if ( (*eit)->hasEndDate() ) {
00345 sortIt = eventListSorted.begin();
00346 if ( sortDirection == SortDirectionAscending ) {
00347 while ( sortIt != eventListSorted.end() &&
00348 (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) {
00349 ++sortIt;
00350 }
00351 } else {
00352 while ( sortIt != eventListSorted.end() &&
00353 (*eit)->dtEnd() < (*sortIt)->dtEnd() ) {
00354 ++sortIt;
00355 }
00356 }
00357 } else {
00358
00359 tempList.append( *eit );
00360 }
00361 eventListSorted.insert( sortIt, *eit );
00362 }
00363 if ( sortDirection == SortDirectionAscending ) {
00364
00365 eventListSorted += tempList;
00366 } else {
00367
00368 tempList += eventListSorted;
00369 eventListSorted = tempList;
00370 }
00371 break;
00372
00373 case EventSortSummary:
00374 for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) {
00375 sortIt = eventListSorted.begin();
00376 if ( sortDirection == SortDirectionAscending ) {
00377 while ( sortIt != eventListSorted.end() &&
00378 (*eit)->summary() >= (*sortIt)->summary() ) {
00379 ++sortIt;
00380 }
00381 } else {
00382 while ( sortIt != eventListSorted.end() &&
00383 (*eit)->summary() < (*sortIt)->summary() ) {
00384 ++sortIt;
00385 }
00386 }
00387 eventListSorted.insert( sortIt, *eit );
00388 }
00389 break;
00390 }
00391
00392 return eventListSorted;
00393
00394 }
00395
00396 Event::List Calendar::events( const QDate &date,
00397 const KDateTime::Spec &timeSpec,
00398 EventSortField sortField,
00399 SortDirection sortDirection )
00400 {
00401 Event::List el = rawEventsForDate( date, timeSpec, sortField, sortDirection );
00402 d->mFilter->apply( &el );
00403 return el;
00404 }
00405
00406 Event::List Calendar::events( const KDateTime &dt )
00407 {
00408 Event::List el = rawEventsForDate( dt );
00409 d->mFilter->apply( &el );
00410 return el;
00411 }
00412
00413 Event::List Calendar::events( const QDate &start, const QDate &end,
00414 const KDateTime::Spec &timeSpec,
00415 bool inclusive )
00416 {
00417 Event::List el = rawEvents( start, end, timeSpec, inclusive );
00418 d->mFilter->apply( &el );
00419 return el;
00420 }
00421
00422 Event::List Calendar::events( EventSortField sortField,
00423 SortDirection sortDirection )
00424 {
00425 Event::List el = rawEvents( sortField, sortDirection );
00426 d->mFilter->apply( &el );
00427 return el;
00428 }
00429
00430 bool Calendar::addIncidence( Incidence *incidence )
00431 {
00432 Incidence::AddVisitor<Calendar> v( this );
00433
00434 return incidence->accept( v );
00435 }
00436
00437 bool Calendar::deleteIncidence( Incidence *incidence )
00438 {
00439 if ( beginChange( incidence ) ) {
00440 Incidence::DeleteVisitor<Calendar> v( this );
00441 bool result = incidence->accept( v );
00442 endChange( incidence );
00443 return result;
00444 } else {
00445 return false;
00446 }
00447 }
00448
00449
00450
00451
00452 Incidence *Calendar::dissociateOccurrence( Incidence *incidence,
00453 const QDate &date,
00454 const KDateTime::Spec &spec,
00455 bool single )
00456 {
00457 if ( !incidence || !incidence->recurs() ) {
00458 return 0;
00459 }
00460
00461 Incidence *newInc = incidence->clone();
00462 newInc->recreate();
00463
00464
00465
00466
00467
00468 Recurrence *recur = newInc->recurrence();
00469 if ( single ) {
00470 recur->clear();
00471 } else {
00472
00473
00474
00475 int duration = recur->duration();
00476 if ( duration > 0 ) {
00477 int doneduration = recur->durationTo( date.addDays( -1 ) );
00478 if ( doneduration >= duration ) {
00479 kDebug() << "The dissociated event already occurred more often"
00480 << "than it was supposed to ever occur. ERROR!";
00481 recur->clear();
00482 } else {
00483 recur->setDuration( duration - doneduration );
00484 }
00485 }
00486 }
00487
00488 if ( incidence->type() == "Event" ) {
00489 Event *ev = static_cast<Event *>( newInc );
00490 KDateTime start( ev->dtStart() );
00491 int daysTo = start.toTimeSpec( spec ).date().daysTo( date );
00492 ev->setDtStart( start.addDays( daysTo ) );
00493 ev->setDtEnd( ev->dtEnd().addDays( daysTo ) );
00494 } else if ( incidence->type() == "Todo" ) {
00495 Todo *td = static_cast<Todo *>( newInc );
00496 bool haveOffset = false;
00497 int daysTo = 0;
00498 if ( td->hasDueDate() ) {
00499 KDateTime due( td->dtDue() );
00500 daysTo = due.toTimeSpec( spec ).date().daysTo( date );
00501 td->setDtDue( due.addDays( daysTo ), true );
00502 haveOffset = true;
00503 }
00504 if ( td->hasStartDate() ) {
00505 KDateTime start( td->dtStart() );
00506 if ( !haveOffset ) {
00507 daysTo = start.toTimeSpec( spec ).date().daysTo( date );
00508 }
00509 td->setDtStart( start.addDays( daysTo ) );
00510 haveOffset = true;
00511 }
00512 }
00513 recur = incidence->recurrence();
00514 if ( recur ) {
00515 if ( single ) {
00516 recur->addExDate( date );
00517 } else {
00518
00519
00520 recur->setEndDate( date.addDays(-1) );
00521 }
00522 }
00523 return newInc;
00524 }
00525
00526 Incidence *Calendar::incidence( const QString &uid )
00527 {
00528 Incidence *i = event( uid );
00529 if ( i ) {
00530 return i;
00531 }
00532
00533 i = todo( uid );
00534 if ( i ) {
00535 return i;
00536 }
00537
00538 i = journal( uid );
00539 return i;
00540 }
00541
00542 Incidence::List Calendar::incidencesFromSchedulingID( const QString &sid )
00543 {
00544 Incidence::List result;
00545 const Incidence::List incidences = rawIncidences();
00546 Incidence::List::const_iterator it = incidences.begin();
00547 for ( ; it != incidences.end(); ++it ) {
00548 if ( (*it)->schedulingID() == sid ) {
00549 result.append( *it );
00550 }
00551 }
00552 return result;
00553 }
00554
00555 Incidence *Calendar::incidenceFromSchedulingID( const QString &UID )
00556 {
00557 const Incidence::List incidences = rawIncidences();
00558 Incidence::List::const_iterator it = incidences.begin();
00559 for ( ; it != incidences.end(); ++it ) {
00560 if ( (*it)->schedulingID() == UID ) {
00561
00562 return *it;
00563 }
00564 }
00565
00566 return 0;
00567 }
00568
00569 Todo::List Calendar::sortTodos( Todo::List *todoList,
00570 TodoSortField sortField,
00571 SortDirection sortDirection )
00572 {
00573 Todo::List todoListSorted;
00574 Todo::List tempList, t;
00575 Todo::List alphaList;
00576 Todo::List::Iterator sortIt;
00577 Todo::List::Iterator eit;
00578
00579
00580
00581
00582
00583
00584 switch( sortField ) {
00585 case TodoSortUnsorted:
00586 todoListSorted = *todoList;
00587 break;
00588
00589 case TodoSortStartDate:
00590 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00591 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00592 if ( (*eit)->hasStartDate() ) {
00593 sortIt = todoListSorted.begin();
00594 if ( sortDirection == SortDirectionAscending ) {
00595 while ( sortIt != todoListSorted.end() &&
00596 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00597 ++sortIt;
00598 }
00599 } else {
00600 while ( sortIt != todoListSorted.end() &&
00601 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00602 ++sortIt;
00603 }
00604 }
00605 todoListSorted.insert( sortIt, *eit );
00606 } else {
00607
00608 tempList.append( *eit );
00609 }
00610 }
00611 if ( sortDirection == SortDirectionAscending ) {
00612
00613 todoListSorted += tempList;
00614 } else {
00615
00616 tempList += todoListSorted;
00617 todoListSorted = tempList;
00618 }
00619 break;
00620
00621 case TodoSortDueDate:
00622 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00623 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00624 if ( (*eit)->hasDueDate() ) {
00625 sortIt = todoListSorted.begin();
00626 if ( sortDirection == SortDirectionAscending ) {
00627 while ( sortIt != todoListSorted.end() &&
00628 (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
00629 ++sortIt;
00630 }
00631 } else {
00632 while ( sortIt != todoListSorted.end() &&
00633 (*eit)->dtDue() < (*sortIt)->dtDue() ) {
00634 ++sortIt;
00635 }
00636 }
00637 todoListSorted.insert( sortIt, *eit );
00638 } else {
00639
00640 tempList.append( *eit );
00641 }
00642 }
00643 if ( sortDirection == SortDirectionAscending ) {
00644
00645 todoListSorted += tempList;
00646 } else {
00647
00648 tempList += todoListSorted;
00649 todoListSorted = tempList;
00650 }
00651 break;
00652
00653 case TodoSortPriority:
00654 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00655 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00656 sortIt = todoListSorted.begin();
00657 if ( sortDirection == SortDirectionAscending ) {
00658 while ( sortIt != todoListSorted.end() &&
00659 (*eit)->priority() >= (*sortIt)->priority() ) {
00660 ++sortIt;
00661 }
00662 } else {
00663 while ( sortIt != todoListSorted.end() &&
00664 (*eit)->priority() < (*sortIt)->priority() ) {
00665 ++sortIt;
00666 }
00667 }
00668 todoListSorted.insert( sortIt, *eit );
00669 }
00670 break;
00671
00672 case TodoSortPercentComplete:
00673 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00674 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00675 sortIt = todoListSorted.begin();
00676 if ( sortDirection == SortDirectionAscending ) {
00677 while ( sortIt != todoListSorted.end() &&
00678 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
00679 ++sortIt;
00680 }
00681 } else {
00682 while ( sortIt != todoListSorted.end() &&
00683 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
00684 ++sortIt;
00685 }
00686 }
00687 todoListSorted.insert( sortIt, *eit );
00688 }
00689 break;
00690
00691 case TodoSortSummary:
00692 for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
00693 sortIt = todoListSorted.begin();
00694 if ( sortDirection == SortDirectionAscending ) {
00695 while ( sortIt != todoListSorted.end() &&
00696 (*eit)->summary() >= (*sortIt)->summary() ) {
00697 ++sortIt;
00698 }
00699 } else {
00700 while ( sortIt != todoListSorted.end() &&
00701 (*eit)->summary() < (*sortIt)->summary() ) {
00702 ++sortIt;
00703 }
00704 }
00705 todoListSorted.insert( sortIt, *eit );
00706 }
00707 break;
00708 }
00709
00710 return todoListSorted;
00711 }
00712
00713 Todo::List Calendar::todos( TodoSortField sortField,
00714 SortDirection sortDirection )
00715 {
00716 Todo::List tl = rawTodos( sortField, sortDirection );
00717 d->mFilter->apply( &tl );
00718 return tl;
00719 }
00720
00721 Todo::List Calendar::todos( const QDate &date )
00722 {
00723 Todo::List el = rawTodosForDate( date );
00724 d->mFilter->apply( &el );
00725 return el;
00726 }
00727
00728 Journal::List Calendar::sortJournals( Journal::List *journalList,
00729 JournalSortField sortField,
00730 SortDirection sortDirection )
00731 {
00732 Journal::List journalListSorted;
00733 Journal::List::Iterator sortIt;
00734 Journal::List::Iterator eit;
00735
00736 switch( sortField ) {
00737 case JournalSortUnsorted:
00738 journalListSorted = *journalList;
00739 break;
00740
00741 case JournalSortDate:
00742 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00743 sortIt = journalListSorted.begin();
00744 if ( sortDirection == SortDirectionAscending ) {
00745 while ( sortIt != journalListSorted.end() &&
00746 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00747 ++sortIt;
00748 }
00749 } else {
00750 while ( sortIt != journalListSorted.end() &&
00751 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00752 ++sortIt;
00753 }
00754 }
00755 journalListSorted.insert( sortIt, *eit );
00756 }
00757 break;
00758
00759 case JournalSortSummary:
00760 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00761 sortIt = journalListSorted.begin();
00762 if ( sortDirection == SortDirectionAscending ) {
00763 while ( sortIt != journalListSorted.end() &&
00764 (*eit)->summary() >= (*sortIt)->summary() ) {
00765 ++sortIt;
00766 }
00767 } else {
00768 while ( sortIt != journalListSorted.end() &&
00769 (*eit)->summary() < (*sortIt)->summary() ) {
00770 ++sortIt;
00771 }
00772 }
00773 journalListSorted.insert( sortIt, *eit );
00774 }
00775 break;
00776 }
00777
00778 return journalListSorted;
00779 }
00780
00781 Journal::List Calendar::journals( JournalSortField sortField,
00782 SortDirection sortDirection )
00783 {
00784 Journal::List jl = rawJournals( sortField, sortDirection );
00785 d->mFilter->apply( &jl );
00786 return jl;
00787 }
00788
00789 Journal::List Calendar::journals( const QDate &date )
00790 {
00791 Journal::List el = rawJournalsForDate( date );
00792 d->mFilter->apply( &el );
00793 return el;
00794 }
00795
00796 void Calendar::beginBatchAdding()
00797 {
00798 emit batchAddingBegins();
00799 }
00800
00801 void Calendar::endBatchAdding()
00802 {
00803 emit batchAddingEnds();
00804 }
00805
00806
00807
00808 void Calendar::setupRelations( Incidence *forincidence )
00809 {
00810 if ( !forincidence ) {
00811 return;
00812 }
00813
00814 QString uid = forincidence->uid();
00815
00816
00817 QList<Incidence*> l = d->mOrphans.values( uid );
00818 d->mOrphans.remove( uid );
00819 for ( int i = 0, end = l.count(); i < end; ++i ) {
00820 l[i]->setRelatedTo( forincidence );
00821 forincidence->addRelation( l[i] );
00822 d->mOrphanUids.remove( l[i]->uid() );
00823 }
00824
00825
00826 if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) {
00827
00828
00829 Incidence *parent = incidence( forincidence->relatedToUid() );
00830 if ( parent ) {
00831
00832 forincidence->setRelatedTo( parent );
00833 parent->addRelation( forincidence );
00834 } else {
00835
00836
00837
00838
00839 d->mOrphans.insert( forincidence->relatedToUid(), forincidence );
00840 d->mOrphanUids.insert( forincidence->uid(), forincidence );
00841 }
00842 }
00843 }
00844
00845
00846 void Calendar::removeRelations( Incidence *incidence )
00847 {
00848 if ( !incidence ) {
00849 kDebug() << "Warning: incidence is 0";
00850 return;
00851 }
00852
00853 QString uid = incidence->uid();
00854 foreach ( Incidence *i, incidence->relations() ) {
00855 if ( !d->mOrphanUids.contains( i->uid() ) ) {
00856 d->mOrphans.insert( uid, i );
00857 d->mOrphanUids.insert( i->uid(), i );
00858 i->setRelatedTo( 0 );
00859 i->setRelatedToUid( uid );
00860 }
00861 }
00862
00863
00864 if ( incidence->relatedTo() ) {
00865 incidence->relatedTo()->removeRelation( incidence );
00866 }
00867
00868
00869 if ( d->mOrphanUids.remove( uid ) ) {
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879 QStringList relatedToUids;
00880
00881
00882
00883 relatedToUids << incidence->relatedToUid();
00884 for ( QMultiHash<QString, Incidence*>::Iterator it = d->mOrphans.begin();
00885 it != d->mOrphans.end(); ++it ) {
00886 if ( it.value()->uid() == uid ) {
00887 relatedToUids << it.key();
00888 }
00889 }
00890
00891
00892 for ( QStringList::const_iterator uidit = relatedToUids.constBegin();
00893 uidit != relatedToUids.constEnd(); ++uidit ) {
00894 Incidence::List tempList;
00895
00896 QList<Incidence*> l = d->mOrphans.values( *uidit );
00897 d->mOrphans.remove( *uidit );
00898 foreach ( Incidence *i, l ) {
00899 if ( i != incidence ) {
00900 tempList.append( i );
00901 }
00902 }
00903
00904 for ( Incidence::List::Iterator incit = tempList.begin();
00905 incit != tempList.end(); ++incit ) {
00906 d->mOrphans.insert( *uidit, *incit );
00907 }
00908 }
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 incidence->setRelatedTo( 0 );
00922 }
00923
00924 void Calendar::CalendarObserver::calendarModified( bool modified, Calendar *calendar )
00925 {
00926 Q_UNUSED( modified );
00927 Q_UNUSED( calendar );
00928 }
00929
00930 void Calendar::CalendarObserver::calendarIncidenceAdded( Incidence *incidence )
00931 {
00932 Q_UNUSED( incidence );
00933 }
00934
00935 void Calendar::CalendarObserver::calendarIncidenceChanged( Incidence *incidence )
00936 {
00937 Q_UNUSED( incidence );
00938 }
00939
00940 void Calendar::CalendarObserver::calendarIncidenceDeleted( Incidence *incidence )
00941 {
00942 Q_UNUSED( incidence );
00943 }
00944
00945 void Calendar::registerObserver( CalendarObserver *observer )
00946 {
00947 if ( !d->mObservers.contains( observer ) ) {
00948 d->mObservers.append( observer );
00949 }
00950 d->mNewObserver = true;
00951 }
00952
00953 void Calendar::unregisterObserver( CalendarObserver *observer )
00954 {
00955 d->mObservers.removeAll( observer );
00956 }
00957
00958 bool Calendar::isSaving()
00959 {
00960 return false;
00961 }
00962
00963 void Calendar::setModified( bool modified )
00964 {
00965 if ( modified != d->mModified || d->mNewObserver ) {
00966 d->mNewObserver = false;
00967 foreach ( CalendarObserver *observer, d->mObservers ) {
00968 observer->calendarModified( modified, this );
00969 }
00970 d->mModified = modified;
00971 }
00972 }
00973
00974 bool Calendar::isModified() const
00975 {
00976 return d->mModified;
00977 }
00978
00979 void Calendar::incidenceUpdated( IncidenceBase *incidence )
00980 {
00981 incidence->setLastModified( KDateTime::currentUtcDateTime() );
00982
00983
00984
00985
00986
00987 notifyIncidenceChanged( static_cast<Incidence *>( incidence ) );
00988
00989 setModified( true );
00990 }
00991
00992 void Calendar::doSetTimeSpec( const KDateTime::Spec &timeSpec )
00993 {
00994 Q_UNUSED( timeSpec );
00995 }
00996
00997 void Calendar::notifyIncidenceAdded( Incidence *i )
00998 {
00999 if ( !d->mObserversEnabled ) {
01000 return;
01001 }
01002
01003 foreach ( CalendarObserver *observer, d->mObservers ) {
01004 observer->calendarIncidenceAdded( i );
01005 }
01006 }
01007
01008 void Calendar::notifyIncidenceChanged( Incidence *i )
01009 {
01010 if ( !d->mObserversEnabled ) {
01011 return;
01012 }
01013
01014 foreach ( CalendarObserver *observer, d->mObservers ) {
01015 observer->calendarIncidenceChanged( i );
01016 }
01017 }
01018
01019 void Calendar::notifyIncidenceDeleted( Incidence *i )
01020 {
01021 if ( !d->mObserversEnabled ) {
01022 return;
01023 }
01024
01025 foreach ( CalendarObserver *observer, d->mObservers ) {
01026 observer->calendarIncidenceDeleted( i );
01027 }
01028 }
01029
01030 void Calendar::customPropertyUpdated()
01031 {
01032 setModified( true );
01033 }
01034
01035 void Calendar::setProductId( const QString &id )
01036 {
01037 d->mProductId = id;
01038 }
01039
01040 QString Calendar::productId() const
01041 {
01042 return d->mProductId;
01043 }
01044
01045 Incidence::List Calendar::mergeIncidenceList( const Event::List &events,
01046 const Todo::List &todos,
01047 const Journal::List &journals )
01048 {
01049 Incidence::List incidences;
01050
01051 int i, end;
01052 for ( i = 0, end = events.count(); i < end; ++i ) {
01053 incidences.append( events[i] );
01054 }
01055
01056 for ( i = 0, end = todos.count(); i < end; ++i ) {
01057 incidences.append( todos[i] );
01058 }
01059
01060 for ( i = 0, end = journals.count(); i < end; ++i ) {
01061 incidences.append( journals[i] );
01062 }
01063
01064 return incidences;
01065 }
01066
01067 bool Calendar::beginChange( Incidence *incidence )
01068 {
01069 Q_UNUSED( incidence );
01070 return true;
01071 }
01072
01073 bool Calendar::endChange( Incidence *incidence )
01074 {
01075 Q_UNUSED( incidence );
01076 return true;
01077 }
01078
01079 void Calendar::setObserversEnabled( bool enabled )
01080 {
01081 d->mObserversEnabled = enabled;
01082 }
01083
01084 void Calendar::appendAlarms( Alarm::List &alarms, Incidence *incidence,
01085 const KDateTime &from, const KDateTime &to )
01086 {
01087 KDateTime preTime = from.addSecs(-1);
01088
01089 Alarm::List alarmlist = incidence->alarms();
01090 for ( int i = 0, iend = alarmlist.count(); i < iend; ++i ) {
01091 if ( alarmlist[i]->enabled() ) {
01092 KDateTime dt = alarmlist[i]->nextRepetition( preTime );
01093 if ( dt.isValid() && dt <= to ) {
01094 kDebug() << incidence->summary() << "':" << dt.toString();
01095 alarms.append( alarmlist[i] );
01096 }
01097 }
01098 }
01099 }
01100
01101 void Calendar::appendRecurringAlarms( Alarm::List &alarms,
01102 Incidence *incidence,
01103 const KDateTime &from,
01104 const KDateTime &to )
01105 {
01106 KDateTime dt;
01107 bool endOffsetValid = false;
01108 Duration endOffset( 0 );
01109 Duration period( from, to );
01110
01111 Alarm::List alarmlist = incidence->alarms();
01112 for ( int i = 0, iend = alarmlist.count(); i < iend; ++i ) {
01113 Alarm *a = alarmlist[i];
01114 if ( a->enabled() ) {
01115 if ( a->hasTime() ) {
01116
01117 dt = a->nextRepetition( from.addSecs(-1) );
01118 if ( !dt.isValid() || dt > to ) {
01119 continue;
01120 }
01121 } else {
01122
01123
01124
01125 Duration offset( 0 );
01126 if ( a->hasStartOffset() ) {
01127 offset = a->startOffset();
01128 } else if ( a->hasEndOffset() ) {
01129 offset = a->endOffset();
01130 if ( !endOffsetValid ) {
01131 endOffset = Duration( incidence->dtStart(), incidence->dtEnd() );
01132 endOffsetValid = true;
01133 }
01134 }
01135
01136
01137 KDateTime alarmStart =
01138 offset.end( a->hasEndOffset() ? incidence->dtEnd() : incidence->dtStart() );
01139
01140 if ( alarmStart > to ) {
01141 continue;
01142 }
01143 KDateTime baseStart = incidence->dtStart();
01144 if ( from > alarmStart ) {
01145 alarmStart = from;
01146 baseStart = (-offset).end( (-endOffset).end( alarmStart ) );
01147 }
01148
01149
01150
01151 dt = incidence->recurrence()->getNextDateTime( baseStart.addSecs(-1) );
01152 if ( !dt.isValid() ||
01153 ( dt = endOffset.end( offset.end( dt ) ) ) > to )
01154 {
01155
01156 if ( !a->repeatCount() ) {
01157 continue;
01158 }
01159
01160
01161
01162 bool found = false;
01163 Duration alarmDuration = a->duration();
01164 for ( KDateTime base = baseStart;
01165 ( dt = incidence->recurrence()->getPreviousDateTime( base ) ).isValid();
01166 base = dt ) {
01167 if ( a->duration().end( dt ) < base ) {
01168 break;
01169 }
01170
01171
01172
01173 int snooze = a->snoozeTime().value();
01174 if ( a->snoozeTime().isDaily() ) {
01175 Duration toFromDuration( dt, base );
01176 int toFrom = toFromDuration.asDays();
01177 if ( a->snoozeTime().end( from ) <= to ||
01178 ( toFromDuration.isDaily() && toFrom % snooze == 0 ) ||
01179 ( toFrom / snooze + 1 ) * snooze <= toFrom + period.asDays() ) {
01180 found = true;
01181 #ifndef NDEBUG
01182
01183 dt = offset.end( dt ).addDays( ( ( toFrom - 1 ) / snooze + 1 ) * snooze );
01184 #endif
01185 break;
01186 }
01187 } else {
01188 int toFrom = dt.secsTo( base );
01189 if ( period.asSeconds() >= snooze ||
01190 toFrom % snooze == 0 ||
01191 ( toFrom / snooze + 1 ) * snooze <= toFrom + period.asSeconds() )
01192 {
01193 found = true;
01194 #ifndef NDEBUG
01195
01196 dt = offset.end( dt ).addSecs( ( ( toFrom - 1 ) / snooze + 1 ) * snooze );
01197 #endif
01198 break;
01199 }
01200 }
01201 }
01202 if ( !found ) {
01203 continue;
01204 }
01205 }
01206 }
01207 kDebug() << incidence->summary() << "':" << dt.toString();
01208 alarms.append( a );
01209 }
01210 }
01211 }
01212
01213 #include "calendar.moc"