libkcal
calendar.cpp
Go to the documentation of this file.
00001 /* 00002 This file is part of libkcal. 00003 00004 Copyright (c) 1998 Preston Brown <pbrown@kde.org> 00005 Copyright (c) 2000-2004 Cornelius Schumacher <schumacher@kde.org> 00006 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com> 00007 00008 This library is free software; you can redistribute it and/or 00009 modify it under the terms of the GNU Library General Public 00010 License as published by the Free Software Foundation; either 00011 version 2 of the License, or (at your option) any later version. 00012 00013 This library is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 Library General Public License for more details. 00017 00018 You should have received a copy of the GNU Library General Public License 00019 along with this library; see the file COPYING.LIB. If not, write to 00020 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00021 Boston, MA 02110-1301, USA. 00022 */ 00031 #include <stdlib.h> 00032 00033 #include <kdebug.h> 00034 #include <klocale.h> 00035 00036 #include "exceptions.h" 00037 #include "calfilter.h" 00038 00039 #include "calendar.h" 00040 00041 using namespace KCal; 00042 00043 Calendar::Calendar( const TQString &timeZoneId ) 00044 { 00045 mTimeZoneId = timeZoneId; 00046 mLocalTime = false; 00047 00048 init(); 00049 } 00050 00051 void Calendar::init() 00052 { 00053 mException = 0; 00054 mNewObserver = false; 00055 mObserversEnabled = true; 00056 00057 mModified = false; 00058 00059 // Setup default filter, which does nothing 00060 mDefaultFilter = new CalFilter; 00061 mFilter = mDefaultFilter; 00062 mFilter->setEnabled( false ); 00063 00064 // user information... 00065 setOwner( Person( i18n( "Unknown Name" ), i18n( "unknown@nowhere" ) ) ); 00066 } 00067 00068 Calendar::~Calendar() 00069 { 00070 clearException(); 00071 delete mDefaultFilter; 00072 } 00073 00074 void Calendar::clearException() 00075 { 00076 delete mException; 00077 mException = 0; 00078 } 00079 00080 ErrorFormat *Calendar::exception() const 00081 { 00082 return mException; 00083 } 00084 00085 void Calendar::setException( ErrorFormat *e ) 00086 { 00087 delete mException; 00088 mException = e; 00089 } 00090 00091 const Person &Calendar::getOwner() const 00092 { 00093 return mOwner; 00094 } 00095 00096 void Calendar::setOwner( const Person &owner ) 00097 { 00098 mOwner = owner; 00099 00100 setModified( true ); 00101 } 00102 00103 void Calendar::setTimeZoneId( const TQString &timeZoneId ) 00104 { 00105 mTimeZoneId = timeZoneId; 00106 mLocalTime = false; 00107 00108 setModified( true ); 00109 doSetTimeZoneId( timeZoneId ); 00110 } 00111 00112 TQString Calendar::timeZoneId() const 00113 { 00114 return mTimeZoneId; 00115 } 00116 00117 void Calendar::setLocalTime() 00118 { 00119 mLocalTime = true; 00120 mTimeZoneId = ""; 00121 00122 setModified( true ); 00123 } 00124 00125 bool Calendar::isLocalTime() const 00126 { 00127 return mLocalTime; 00128 } 00129 00130 void Calendar::setFilter( CalFilter *filter ) 00131 { 00132 if ( filter ) { 00133 mFilter = filter; 00134 } else { 00135 mFilter = mDefaultFilter; 00136 } 00137 } 00138 00139 CalFilter *Calendar::filter() 00140 { 00141 return mFilter; 00142 } 00143 00144 void Calendar::beginBatchAdding() 00145 { 00146 emit batchAddingBegins(); 00147 } 00148 00149 void Calendar::endBatchAdding() 00150 { 00151 emit batchAddingEnds(); 00152 } 00153 00154 TQStringList Calendar::categories() 00155 { 00156 Incidence::List rawInc( rawIncidences() ); 00157 TQStringList cats, thisCats; 00158 // @TODO: For now just iterate over all incidences. In the future, 00159 // the list of categories should be built when reading the file. 00160 for ( Incidence::List::ConstIterator i = rawInc.constBegin(); 00161 i != rawInc.constEnd(); ++i ) { 00162 thisCats = (*i)->categories(); 00163 for ( TQStringList::ConstIterator si = thisCats.constBegin(); 00164 si != thisCats.constEnd(); ++si ) { 00165 if ( cats.find( *si ) == cats.end() ) { 00166 cats.append( *si ); 00167 } 00168 } 00169 } 00170 return cats; 00171 } 00172 00173 Incidence::List Calendar::incidences( const TQDate &date ) 00174 { 00175 return mergeIncidenceList( events( date ), todos( date ), journals( date ) ); 00176 } 00177 00178 Incidence::List Calendar::incidences() 00179 { 00180 return mergeIncidenceList( events(), todos(), journals() ); 00181 } 00182 00183 Incidence::List Calendar::rawIncidences() 00184 { 00185 return mergeIncidenceList( rawEvents(), rawTodos(), rawJournals() ); 00186 } 00187 00188 Event::List Calendar::sortEvents( Event::List *eventList, 00189 EventSortField sortField, 00190 SortDirection sortDirection ) 00191 { 00192 Event::List eventListSorted; 00193 Event::List tempList; 00194 Event::List alphaList; 00195 Event::List::Iterator sortIt; 00196 Event::List::Iterator eit; 00197 00198 // Notice we alphabetically presort Summaries first. 00199 // We do this so comparison "ties" stay in a nice order. 00200 00201 switch( sortField ) { 00202 case EventSortUnsorted: 00203 eventListSorted = *eventList; 00204 break; 00205 00206 case EventSortStartDate: 00207 alphaList = sortEvents( eventList, EventSortSummary, sortDirection ); 00208 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00209 if ( (*eit)->doesFloat() ) { 00210 tempList.append( *eit ); 00211 continue; 00212 } 00213 sortIt = eventListSorted.begin(); 00214 if ( sortDirection == SortDirectionAscending ) { 00215 while ( sortIt != eventListSorted.end() && 00216 (*eit)->dtStart() >= (*sortIt)->dtStart() ) { 00217 ++sortIt; 00218 } 00219 } else { 00220 while ( sortIt != eventListSorted.end() && 00221 (*eit)->dtStart() < (*sortIt)->dtStart() ) { 00222 ++sortIt; 00223 } 00224 } 00225 eventListSorted.insert( sortIt, *eit ); 00226 } 00227 if ( sortDirection == SortDirectionAscending ) { 00228 // Prepend the list of all-day Events 00229 tempList += eventListSorted; 00230 eventListSorted = tempList; 00231 } else { 00232 // Append the list of all-day Events 00233 eventListSorted += tempList; 00234 } 00235 break; 00236 00237 case EventSortEndDate: 00238 alphaList = sortEvents( eventList, EventSortSummary, sortDirection ); 00239 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00240 if ( (*eit)->hasEndDate() ) { 00241 sortIt = eventListSorted.begin(); 00242 if ( sortDirection == SortDirectionAscending ) { 00243 while ( sortIt != eventListSorted.end() && 00244 (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) { 00245 ++sortIt; 00246 } 00247 } else { 00248 while ( sortIt != eventListSorted.end() && 00249 (*eit)->dtEnd() < (*sortIt)->dtEnd() ) { 00250 ++sortIt; 00251 } 00252 } 00253 } else { 00254 // Keep a list of the Events without End DateTimes 00255 tempList.append( *eit ); 00256 } 00257 eventListSorted.insert( sortIt, *eit ); 00258 } 00259 if ( sortDirection == SortDirectionAscending ) { 00260 // Append the list of Events without End DateTimes 00261 eventListSorted += tempList; 00262 } else { 00263 // Prepend the list of Events without End DateTimes 00264 tempList += eventListSorted; 00265 eventListSorted = tempList; 00266 } 00267 break; 00268 00269 case EventSortSummary: 00270 for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) { 00271 sortIt = eventListSorted.begin(); 00272 if ( sortDirection == SortDirectionAscending ) { 00273 while ( sortIt != eventListSorted.end() && 00274 (*eit)->summary() >= (*sortIt)->summary() ) { 00275 ++sortIt; 00276 } 00277 } else { 00278 while ( sortIt != eventListSorted.end() && 00279 (*eit)->summary() < (*sortIt)->summary() ) { 00280 ++sortIt; 00281 } 00282 } 00283 eventListSorted.insert( sortIt, *eit ); 00284 } 00285 break; 00286 } 00287 00288 return eventListSorted; 00289 } 00290 00291 Event::List Calendar::sortEventsForDate( Event::List *eventList, 00292 const TQDate &date, 00293 EventSortField sortField, 00294 SortDirection sortDirection ) 00295 { 00296 Event::List eventListSorted; 00297 Event::List tempList; 00298 Event::List alphaList; 00299 Event::List::Iterator sortIt; 00300 Event::List::Iterator eit; 00301 00302 switch( sortField ) { 00303 case EventSortStartDate: 00304 alphaList = sortEvents( eventList, EventSortSummary, sortDirection ); 00305 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00306 if ( (*eit)->doesFloat() ) { 00307 tempList.append( *eit ); 00308 continue; 00309 } 00310 sortIt = eventListSorted.begin(); 00311 if ( sortDirection == SortDirectionAscending ) { 00312 while ( sortIt != eventListSorted.end() ) { 00313 if ( !(*eit)->doesRecur() ) { 00314 if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) { 00315 ++sortIt; 00316 } else { 00317 break; 00318 } 00319 } else { 00320 if ( (*eit)->recursOn( date ) ) { 00321 if ( (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) { 00322 ++sortIt; 00323 } else { 00324 break; 00325 } 00326 } else { 00327 ++sortIt; 00328 } 00329 } 00330 } 00331 } else { // descending 00332 while ( sortIt != eventListSorted.end() ) { 00333 if ( !(*eit)->doesRecur() ) { 00334 if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) { 00335 ++sortIt; 00336 } else { 00337 break; 00338 } 00339 } else { 00340 if ( (*eit)->recursOn( date ) ) { 00341 if ( (*eit)->dtStart().time() < (*sortIt)->dtStart().time() ) { 00342 ++sortIt; 00343 } else { 00344 break; 00345 } 00346 } else { 00347 ++sortIt; 00348 } 00349 } 00350 } 00351 } 00352 eventListSorted.insert( sortIt, *eit ); 00353 } 00354 if ( sortDirection == SortDirectionAscending ) { 00355 // Prepend the list of all-day Events 00356 tempList += eventListSorted; 00357 eventListSorted = tempList; 00358 } else { 00359 // Append the list of all-day Events 00360 eventListSorted += tempList; 00361 } 00362 break; 00363 00364 case EventSortEndDate: 00365 alphaList = sortEvents( eventList, EventSortSummary, sortDirection ); 00366 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00367 if ( (*eit)->hasEndDate() ) { 00368 sortIt = eventListSorted.begin(); 00369 if ( sortDirection == SortDirectionAscending ) { 00370 while ( sortIt != eventListSorted.end() ) { 00371 if ( !(*eit)->doesRecur() ) { 00372 if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) { 00373 ++sortIt; 00374 } else { 00375 break; 00376 } 00377 } else { 00378 if ( (*eit)->recursOn( date ) ) { 00379 if ( (*eit)->dtEnd().time() >= (*sortIt)->dtEnd().time() ) { 00380 ++sortIt; 00381 } else { 00382 break; 00383 } 00384 } else { 00385 ++sortIt; 00386 } 00387 } 00388 } 00389 } else { // descending 00390 while ( sortIt != eventListSorted.end() ) { 00391 if ( !(*eit)->doesRecur() ) { 00392 if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) { 00393 ++sortIt; 00394 } else { 00395 break; 00396 } 00397 } else { 00398 if ( (*eit)->recursOn( date ) ) { 00399 if ( (*eit)->dtEnd().time() < (*sortIt)->dtEnd().time() ) { 00400 ++sortIt; 00401 } else { 00402 break; 00403 } 00404 } else { 00405 ++sortIt; 00406 } 00407 } 00408 } 00409 } 00410 } else { 00411 // Keep a list of the Events without End DateTimes 00412 tempList.append( *eit ); 00413 } 00414 eventListSorted.insert( sortIt, *eit ); 00415 } 00416 if ( sortDirection == SortDirectionAscending ) { 00417 // Prepend the list of Events without End DateTimes 00418 tempList += eventListSorted; 00419 eventListSorted = tempList; 00420 } else { 00421 // Append the list of Events without End DateTimes 00422 eventListSorted += tempList; 00423 } 00424 break; 00425 00426 default: 00427 eventListSorted = sortEvents( eventList, sortField, sortDirection ); 00428 break; 00429 } 00430 00431 return eventListSorted; 00432 } 00433 00434 Event::List Calendar::events( const TQDate &date, 00435 EventSortField sortField, 00436 SortDirection sortDirection ) 00437 { 00438 Event::List el = rawEventsForDate( date, sortField, sortDirection ); 00439 mFilter->apply( &el ); 00440 return el; 00441 } 00442 00443 Event::List Calendar::events( const TQDateTime &qdt ) 00444 { 00445 Event::List el = rawEventsForDate( qdt ); 00446 mFilter->apply( &el ); 00447 return el; 00448 } 00449 00450 Event::List Calendar::events( const TQDate &start, const TQDate &end, 00451 bool inclusive) 00452 { 00453 Event::List el = rawEvents( start, end, inclusive ); 00454 mFilter->apply( &el ); 00455 return el; 00456 } 00457 00458 Event::List Calendar::events( EventSortField sortField, 00459 SortDirection sortDirection ) 00460 { 00461 Event::List el = rawEvents( sortField, sortDirection ); 00462 mFilter->apply( &el ); 00463 return el; 00464 } 00465 00466 bool Calendar::addIncidence( Incidence *incidence ) 00467 { 00468 Incidence::AddVisitor<Calendar> v( this ); 00469 00470 return incidence->accept(v); 00471 } 00472 00473 bool Calendar::deleteIncidence( Incidence *incidence ) 00474 { 00475 if ( beginChange( incidence ) ) { 00476 if (incidence->hasRecurrenceID()) { 00477 // Delete this event's UID from the parent's list of children 00478 Incidence *parentIncidence; 00479 IncidenceList il = incidence->childIncidences(); 00480 IncidenceListIterator it; 00481 it = il.begin(); 00482 parentIncidence = this->incidence(*it); 00483 parentIncidence->deleteChildIncidence(incidence->uid()); 00484 } 00485 else { 00486 // Delete all children as well 00487 IncidenceList il = incidence->childIncidences(); 00488 IncidenceListIterator it; 00489 for ( it = il.begin(); it != il.end(); ++it ) { 00490 deleteIncidence( this->incidence(*it) ); 00491 // Avoid a crash, reset the iterator every time the list is modified 00492 it = il.begin(); 00493 } 00494 } 00495 Incidence::DeleteVisitor<Calendar> v( this ); 00496 bool result = incidence->accept( v ); 00497 endChange( incidence ); 00498 return result; 00499 } else 00500 return false; 00501 } 00502 00506 Incidence *Calendar::dissociateOccurrence( Incidence *incidence, TQDate date, 00507 bool single ) 00508 { 00509 if ( !incidence || !incidence->doesRecur() ) 00510 return 0; 00511 00512 Incidence *newInc = incidence->clone(); 00513 newInc->recreate(); 00514 newInc->setHasRecurrenceID(false); 00515 // newInc->setRecurrenceID(TQString()); 00516 newInc->setRelatedTo( incidence ); 00517 Recurrence *recur = newInc->recurrence(); 00518 if ( single ) { 00519 recur->clear(); 00520 } else { 00521 // Adjust the recurrence for the future incidences. In particular 00522 // adjust the "end after n occurrences" rules! "No end date" and "end by ..." 00523 // don't need to be modified. 00524 int duration = recur->duration(); 00525 if ( duration > 0 ) { 00526 int doneduration = recur->durationTo( date.addDays(-1) ); 00527 if ( doneduration >= duration ) { 00528 kdDebug(5850) << "The dissociated event already occurred more often " 00529 << "than it was supposed to ever occur. ERROR!" << endl; 00530 recur->clear(); 00531 } else { 00532 recur->setDuration( duration - doneduration ); 00533 } 00534 } 00535 } 00536 // Adjust the date of the incidence 00537 if ( incidence->type() == "Event" ) { 00538 Event *ev = static_cast<Event *>( newInc ); 00539 TQDateTime start( ev->dtStart() ); 00540 int daysTo = start.date().daysTo( date ); 00541 ev->setDtStart( start.addDays( daysTo ) ); 00542 ev->setDtEnd( ev->dtEnd().addDays( daysTo ) ); 00543 } else if ( incidence->type() == "Todo" ) { 00544 Todo *td = static_cast<Todo *>( newInc ); 00545 bool haveOffset = false; 00546 int daysTo = 0; 00547 if ( td->hasDueDate() ) { 00548 TQDateTime due( td->dtDue() ); 00549 daysTo = due.date().daysTo( date ); 00550 td->setDtDue( due.addDays( daysTo ), true ); 00551 haveOffset = true; 00552 } 00553 if ( td->hasStartDate() ) { 00554 TQDateTime start( td->dtStart() ); 00555 if ( !haveOffset ) 00556 daysTo = start.date().daysTo( date ); 00557 td->setDtStart( start.addDays( daysTo ) ); 00558 haveOffset = true; 00559 } 00560 } 00561 recur = incidence->recurrence(); 00562 if ( recur ) { 00563 if ( single ) { 00564 recur->addExDate( date ); 00565 } else { 00566 // Make sure the recurrence of the past events ends 00567 // at the corresponding day 00568 recur->setEndDate( date.addDays(-1) ); 00569 } 00570 } 00571 return newInc; 00572 } 00573 00574 Incidence *Calendar::incidence( const TQString &uid ) 00575 { 00576 Incidence *i = event( uid ); 00577 if ( i ) 00578 return i; 00579 i = todo( uid ); 00580 if ( i ) 00581 return i; 00582 i = journal( uid ); 00583 return i; 00584 } 00585 00586 Incidence::List Calendar::incidencesFromSchedulingID( const TQString &UID ) 00587 { 00588 Incidence::List result; 00589 Incidence::List incidences = rawIncidences(); 00590 Incidence::List::iterator it = incidences.begin(); 00591 for ( ; it != incidences.end(); ++it ) 00592 if ( (*it)->schedulingID() == UID ) 00593 result.append( *it ); 00594 return result; 00595 } 00596 00597 Incidence *Calendar::incidenceFromSchedulingID( const TQString &UID ) 00598 { 00599 Incidence::List incidences = rawIncidences(); 00600 Incidence::List::iterator it = incidences.begin(); 00601 for ( ; it != incidences.end(); ++it ) 00602 if ( (*it)->schedulingID() == UID ) 00603 // Touchdown, and the crowd goes wild 00604 return *it; 00605 // Not found 00606 return 0; 00607 } 00608 00609 Todo::List Calendar::sortTodos( Todo::List *todoList, 00610 TodoSortField sortField, 00611 SortDirection sortDirection ) 00612 { 00613 Todo::List todoListSorted; 00614 Todo::List tempList, t; 00615 Todo::List alphaList; 00616 Todo::List::Iterator sortIt; 00617 Todo::List::Iterator eit; 00618 00619 // Notice we alphabetically presort Summaries first. 00620 // We do this so comparison "ties" stay in a nice order. 00621 00622 // Note that Todos may not have Start DateTimes nor due DateTimes. 00623 00624 switch( sortField ) { 00625 case TodoSortUnsorted: 00626 todoListSorted = *todoList; 00627 break; 00628 00629 case TodoSortStartDate: 00630 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00631 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00632 if ( (*eit)->hasStartDate() ) { 00633 sortIt = todoListSorted.begin(); 00634 if ( sortDirection == SortDirectionAscending ) { 00635 while ( sortIt != todoListSorted.end() && 00636 (*eit)->dtStart() >= (*sortIt)->dtStart() ) { 00637 ++sortIt; 00638 } 00639 } else { 00640 while ( sortIt != todoListSorted.end() && 00641 (*eit)->dtStart() < (*sortIt)->dtStart() ) { 00642 ++sortIt; 00643 } 00644 } 00645 todoListSorted.insert( sortIt, *eit ); 00646 } else { 00647 // Keep a list of the Todos without Start DateTimes 00648 tempList.append( *eit ); 00649 } 00650 } 00651 if ( sortDirection == SortDirectionAscending ) { 00652 // Append the list of Todos without Start DateTimes 00653 todoListSorted += tempList; 00654 } else { 00655 // Prepend the list of Todos without Start DateTimes 00656 tempList += todoListSorted; 00657 todoListSorted = tempList; 00658 } 00659 break; 00660 00661 case TodoSortDueDate: 00662 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00663 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00664 if ( (*eit)->hasDueDate() ) { 00665 sortIt = todoListSorted.begin(); 00666 if ( sortDirection == SortDirectionAscending ) { 00667 while ( sortIt != todoListSorted.end() && 00668 (*eit)->dtDue() >= (*sortIt)->dtDue() ) { 00669 ++sortIt; 00670 } 00671 } else { 00672 while ( sortIt != todoListSorted.end() && 00673 (*eit)->dtDue() < (*sortIt)->dtDue() ) { 00674 ++sortIt; 00675 } 00676 } 00677 todoListSorted.insert( sortIt, *eit ); 00678 } else { 00679 // Keep a list of the Todos without Due DateTimes 00680 tempList.append( *eit ); 00681 } 00682 } 00683 if ( sortDirection == SortDirectionAscending ) { 00684 // Append the list of Todos without Due DateTimes 00685 todoListSorted += tempList; 00686 } else { 00687 // Prepend the list of Todos without Due DateTimes 00688 tempList += todoListSorted; 00689 todoListSorted = tempList; 00690 } 00691 break; 00692 00693 case TodoSortPriority: 00694 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00695 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00696 sortIt = todoListSorted.begin(); 00697 if ( sortDirection == SortDirectionAscending ) { 00698 while ( sortIt != todoListSorted.end() && 00699 (*eit)->priority() >= (*sortIt)->priority() ) { 00700 ++sortIt; 00701 } 00702 } else { 00703 while ( sortIt != todoListSorted.end() && 00704 (*eit)->priority() < (*sortIt)->priority() ) { 00705 ++sortIt; 00706 } 00707 } 00708 todoListSorted.insert( sortIt, *eit ); 00709 } 00710 break; 00711 00712 case TodoSortPercentComplete: 00713 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00714 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00715 sortIt = todoListSorted.begin(); 00716 if ( sortDirection == SortDirectionAscending ) { 00717 while ( sortIt != todoListSorted.end() && 00718 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) { 00719 ++sortIt; 00720 } 00721 } else { 00722 while ( sortIt != todoListSorted.end() && 00723 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) { 00724 ++sortIt; 00725 } 00726 } 00727 todoListSorted.insert( sortIt, *eit ); 00728 } 00729 break; 00730 00731 case TodoSortSummary: 00732 for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) { 00733 sortIt = todoListSorted.begin(); 00734 if ( sortDirection == SortDirectionAscending ) { 00735 while ( sortIt != todoListSorted.end() && 00736 (*eit)->summary() >= (*sortIt)->summary() ) { 00737 ++sortIt; 00738 } 00739 } else { 00740 while ( sortIt != todoListSorted.end() && 00741 (*eit)->summary() < (*sortIt)->summary() ) { 00742 ++sortIt; 00743 } 00744 } 00745 todoListSorted.insert( sortIt, *eit ); 00746 } 00747 break; 00748 } 00749 00750 return todoListSorted; 00751 } 00752 00753 Todo::List Calendar::todos( TodoSortField sortField, 00754 SortDirection sortDirection ) 00755 { 00756 Todo::List tl = rawTodos( sortField, sortDirection ); 00757 mFilter->apply( &tl ); 00758 return tl; 00759 } 00760 00761 Todo::List Calendar::todos( const TQDate &date ) 00762 { 00763 Todo::List el = rawTodosForDate( date ); 00764 mFilter->apply( &el ); 00765 return el; 00766 } 00767 00768 Journal::List Calendar::sortJournals( Journal::List *journalList, 00769 JournalSortField sortField, 00770 SortDirection sortDirection ) 00771 { 00772 Journal::List journalListSorted; 00773 Journal::List::Iterator sortIt; 00774 Journal::List::Iterator eit; 00775 00776 switch( sortField ) { 00777 case JournalSortUnsorted: 00778 journalListSorted = *journalList; 00779 break; 00780 00781 case JournalSortDate: 00782 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) { 00783 sortIt = journalListSorted.begin(); 00784 if ( sortDirection == SortDirectionAscending ) { 00785 while ( sortIt != journalListSorted.end() && 00786 (*eit)->dtStart() >= (*sortIt)->dtStart() ) { 00787 ++sortIt; 00788 } 00789 } else { 00790 while ( sortIt != journalListSorted.end() && 00791 (*eit)->dtStart() < (*sortIt)->dtStart() ) { 00792 ++sortIt; 00793 } 00794 } 00795 journalListSorted.insert( sortIt, *eit ); 00796 } 00797 break; 00798 00799 case JournalSortSummary: 00800 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) { 00801 sortIt = journalListSorted.begin(); 00802 if ( sortDirection == SortDirectionAscending ) { 00803 while ( sortIt != journalListSorted.end() && 00804 (*eit)->summary() >= (*sortIt)->summary() ) { 00805 ++sortIt; 00806 } 00807 } else { 00808 while ( sortIt != journalListSorted.end() && 00809 (*eit)->summary() < (*sortIt)->summary() ) { 00810 ++sortIt; 00811 } 00812 } 00813 journalListSorted.insert( sortIt, *eit ); 00814 } 00815 break; 00816 } 00817 00818 return journalListSorted; 00819 } 00820 00821 Journal::List Calendar::journals( JournalSortField sortField, 00822 SortDirection sortDirection ) 00823 { 00824 Journal::List jl = rawJournals( sortField, sortDirection ); 00825 mFilter->apply( &jl ); 00826 return jl; 00827 } 00828 00829 Journal::List Calendar::journals( const TQDate &date ) 00830 { 00831 Journal::List el = rawJournalsForDate( date ); 00832 mFilter->apply( &el ); 00833 return el; 00834 } 00835 00836 // When this is called, the todo have already been added to the calendar. 00837 // This method is only about linking related todos 00838 void Calendar::setupRelations( Incidence *forincidence ) 00839 { 00840 if ( !forincidence ) return; 00841 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl; 00842 TQString uid = forincidence->uid(); 00843 00844 // First, go over the list of orphans and see if this is their parent 00845 while ( Incidence* i = mOrphans[ uid ] ) { 00846 mOrphans.remove( uid ); 00847 i->setRelatedTo( forincidence ); 00848 forincidence->addRelation( i ); 00849 mOrphanUids.remove( i->uid() ); 00850 } 00851 00852 // Now see about this incidences parent 00853 if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) { 00854 // This incidence has a uid it is related to but is not registered to it yet 00855 // Try to find it 00856 Incidence* parent = incidence( forincidence->relatedToUid() ); 00857 if ( parent ) { 00858 // Found it 00859 forincidence->setRelatedTo( parent ); 00860 parent->addRelation( forincidence ); 00861 } else { 00862 // Not found, put this in the mOrphans list 00863 // Note that the mOrphans dict might have several entries with the same key! That are 00864 // multiple children that wait for the parent incidence to be inserted. 00865 mOrphans.insert( forincidence->relatedToUid(), forincidence ); 00866 mOrphanUids.insert( forincidence->uid(), forincidence ); 00867 } 00868 } 00869 } 00870 00871 // If a task with subtasks is deleted, move it's subtasks to the orphans list 00872 void Calendar::removeRelations( Incidence *incidence ) 00873 { 00874 if( !incidence ) { 00875 kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n"; 00876 return; 00877 } 00878 00879 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl; 00880 TQString uid = incidence->uid(); 00881 00882 Incidence::List relations = incidence->relations(); 00883 Incidence::List::ConstIterator it; 00884 for ( it = relations.begin(); it != relations.end(); ++it ) { 00885 Incidence *i = *it; 00886 if ( !mOrphanUids.find( i->uid() ) ) { 00887 mOrphans.insert( uid, i ); 00888 mOrphanUids.insert( i->uid(), i ); 00889 i->setRelatedTo( 0 ); 00890 i->setRelatedToUid( uid ); 00891 } 00892 } 00893 00894 // If this incidence is related to something else, tell that about it 00895 if ( incidence->relatedTo() ) 00896 incidence->relatedTo()->removeRelation( incidence ); 00897 00898 // Remove this one from the orphans list 00899 if ( mOrphanUids.remove( uid ) ) { 00900 // This incidence is located in the orphans list - it should be removed 00901 // Since the mOrphans dict might contain the same key (with different 00902 // child incidence pointers!) multiple times, take care that we remove 00903 // the correct one. So we need to remove all items with the given 00904 // parent UID, and readd those that are not for this item. Also, there 00905 // might be other entries with differnet UID that point to this 00906 // incidence (this might happen when the relatedTo of the item is 00907 // changed before its parent is inserted. This might happen with 00908 // groupware servers....). Remove them, too 00909 TQStringList relatedToUids; 00910 // First get the list of all keys in the mOrphans list that point to the removed item 00911 relatedToUids << incidence->relatedToUid(); 00912 for ( TQDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) { 00913 if ( it.current()->uid() == uid ) { 00914 relatedToUids << it.currentKey(); 00915 } 00916 } 00917 00918 // now go through all uids that have one entry that point to the incidence 00919 for ( TQStringList::Iterator uidit = relatedToUids.begin(); 00920 uidit != relatedToUids.end(); ++uidit ) { 00921 Incidence::List tempList; 00922 // Remove all to get access to the remaining entries 00923 while( Incidence* i = mOrphans[ *uidit ] ) { 00924 mOrphans.remove( *uidit ); 00925 if ( i != incidence ) tempList.append( i ); 00926 } 00927 // Readd those that point to a different orphan incidence 00928 for ( Incidence::List::Iterator incit = tempList.begin(); 00929 incit != tempList.end(); ++incit ) { 00930 mOrphans.insert( *uidit, *incit ); 00931 } 00932 } 00933 } 00934 } 00935 00936 void Calendar::registerObserver( Observer *observer ) 00937 { 00938 if( !mObservers.contains( observer ) ) 00939 mObservers.append( observer ); 00940 mNewObserver = true; 00941 } 00942 00943 void Calendar::unregisterObserver( Observer *observer ) 00944 { 00945 mObservers.remove( observer ); 00946 } 00947 00948 void Calendar::setModified( bool modified ) 00949 { 00950 if ( modified != mModified || mNewObserver ) { 00951 mNewObserver = false; 00952 Observer *observer; 00953 for ( observer = mObservers.first(); observer; 00954 observer = mObservers.next() ) { 00955 observer->calendarModified( modified, this ); 00956 } 00957 mModified = modified; 00958 } 00959 } 00960 00961 void Calendar::incidenceUpdated( IncidenceBase *incidence ) 00962 { 00963 incidence->setSyncStatus( Event::SYNCMOD ); 00964 incidence->setLastModified( TQDateTime::currentDateTime() ); 00965 // we should probably update the revision number here, 00966 // or internally in the Event itself when certain things change. 00967 // need to verify with ical documentation. 00968 00969 // The static_cast is ok as the CalendarLocal only observes Incidence objects 00970 notifyIncidenceChanged( static_cast<Incidence *>( incidence ) ); 00971 00972 setModified( true ); 00973 } 00974 00975 void Calendar::notifyIncidenceAdded( Incidence *i ) 00976 { 00977 if ( !mObserversEnabled ) 00978 return; 00979 00980 Observer *observer; 00981 for ( observer = mObservers.first(); observer; 00982 observer = mObservers.next() ) { 00983 observer->calendarIncidenceAdded( i ); 00984 } 00985 } 00986 00987 void Calendar::notifyIncidenceChanged( Incidence *i ) 00988 { 00989 if ( !mObserversEnabled ) 00990 return; 00991 00992 Observer *observer; 00993 for ( observer = mObservers.first(); observer; 00994 observer = mObservers.next() ) { 00995 observer->calendarIncidenceChanged( i ); 00996 } 00997 } 00998 00999 void Calendar::notifyIncidenceDeleted( Incidence *i ) 01000 { 01001 if ( !mObserversEnabled ) 01002 return; 01003 01004 Observer *observer; 01005 for ( observer = mObservers.first(); observer; 01006 observer = mObservers.next() ) { 01007 observer->calendarIncidenceDeleted( i ); 01008 } 01009 } 01010 01011 void Calendar::customPropertyUpdated() 01012 { 01013 setModified( true ); 01014 } 01015 01016 void Calendar::setProductId( const TQString &productId ) 01017 { 01018 mProductId = productId; 01019 } 01020 01021 TQString Calendar::productId() 01022 { 01023 return mProductId; 01024 } 01025 01026 Incidence::List Calendar::mergeIncidenceList( const Event::List &events, 01027 const Todo::List &todos, 01028 const Journal::List &journals ) 01029 { 01030 Incidence::List incidences; 01031 01032 Event::List::ConstIterator it1; 01033 for ( it1 = events.begin(); it1 != events.end(); ++it1 ) 01034 incidences.append( *it1 ); 01035 01036 Todo::List::ConstIterator it2; 01037 for ( it2 = todos.begin(); it2 != todos.end(); ++it2 ) 01038 incidences.append( *it2 ); 01039 01040 Journal::List::ConstIterator it3; 01041 for ( it3 = journals.begin(); it3 != journals.end(); ++it3 ) 01042 incidences.append( *it3 ); 01043 01044 return incidences; 01045 } 01046 01047 bool Calendar::beginChange( Incidence * ) 01048 { 01049 return true; 01050 } 01051 01052 bool Calendar::endChange( Incidence * ) 01053 { 01054 return true; 01055 } 01056 01057 void Calendar::setObserversEnabled( bool enabled ) 01058 { 01059 mObserversEnabled = enabled; 01060 } 01061 01062 #include "calendar.moc"