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 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 } 00056 00057 00058 CalendarLocal::~CalendarLocal() 00059 { 00060 close(); 00061 } 00062 00063 bool CalendarLocal::load( const QString &fileName ) 00064 { 00065 FileStorage storage( this, fileName ); 00066 return storage.load(); 00067 } 00068 00069 bool CalendarLocal::save( const QString &fileName, CalFormat *format ) 00070 { 00071 FileStorage storage( this, fileName, format ); 00072 return storage.save(); 00073 } 00074 00075 void CalendarLocal::close() 00076 { 00077 deleteAllEvents(); 00078 deleteAllTodos(); 00079 deleteAllJournals(); 00080 00081 setModified( false ); 00082 } 00083 00084 00085 bool CalendarLocal::addEvent( Event *event ) 00086 { 00087 insertEvent( event ); 00088 00089 event->registerObserver( this ); 00090 00091 setModified( true ); 00092 00093 return true; 00094 } 00095 00096 void CalendarLocal::deleteEvent( Event *event ) 00097 { 00098 kdDebug(5800) << "CalendarLocal::deleteEvent" << endl; 00099 00100 if ( mEvents.remove( event->uid() ) ) { 00101 setModified( true ); 00102 } else { 00103 kdWarning() << "CalendarLocal::deleteEvent(): Event not found." << endl; 00104 } 00105 } 00106 00107 void CalendarLocal::deleteAllEvents() 00108 { 00109 // kdDebug(5800) << "CalendarLocal::deleteAllEvents" << endl; 00110 mEvents.setAutoDelete( true ); 00111 mEvents.clear(); 00112 mEvents.setAutoDelete( false ); 00113 } 00114 00115 Event *CalendarLocal::event( const QString &uid ) 00116 { 00117 // kdDebug(5800) << "CalendarLocal::event(): " << uid << endl; 00118 return mEvents[ uid ]; 00119 } 00120 00121 bool CalendarLocal::addTodo( Todo *todo ) 00122 { 00123 mTodoList.append( todo ); 00124 00125 todo->registerObserver( this ); 00126 00127 // Set up subtask relations 00128 setupRelations( todo ); 00129 00130 setModified( true ); 00131 00132 return true; 00133 } 00134 00135 void CalendarLocal::deleteTodo( Todo *todo ) 00136 { 00137 // Handle orphaned children 00138 removeRelations( todo ); 00139 00140 if ( mTodoList.removeRef( todo ) ) { 00141 setModified( true ); 00142 } 00143 } 00144 00145 void CalendarLocal::deleteAllTodos() 00146 { 00147 // kdDebug(5800) << "CalendarLocal::deleteAllTodos()\n"; 00148 mTodoList.setAutoDelete( true ); 00149 mTodoList.clear(); 00150 mTodoList.setAutoDelete( false ); 00151 } 00152 00153 Todo::List CalendarLocal::rawTodos() 00154 { 00155 return mTodoList; 00156 } 00157 00158 Todo *CalendarLocal::todo( const QString &uid ) 00159 { 00160 Todo::List::ConstIterator it; 00161 for ( it = mTodoList.begin(); it != mTodoList.end(); ++it ) { 00162 if ( (*it)->uid() == uid ) return *it; 00163 } 00164 00165 return 0; 00166 } 00167 00168 Todo::List CalendarLocal::todos( const QDate &date ) 00169 { 00170 Todo::List todos; 00171 00172 Todo::List::ConstIterator it; 00173 for ( it = mTodoList.begin(); it != mTodoList.end(); ++it ) { 00174 Todo *todo = *it; 00175 if ( todo->hasDueDate() && todo->dtDue().date() == date ) { 00176 todos.append( todo ); 00177 } 00178 } 00179 00180 return todos; 00181 } 00182 00183 Alarm::List CalendarLocal::alarmsTo( const QDateTime &to ) 00184 { 00185 return alarms( QDateTime( QDate( 1900, 1, 1 ) ), to ); 00186 } 00187 00188 Alarm::List CalendarLocal::alarms( const QDateTime &from, const QDateTime &to ) 00189 { 00190 // kdDebug(5800) << "CalendarLocal::alarms(" << from.toString() << " - " 00191 // << to.toString() << ")" << endl; 00192 00193 Alarm::List alarms; 00194 00195 EventDictIterator it( mEvents ); 00196 for( ; it.current(); ++it ) { 00197 Event *e = *it; 00198 if ( e->doesRecur() ) appendRecurringAlarms( alarms, e, from, to ); 00199 else appendAlarms( alarms, e, from, to ); 00200 } 00201 00202 Todo::List::ConstIterator it2; 00203 for( it2 = mTodoList.begin(); it2 != mTodoList.end(); ++it2 ) { 00204 if (! (*it2)->isCompleted() ) appendAlarms( alarms, *it2, from, to ); 00205 } 00206 00207 return alarms; 00208 } 00209 00210 void CalendarLocal::appendAlarms( Alarm::List &alarms, Incidence *incidence, 00211 const QDateTime &from, const QDateTime &to ) 00212 { 00213 Alarm::List::ConstIterator it; 00214 for( it = incidence->alarms().begin(); it != incidence->alarms().end(); 00215 ++it ) { 00216 // kdDebug(5800) << "CalendarLocal::appendAlarms() '" << alarm->text() 00217 // << "': " << alarm->time().toString() << " - " << alarm->enabled() << endl; 00218 if ( (*it)->enabled() ) { 00219 if ( (*it)->time() >= from && (*it)->time() <= to ) { 00220 kdDebug(5800) << "CalendarLocal::appendAlarms() '" 00221 << incidence->summary() << "': " 00222 << (*it)->time().toString() << endl; 00223 alarms.append( *it ); 00224 } 00225 } 00226 } 00227 } 00228 00229 void CalendarLocal::appendRecurringAlarms( Alarm::List &alarms, 00230 Incidence *incidence, 00231 const QDateTime &from, 00232 const QDateTime &to ) 00233 { 00234 Alarm::List::ConstIterator it; 00235 QDateTime qdt; 00236 int endOffset = 0; 00237 bool endOffsetValid = false; 00238 for( it = incidence->alarms().begin(); it != incidence->alarms().end(); 00239 ++it ) { 00240 Alarm *alarm = *it; 00241 if ( alarm->hasTime() ) { 00242 // The alarm time is defined as an absolute date/time 00243 qdt = alarm->time(); 00244 } else { 00245 // The alarm time is defined by an offset from the event start or end time. 00246 // Find the offset from the event start time, which is also used as the 00247 // offset from the recurrence time. 00248 int offset = 0; 00249 if ( alarm->hasStartOffset() ) { 00250 offset = alarm->startOffset().asSeconds(); 00251 } else if ( alarm->hasEndOffset() ) { 00252 if ( !endOffsetValid ) { 00253 endOffset = incidence->dtStart().secsTo( incidence->dtEnd() ); 00254 endOffsetValid = true; 00255 } 00256 offset = alarm->endOffset().asSeconds() + endOffset; 00257 } 00258 // Adjust the 'from' date/time and find the next recurrence at or after it 00259 qdt = incidence->recurrence()->getNextDateTime( from.addSecs(-offset - 1) ); 00260 if (!qdt.isValid() || incidence->isException(qdt.date()) ) 00261 continue; 00262 // Remove the adjustment to get the alarm time 00263 qdt = qdt.addSecs( offset ); 00264 } 00265 kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary() 00266 << "': " << qdt.toString() << " - " << (*it)->enabled() 00267 << endl; 00268 if ( (*it)->enabled() ) { 00269 // kdDebug(5800) << "CalendarLocal::appendAlarms() '" << incidence->summary() 00270 // << "': " << (*it)->time().toString() << endl; 00271 if ( qdt >= from && qdt <= to ) { 00272 alarms.append( *it ); 00273 } 00274 } 00275 } 00276 } 00277 00278 00279 // after changes are made to an event, this should be called. 00280 void CalendarLocal::update( IncidenceBase *incidence ) 00281 { 00282 incidence->setSyncStatus( Event::SYNCMOD ); 00283 incidence->setLastModified( QDateTime::currentDateTime() ); 00284 // we should probably update the revision number here, 00285 // or internally in the Event itself when certain things change. 00286 // need to verify with ical documentation. 00287 00288 setModified( true ); 00289 } 00290 00291 void CalendarLocal::insertEvent( Event *event ) 00292 { 00293 QString uid = event->uid(); 00294 if ( mEvents[ uid ] == 0 ) { 00295 mEvents.insert( uid, event ); 00296 } 00297 #ifndef NDEBUG 00298 else // if we already have an event with this UID, it has to be the same event, 00299 // otherwise something's really broken 00300 Q_ASSERT( mEvents[uid] == event ); 00301 #endif 00302 } 00303 00304 00305 Event::List CalendarLocal::rawEventsForDate( const QDate &qd, bool sorted ) 00306 { 00307 Event::List eventList; 00308 00309 EventDictIterator it( mEvents ); 00310 for( ; it.current(); ++it ) { 00311 Event *event = *it; 00312 00313 if ( event->doesRecur() ) { 00314 if ( event->isMultiDay() ) { 00315 int extraDays = event->dtStart().date().daysTo( event->dtEnd().date() ); 00316 int i; 00317 for ( i = 0; i <= extraDays; i++ ) { 00318 if ( event->recursOn( qd.addDays( -i ) ) ) { 00319 eventList.append( event ); 00320 break; 00321 } 00322 } 00323 } else { 00324 if ( event->recursOn( qd ) ) 00325 eventList.append( event ); 00326 } 00327 } else { 00328 if ( event->dtStart().date() <= qd && event->dtEnd().date() >= qd ) { 00329 eventList.append( event ); 00330 } 00331 } 00332 } 00333 00334 if ( !sorted ) { 00335 return eventList; 00336 } 00337 00338 // kdDebug(5800) << "Sorting events for date\n" << endl; 00339 // now, we have to sort it based on dtStart.time() 00340 Event::List eventListSorted; 00341 Event::List::Iterator sortIt; 00342 Event::List::Iterator eit; 00343 for ( eit = eventList.begin(); eit != eventList.end(); ++eit ) { 00344 sortIt = eventListSorted.begin(); 00345 while ( sortIt != eventListSorted.end() && 00346 (*eit)->dtStart().time() >= (*sortIt)->dtStart().time() ) { 00347 ++sortIt; 00348 } 00349 eventListSorted.insert( sortIt, *eit ); 00350 } 00351 return eventListSorted; 00352 } 00353 00354 00355 Event::List CalendarLocal::rawEvents( const QDate &start, const QDate &end, 00356 bool inclusive ) 00357 { 00358 Event::List eventList; 00359 00360 // Get non-recurring events 00361 EventDictIterator it( mEvents ); 00362 for( ; it.current(); ++it ) { 00363 Event *event = *it; 00364 if ( event->doesRecur() ) { 00365 QDate rStart = event->dtStart().date(); 00366 bool found = false; 00367 if ( inclusive ) { 00368 if ( rStart >= start && rStart <= end ) { 00369 // Start date of event is in range. Now check for end date. 00370 // if duration is negative, event recurs forever, so do not include it. 00371 if ( event->recurrence()->duration() == 0 ) { // End date set 00372 QDate rEnd = event->recurrence()->endDate(); 00373 if ( rEnd >= start && rEnd <= end ) { // End date within range 00374 found = true; 00375 } 00376 } else if ( event->recurrence()->duration() > 0 ) { // Duration set 00377 // TODO: Calculate end date from duration. Should be done in Event 00378 // For now exclude all events with a duration. 00379 } 00380 } 00381 } else { 00382 if ( rStart <= end ) { // Start date not after range 00383 if ( rStart >= start ) { // Start date within range 00384 found = true; 00385 } else if ( event->recurrence()->duration() == -1 ) { // Recurs forever 00386 found = true; 00387 } else if ( event->recurrence()->duration() == 0 ) { // End date set 00388 QDate rEnd = event->recurrence()->endDate(); 00389 if ( rEnd >= start && rEnd <= end ) { // End date within range 00390 found = true; 00391 } 00392 } else { // Duration set 00393 // TODO: Calculate end date from duration. Should be done in Event 00394 // For now include all events with a duration. 00395 found = true; 00396 } 00397 } 00398 } 00399 00400 if ( found ) eventList.append( event ); 00401 } else { 00402 QDate s = event->dtStart().date(); 00403 QDate e = event->dtEnd().date(); 00404 00405 if ( inclusive ) { 00406 if ( s >= start && e <= end ) { 00407 eventList.append( event ); 00408 } 00409 } else { 00410 if ( ( s >= start && s <= end ) || ( e >= start && e <= end ) ) { 00411 eventList.append( event ); 00412 } 00413 } 00414 } 00415 } 00416 00417 return eventList; 00418 } 00419 00420 Event::List CalendarLocal::rawEventsForDate( const QDateTime &qdt ) 00421 { 00422 return rawEventsForDate( qdt.date() ); 00423 } 00424 00425 Event::List CalendarLocal::rawEvents() 00426 { 00427 Event::List eventList; 00428 EventDictIterator it( mEvents ); 00429 for( ; it.current(); ++it ) 00430 eventList.append( *it ); 00431 return eventList; 00432 } 00433 00434 bool CalendarLocal::addJournal(Journal *journal) 00435 { 00436 if (journal->dtStart().isValid()) 00437 kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl; 00438 else 00439 kdDebug(5800) << "Adding Journal without a DTSTART" << endl; 00440 00441 mJournalList.append(journal); 00442 00443 journal->registerObserver( this ); 00444 00445 setModified( true ); 00446 00447 return true; 00448 } 00449 00450 void CalendarLocal::deleteJournal( Journal *journal ) 00451 { 00452 if ( mJournalList.removeRef(journal) ) { 00453 setModified( true ); 00454 } 00455 } 00456 00457 void CalendarLocal::deleteAllJournals() 00458 { 00459 mJournalList.setAutoDelete( true ); 00460 mJournalList.clear(); 00461 mJournalList.setAutoDelete( false ); 00462 } 00463 00464 Journal *CalendarLocal::journal( const QDate &date ) 00465 { 00466 // kdDebug(5800) << "CalendarLocal::journal() " << date.toString() << endl; 00467 00468 Journal::List::ConstIterator it; 00469 for ( it = mJournalList.begin(); it != mJournalList.end(); ++it ) 00470 if ( (*it)->dtStart().date() == date ) 00471 return *it; 00472 00473 return 0; 00474 } 00475 00476 Journal *CalendarLocal::journal( const QString &uid ) 00477 { 00478 Journal::List::ConstIterator it; 00479 for ( it = mJournalList.begin(); it != mJournalList.end(); ++it ) 00480 if ( (*it)->uid() == uid ) 00481 return *it; 00482 00483 return 0; 00484 } 00485 00486 Journal::List CalendarLocal::journals() 00487 { 00488 return mJournalList; 00489 } 00490
KDE Logo
This file is part of the documentation for libkcal Library Version 3.2.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 28 23:57:44 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003