libkcal

calendar.cpp

Go to the documentation of this file.
00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 1998 Preston Brown <pbrown@kde.org>
00005     Copyright (c) 2000-2004 Cornelius Schumacher <schumacher@kde.org>
00006     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00007 
00008     This library is free software; you can redistribute it and/or
00009     modify it under the terms of the GNU Library General Public
00010     License as published by the Free Software Foundation; either
00011     version 2 of the License, or (at your option) any later version.
00012 
00013     This library is distributed in the hope that it will be useful,
00014     but WITHOUT ANY WARRANTY; without even the implied warranty of
00015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016     Library General Public License for more details.
00017 
00018     You should have received a copy of the GNU Library General Public License
00019     along with this library; see the file COPYING.LIB.  If not, write to
00020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021     Boston, MA 02110-1301, USA.
00022 */
00031 #include <stdlib.h>
00032 
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035 
00036 #include "exceptions.h"
00037 #include "calfilter.h"
00038 
00039 #include "calendar.h"
00040 
00041 using namespace KCal;
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   // user information...
00064   setOwner( Person( i18n( "Unknown Name" ), i18n( "unknown@nowhere" ) ) );
00065 }
00066 
00067 Calendar::~Calendar()
00068 {
00069   delete mDefaultFilter;
00070 }
00071 
00072 const Person &Calendar::getOwner() const
00073 {
00074   return mOwner;
00075 }
00076 
00077 void Calendar::setOwner( const Person &owner )
00078 {
00079   mOwner = owner;
00080 
00081   setModified( true );
00082 }
00083 
00084 void Calendar::setTimeZoneId( const QString &timeZoneId )
00085 {
00086   mTimeZoneId = timeZoneId;
00087   mLocalTime = false;
00088 
00089   setModified( true );
00090   doSetTimeZoneId( timeZoneId );
00091 }
00092 
00093 QString Calendar::timeZoneId() const
00094 {
00095   return mTimeZoneId;
00096 }
00097 
00098 void Calendar::setLocalTime()
00099 {
00100   mLocalTime = true;
00101   mTimeZoneId = "";
00102 
00103   setModified( true );
00104 }
00105 
00106 bool Calendar::isLocalTime() const
00107 {
00108   return mLocalTime;
00109 }
00110 
00111 void Calendar::setFilter( CalFilter *filter )
00112 {
00113   if ( filter ) {
00114     mFilter = filter;
00115   } else {
00116     mFilter = mDefaultFilter;
00117   }
00118 }
00119 
00120 CalFilter *Calendar::filter()
00121 {
00122   return mFilter;
00123 }
00124 
00125 QStringList Calendar::categories()
00126 {
00127   Incidence::List rawInc( rawIncidences() );
00128   QStringList cats, thisCats;
00129   // @TODO: For now just iterate over all incidences. In the future,
00130   // the list of categories should be built when reading the file.
00131   for ( Incidence::List::ConstIterator i = rawInc.constBegin();
00132         i != rawInc.constEnd(); ++i ) {
00133     thisCats = (*i)->categories();
00134     for ( QStringList::ConstIterator si = thisCats.constBegin();
00135           si != thisCats.constEnd(); ++si ) {
00136       if ( cats.find( *si ) == cats.end() ) {
00137         cats.append( *si );
00138       }
00139     }
00140   }
00141   return cats;
00142 }
00143 
00144 Incidence::List Calendar::incidences( const QDate &date )
00145 {
00146   return mergeIncidenceList( events( date ), todos( date ), journals( date ) );
00147 }
00148 
00149 Incidence::List Calendar::incidences()
00150 {
00151   return mergeIncidenceList( events(), todos(), journals() );
00152 }
00153 
00154 Incidence::List Calendar::rawIncidences()
00155 {
00156   return mergeIncidenceList( rawEvents(), rawTodos(), rawJournals() );
00157 }
00158 
00159 Event::List Calendar::sortEvents( Event::List *eventList,
00160                                   EventSortField sortField,
00161                                   SortDirection sortDirection )
00162 {
00163   Event::List eventListSorted;
00164   Event::List tempList, t;
00165   Event::List alphaList;
00166   Event::List::Iterator sortIt;
00167   Event::List::Iterator eit;
00168 
00169   // Notice we alphabetically presort Summaries first.
00170   // We do this so comparison "ties" stay in a nice order.
00171 
00172   switch( sortField ) {
00173   case EventSortUnsorted:
00174     eventListSorted = *eventList;
00175     break;
00176 
00177   case EventSortStartDate:
00178     alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
00179     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00180       sortIt = eventListSorted.begin();
00181       if ( sortDirection == SortDirectionAscending ) {
00182         while ( sortIt != eventListSorted.end() &&
00183                 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00184           ++sortIt;
00185         }
00186       } else {
00187         while ( sortIt != eventListSorted.end() &&
00188                 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00189           ++sortIt;
00190         }
00191       }
00192       eventListSorted.insert( sortIt, *eit );
00193     }
00194     break;
00195 
00196   case EventSortEndDate:
00197     alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
00198     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00199       if ( (*eit)->hasEndDate() ) {
00200         sortIt = eventListSorted.begin();
00201         if ( sortDirection == SortDirectionAscending ) {
00202           while ( sortIt != eventListSorted.end() &&
00203                   (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) {
00204             ++sortIt;
00205           }
00206         } else {
00207           while ( sortIt != eventListSorted.end() &&
00208                   (*eit)->dtEnd() < (*sortIt)->dtEnd() ) {
00209             ++sortIt;
00210           }
00211         }
00212       } else {
00213         // Keep a list of the Events without End DateTimes
00214         tempList.append( *eit );
00215       }
00216       eventListSorted.insert( sortIt, *eit );
00217     }
00218     if ( sortDirection == SortDirectionAscending ) {
00219       // Append the list of Events without End DateTimes
00220       eventListSorted += tempList;
00221     } else {
00222       // Prepend the list of Events without End DateTimes
00223       tempList += eventListSorted;
00224       eventListSorted = tempList;
00225     }
00226     break;
00227 
00228   case EventSortSummary:
00229     for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) {
00230       sortIt = eventListSorted.begin();
00231       if ( sortDirection == SortDirectionAscending ) {
00232         while ( sortIt != eventListSorted.end() &&
00233                 (*eit)->summary() >= (*sortIt)->summary() ) {
00234           ++sortIt;
00235         }
00236       } else {
00237         while ( sortIt != eventListSorted.end() &&
00238                 (*eit)->summary() < (*sortIt)->summary() ) {
00239           ++sortIt;
00240         }
00241       }
00242       eventListSorted.insert( sortIt, *eit );
00243     }
00244     break;
00245   }
00246 
00247   return eventListSorted;
00248 
00249 }
00250 
00251 Event::List Calendar::events( const QDate &date,
00252                               EventSortField sortField,
00253                               SortDirection sortDirection )
00254 {
00255   Event::List el = rawEventsForDate( date, sortField, sortDirection );
00256   mFilter->apply( &el );
00257   return el;
00258 }
00259 
00260 Event::List Calendar::events( const QDateTime &qdt )
00261 {
00262   Event::List el = rawEventsForDate( qdt );
00263   mFilter->apply( &el );
00264   return el;
00265 }
00266 
00267 Event::List Calendar::events( const QDate &start, const QDate &end,
00268                               bool inclusive)
00269 {
00270   Event::List el = rawEvents( start, end, inclusive );
00271   mFilter->apply( &el );
00272   return el;
00273 }
00274 
00275 Event::List Calendar::events( EventSortField sortField,
00276                               SortDirection sortDirection )
00277 {
00278   Event::List el = rawEvents( sortField, sortDirection );
00279   mFilter->apply( &el );
00280   return el;
00281 }
00282 
00283 bool Calendar::addIncidence( Incidence *incidence )
00284 {
00285   Incidence::AddVisitor<Calendar> v( this );
00286 
00287   return incidence->accept(v);
00288 }
00289 
00290 bool Calendar::deleteIncidence( Incidence *incidence )
00291 {
00292   if ( beginChange( incidence ) ) {
00293     Incidence::DeleteVisitor<Calendar> v( this );
00294     bool result = incidence->accept( v );
00295     endChange( incidence );
00296     return result;
00297   } else
00298     return false;
00299 }
00300 
00304 Incidence *Calendar::dissociateOccurrence( Incidence *incidence, QDate date,
00305                                            bool single )
00306 {
00307   if ( !incidence || !incidence->doesRecur() )
00308     return 0;
00309 
00310   Incidence *newInc = incidence->clone();
00311   newInc->recreate();
00312   newInc->setRelatedTo( incidence );
00313   Recurrence *recur = newInc->recurrence();
00314   if ( single ) {
00315     recur->clear();
00316   } else {
00317     // Adjust the recurrence for the future incidences. In particular
00318     // adjust the "end after n occurrences" rules! "No end date" and "end by ..."
00319     // don't need to be modified.
00320     int duration = recur->duration();
00321     if ( duration > 0 ) {
00322       int doneduration = recur->durationTo( date.addDays(-1) );
00323       if ( doneduration >= duration ) {
00324         kdDebug(5850) << "The dissociated event already occurred more often "
00325                       << "than it was supposed to ever occur. ERROR!" << endl;
00326         recur->clear();
00327       } else {
00328         recur->setDuration( duration - doneduration );
00329       }
00330     }
00331   }
00332   // Adjust the date of the incidence
00333   if ( incidence->type() == "Event" ) {
00334     Event *ev = static_cast<Event *>( newInc );
00335     QDateTime start( ev->dtStart() );
00336     int daysTo = start.date().daysTo( date );
00337     ev->setDtStart( start.addDays( daysTo ) );
00338     ev->setDtEnd( ev->dtEnd().addDays( daysTo ) );
00339   } else if ( incidence->type() == "Todo" ) {
00340     Todo *td = static_cast<Todo *>( newInc );
00341     bool haveOffset = false;
00342     int daysTo = 0;
00343     if ( td->hasDueDate() ) {
00344       QDateTime due( td->dtDue() );
00345       daysTo = due.date().daysTo( date );
00346       td->setDtDue( due.addDays( daysTo ), true );
00347       haveOffset = true;
00348     }
00349     if ( td->hasStartDate() ) {
00350       QDateTime start( td->dtStart() );
00351       if ( !haveOffset )
00352         daysTo = start.date().daysTo( date );
00353       td->setDtStart( start.addDays( daysTo ) );
00354       haveOffset = true;
00355     }
00356   }
00357   recur = incidence->recurrence();
00358   if ( recur ) {
00359     if ( single ) {
00360       recur->addExDate( date );
00361     } else {
00362       // Make sure the recurrence of the past events ends
00363       // at the corresponding day
00364       recur->setEndDate( date.addDays(-1) );
00365     }
00366   }
00367   return newInc;
00368 }
00369 
00370 Incidence *Calendar::incidence( const QString &uid )
00371 {
00372   Incidence *i = event( uid );
00373   if ( i )
00374     return i;
00375   i = todo( uid );
00376   if ( i )
00377     return i;
00378   i = journal( uid );
00379   return i;
00380 }
00381 
00382 Incidence *Calendar::incidenceFromSchedulingID( const QString &sid )
00383 {
00384   Incidence::List incidences = rawIncidences();
00385   Incidence::List::iterator it = incidences.begin();
00386   for ( ; it != incidences.end(); ++it )
00387     if ( (*it)->schedulingID() == sid )
00388       // Touchdown, and the crowd goes wild
00389       return *it;
00390   // Not found
00391   return 0;
00392 }
00393 
00394 Todo::List Calendar::sortTodos( Todo::List *todoList,
00395                                 TodoSortField sortField,
00396                                 SortDirection sortDirection )
00397 {
00398   Todo::List todoListSorted;
00399   Todo::List tempList, t;
00400   Todo::List alphaList;
00401   Todo::List::Iterator sortIt;
00402   Todo::List::Iterator eit;
00403 
00404   // Notice we alphabetically presort Summaries first.
00405   // We do this so comparison "ties" stay in a nice order.
00406 
00407   // Note that Todos may not have Start DateTimes nor due DateTimes.
00408 
00409   switch( sortField ) {
00410   case TodoSortUnsorted:
00411     todoListSorted = *todoList;
00412     break;
00413 
00414   case TodoSortStartDate:
00415     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00416     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00417       if ( (*eit)->hasStartDate() ) {
00418         sortIt = todoListSorted.begin();
00419         if ( sortDirection == SortDirectionAscending ) {
00420           while ( sortIt != todoListSorted.end() &&
00421                   (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00422             ++sortIt;
00423           }
00424         } else {
00425           while ( sortIt != todoListSorted.end() &&
00426                   (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00427             ++sortIt;
00428           }
00429         }
00430         todoListSorted.insert( sortIt, *eit );
00431       } else {
00432         // Keep a list of the Todos without Start DateTimes
00433         tempList.append( *eit );
00434       }
00435     }
00436     if ( sortDirection == SortDirectionAscending ) {
00437       // Append the list of Todos without Start DateTimes
00438       todoListSorted += tempList;
00439     } else {
00440       // Prepend the list of Todos without Start DateTimes
00441       tempList += todoListSorted;
00442       todoListSorted = tempList;
00443     }
00444     break;
00445 
00446   case TodoSortDueDate:
00447     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00448     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00449       if ( (*eit)->hasDueDate() ) {
00450         sortIt = todoListSorted.begin();
00451         if ( sortDirection == SortDirectionAscending ) {
00452           while ( sortIt != todoListSorted.end() &&
00453                   (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
00454             ++sortIt;
00455           }
00456         } else {
00457           while ( sortIt != todoListSorted.end() &&
00458                   (*eit)->dtDue() < (*sortIt)->dtDue() ) {
00459             ++sortIt;
00460           }
00461         }
00462         todoListSorted.insert( sortIt, *eit );
00463       } else {
00464         // Keep a list of the Todos without Due DateTimes
00465         tempList.append( *eit );
00466       }
00467     }
00468     if ( sortDirection == SortDirectionAscending ) {
00469       // Append the list of Todos without Due DateTimes
00470       todoListSorted += tempList;
00471     } else {
00472       // Prepend the list of Todos without Due DateTimes
00473       tempList += todoListSorted;
00474       todoListSorted = tempList;
00475     }
00476     break;
00477 
00478   case TodoSortPriority:
00479     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00480     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00481       sortIt = todoListSorted.begin();
00482       if ( sortDirection == SortDirectionAscending ) {
00483         while ( sortIt != todoListSorted.end() &&
00484                 (*eit)->priority() >= (*sortIt)->priority() ) {
00485           ++sortIt;
00486         }
00487       } else {
00488         while ( sortIt != todoListSorted.end() &&
00489                 (*eit)->priority() < (*sortIt)->priority() ) {
00490           ++sortIt;
00491         }
00492       }
00493       todoListSorted.insert( sortIt, *eit );
00494     }
00495     break;
00496 
00497   case TodoSortPercentComplete:
00498     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00499     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00500       sortIt = todoListSorted.begin();
00501       if ( sortDirection == SortDirectionAscending ) {
00502         while ( sortIt != todoListSorted.end() &&
00503                 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
00504           ++sortIt;
00505         }
00506       } else {
00507         while ( sortIt != todoListSorted.end() &&
00508                 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
00509           ++sortIt;
00510         }
00511       }
00512       todoListSorted.insert( sortIt, *eit );
00513     }
00514     break;
00515 
00516   case TodoSortSummary:
00517     for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
00518       sortIt = todoListSorted.begin();
00519       if ( sortDirection == SortDirectionAscending ) {
00520         while ( sortIt != todoListSorted.end() &&
00521                 (*eit)->summary() >= (*sortIt)->summary() ) {
00522           ++sortIt;
00523         }
00524       } else {
00525         while ( sortIt != todoListSorted.end() &&
00526                 (*eit)->summary() < (*sortIt)->summary() ) {
00527           ++sortIt;
00528         }
00529       }
00530       todoListSorted.insert( sortIt, *eit );
00531     }
00532     break;
00533   }
00534 
00535   return todoListSorted;
00536 }
00537 
00538 Todo::List Calendar::todos( TodoSortField sortField,
00539                             SortDirection sortDirection )
00540 {
00541   Todo::List tl = rawTodos( sortField, sortDirection );
00542   mFilter->apply( &tl );
00543   return tl;
00544 }
00545 
00546 Todo::List Calendar::todos( const QDate &date )
00547 {
00548   Todo::List el = rawTodosForDate( date );
00549   mFilter->apply( &el );
00550   return el;
00551 }
00552 
00553 Journal::List Calendar::sortJournals( Journal::List *journalList,
00554                                       JournalSortField sortField,
00555                                       SortDirection sortDirection )
00556 {
00557   Journal::List journalListSorted;
00558   Journal::List::Iterator sortIt;
00559   Journal::List::Iterator eit;
00560 
00561   switch( sortField ) {
00562   case JournalSortUnsorted:
00563     journalListSorted = *journalList;
00564     break;
00565 
00566   case JournalSortDate:
00567     for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00568       sortIt = journalListSorted.begin();
00569       if ( sortDirection == SortDirectionAscending ) {
00570         while ( sortIt != journalListSorted.end() &&
00571                 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00572           ++sortIt;
00573         }
00574       } else {
00575         while ( sortIt != journalListSorted.end() &&
00576                 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00577           ++sortIt;
00578         }
00579       }
00580       journalListSorted.insert( sortIt, *eit );
00581     }
00582     break;
00583 
00584   case JournalSortSummary:
00585     for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00586       sortIt = journalListSorted.begin();
00587       if ( sortDirection == SortDirectionAscending ) {
00588         while ( sortIt != journalListSorted.end() &&
00589                 (*eit)->summary() >= (*sortIt)->summary() ) {
00590           ++sortIt;
00591         }
00592       } else {
00593         while ( sortIt != journalListSorted.end() &&
00594                 (*eit)->summary() < (*sortIt)->summary() ) {
00595           ++sortIt;
00596         }
00597       }
00598       journalListSorted.insert( sortIt, *eit );
00599     }
00600     break;
00601   }
00602 
00603   return journalListSorted;
00604 }
00605 
00606 Journal::List Calendar::journals( JournalSortField sortField,
00607                                   SortDirection sortDirection )
00608 {
00609   Journal::List jl = rawJournals( sortField, sortDirection );
00610   mFilter->apply( &jl );
00611   return jl;
00612 }
00613 
00614 Journal::List Calendar::journals( const QDate &date )
00615 {
00616   Journal::List el = rawJournalsForDate( date );
00617   mFilter->apply( &el );
00618   return el;
00619 }
00620 
00621 // When this is called, the todo have already been added to the calendar.
00622 // This method is only about linking related todos
00623 void Calendar::setupRelations( Incidence *forincidence )
00624 {
00625   if ( !forincidence ) return;
00626 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
00627   QString uid = forincidence->uid();
00628 
00629   // First, go over the list of orphans and see if this is their parent
00630   while ( Incidence* i = mOrphans[ uid ] ) {
00631     mOrphans.remove( uid );
00632     i->setRelatedTo( forincidence );
00633     forincidence->addRelation( i );
00634     mOrphanUids.remove( i->uid() );
00635   }
00636 
00637   // Now see about this incidences parent
00638   if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) {
00639     // This incidence has a uid it is related to but is not registered to it yet
00640     // Try to find it
00641     Incidence* parent = incidence( forincidence->relatedToUid() );
00642     if ( parent ) {
00643       // Found it
00644       forincidence->setRelatedTo( parent );
00645       parent->addRelation( forincidence );
00646     } else {
00647       // Not found, put this in the mOrphans list
00648       // Note that the mOrphans dict might have several entries with the same key! That are
00649       // multiple children that wait for the parent incidence to be inserted.
00650       mOrphans.insert( forincidence->relatedToUid(), forincidence );
00651       mOrphanUids.insert( forincidence->uid(), forincidence );
00652     }
00653   }
00654 }
00655 
00656 // If a task with subtasks is deleted, move it's subtasks to the orphans list
00657 void Calendar::removeRelations( Incidence *incidence )
00658 {
00659   if( !incidence ) {
00660     kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n";
00661     return;
00662   }
00663 
00664 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
00665   QString uid = incidence->uid();
00666 
00667   Incidence::List relations = incidence->relations();
00668   Incidence::List::ConstIterator it;
00669   for ( it = relations.begin(); it != relations.end(); ++it ) {
00670     Incidence *i = *it;
00671     if ( !mOrphanUids.find( i->uid() ) ) {
00672       mOrphans.insert( uid, i );
00673       mOrphanUids.insert( i->uid(), i );
00674       i->setRelatedTo( 0 );
00675       i->setRelatedToUid( uid );
00676     }
00677   }
00678 
00679   // If this incidence is related to something else, tell that about it
00680   if ( incidence->relatedTo() )
00681     incidence->relatedTo()->removeRelation( incidence );
00682 
00683   // Remove this one from the orphans list
00684   if ( mOrphanUids.remove( uid ) ) {
00685     // This incidence is located in the orphans list - it should be removed
00686     // Since the mOrphans dict might contain the same key (with different
00687     // child incidence pointers!) multiple times, take care that we remove
00688     // the correct one. So we need to remove all items with the given
00689     // parent UID, and readd those that are not for this item. Also, there
00690     // might be other entries with differnet UID that point to this
00691     // incidence (this might happen when the relatedTo of the item is
00692     // changed before its parent is inserted. This might happen with
00693     // groupware servers....). Remove them, too
00694     QStringList relatedToUids;
00695     // First get the list of all keys in the mOrphans list that point to the removed item
00696     relatedToUids << incidence->relatedToUid();
00697     for ( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) {
00698       if ( it.current()->uid() == uid ) {
00699         relatedToUids << it.currentKey();
00700       }
00701     }
00702 
00703     // now go through all uids that have one entry that point to the incidence
00704     for ( QStringList::Iterator uidit = relatedToUids.begin();
00705           uidit != relatedToUids.end(); ++uidit ) {
00706       Incidence::List tempList;
00707       // Remove all to get access to the remaining entries
00708       while( Incidence* i = mOrphans[ *uidit ] ) {
00709         mOrphans.remove( *uidit );
00710         if ( i != incidence ) tempList.append( i );
00711       }
00712       // Readd those that point to a different orphan incidence
00713       for ( Incidence::List::Iterator incit = tempList.begin();
00714             incit != tempList.end(); ++incit ) {
00715         mOrphans.insert( *uidit, *incit );
00716       }
00717     }
00718   }
00719 }
00720 
00721 void Calendar::registerObserver( Observer *observer )
00722 {
00723   if( !mObservers.contains( observer ) )
00724     mObservers.append( observer );
00725   mNewObserver = true;
00726 }
00727 
00728 void Calendar::unregisterObserver( Observer *observer )
00729 {
00730   mObservers.remove( observer );
00731 }
00732 
00733 void Calendar::setModified( bool modified )
00734 {
00735   if ( modified != mModified || mNewObserver ) {
00736     mNewObserver = false;
00737     Observer *observer;
00738     for ( observer = mObservers.first(); observer;
00739           observer = mObservers.next() ) {
00740       observer->calendarModified( modified, this );
00741     }
00742     mModified = modified;
00743   }
00744 }
00745 
00746 void Calendar::incidenceUpdated( IncidenceBase *incidence )
00747 {
00748   incidence->setSyncStatus( Event::SYNCMOD );
00749   incidence->setLastModified( QDateTime::currentDateTime() );
00750   // we should probably update the revision number here,
00751   // or internally in the Event itself when certain things change.
00752   // need to verify with ical documentation.
00753 
00754   // The static_cast is ok as the CalendarLocal only observes Incidence objects
00755   notifyIncidenceChanged( static_cast<Incidence *>( incidence ) );
00756 
00757   setModified( true );
00758 }
00759 
00760 void Calendar::notifyIncidenceAdded( Incidence *i )
00761 {
00762   if ( !mObserversEnabled )
00763     return;
00764 
00765   Observer *observer;
00766   for ( observer = mObservers.first(); observer;
00767         observer = mObservers.next() ) {
00768     observer->calendarIncidenceAdded( i );
00769   }
00770 }
00771 
00772 void Calendar::notifyIncidenceChanged( Incidence *i )
00773 {
00774   if ( !mObserversEnabled )
00775     return;
00776 
00777   Observer *observer;
00778   for ( observer = mObservers.first(); observer;
00779         observer = mObservers.next() ) {
00780     observer->calendarIncidenceChanged( i );
00781   }
00782 }
00783 
00784 void Calendar::notifyIncidenceDeleted( Incidence *i )
00785 {
00786   if ( !mObserversEnabled )
00787     return;
00788 
00789   Observer *observer;
00790   for ( observer = mObservers.first(); observer;
00791         observer = mObservers.next() ) {
00792     observer->calendarIncidenceDeleted( i );
00793   }
00794 }
00795 
00796 void Calendar::customPropertyUpdated()
00797 {
00798   setModified( true );
00799 }
00800 
00801 void Calendar::setProductId( const QString &productId )
00802 {
00803   mProductId = productId;
00804 }
00805 
00806 QString Calendar::productId()
00807 {
00808   return mProductId;
00809 }
00810 
00811 Incidence::List Calendar::mergeIncidenceList( const Event::List &events,
00812                                               const Todo::List &todos,
00813                                               const Journal::List &journals )
00814 {
00815   Incidence::List incidences;
00816 
00817   Event::List::ConstIterator it1;
00818   for ( it1 = events.begin(); it1 != events.end(); ++it1 )
00819     incidences.append( *it1 );
00820 
00821   Todo::List::ConstIterator it2;
00822   for ( it2 = todos.begin(); it2 != todos.end(); ++it2 )
00823     incidences.append( *it2 );
00824 
00825   Journal::List::ConstIterator it3;
00826   for ( it3 = journals.begin(); it3 != journals.end(); ++it3 )
00827     incidences.append( *it3 );
00828 
00829   return incidences;
00830 }
00831 
00832 bool Calendar::beginChange( Incidence * )
00833 {
00834   return true;
00835 }
00836 
00837 bool Calendar::endChange( Incidence * )
00838 {
00839   return true;
00840 }
00841 
00842 void Calendar::setObserversEnabled( bool enabled )
00843 {
00844   mObserversEnabled = enabled;
00845 }
00846 
00847 #include "calendar.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys