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 Incidence::List Calendar::incidencesFromSchedulingID( const QString &UID )
00338 {
00339   Incidence::List result;
00340   Incidence::List incidences = rawIncidences();
00341   Incidence::List::iterator it = incidences.begin();
00342   for ( ; it != incidences.end(); ++it )
00343     if ( (*it)->schedulingID() == UID )
00344       result.append( *it );
00345   return result;
00346 }
00347 
00348 Incidence *Calendar::incidenceFromSchedulingID( const QString &UID )
00349 {
00350   Incidence::List incidences = rawIncidences();
00351   Incidence::List::iterator it = incidences.begin();
00352   for ( ; it != incidences.end(); ++it )
00353     if ( (*it)->schedulingID() == UID )
00354       // Touchdown, and the crowd goes wild
00355       return *it;
00356   // Not found
00357   return 0;
00358 }
00359 
00360 Todo::List Calendar::todos()
00361 {
00362   Todo::List tl = rawTodos();
00363   mFilter->apply( &tl );
00364   return tl;
00365 }
00366 
00367 Todo::List Calendar::todos( const QDate &date )
00368 {
00369   Todo::List el = rawTodosForDate( date );
00370 
00371   mFilter->apply(&el);
00372 
00373   return el;
00374 }
00375 
00376 
00377 // When this is called, the todo have already been added to the calendar.
00378 // This method is only about linking related todos
00379 void Calendar::setupRelations( Incidence *incidence )
00380 {
00381   QString uid = incidence->uid();
00382 
00383   // First, go over the list of orphans and see if this is their parent
00384   while( Incidence* i = mOrphans[ uid ] ) {
00385     mOrphans.remove( uid );
00386     i->setRelatedTo( incidence );
00387     incidence->addRelation( i );
00388     mOrphanUids.remove( i->uid() );
00389   }
00390 
00391   // Now see about this incidences parent
00392   if( !incidence->relatedTo() && !incidence->relatedToUid().isEmpty() ) {
00393     // This incidence has a uid it is related to, but is not registered to it yet
00394     // Try to find it
00395     Incidence* parent = this->incidence( incidence->relatedToUid() );
00396     if( parent ) {
00397       // Found it
00398       incidence->setRelatedTo( parent );
00399       parent->addRelation( incidence );
00400     } else {
00401       // Not found, put this in the mOrphans list
00402       mOrphans.insert( incidence->relatedToUid(), incidence );
00403       mOrphanUids.insert( incidence->uid(), incidence );
00404     }
00405   }
00406 }
00407 
00408 // If a task with subtasks is deleted, move it's subtasks to the orphans list
00409 void Calendar::removeRelations( Incidence *incidence )
00410 {
00411   if( !incidence ) {
00412     kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n";
00413     return;
00414   }
00415 
00416   QString uid = incidence->uid();
00417 
00418   Incidence::List relations = incidence->relations();
00419   Incidence::List::ConstIterator it;
00420   for( it = relations.begin(); it != relations.end(); ++it ) {
00421     Incidence *i = *it;
00422     if( !mOrphanUids.find( i->uid() ) ) {
00423       mOrphans.insert( uid, i );
00424       mOrphanUids.insert( i->uid(), i );
00425       i->setRelatedTo( 0 );
00426       i->setRelatedToUid( uid );
00427     }
00428   }
00429 
00430   // If this incidence is related to something else, tell that about it
00431   if( incidence->relatedTo() )
00432     incidence->relatedTo()->removeRelation( incidence );
00433 
00434   // Remove this one from the orphans list
00435   if( mOrphanUids.remove( uid ) )
00436     // This incidence is located in the orphans list - it should be removed
00437     if( !( incidence->relatedTo() != 0 && mOrphans.remove( incidence->relatedTo()->uid() ) ) ) {
00438       // Removing wasn't that easy
00439       for( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) {
00440     if( it.current()->uid() == uid ) {
00441       mOrphans.remove( it.currentKey() );
00442       break;
00443     }
00444       }
00445     }
00446 }
00447 
00448 void Calendar::registerObserver( Observer *observer )
00449 {
00450   if( !mObservers.contains( observer ) ) mObservers.append( observer );
00451   mNewObserver = true;
00452 }
00453 
00454 void Calendar::unregisterObserver( Observer *observer )
00455 {
00456   mObservers.remove( observer );
00457 }
00458 
00459 void Calendar::setModified( bool modified )
00460 {
00461   if ( modified != mModified || mNewObserver ) {
00462     mNewObserver = false;
00463     Observer *observer;
00464     for( observer = mObservers.first(); observer;
00465          observer = mObservers.next() ) {
00466       observer->calendarModified( modified, this );
00467     }
00468     mModified = modified;
00469   }
00470 }
00471 
00472 void Calendar::notifyIncidenceAdded( Incidence *i )
00473 {
00474   if ( !mObserversEnabled ) return;
00475 
00476   Observer *observer;
00477   for( observer = mObservers.first(); observer;
00478        observer = mObservers.next() ) {
00479     observer->calendarIncidenceAdded( i );
00480   }
00481 }
00482 
00483 void Calendar::notifyIncidenceChanged( Incidence *i )
00484 {
00485   if ( !mObserversEnabled ) return;
00486 
00487   Observer *observer;
00488   for( observer = mObservers.first(); observer;
00489        observer = mObservers.next() ) {
00490     observer->calendarIncidenceChanged( i );
00491   }
00492 }
00493 
00494 void Calendar::notifyIncidenceDeleted( Incidence *i )
00495 {
00496   if ( !mObserversEnabled ) return;
00497 
00498   Observer *observer;
00499   for( observer = mObservers.first(); observer;
00500        observer = mObservers.next() ) {
00501     observer->calendarIncidenceDeleted( i );
00502   }
00503 }
00504 
00505 void Calendar::setLoadedProductId( const QString &id )
00506 {
00507   mLoadedProductId = id;
00508 }
00509 
00510 QString Calendar::loadedProductId()
00511 {
00512   return mLoadedProductId;
00513 }
00514 
00515 Incidence::List Calendar::mergeIncidenceList( const Event::List &e,
00516                                               const Todo::List &t,
00517                                               const Journal::List &j )
00518 {
00519   Incidence::List incidences;
00520 
00521   Event::List::ConstIterator it1;
00522   for( it1 = e.begin(); it1 != e.end(); ++it1 ) incidences.append( *it1 );
00523 
00524   Todo::List::ConstIterator it2;
00525   for( it2 = t.begin(); it2 != t.end(); ++it2 ) incidences.append( *it2 );
00526 
00527   Journal::List::ConstIterator it3;
00528   for( it3 = j.begin(); it3 != j.end(); ++it3 ) incidences.append( *it3 );
00529 
00530   return incidences;
00531 }
00532 
00533 bool Calendar::beginChange( Incidence * )
00534 {
00535   return true;
00536 }
00537 
00538 bool Calendar::endChange( Incidence * )
00539 {
00540   return true;
00541 }
00542 
00543 void Calendar::setObserversEnabled( bool enabled )
00544 {
00545   mObserversEnabled = enabled;
00546 }
00547 
00548 #include "calendar.moc"
KDE Logo
This file is part of the documentation for libkcal Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Dec 21 14:22:06 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003