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 <tdelocale.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 if (it != il.end()) { 00483 parentIncidence = this->incidence(*it); 00484 parentIncidence->deleteChildIncidence(incidence->uid()); 00485 } 00486 } 00487 else { 00488 // Delete all children as well 00489 IncidenceList il = incidence->childIncidences(); 00490 IncidenceListIterator it; 00491 for ( it = il.begin(); it != il.end(); ++it ) { 00492 deleteIncidence( this->incidence(*it) ); 00493 // Avoid a crash, reset the iterator every time the list is modified 00494 it = il.begin(); 00495 } 00496 } 00497 Incidence::DeleteVisitor<Calendar> v( this ); 00498 bool result = incidence->accept( v ); 00499 endChange( incidence ); 00500 return result; 00501 } else 00502 return false; 00503 } 00504 00508 Incidence *Calendar::dissociateOccurrence( Incidence *incidence, TQDate date, 00509 bool single ) 00510 { 00511 if ( !incidence || !incidence->doesRecur() ) 00512 return 0; 00513 00514 Incidence *newInc = incidence->clone(); 00515 newInc->recreate(); 00516 newInc->setHasRecurrenceID(false); 00517 // newInc->setRecurrenceID(TQString()); 00518 newInc->setRelatedTo( incidence ); 00519 Recurrence *recur = newInc->recurrence(); 00520 if ( single ) { 00521 recur->clear(); 00522 } else { 00523 // Adjust the recurrence for the future incidences. In particular 00524 // adjust the "end after n occurrences" rules! "No end date" and "end by ..." 00525 // don't need to be modified. 00526 int duration = recur->duration(); 00527 if ( duration > 0 ) { 00528 int doneduration = recur->durationTo( date.addDays(-1) ); 00529 if ( doneduration >= duration ) { 00530 kdDebug(5850) << "The dissociated event already occurred more often " 00531 << "than it was supposed to ever occur. ERROR!" << endl; 00532 recur->clear(); 00533 } else { 00534 recur->setDuration( duration - doneduration ); 00535 } 00536 } 00537 } 00538 // Adjust the date of the incidence 00539 if ( incidence->type() == "Event" ) { 00540 Event *ev = static_cast<Event *>( newInc ); 00541 TQDateTime start( ev->dtStart() ); 00542 int daysTo = start.date().daysTo( date ); 00543 ev->setDtStart( start.addDays( daysTo ) ); 00544 ev->setDtEnd( ev->dtEnd().addDays( daysTo ) ); 00545 } else if ( incidence->type() == "Todo" ) { 00546 Todo *td = static_cast<Todo *>( newInc ); 00547 bool haveOffset = false; 00548 int daysTo = 0; 00549 if ( td->hasDueDate() ) { 00550 TQDateTime due( td->dtDue() ); 00551 daysTo = due.date().daysTo( date ); 00552 td->setDtDue( due.addDays( daysTo ), true ); 00553 haveOffset = true; 00554 } 00555 if ( td->hasStartDate() ) { 00556 TQDateTime start( td->dtStart() ); 00557 if ( !haveOffset ) 00558 daysTo = start.date().daysTo( date ); 00559 td->setDtStart( start.addDays( daysTo ) ); 00560 haveOffset = true; 00561 } 00562 } 00563 recur = incidence->recurrence(); 00564 if ( recur ) { 00565 if ( single ) { 00566 recur->addExDate( date ); 00567 } else { 00568 // Make sure the recurrence of the past events ends 00569 // at the corresponding day 00570 recur->setEndDate( date.addDays(-1) ); 00571 } 00572 } 00573 return newInc; 00574 } 00575 00576 Incidence *Calendar::incidence( const TQString &uid ) 00577 { 00578 Incidence *i = event( uid ); 00579 if ( i ) 00580 return i; 00581 i = todo( uid ); 00582 if ( i ) 00583 return i; 00584 i = journal( uid ); 00585 return i; 00586 } 00587 00588 Incidence::List Calendar::incidencesFromSchedulingID( const TQString &UID ) 00589 { 00590 Incidence::List result; 00591 Incidence::List incidences = rawIncidences(); 00592 Incidence::List::iterator it = incidences.begin(); 00593 for ( ; it != incidences.end(); ++it ) 00594 if ( (*it)->schedulingID() == UID ) 00595 result.append( *it ); 00596 return result; 00597 } 00598 00599 Incidence *Calendar::incidenceFromSchedulingID( const TQString &UID ) 00600 { 00601 Incidence::List incidences = rawIncidences(); 00602 Incidence::List::iterator it = incidences.begin(); 00603 for ( ; it != incidences.end(); ++it ) 00604 if ( (*it)->schedulingID() == UID ) 00605 // Touchdown, and the crowd goes wild 00606 return *it; 00607 // Not found 00608 return 0; 00609 } 00610 00611 Todo::List Calendar::sortTodos( Todo::List *todoList, 00612 TodoSortField sortField, 00613 SortDirection sortDirection ) 00614 { 00615 Todo::List todoListSorted; 00616 Todo::List tempList, t; 00617 Todo::List alphaList; 00618 Todo::List::Iterator sortIt; 00619 Todo::List::Iterator eit; 00620 00621 // Notice we alphabetically presort Summaries first. 00622 // We do this so comparison "ties" stay in a nice order. 00623 00624 // Note that Todos may not have Start DateTimes nor due DateTimes. 00625 00626 switch( sortField ) { 00627 case TodoSortUnsorted: 00628 todoListSorted = *todoList; 00629 break; 00630 00631 case TodoSortStartDate: 00632 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00633 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00634 if ( (*eit)->hasStartDate() ) { 00635 sortIt = todoListSorted.begin(); 00636 if ( sortDirection == SortDirectionAscending ) { 00637 while ( sortIt != todoListSorted.end() && 00638 (*eit)->dtStart() >= (*sortIt)->dtStart() ) { 00639 ++sortIt; 00640 } 00641 } else { 00642 while ( sortIt != todoListSorted.end() && 00643 (*eit)->dtStart() < (*sortIt)->dtStart() ) { 00644 ++sortIt; 00645 } 00646 } 00647 todoListSorted.insert( sortIt, *eit ); 00648 } else { 00649 // Keep a list of the Todos without Start DateTimes 00650 tempList.append( *eit ); 00651 } 00652 } 00653 if ( sortDirection == SortDirectionAscending ) { 00654 // Append the list of Todos without Start DateTimes 00655 todoListSorted += tempList; 00656 } else { 00657 // Prepend the list of Todos without Start DateTimes 00658 tempList += todoListSorted; 00659 todoListSorted = tempList; 00660 } 00661 break; 00662 00663 case TodoSortDueDate: 00664 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00665 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00666 if ( (*eit)->hasDueDate() ) { 00667 sortIt = todoListSorted.begin(); 00668 if ( sortDirection == SortDirectionAscending ) { 00669 while ( sortIt != todoListSorted.end() && 00670 (*eit)->dtDue() >= (*sortIt)->dtDue() ) { 00671 ++sortIt; 00672 } 00673 } else { 00674 while ( sortIt != todoListSorted.end() && 00675 (*eit)->dtDue() < (*sortIt)->dtDue() ) { 00676 ++sortIt; 00677 } 00678 } 00679 todoListSorted.insert( sortIt, *eit ); 00680 } else { 00681 // Keep a list of the Todos without Due DateTimes 00682 tempList.append( *eit ); 00683 } 00684 } 00685 if ( sortDirection == SortDirectionAscending ) { 00686 // Append the list of Todos without Due DateTimes 00687 todoListSorted += tempList; 00688 } else { 00689 // Prepend the list of Todos without Due DateTimes 00690 tempList += todoListSorted; 00691 todoListSorted = tempList; 00692 } 00693 break; 00694 00695 case TodoSortPriority: 00696 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00697 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00698 sortIt = todoListSorted.begin(); 00699 if ( sortDirection == SortDirectionAscending ) { 00700 while ( sortIt != todoListSorted.end() && 00701 (*eit)->priority() >= (*sortIt)->priority() ) { 00702 ++sortIt; 00703 } 00704 } else { 00705 while ( sortIt != todoListSorted.end() && 00706 (*eit)->priority() < (*sortIt)->priority() ) { 00707 ++sortIt; 00708 } 00709 } 00710 todoListSorted.insert( sortIt, *eit ); 00711 } 00712 break; 00713 00714 case TodoSortPercentComplete: 00715 alphaList = sortTodos( todoList, TodoSortSummary, sortDirection ); 00716 for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) { 00717 sortIt = todoListSorted.begin(); 00718 if ( sortDirection == SortDirectionAscending ) { 00719 while ( sortIt != todoListSorted.end() && 00720 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) { 00721 ++sortIt; 00722 } 00723 } else { 00724 while ( sortIt != todoListSorted.end() && 00725 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) { 00726 ++sortIt; 00727 } 00728 } 00729 todoListSorted.insert( sortIt, *eit ); 00730 } 00731 break; 00732 00733 case TodoSortSummary: 00734 for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) { 00735 sortIt = todoListSorted.begin(); 00736 if ( sortDirection == SortDirectionAscending ) { 00737 while ( sortIt != todoListSorted.end() && 00738 (*eit)->summary() >= (*sortIt)->summary() ) { 00739 ++sortIt; 00740 } 00741 } else { 00742 while ( sortIt != todoListSorted.end() && 00743 (*eit)->summary() < (*sortIt)->summary() ) { 00744 ++sortIt; 00745 } 00746 } 00747 todoListSorted.insert( sortIt, *eit ); 00748 } 00749 break; 00750 } 00751 00752 return todoListSorted; 00753 } 00754 00755 Todo::List Calendar::todos( TodoSortField sortField, 00756 SortDirection sortDirection ) 00757 { 00758 Todo::List tl = rawTodos( sortField, sortDirection ); 00759 mFilter->apply( &tl ); 00760 return tl; 00761 } 00762 00763 Todo::List Calendar::todos( const TQDate &date ) 00764 { 00765 Todo::List el = rawTodosForDate( date ); 00766 mFilter->apply( &el ); 00767 return el; 00768 } 00769 00770 Journal::List Calendar::sortJournals( Journal::List *journalList, 00771 JournalSortField sortField, 00772 SortDirection sortDirection ) 00773 { 00774 Journal::List journalListSorted; 00775 Journal::List::Iterator sortIt; 00776 Journal::List::Iterator eit; 00777 00778 switch( sortField ) { 00779 case JournalSortUnsorted: 00780 journalListSorted = *journalList; 00781 break; 00782 00783 case JournalSortDate: 00784 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) { 00785 sortIt = journalListSorted.begin(); 00786 if ( sortDirection == SortDirectionAscending ) { 00787 while ( sortIt != journalListSorted.end() && 00788 (*eit)->dtStart() >= (*sortIt)->dtStart() ) { 00789 ++sortIt; 00790 } 00791 } else { 00792 while ( sortIt != journalListSorted.end() && 00793 (*eit)->dtStart() < (*sortIt)->dtStart() ) { 00794 ++sortIt; 00795 } 00796 } 00797 journalListSorted.insert( sortIt, *eit ); 00798 } 00799 break; 00800 00801 case JournalSortSummary: 00802 for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) { 00803 sortIt = journalListSorted.begin(); 00804 if ( sortDirection == SortDirectionAscending ) { 00805 while ( sortIt != journalListSorted.end() && 00806 (*eit)->summary() >= (*sortIt)->summary() ) { 00807 ++sortIt; 00808 } 00809 } else { 00810 while ( sortIt != journalListSorted.end() && 00811 (*eit)->summary() < (*sortIt)->summary() ) { 00812 ++sortIt; 00813 } 00814 } 00815 journalListSorted.insert( sortIt, *eit ); 00816 } 00817 break; 00818 } 00819 00820 return journalListSorted; 00821 } 00822 00823 Journal::List Calendar::journals( JournalSortField sortField, 00824 SortDirection sortDirection ) 00825 { 00826 Journal::List jl = rawJournals( sortField, sortDirection ); 00827 mFilter->apply( &jl ); 00828 return jl; 00829 } 00830 00831 Journal::List Calendar::journals( const TQDate &date ) 00832 { 00833 Journal::List el = rawJournalsForDate( date ); 00834 mFilter->apply( &el ); 00835 return el; 00836 } 00837 00838 // When this is called, the todo have already been added to the calendar. 00839 // This method is only about linking related todos 00840 void Calendar::setupRelations( Incidence *forincidence ) 00841 { 00842 if ( !forincidence ) return; 00843 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl; 00844 TQString uid = forincidence->uid(); 00845 00846 // First, go over the list of orphans and see if this is their parent 00847 while ( Incidence* i = mOrphans[ uid ] ) { 00848 mOrphans.remove( uid ); 00849 i->setRelatedTo( forincidence ); 00850 forincidence->addRelation( i ); 00851 mOrphanUids.remove( i->uid() ); 00852 } 00853 00854 // Now see about this incidences parent 00855 if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) { 00856 // This incidence has a uid it is related to but is not registered to it yet 00857 // Try to find it 00858 Incidence* parent = incidence( forincidence->relatedToUid() ); 00859 if ( parent ) { 00860 // Found it 00861 forincidence->setRelatedTo( parent ); 00862 parent->addRelation( forincidence ); 00863 } else { 00864 // Not found, put this in the mOrphans list 00865 // Note that the mOrphans dict might have several entries with the same key! That are 00866 // multiple children that wait for the parent incidence to be inserted. 00867 mOrphans.insert( forincidence->relatedToUid(), forincidence ); 00868 mOrphanUids.insert( forincidence->uid(), forincidence ); 00869 } 00870 } 00871 } 00872 00873 // If a task with subtasks is deleted, move it's subtasks to the orphans list 00874 void Calendar::removeRelations( Incidence *incidence ) 00875 { 00876 if( !incidence ) { 00877 kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n"; 00878 return; 00879 } 00880 00881 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl; 00882 TQString uid = incidence->uid(); 00883 00884 Incidence::List relations = incidence->relations(); 00885 Incidence::List::ConstIterator it; 00886 for ( it = relations.begin(); it != relations.end(); ++it ) { 00887 Incidence *i = *it; 00888 if ( !mOrphanUids.find( i->uid() ) ) { 00889 mOrphans.insert( uid, i ); 00890 mOrphanUids.insert( i->uid(), i ); 00891 i->setRelatedTo( 0 ); 00892 i->setRelatedToUid( uid ); 00893 } 00894 } 00895 00896 // If this incidence is related to something else, tell that about it 00897 if ( incidence->relatedTo() ) 00898 incidence->relatedTo()->removeRelation( incidence ); 00899 00900 // Remove this one from the orphans list 00901 if ( mOrphanUids.remove( uid ) ) { 00902 // This incidence is located in the orphans list - it should be removed 00903 // Since the mOrphans dict might contain the same key (with different 00904 // child incidence pointers!) multiple times, take care that we remove 00905 // the correct one. So we need to remove all items with the given 00906 // parent UID, and readd those that are not for this item. Also, there 00907 // might be other entries with differnet UID that point to this 00908 // incidence (this might happen when the relatedTo of the item is 00909 // changed before its parent is inserted. This might happen with 00910 // groupware servers....). Remove them, too 00911 TQStringList relatedToUids; 00912 // First get the list of all keys in the mOrphans list that point to the removed item 00913 relatedToUids << incidence->relatedToUid(); 00914 for ( TQDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) { 00915 if ( it.current()->uid() == uid ) { 00916 relatedToUids << it.currentKey(); 00917 } 00918 } 00919 00920 // now go through all uids that have one entry that point to the incidence 00921 for ( TQStringList::Iterator uidit = relatedToUids.begin(); 00922 uidit != relatedToUids.end(); ++uidit ) { 00923 Incidence::List tempList; 00924 // Remove all to get access to the remaining entries 00925 while( Incidence* i = mOrphans[ *uidit ] ) { 00926 mOrphans.remove( *uidit ); 00927 if ( i != incidence ) tempList.append( i ); 00928 } 00929 // Readd those that point to a different orphan incidence 00930 for ( Incidence::List::Iterator incit = tempList.begin(); 00931 incit != tempList.end(); ++incit ) { 00932 mOrphans.insert( *uidit, *incit ); 00933 } 00934 } 00935 } 00936 } 00937 00938 void Calendar::registerObserver( Observer *observer ) 00939 { 00940 if( !mObservers.contains( observer ) ) 00941 mObservers.append( observer ); 00942 mNewObserver = true; 00943 } 00944 00945 void Calendar::unregisterObserver( Observer *observer ) 00946 { 00947 mObservers.remove( observer ); 00948 } 00949 00950 void Calendar::setModified( bool modified ) 00951 { 00952 if ( modified != mModified || mNewObserver ) { 00953 mNewObserver = false; 00954 Observer *observer; 00955 for ( observer = mObservers.first(); observer; 00956 observer = mObservers.next() ) { 00957 observer->calendarModified( modified, this ); 00958 } 00959 mModified = modified; 00960 } 00961 } 00962 00963 void Calendar::incidenceUpdated( IncidenceBase *incidence ) 00964 { 00965 incidence->setSyncStatus( Event::SYNCMOD ); 00966 incidence->setLastModified( TQDateTime::currentDateTime() ); 00967 // we should probably update the revision number here, 00968 // or internally in the Event itself when certain things change. 00969 // need to verify with ical documentation. 00970 00971 // The static_cast is ok as the CalendarLocal only observes Incidence objects 00972 notifyIncidenceChanged( static_cast<Incidence *>( incidence ) ); 00973 00974 setModified( true ); 00975 } 00976 00977 void Calendar::notifyIncidenceAdded( Incidence *i ) 00978 { 00979 if ( !mObserversEnabled ) 00980 return; 00981 00982 Observer *observer; 00983 for ( observer = mObservers.first(); observer; 00984 observer = mObservers.next() ) { 00985 observer->calendarIncidenceAdded( i ); 00986 } 00987 } 00988 00989 void Calendar::notifyIncidenceChanged( Incidence *i ) 00990 { 00991 if ( !mObserversEnabled ) 00992 return; 00993 00994 Observer *observer; 00995 for ( observer = mObservers.first(); observer; 00996 observer = mObservers.next() ) { 00997 observer->calendarIncidenceChanged( i ); 00998 } 00999 } 01000 01001 void Calendar::notifyIncidenceDeleted( Incidence *i ) 01002 { 01003 if ( !mObserversEnabled ) 01004 return; 01005 01006 Observer *observer; 01007 for ( observer = mObservers.first(); observer; 01008 observer = mObservers.next() ) { 01009 observer->calendarIncidenceDeleted( i ); 01010 } 01011 } 01012 01013 void Calendar::customPropertyUpdated() 01014 { 01015 setModified( true ); 01016 } 01017 01018 void Calendar::setProductId( const TQString &productId ) 01019 { 01020 mProductId = productId; 01021 } 01022 01023 TQString Calendar::productId() 01024 { 01025 return mProductId; 01026 } 01027 01028 Incidence::List Calendar::mergeIncidenceList( const Event::List &events, 01029 const Todo::List &todos, 01030 const Journal::List &journals ) 01031 { 01032 Incidence::List incidences; 01033 01034 Event::List::ConstIterator it1; 01035 for ( it1 = events.begin(); it1 != events.end(); ++it1 ) 01036 incidences.append( *it1 ); 01037 01038 Todo::List::ConstIterator it2; 01039 for ( it2 = todos.begin(); it2 != todos.end(); ++it2 ) 01040 incidences.append( *it2 ); 01041 01042 Journal::List::ConstIterator it3; 01043 for ( it3 = journals.begin(); it3 != journals.end(); ++it3 ) 01044 incidences.append( *it3 ); 01045 01046 return incidences; 01047 } 01048 01049 bool Calendar::beginChange( Incidence * ) 01050 { 01051 return true; 01052 } 01053 01054 bool Calendar::endChange( Incidence * ) 01055 { 01056 return true; 01057 } 01058 01059 void Calendar::setObserversEnabled( bool enabled ) 01060 { 01061 mObserversEnabled = enabled; 01062 } 01063 01064 #include "calendar.moc"