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 Sat May 1 11:36:21 2004 by doxygen 1.2.15 written by Dimitri van Heesch, © 1997-2003