libkcal Library API Documentation

calendarlocal.cpp

00001 /* 00002 This file is part of libkcal. 00003 00004 Copyright (c) 1998 Preston Brown 00005 Copyright (c) 2001,2003,2004 Cornelius Schumacher <schumacher@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License as published by the Free Software Foundation; either 00010 version 2 of the License, or (at your option) any later version. 00011 00012 This library is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 Library General Public License for more details. 00016 00017 You should have received a copy of the GNU Library General Public License 00018 along with this library; see the file COPYING.LIB. If not, write to 00019 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00020 Boston, MA 02111-1307, USA. 00021 */ 00022 00023 #include <qdatetime.h> 00024 #include <qstring.h> 00025 #include <qptrlist.h> 00026 00027 #include <kdebug.h> 00028 00029 #include "vcaldrag.h" 00030 #include "vcalformat.h" 00031 #include "icalformat.h" 00032 #include "exceptions.h" 00033 #include "incidence.h" 00034 #include "journal.h" 00035 #include "filestorage.h" 00036 00037 #include "calendarlocal.h" 00038 00039 using namespace KCal; 00040 00041 CalendarLocal::CalendarLocal() 00042 : Calendar(), mEvents( 47 ) 00043 { 00044 init(); 00045 } 00046 00047 CalendarLocal::CalendarLocal( const QString &timeZoneId ) 00048 : Calendar( timeZoneId ), mEvents( 47 ) 00049 { 00050 init(); 00051 } 00052 00053 void CalendarLocal::init() 00054 { 00055 mDeletedIncidences.setAutoDelete( true ); 00056 } 00057 00058 00059 CalendarLocal::~CalendarLocal() 00060 { 00061 close(); 00062 } 00063 00064 bool CalendarLocal::load( const QString &fileName ) 00065 { 00066 FileStorage storage( this, fileName ); 00067 return storage.load(); 00068 } 00069 00070 bool CalendarLocal::save( const QString &fileName, CalFormat *format ) 00071 { 00072 FileStorage storage( this, fileName, format ); 00073 return storage.save(); 00074 } 00075 00076 void CalendarLocal::close() 00077 { 00078 setObserversEnabled( false ); 00079 00080 deleteAllEvents(); 00081 deleteAllTodos(); 00082 deleteAllJournals(); 00083 00084 mDeletedIncidences.clear(); 00085 setModified( false ); 00086 00087 setObserversEnabled( true ); 00088 } 00089 00090 00091 bool CalendarLocal::addEvent( Event *event ) 00092 { 00093 insertEvent( event ); 00094 00095 event->registerObserver( this ); 00096 00097 setModified( true ); 00098 00099 notifyIncidenceAdded( event ); 00100 00101 return true; 00102 } 00103 00104 void CalendarLocal::deleteEvent( Event *event ) 00105 { 00106 kdDebug(5800) << "CalendarLocal::deleteEvent" << endl; 00107 00108 if ( mEvents.remove( event->uid() ) ) { 00109 setModified( true ); 00110 notifyIncidenceDeleted( event ); 00111 mDeletedIncidences.append( event ); 00112 } else { 00113 kdWarning() << "CalendarLocal::deleteEvent(): Event not found." << endl; 00114 } 00115 } 00116 00117 void CalendarLocal::deleteAllEvents() 00118 { 00119 // kdDebug(5800) << "CalendarLocal::deleteAllEvents" << endl; 00120 QDictIterator<Event> it( mEvents ); 00121 while( it.current() ) { 00122 notifyIncidenceDeleted( it.current() ); 00123 ++it; 00124 } 00125 00126 mEvents.setAutoDelete( true ); 00127 mEvents.clear(); 00128 mEvents.setAutoDelete( false ); 00129 } 00130 00131 Event *CalendarLocal::event( const QString &uid ) 00132 { 00133 // kdDebug(5800) << "CalendarLocal::event(): " << uid << endl; 00134 return mEvents[ uid ]; 00135 } 00136 00137 bool CalendarLocal::addTodo( Todo *todo ) 00138 { 00139 mTodoList.append( todo ); 00140 00141 todo->registerObserver( this ); 00142 00143 // Set up subtask relations 00144 setupRelations( todo ); 00145 00146 setModified( true ); 00147 00148 notifyIncidenceAdded( todo ); 00149 00150 return true; 00151 } 00152 00153 void CalendarLocal::deleteTodo( Todo *todo ) 00154 { 00155 // Handle orphaned children 00156 removeRelations( todo ); 00157 00158 if ( mTodoList.removeRef( todo ) ) { 00159 setModified( true ); 00160 notifyIncidenceDeleted( todo ); 00161 mDeletedIncidences.append( todo ); 00162 } 00163 } 00164 00165 void CalendarLocal::deleteAllTodos() 00166 { 00167 // kdDebug(5800) << "CalendarLocal::deleteAllTodos()\n"; 00168 Todo::List::ConstIterator it; 00169 for( it = mTodoList.begin(); it != mTodoList.end(); ++it ) { 00170 notifyIncidenceDeleted( *it ); 00171 } 00172 00173 mTodoList.setAutoDelete( true ); 00174 mTodoList.clear(); 00175 mTodoList.setAutoDelete( false ); 00176 } 00177 00178 Todo::List CalendarLocal::rawTodos() 00179 { 00180 return mTodoList; 00181 } 00182 00183 Todo *CalendarLocal::todo( const QString &uid ) 00184 { 00185 Todo::List::ConstIterator it; 00186 for ( it = mTodoList.begin(); it != mTodoList.end(); ++it ) { 00187 if ( (*it)->uid() == uid ) return *it; 00188 } 00189 00190 return 0; 00191 } 00192 00193 Todo::List CalendarLocal::rawTodosForDate( const QDate &date ) 00194 { 00195 Todo::List todos; 00196 00197 Todo::List::ConstIterator it; 00198 for ( it = mTodoList.begin(); it != mTodoList.end(); ++it ) { 00199 Todo *todo = *it; 00200 if ( todo->hasDueDate() && todo->dtDue().date() == date ) { 00201 todos.append( todo ); 00202 } 00203 } 00204 00205 return todos; 00206 } 00207 00208 Alarm::List CalendarLocal::alarmsTo( const QDateTime &to ) 00209 { 00210 return alarms( QDateTime( QDate( 1900, 1, 1 ) ), to ); 00211 } 00212 00213 Alarm::List CalendarLocal::alarms( const QDateTime &from, const QDateTime &to ) 00214 { 00215 // kdDebug(5800) << "CalendarLocal::alarms(" << from.toString() << " - " 00216 // << to.toString() << ")" << endl; 00217 00218 Alarm::List alarms; 00219 00220 EventDictIterator it( mEvents ); 00221 for( ; it.current(); ++it ) { 00222 Event *e = *it; 00223 if ( e->doesRecur() ) appendRecurringAlarms( alarms, e, from, to ); 00224 else appendAlarms( alarms, e, from, to ); 00225 } 00226 00227 Todo::List::ConstIterator it2; 00228 for( it2 = mTodoList.begin(); it2 != mTodoList.end(); ++it2 ) { 00229 if (! (*it2)->isCompleted() ) appendAlarms( alarms, *it2, from, to ); 00230 } 00231 00232 return alarms; 00233 } 00234 00235 void CalendarLocal::appendAlarms( Alarm::List &alarms, Incidence *incidence, 00236 const QDateTime &from, const QDateTime &to ) 00237 { 00238 Alarm::List::ConstIterator it; 00239 for( it = incidence->alarms().begin(); it != incidence->alarms().end(); 00240 ++it ) { 00241 // kdDebug(5800) << "CalendarLocal::appendAlarms() '" << alarm->text() 00242 // << "': " << alarm->time().toString() << " - " << alarm->enabled() << endl; 00243 if ( (*it)->enabled() ) { 00244 if ( (*it)->time() >= from && (*it)->time() <= to ) { 00245 // kdDebug(5800) << "CalendarLocal::appendAlarms() '" 00246 // << incidence->summary() << "': " 00247 // << (*it)->time().toString() << endl; 00248 alarms.append( *it ); 00249 } 00250 } 00251 } 00252 } 00253 00254 void CalendarLocal::appendRecurringAlarms( Alarm::List &alarms, 00255 Incidence *incidence, 00256 const QDateTime &from, 00257 const QDateTime &to ) 00258 { 00259 Alarm::List::ConstIterator it; 00260 QDateTime qdt; 00261 int endOffset = 0; 00262 bool endOffsetValid = false; 00263 for( it = incidence->alarms().begin(); it != incidence->alarms().end(); 00264 ++it ) { 00265 Alarm *alarm = *it; 00266 if ( alarm->hasTime() ) { 00267 // The alarm time is defined as an absolute date/time 00268 qdt = alarm->time(); 00269 } else { 00270 // The alarm time is defined by an offset from the event start or end time. 00271 // Find the offset from the event start time, which is also used as the 00272 // offset from the recurrence time. 00273 int offset = 0; 00274 if ( alarm->hasStartOffset() ) { 00275 offset = alarm->startOffset().asSeconds(); 00276 } else if ( alarm->hasEndOffset() ) { 00277 if ( !endOffsetValid ) { 00278 endOffset = incidence->dtStart().secsTo( incidence->dtEnd() ); 00279 endOffsetValid = true; 00280 } 00281 offset = alarm->endOffset().asSeconds() + endOffset; 00282 } 00283 // Adjust the 'from' date/time and find the next recurrence at or after it 00284 qdt = incidence->recurrence()->getNextDateTime( from.addSecs(-offset - 1) ); 00285 if (!qdt.isValid() || incidence->isException(qdt.date()) ) 00286 continue; 00287 // Remove the adjustment to get the alarm time 00288 qdt = qdt.addSecs( offset ); 00289 } 00290 kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary() 00291 << "': " << qdt.toString() << " - " << (*it)->enabled() 00292 << endl; 00293 if ( (*it)->enabled() ) { 00294 // kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary() 00295 // << "': " << (*it)->time().toString() << endl; 00296 if ( qdt >= from && qdt <= to ) { 00297 alarms.append( *it ); 00298 } 00299 } 00300 } 00301 } 00302 00303 00304 void CalendarLocal::incidenceUpdated( IncidenceBase *incidence ) 00305 { 00306 incidence->setSyncStatus( Event::SYNCMOD ); 00307 incidence->setLastModified( QDateTime::currentDateTime() ); 00308 // we should probably update the revision number here, 00309 // or internally in the Event itself when certain things change. 00310 // need to verify with ical documentation. 00311 00312 // The static_cast is ok as the CalendarLocal only observes Incidence objects 00313 notifyIncidenceChanged( static_cast<Incidence *>( incidence ) ); 00314 00315 setModified( true ); 00316 } 00317 00318 void CalendarLocal::insertEvent( Event *event ) 00319 { 00320 QString uid = event->uid(); 00321 if ( mEvents[ uid ] == 0 ) { 00322 mEvents.insert( uid, event ); 00323 } 00324 #ifndef NDEBUG 00325 else // if we already have an event with this UID, it has to be the same event, 00326 // otherwise something's really broken 00327 Q_ASSERT( mEvents[uid] == event ); 00328 #endif 00329 } 00330 00331 00332 Event::List CalendarLocal::rawEventsForDate( const QDate &qd, bool sorted ) 00333 { 00334 Event::List eventList; 00335 00336 EventDictIterator it( mEvents ); 00337 for( ; it.current(); ++it ) { 00338 Event *event = *it; 00339 00340 if ( event->doesRecur() ) { 00341 if ( event->isMultiDay() ) { 00342 int extraDays = event->dtStart().date().daysTo( event->dtEnd().date() ); 00343 int i; 00344 for ( i = 0; i <= extraDays; i++ ) { 00345 if ( event->recursOn( qd.addDays( -i ) ) ) { 00346 eventList.append( event ); 00347 break; 00348 } 00349 } 00350 } else { 00351 if ( event->recursOn( qd ) ) 00352 eventList.append( event ); 00353 } 00354 } else { 00355 if ( event->dtStart().date() <= qd && event->dtEnd().date() >= qd ) { 00356 eventList.append( event ); 00357 } 00358 } 00359 } 00360 00361 if ( !sorted ) { 00362 return eventList; 00363 } 00364 00365 // kdDebug(5800) << "Sorting events for date\n" << endl; 00366 // now, we have to sort it based on dtStart.time() 00367 Event::List eventListSorted; 00368 Event::List::Iterator sortIt; 00369 Event::List::Iterator eit; 00370 for ( eit = eventList.begin(); eit != eventList.end(); ++eit ) { 00371 sortIt = eventListSorted.begin(); 00372 while ( sortIt != eventListSorted.end() && 00373 (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) { 00374 ++sortIt; 00375 } 00376 eventListSorted.insert( sortIt, *eit ); 00377 } 00378 return eventListSorted; 00379 } 00380 00381 00382 Event::List CalendarLocal::rawEvents( const QDate &start, const QDate &end, 00383 bool inclusive ) 00384 { 00385 Event::List eventList; 00386 00387 // Get non-recurring events 00388 EventDictIterator it( mEvents ); 00389 for( ; it.current(); ++it ) { 00390 Event *event = *it; 00391 if ( event->doesRecur() ) { 00392 QDate rStart = event->dtStart().date(); 00393 bool found = false; 00394 if ( inclusive ) { 00395 if ( rStart >= start && rStart <= end ) { 00396 // Start date of event is in range. Now check for end date. 00397 // if duration is negative, event recurs forever, so do not include it. 00398 if ( event->recurrence()->duration() == 0 ) { // End date set 00399 QDate rEnd = event->recurrence()->endDate(); 00400 if ( rEnd >= start && rEnd <= end ) { // End date within range 00401 found = true; 00402 } 00403 } else if ( event->recurrence()->duration() > 0 ) { // Duration set 00404 // TODO: Calculate end date from duration. Should be done in Event 00405 // For now exclude all events with a duration. 00406 } 00407 } 00408 } else { 00409 if ( rStart <= end ) { // Start date not after range 00410 if ( rStart >= start ) { // Start date within range 00411 found = true; 00412 } else if ( event->recurrence()->duration() == -1 ) { // Recurs forever 00413 found = true; 00414 } else if ( event->recurrence()->duration() == 0 ) { // End date set 00415 QDate rEnd = event->recurrence()->endDate(); 00416 if ( rEnd >= start && rEnd <= end ) { // End date within range 00417 found = true; 00418 } 00419 } else { // Duration set 00420 // TODO: Calculate end date from duration. Should be done in Event 00421 // For now include all events with a duration. 00422 found = true; 00423 } 00424 } 00425 } 00426 00427 if ( found ) eventList.append( event ); 00428 } else { 00429 QDate s = event->dtStart().date(); 00430 QDate e = event->dtEnd().date(); 00431 00432 if ( inclusive ) { 00433 if ( s >= start && e <= end ) { 00434 eventList.append( event ); 00435 } 00436 } else { 00437 if ( ( s >= start && s <= end ) || ( e >= start && e <= end ) ) { 00438 eventList.append( event ); 00439 } 00440 } 00441 } 00442 } 00443 00444 return eventList; 00445 } 00446 00447 Event::List CalendarLocal::rawEventsForDate( const QDateTime &qdt ) 00448 { 00449 return rawEventsForDate( qdt.date() ); 00450 } 00451 00452 // This bool is only used by the regression testing program, to save in a stable order 00453 bool KCal_CalendarLocal_saveOrdered = false; 00454 00455 Event::List CalendarLocal::rawEvents() 00456 { 00457 Event::List eventList; 00458 if ( !KCal_CalendarLocal_saveOrdered ) { // normal case: save in random order 00459 EventDictIterator it( mEvents ); 00460 for( ; it.current(); ++it ) 00461 eventList.append( *it ); 00462 } else { // regression testing: save in sorted order 00463 Event::List::Iterator sortIt; 00464 EventDictIterator it( mEvents ); 00465 for( ; it.current(); ++it ) { 00466 sortIt = eventList.begin(); 00467 while ( sortIt != eventList.end() && 00468 it.current()->dtStart().time() >= (*sortIt)->dtStart().time() ) { 00469 ++sortIt; 00470 } 00471 eventList.insert( sortIt, it.current() ); 00472 } 00473 } 00474 return eventList; 00475 } 00476 00477 bool CalendarLocal::addJournal(Journal *journal) 00478 { 00479 if (journal->dtStart().isValid()) 00480 kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl; 00481 else 00482 kdDebug(5800) << "Adding Journal without a DTSTART" << endl; 00483 00484 mJournalList.append(journal); 00485 00486 journal->registerObserver( this ); 00487 00488 setModified( true ); 00489 00490 notifyIncidenceAdded( journal ); 00491 00492 return true; 00493 } 00494 00495 void CalendarLocal::deleteJournal( Journal *journal ) 00496 { 00497 if ( mJournalList.removeRef( journal ) ) { 00498 setModified( true ); 00499 notifyIncidenceDeleted( journal ); 00500 mDeletedIncidences.append( journal ); 00501 } 00502 } 00503 00504 void CalendarLocal::deleteAllJournals() 00505 { 00506 Journal::List::ConstIterator it; 00507 for( it = mJournalList.begin(); it != mJournalList.end(); ++it ) { 00508 notifyIncidenceDeleted( *it ); 00509 } 00510 00511 mJournalList.setAutoDelete( true ); 00512 mJournalList.clear(); 00513 mJournalList.setAutoDelete( false ); 00514 } 00515 00516 Journal *CalendarLocal::journal( const QDate &date ) 00517 { 00518 // kdDebug(5800) << "CalendarLocal::journal() " << date.toString() << endl; 00519 00520 Journal::List::ConstIterator it; 00521 for ( it = mJournalList.begin(); it != mJournalList.end(); ++it ) 00522 if ( (*it)->dtStart().date() == date ) 00523 return *it; 00524 00525 return 0; 00526 } 00527 00528 Journal *CalendarLocal::journal( const QString &uid ) 00529 { 00530 Journal::List::ConstIterator it; 00531 for ( it = mJournalList.begin(); it != mJournalList.end(); ++it ) 00532 if ( (*it)->uid() == uid ) 00533 return *it; 00534 00535 return 0; 00536 } 00537 00538 Journal::List CalendarLocal::journals() 00539 { 00540 return mJournalList; 00541 } 00542
KDE Logo
This file is part of the documentation for libkcal Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Aug 27 12:49:07 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003