libkcal Library API Documentation

calendar.cpp

00001 /* 00002 This file is part of libkcal. 00003 00004 Copyright (c) 1998 Preston Brown 00005 Copyright (c) 2000-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 <stdlib.h> 00024 00025 #include <kdebug.h> 00026 #include <klocale.h> 00027 00028 #include "exceptions.h" 00029 #include "calfilter.h" 00030 00031 #include "calendar.h" 00032 00033 using namespace KCal; 00034 00035 Calendar::Calendar() 00036 { 00037 mTimeZoneId = QString::fromLatin1( "UTC" ); 00038 mLocalTime = false; 00039 00040 init(); 00041 } 00042 00043 Calendar::Calendar( const QString &timeZoneId ) 00044 { 00045 mTimeZoneId = timeZoneId; 00046 mLocalTime = false; 00047 00048 init(); 00049 } 00050 00051 void Calendar::init() 00052 { 00053 mNewObserver = false; 00054 mObserversEnabled = true; 00055 00056 mModified = false; 00057 00058 // Setup default filter, which does nothing 00059 mDefaultFilter = new CalFilter; 00060 mFilter = mDefaultFilter; 00061 mFilter->setEnabled(false); 00062 00063 // initialize random numbers. This is a hack, and not 00064 // even that good of one at that. 00065 // srandom(time(0)); 00066 00067 // user information... 00068 setOwner(i18n("Unknown Name")); 00069 setEmail(i18n("unknown@nowhere")); 00070 00071 #if 0 00072 tmpStr = KOPrefs::instance()->mTimeZone; 00073 // kdDebug(5800) << "Calendar::Calendar(): TimeZone: " << tmpStr << endl; 00074 int dstSetting = KOPrefs::instance()->mDaylightSavings; 00075 extern long int timezone; 00076 struct tm *now; 00077 time_t curtime; 00078 curtime = time(0); 00079 now = localtime(&curtime); 00080 int hourOff = - ((timezone / 60) / 60); 00081 if (now->tm_isdst) 00082 hourOff += 1; 00083 QString tzStr; 00084 tzStr.sprintf("%.2d%.2d", 00085 hourOff, 00086 abs((timezone / 60) % 60)); 00087 00088 // if no time zone was in the config file, write what we just discovered. 00089 if (tmpStr.isEmpty()) { 00090 // KOPrefs::instance()->mTimeZone = tzStr; 00091 } else { 00092 tzStr = tmpStr; 00093 } 00094 00095 // if daylight savings has changed since last load time, we need 00096 // to rewrite these settings to the config file. 00097 if ((now->tm_isdst && !dstSetting) || 00098 (!now->tm_isdst && dstSetting)) { 00099 KOPrefs::instance()->mTimeZone = tzStr; 00100 KOPrefs::instance()->mDaylightSavings = now->tm_isdst; 00101 } 00102 00103 setTimeZone(tzStr); 00104 #endif 00105 00106 // KOPrefs::instance()->writeConfig(); 00107 } 00108 00109 Calendar::~Calendar() 00110 { 00111 delete mDefaultFilter; 00112 } 00113 00114 const QString &Calendar::getOwner() const 00115 { 00116 return mOwner; 00117 } 00118 00119 void Calendar::setOwner(const QString &os) 00120 { 00121 int i; 00122 mOwner = os; 00123 i = mOwner.find(','); 00124 if (i != -1) 00125 mOwner = mOwner.left(i); 00126 00127 setModified( true ); 00128 } 00129 00130 void Calendar::setTimeZoneId(const QString &id) 00131 { 00132 mTimeZoneId = id; 00133 mLocalTime = false; 00134 00135 setModified( true ); 00136 doSetTimeZoneId( id ); 00137 } 00138 00139 QString Calendar::timeZoneId() const 00140 { 00141 return mTimeZoneId; 00142 } 00143 00144 void Calendar::setLocalTime() 00145 { 00146 mLocalTime = true; 00147 mTimeZone = 0; 00148 mTimeZoneId = ""; 00149 00150 setModified( true ); 00151 } 00152 00153 bool Calendar::isLocalTime() const 00154 { 00155 return mLocalTime; 00156 } 00157 00158 const QString &Calendar::getEmail() 00159 { 00160 return mOwnerEmail; 00161 } 00162 00163 void Calendar::setEmail(const QString &e) 00164 { 00165 mOwnerEmail = e; 00166 00167 setModified( true ); 00168 } 00169 00170 void Calendar::setFilter(CalFilter *filter) 00171 { 00172 mFilter = filter; 00173 } 00174 00175 CalFilter *Calendar::filter() 00176 { 00177 return mFilter; 00178 } 00179 00180 QStringList Calendar::incidenceCategories() 00181 { 00182 Incidence::List rawInc( rawIncidences() ); 00183 QStringList categories, thisCats; 00184 // TODO: For now just iterate over all incidences. In the future, 00185 // the list of categories should be built when reading the file. 00186 for ( Incidence::List::ConstIterator i = rawInc.constBegin(); i != rawInc.constEnd(); ++i ) { 00187 thisCats = (*i)->categories(); 00188 for ( QStringList::ConstIterator si = thisCats.constBegin(); si != thisCats.constEnd(); ++si ) { 00189 if ( categories.find( *si ) == categories.end() ) { 00190 categories.append( *si ); 00191 } 00192 } 00193 } 00194 return categories; 00195 } 00196 00197 Incidence::List Calendar::incidences( const QDate &qdt ) 00198 { 00199 Journal::List jnls; 00200 Journal*jnl = journal(qdt); 00201 if (jnl) jnls.append( journal(qdt) ); 00202 return mergeIncidenceList( events( qdt ), todos( qdt ), jnls ); 00203 } 00204 00205 Incidence::List Calendar::incidences() 00206 { 00207 return mergeIncidenceList( events(), todos(), journals() ); 00208 } 00209 00210 Incidence::List Calendar::rawIncidences() 00211 { 00212 return mergeIncidenceList( rawEvents(), rawTodos(), journals() ); 00213 } 00214 00215 Event::List Calendar::events( const QDate &date, bool sorted ) 00216 { 00217 Event::List el = rawEventsForDate( date, sorted ); 00218 00219 mFilter->apply(&el); 00220 00221 return el; 00222 } 00223 00224 Event::List Calendar::events( const QDateTime &qdt ) 00225 { 00226 Event::List el = rawEventsForDate(qdt); 00227 mFilter->apply(&el); 00228 return el; 00229 } 00230 00231 Event::List Calendar::events( const QDate &start, const QDate &end, 00232 bool inclusive) 00233 { 00234 Event::List el = rawEvents(start,end,inclusive); 00235 mFilter->apply(&el); 00236 return el; 00237 } 00238 00239 Event::List Calendar::events() 00240 { 00241 Event::List el = rawEvents(); 00242 mFilter->apply(&el); 00243 return el; 00244 } 00245 00246 00247 bool Calendar::addIncidence(Incidence *i) 00248 { 00249 Incidence::AddVisitor<Calendar> v(this); 00250 00251 return i->accept(v); 00252 } 00253 00254 bool Calendar::deleteIncidence( Incidence *i ) 00255 { 00256 Incidence::DeleteVisitor<Calendar> v( this ); 00257 return i->accept( v ); 00258 } 00259 00260 Incidence *Calendar::dissociateOccurrence( Incidence *incidence, QDate date, 00261 bool single ) 00262 { 00263 if ( !incidence || !incidence->doesRecur() ) return 0; 00264 00265 Incidence *newInc = incidence->clone(); 00266 newInc->recreate(); 00267 newInc->setRelatedTo( incidence ); 00268 Recurrence *recur = newInc->recurrence(); 00269 if ( single ) { 00270 recur->unsetRecurs(); 00271 } else { 00272 // Adjust the recurrence for the future incidences. In particular 00273 // adjust the "end after n occurences" rules! "No end date" and "end by ..." 00274 // don't need to be modified. 00275 int duration = recur->duration(); 00276 if ( duration > 0 ) { 00277 int doneduration = recur->durationTo( date.addDays(-1) ); 00278 if ( doneduration >= duration ) { 00279 kdDebug(5850) << "The dissociated event already occured more often that it was supposed to ever occur. ERROR!" << endl; 00280 recur->unsetRecurs(); 00281 } else { 00282 recur->setDuration( duration - doneduration ); 00283 } 00284 } 00285 } 00286 // Adjust the date of the incidence 00287 if ( incidence->type() == "Event" ) { 00288 Event *ev = static_cast<Event *>( newInc ); 00289 QDateTime start( ev->dtStart() ); 00290 int daysTo = start.date().daysTo( date ); 00291 ev->setDtStart( start.addDays( daysTo ) ); 00292 ev->setDtEnd( ev->dtEnd().addDays( daysTo ) ); 00293 } else if ( incidence->type() == "Todo" ) { 00294 Todo *td = static_cast<Todo *>( newInc ); 00295 bool haveOffset = false; 00296 int daysTo = 0; 00297 if ( td->hasDueDate() ) { 00298 QDateTime due( td->dtDue() ); 00299 daysTo = due.date().daysTo( date ) ; 00300 td->setDtDue( due.addDays( daysTo ) ); 00301 haveOffset = true; 00302 } 00303 if ( td->hasStartDate() ) { 00304 QDateTime start( td->dtStart() ); 00305 if ( !haveOffset ) daysTo = start.date().daysTo( date ); 00306 td->setDtStart( start.addDays( daysTo ) ); 00307 haveOffset = true; 00308 } 00309 } 00310 if ( addIncidence( newInc ) ) { 00311 if (single) { 00312 incidence->addExDate( date ); 00313 } else { 00314 recur = incidence->recurrence(); 00315 if ( recur ) { 00316 // Make sure the recurrence of the past events ends at the corresponding day 00317 recur->setEndDate( date.addDays(-1) ); 00318 } 00319 } 00320 } else { 00321 delete newInc; 00322 return 0; 00323 } 00324 return newInc; 00325 } 00326 00327 Incidence *Calendar::incidence( const QString& uid ) 00328 { 00329 Incidence *i = event( uid ); 00330 if ( i ) return i; 00331 i = todo( uid ); 00332 if ( i ) return i; 00333 i = journal( uid ); 00334 return i; 00335 } 00336 00337 Todo::List Calendar::todos() 00338 { 00339 Todo::List tl = rawTodos(); 00340 mFilter->apply( &tl ); 00341 return tl; 00342 } 00343 00344 Todo::List Calendar::todos( const QDate &date ) 00345 { 00346 Todo::List el = rawTodosForDate( date ); 00347 00348 mFilter->apply(&el); 00349 00350 return el; 00351 } 00352 00353 00354 // When this is called, the todo have already been added to the calendar. 00355 // This method is only about linking related todos 00356 void Calendar::setupRelations( Incidence *incidence ) 00357 { 00358 QString uid = incidence->uid(); 00359 00360 // First, go over the list of orphans and see if this is their parent 00361 while( Incidence* i = mOrphans[ uid ] ) { 00362 mOrphans.remove( uid ); 00363 i->setRelatedTo( incidence ); 00364 incidence->addRelation( i ); 00365 mOrphanUids.remove( i->uid() ); 00366 } 00367 00368 // Now see about this incidences parent 00369 if( !incidence->relatedTo() && !incidence->relatedToUid().isEmpty() ) { 00370 // This incidence has a uid it is related to, but is not registered to it yet 00371 // Try to find it 00372 Incidence* parent = this->incidence( incidence->relatedToUid() ); 00373 if( parent ) { 00374 // Found it 00375 incidence->setRelatedTo( parent ); 00376 parent->addRelation( incidence ); 00377 } else { 00378 // Not found, put this in the mOrphans list 00379 mOrphans.insert( incidence->relatedToUid(), incidence ); 00380 mOrphanUids.insert( incidence->uid(), incidence ); 00381 } 00382 } 00383 } 00384 00385 // If a task with subtasks is deleted, move it's subtasks to the orphans list 00386 void Calendar::removeRelations( Incidence *incidence ) 00387 { 00388 if( !incidence ) { 00389 kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n"; 00390 return; 00391 } 00392 00393 QString uid = incidence->uid(); 00394 00395 Incidence::List relations = incidence->relations(); 00396 Incidence::List::ConstIterator it; 00397 for( it = relations.begin(); it != relations.end(); ++it ) { 00398 Incidence *i = *it; 00399 if( !mOrphanUids.find( i->uid() ) ) { 00400 mOrphans.insert( uid, i ); 00401 mOrphanUids.insert( i->uid(), i ); 00402 i->setRelatedTo( 0 ); 00403 i->setRelatedToUid( uid ); 00404 } 00405 } 00406 00407 // If this incidence is related to something else, tell that about it 00408 if( incidence->relatedTo() ) 00409 incidence->relatedTo()->removeRelation( incidence ); 00410 00411 // Remove this one from the orphans list 00412 if( mOrphanUids.remove( uid ) ) 00413 // This incidence is located in the orphans list - it should be removed 00414 if( !( incidence->relatedTo() != 0 && mOrphans.remove( incidence->relatedTo()->uid() ) ) ) { 00415 // Removing wasn't that easy 00416 for( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) { 00417 if( it.current()->uid() == uid ) { 00418 mOrphans.remove( it.currentKey() ); 00419 break; 00420 } 00421 } 00422 } 00423 } 00424 00425 void Calendar::registerObserver( Observer *observer ) 00426 { 00427 if( !mObservers.contains( observer ) ) mObservers.append( observer ); 00428 mNewObserver = true; 00429 } 00430 00431 void Calendar::unregisterObserver( Observer *observer ) 00432 { 00433 mObservers.remove( observer ); 00434 } 00435 00436 void Calendar::setModified( bool modified ) 00437 { 00438 if ( modified != mModified || mNewObserver ) { 00439 mNewObserver = false; 00440 Observer *observer; 00441 for( observer = mObservers.first(); observer; 00442 observer = mObservers.next() ) { 00443 observer->calendarModified( modified, this ); 00444 } 00445 mModified = modified; 00446 } 00447 } 00448 00449 void Calendar::notifyIncidenceAdded( Incidence *i ) 00450 { 00451 if ( !mObserversEnabled ) return; 00452 00453 Observer *observer; 00454 for( observer = mObservers.first(); observer; 00455 observer = mObservers.next() ) { 00456 observer->calendarIncidenceAdded( i ); 00457 } 00458 } 00459 00460 void Calendar::notifyIncidenceChanged( Incidence *i ) 00461 { 00462 if ( !mObserversEnabled ) return; 00463 00464 Observer *observer; 00465 for( observer = mObservers.first(); observer; 00466 observer = mObservers.next() ) { 00467 observer->calendarIncidenceChanged( i ); 00468 } 00469 } 00470 00471 void Calendar::notifyIncidenceDeleted( Incidence *i ) 00472 { 00473 if ( !mObserversEnabled ) return; 00474 00475 Observer *observer; 00476 for( observer = mObservers.first(); observer; 00477 observer = mObservers.next() ) { 00478 observer->calendarIncidenceDeleted( i ); 00479 } 00480 } 00481 00482 void Calendar::setLoadedProductId( const QString &id ) 00483 { 00484 mLoadedProductId = id; 00485 } 00486 00487 QString Calendar::loadedProductId() 00488 { 00489 return mLoadedProductId; 00490 } 00491 00492 Incidence::List Calendar::mergeIncidenceList( const Event::List &e, 00493 const Todo::List &t, 00494 const Journal::List &j ) 00495 { 00496 Incidence::List incidences; 00497 00498 Event::List::ConstIterator it1; 00499 for( it1 = e.begin(); it1 != e.end(); ++it1 ) incidences.append( *it1 ); 00500 00501 Todo::List::ConstIterator it2; 00502 for( it2 = t.begin(); it2 != t.end(); ++it2 ) incidences.append( *it2 ); 00503 00504 Journal::List::ConstIterator it3; 00505 for( it3 = j.begin(); it3 != j.end(); ++it3 ) incidences.append( *it3 ); 00506 00507 return incidences; 00508 } 00509 00510 bool Calendar::beginChange( Incidence * ) 00511 { 00512 return true; 00513 } 00514 00515 bool Calendar::endChange( Incidence * ) 00516 { 00517 return true; 00518 } 00519 00520 void Calendar::setObserversEnabled( bool enabled ) 00521 { 00522 mObserversEnabled = enabled; 00523 } 00524 00525 #include "calendar.moc"
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 Oct 1 15:18:42 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003