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       if ( (*eit)->doesFloat() ) {
00181         tempList.append( *eit );
00182         continue;
00183       }
00184       sortIt = eventListSorted.begin();
00185       if ( sortDirection == SortDirectionAscending ) {
00186         while ( sortIt != eventListSorted.end() &&
00187                 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00188           ++sortIt;
00189         }
00190       } else {
00191         while ( sortIt != eventListSorted.end() &&
00192                 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00193           ++sortIt;
00194         }
00195       }
00196       eventListSorted.insert( sortIt, *eit );
00197     }
00198     if ( sortDirection == SortDirectionAscending ) {
00199       // Prepend the list of Events without End DateTimes
00200       tempList += eventListSorted;
00201       eventListSorted = tempList;
00202     } else {
00203       // Append the list of Events without End DateTimes
00204       eventListSorted += tempList;
00205     }
00206     break;
00207 
00208   case EventSortEndDate:
00209     alphaList = sortEvents( eventList, EventSortSummary, sortDirection );
00210     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00211       if ( (*eit)->hasEndDate() ) {
00212         sortIt = eventListSorted.begin();
00213         if ( sortDirection == SortDirectionAscending ) {
00214           while ( sortIt != eventListSorted.end() &&
00215                   (*eit)->dtEnd() >= (*sortIt)->dtEnd() ) {
00216             ++sortIt;
00217           }
00218         } else {
00219           while ( sortIt != eventListSorted.end() &&
00220                   (*eit)->dtEnd() < (*sortIt)->dtEnd() ) {
00221             ++sortIt;
00222           }
00223         }
00224       } else {
00225         // Keep a list of the Events without End DateTimes
00226         tempList.append( *eit );
00227       }
00228       eventListSorted.insert( sortIt, *eit );
00229     }
00230     if ( sortDirection == SortDirectionAscending ) {
00231       // Append the list of Events without End DateTimes
00232       eventListSorted += tempList;
00233     } else {
00234       // Prepend the list of Events without End DateTimes
00235       tempList += eventListSorted;
00236       eventListSorted = tempList;
00237     }
00238     break;
00239 
00240   case EventSortSummary:
00241     for ( eit = eventList->begin(); eit != eventList->end(); ++eit ) {
00242       sortIt = eventListSorted.begin();
00243       if ( sortDirection == SortDirectionAscending ) {
00244         while ( sortIt != eventListSorted.end() &&
00245                 (*eit)->summary() >= (*sortIt)->summary() ) {
00246           ++sortIt;
00247         }
00248       } else {
00249         while ( sortIt != eventListSorted.end() &&
00250                 (*eit)->summary() < (*sortIt)->summary() ) {
00251           ++sortIt;
00252         }
00253       }
00254       eventListSorted.insert( sortIt, *eit );
00255     }
00256     break;
00257   }
00258 
00259   return eventListSorted;
00260 
00261 }
00262 
00263 Event::List Calendar::events( const QDate &date,
00264                               EventSortField sortField,
00265                               SortDirection sortDirection )
00266 {
00267   Event::List el = rawEventsForDate( date, sortField, sortDirection );
00268   mFilter->apply( &el );
00269   return el;
00270 }
00271 
00272 Event::List Calendar::events( const QDateTime &qdt )
00273 {
00274   Event::List el = rawEventsForDate( qdt );
00275   mFilter->apply( &el );
00276   return el;
00277 }
00278 
00279 Event::List Calendar::events( const QDate &start, const QDate &end,
00280                               bool inclusive)
00281 {
00282   Event::List el = rawEvents( start, end, inclusive );
00283   mFilter->apply( &el );
00284   return el;
00285 }
00286 
00287 Event::List Calendar::events( EventSortField sortField,
00288                               SortDirection sortDirection )
00289 {
00290   Event::List el = rawEvents( sortField, sortDirection );
00291   mFilter->apply( &el );
00292   return el;
00293 }
00294 
00295 bool Calendar::addIncidence( Incidence *incidence )
00296 {
00297   Incidence::AddVisitor<Calendar> v( this );
00298 
00299   return incidence->accept(v);
00300 }
00301 
00302 bool Calendar::deleteIncidence( Incidence *incidence )
00303 {
00304   if ( beginChange( incidence ) ) {
00305     Incidence::DeleteVisitor<Calendar> v( this );
00306     bool result = incidence->accept( v );
00307     endChange( incidence );
00308     return result;
00309   } else
00310     return false;
00311 }
00312 
00316 Incidence *Calendar::dissociateOccurrence( Incidence *incidence, QDate date,
00317                                            bool single )
00318 {
00319   if ( !incidence || !incidence->doesRecur() )
00320     return 0;
00321 
00322   Incidence *newInc = incidence->clone();
00323   newInc->recreate();
00324   newInc->setRelatedTo( incidence );
00325   Recurrence *recur = newInc->recurrence();
00326   if ( single ) {
00327     recur->clear();
00328   } else {
00329     // Adjust the recurrence for the future incidences. In particular
00330     // adjust the "end after n occurrences" rules! "No end date" and "end by ..."
00331     // don't need to be modified.
00332     int duration = recur->duration();
00333     if ( duration > 0 ) {
00334       int doneduration = recur->durationTo( date.addDays(-1) );
00335       if ( doneduration >= duration ) {
00336         kdDebug(5850) << "The dissociated event already occurred more often "
00337                       << "than it was supposed to ever occur. ERROR!" << endl;
00338         recur->clear();
00339       } else {
00340         recur->setDuration( duration - doneduration );
00341       }
00342     }
00343   }
00344   // Adjust the date of the incidence
00345   if ( incidence->type() == "Event" ) {
00346     Event *ev = static_cast<Event *>( newInc );
00347     QDateTime start( ev->dtStart() );
00348     int daysTo = start.date().daysTo( date );
00349     ev->setDtStart( start.addDays( daysTo ) );
00350     ev->setDtEnd( ev->dtEnd().addDays( daysTo ) );
00351   } else if ( incidence->type() == "Todo" ) {
00352     Todo *td = static_cast<Todo *>( newInc );
00353     bool haveOffset = false;
00354     int daysTo = 0;
00355     if ( td->hasDueDate() ) {
00356       QDateTime due( td->dtDue() );
00357       daysTo = due.date().daysTo( date );
00358       td->setDtDue( due.addDays( daysTo ), true );
00359       haveOffset = true;
00360     }
00361     if ( td->hasStartDate() ) {
00362       QDateTime start( td->dtStart() );
00363       if ( !haveOffset )
00364         daysTo = start.date().daysTo( date );
00365       td->setDtStart( start.addDays( daysTo ) );
00366       haveOffset = true;
00367     }
00368   }
00369   recur = incidence->recurrence();
00370   if ( recur ) {
00371     if ( single ) {
00372       recur->addExDate( date );
00373     } else {
00374       // Make sure the recurrence of the past events ends
00375       // at the corresponding day
00376       recur->setEndDate( date.addDays(-1) );
00377     }
00378   }
00379   return newInc;
00380 }
00381 
00382 Incidence *Calendar::incidence( const QString &uid )
00383 {
00384   Incidence *i = event( uid );
00385   if ( i )
00386     return i;
00387   i = todo( uid );
00388   if ( i )
00389     return i;
00390   i = journal( uid );
00391   return i;
00392 }
00393 
00394 Incidence::List Calendar::incidencesFromSchedulingID( const QString &UID )
00395 {
00396   Incidence::List result;
00397   Incidence::List incidences = rawIncidences();
00398   Incidence::List::iterator it = incidences.begin();
00399   for ( ; it != incidences.end(); ++it )
00400     if ( (*it)->schedulingID() == UID )
00401       result.append( *it );
00402   return result;
00403 }
00404 
00405 Incidence *Calendar::incidenceFromSchedulingID( const QString &UID )
00406 {
00407   Incidence::List incidences = rawIncidences();
00408   Incidence::List::iterator it = incidences.begin();
00409   for ( ; it != incidences.end(); ++it )
00410     if ( (*it)->schedulingID() == UID )
00411       // Touchdown, and the crowd goes wild
00412       return *it;
00413   // Not found
00414   return 0;
00415 }
00416 
00417 Todo::List Calendar::sortTodos( Todo::List *todoList,
00418                                 TodoSortField sortField,
00419                                 SortDirection sortDirection )
00420 {
00421   Todo::List todoListSorted;
00422   Todo::List tempList, t;
00423   Todo::List alphaList;
00424   Todo::List::Iterator sortIt;
00425   Todo::List::Iterator eit;
00426 
00427   // Notice we alphabetically presort Summaries first.
00428   // We do this so comparison "ties" stay in a nice order.
00429 
00430   // Note that Todos may not have Start DateTimes nor due DateTimes.
00431 
00432   switch( sortField ) {
00433   case TodoSortUnsorted:
00434     todoListSorted = *todoList;
00435     break;
00436 
00437   case TodoSortStartDate:
00438     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00439     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00440       if ( (*eit)->hasStartDate() ) {
00441         sortIt = todoListSorted.begin();
00442         if ( sortDirection == SortDirectionAscending ) {
00443           while ( sortIt != todoListSorted.end() &&
00444                   (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00445             ++sortIt;
00446           }
00447         } else {
00448           while ( sortIt != todoListSorted.end() &&
00449                   (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00450             ++sortIt;
00451           }
00452         }
00453         todoListSorted.insert( sortIt, *eit );
00454       } else {
00455         // Keep a list of the Todos without Start DateTimes
00456         tempList.append( *eit );
00457       }
00458     }
00459     if ( sortDirection == SortDirectionAscending ) {
00460       // Append the list of Todos without Start DateTimes
00461       todoListSorted += tempList;
00462     } else {
00463       // Prepend the list of Todos without Start DateTimes
00464       tempList += todoListSorted;
00465       todoListSorted = tempList;
00466     }
00467     break;
00468 
00469   case TodoSortDueDate:
00470     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00471     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00472       if ( (*eit)->hasDueDate() ) {
00473         sortIt = todoListSorted.begin();
00474         if ( sortDirection == SortDirectionAscending ) {
00475           while ( sortIt != todoListSorted.end() &&
00476                   (*eit)->dtDue() >= (*sortIt)->dtDue() ) {
00477             ++sortIt;
00478           }
00479         } else {
00480           while ( sortIt != todoListSorted.end() &&
00481                   (*eit)->dtDue() < (*sortIt)->dtDue() ) {
00482             ++sortIt;
00483           }
00484         }
00485         todoListSorted.insert( sortIt, *eit );
00486       } else {
00487         // Keep a list of the Todos without Due DateTimes
00488         tempList.append( *eit );
00489       }
00490     }
00491     if ( sortDirection == SortDirectionAscending ) {
00492       // Append the list of Todos without Due DateTimes
00493       todoListSorted += tempList;
00494     } else {
00495       // Prepend the list of Todos without Due DateTimes
00496       tempList += todoListSorted;
00497       todoListSorted = tempList;
00498     }
00499     break;
00500 
00501   case TodoSortPriority:
00502     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00503     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00504       sortIt = todoListSorted.begin();
00505       if ( sortDirection == SortDirectionAscending ) {
00506         while ( sortIt != todoListSorted.end() &&
00507                 (*eit)->priority() >= (*sortIt)->priority() ) {
00508           ++sortIt;
00509         }
00510       } else {
00511         while ( sortIt != todoListSorted.end() &&
00512                 (*eit)->priority() < (*sortIt)->priority() ) {
00513           ++sortIt;
00514         }
00515       }
00516       todoListSorted.insert( sortIt, *eit );
00517     }
00518     break;
00519 
00520   case TodoSortPercentComplete:
00521     alphaList = sortTodos( todoList, TodoSortSummary, sortDirection );
00522     for ( eit = alphaList.begin(); eit != alphaList.end(); ++eit ) {
00523       sortIt = todoListSorted.begin();
00524       if ( sortDirection == SortDirectionAscending ) {
00525         while ( sortIt != todoListSorted.end() &&
00526                 (*eit)->percentComplete() >= (*sortIt)->percentComplete() ) {
00527           ++sortIt;
00528         }
00529       } else {
00530         while ( sortIt != todoListSorted.end() &&
00531                 (*eit)->percentComplete() < (*sortIt)->percentComplete() ) {
00532           ++sortIt;
00533         }
00534       }
00535       todoListSorted.insert( sortIt, *eit );
00536     }
00537     break;
00538 
00539   case TodoSortSummary:
00540     for ( eit = todoList->begin(); eit != todoList->end(); ++eit ) {
00541       sortIt = todoListSorted.begin();
00542       if ( sortDirection == SortDirectionAscending ) {
00543         while ( sortIt != todoListSorted.end() &&
00544                 (*eit)->summary() >= (*sortIt)->summary() ) {
00545           ++sortIt;
00546         }
00547       } else {
00548         while ( sortIt != todoListSorted.end() &&
00549                 (*eit)->summary() < (*sortIt)->summary() ) {
00550           ++sortIt;
00551         }
00552       }
00553       todoListSorted.insert( sortIt, *eit );
00554     }
00555     break;
00556   }
00557 
00558   return todoListSorted;
00559 }
00560 
00561 Todo::List Calendar::todos( TodoSortField sortField,
00562                             SortDirection sortDirection )
00563 {
00564   Todo::List tl = rawTodos( sortField, sortDirection );
00565   mFilter->apply( &tl );
00566   return tl;
00567 }
00568 
00569 Todo::List Calendar::todos( const QDate &date )
00570 {
00571   Todo::List el = rawTodosForDate( date );
00572   mFilter->apply( &el );
00573   return el;
00574 }
00575 
00576 Journal::List Calendar::sortJournals( Journal::List *journalList,
00577                                       JournalSortField sortField,
00578                                       SortDirection sortDirection )
00579 {
00580   Journal::List journalListSorted;
00581   Journal::List::Iterator sortIt;
00582   Journal::List::Iterator eit;
00583 
00584   switch( sortField ) {
00585   case JournalSortUnsorted:
00586     journalListSorted = *journalList;
00587     break;
00588 
00589   case JournalSortDate:
00590     for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00591       sortIt = journalListSorted.begin();
00592       if ( sortDirection == SortDirectionAscending ) {
00593         while ( sortIt != journalListSorted.end() &&
00594                 (*eit)->dtStart() >= (*sortIt)->dtStart() ) {
00595           ++sortIt;
00596         }
00597       } else {
00598         while ( sortIt != journalListSorted.end() &&
00599                 (*eit)->dtStart() < (*sortIt)->dtStart() ) {
00600           ++sortIt;
00601         }
00602       }
00603       journalListSorted.insert( sortIt, *eit );
00604     }
00605     break;
00606 
00607   case JournalSortSummary:
00608     for ( eit = journalList->begin(); eit != journalList->end(); ++eit ) {
00609       sortIt = journalListSorted.begin();
00610       if ( sortDirection == SortDirectionAscending ) {
00611         while ( sortIt != journalListSorted.end() &&
00612                 (*eit)->summary() >= (*sortIt)->summary() ) {
00613           ++sortIt;
00614         }
00615       } else {
00616         while ( sortIt != journalListSorted.end() &&
00617                 (*eit)->summary() < (*sortIt)->summary() ) {
00618           ++sortIt;
00619         }
00620       }
00621       journalListSorted.insert( sortIt, *eit );
00622     }
00623     break;
00624   }
00625 
00626   return journalListSorted;
00627 }
00628 
00629 Journal::List Calendar::journals( JournalSortField sortField,
00630                                   SortDirection sortDirection )
00631 {
00632   Journal::List jl = rawJournals( sortField, sortDirection );
00633   mFilter->apply( &jl );
00634   return jl;
00635 }
00636 
00637 Journal::List Calendar::journals( const QDate &date )
00638 {
00639   Journal::List el = rawJournalsForDate( date );
00640   mFilter->apply( &el );
00641   return el;
00642 }
00643 
00644 // When this is called, the todo have already been added to the calendar.
00645 // This method is only about linking related todos
00646 void Calendar::setupRelations( Incidence *forincidence )
00647 {
00648   if ( !forincidence ) return;
00649 // kdDebug(5850) << "Calendar::setupRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
00650   QString uid = forincidence->uid();
00651 
00652   // First, go over the list of orphans and see if this is their parent
00653   while ( Incidence* i = mOrphans[ uid ] ) {
00654     mOrphans.remove( uid );
00655     i->setRelatedTo( forincidence );
00656     forincidence->addRelation( i );
00657     mOrphanUids.remove( i->uid() );
00658   }
00659 
00660   // Now see about this incidences parent
00661   if ( !forincidence->relatedTo() && !forincidence->relatedToUid().isEmpty() ) {
00662     // This incidence has a uid it is related to but is not registered to it yet
00663     // Try to find it
00664     Incidence* parent = incidence( forincidence->relatedToUid() );
00665     if ( parent ) {
00666       // Found it
00667       forincidence->setRelatedTo( parent );
00668       parent->addRelation( forincidence );
00669     } else {
00670       // Not found, put this in the mOrphans list
00671       // Note that the mOrphans dict might have several entries with the same key! That are
00672       // multiple children that wait for the parent incidence to be inserted.
00673       mOrphans.insert( forincidence->relatedToUid(), forincidence );
00674       mOrphanUids.insert( forincidence->uid(), forincidence );
00675     }
00676   }
00677 }
00678 
00679 // If a task with subtasks is deleted, move it's subtasks to the orphans list
00680 void Calendar::removeRelations( Incidence *incidence )
00681 {
00682   if( !incidence ) {
00683     kdDebug(5800) << "Warning: Calendar::removeRelations( 0 )!\n";
00684     return;
00685   }
00686 
00687 // kdDebug(5850) << "Calendar::removeRelations for incidence " << forincidence << " with UID " << forincidence->uid() << ", summary: " << forincidence->summary() << endl;
00688   QString uid = incidence->uid();
00689 
00690   Incidence::List relations = incidence->relations();
00691   Incidence::List::ConstIterator it;
00692   for ( it = relations.begin(); it != relations.end(); ++it ) {
00693     Incidence *i = *it;
00694     if ( !mOrphanUids.find( i->uid() ) ) {
00695       mOrphans.insert( uid, i );
00696       mOrphanUids.insert( i->uid(), i );
00697       i->setRelatedTo( 0 );
00698       i->setRelatedToUid( uid );
00699     }
00700   }
00701 
00702   // If this incidence is related to something else, tell that about it
00703   if ( incidence->relatedTo() )
00704     incidence->relatedTo()->removeRelation( incidence );
00705 
00706   // Remove this one from the orphans list
00707   if ( mOrphanUids.remove( uid ) ) {
00708     // This incidence is located in the orphans list - it should be removed
00709     // Since the mOrphans dict might contain the same key (with different
00710     // child incidence pointers!) multiple times, take care that we remove
00711     // the correct one. So we need to remove all items with the given
00712     // parent UID, and readd those that are not for this item. Also, there
00713     // might be other entries with differnet UID that point to this
00714     // incidence (this might happen when the relatedTo of the item is
00715     // changed before its parent is inserted. This might happen with
00716     // groupware servers....). Remove them, too
00717     QStringList relatedToUids;
00718     // First get the list of all keys in the mOrphans list that point to the removed item
00719     relatedToUids << incidence->relatedToUid();
00720     for ( QDictIterator<Incidence> it( mOrphans ); it.current(); ++it ) {
00721       if ( it.current()->uid() == uid ) {
00722         relatedToUids << it.currentKey();
00723       }
00724     }
00725 
00726     // now go through all uids that have one entry that point to the incidence
00727     for ( QStringList::Iterator uidit = relatedToUids.begin();
00728           uidit != relatedToUids.end(); ++uidit ) {
00729       Incidence::List tempList;
00730       // Remove all to get access to the remaining entries
00731       while( Incidence* i = mOrphans[ *uidit ] ) {
00732         mOrphans.remove( *uidit );
00733         if ( i != incidence ) tempList.append( i );
00734       }
00735       // Readd those that point to a different orphan incidence
00736       for ( Incidence::List::Iterator incit = tempList.begin();
00737             incit != tempList.end(); ++incit ) {
00738         mOrphans.insert( *uidit, *incit );
00739       }
00740     }
00741   }
00742 }
00743 
00744 void Calendar::registerObserver( Observer *observer )
00745 {
00746   if( !mObservers.contains( observer ) )
00747     mObservers.append( observer );
00748   mNewObserver = true;
00749 }
00750 
00751 void Calendar::unregisterObserver( Observer *observer )
00752 {
00753   mObservers.remove( observer );
00754 }
00755 
00756 void Calendar::setModified( bool modified )
00757 {
00758   if ( modified != mModified || mNewObserver ) {
00759     mNewObserver = false;
00760     Observer *observer;
00761     for ( observer = mObservers.first(); observer;
00762           observer = mObservers.next() ) {
00763       observer->calendarModified( modified, this );
00764     }
00765     mModified = modified;
00766   }
00767 }
00768 
00769 void Calendar::incidenceUpdated( IncidenceBase *incidence )
00770 {
00771   incidence->setSyncStatus( Event::SYNCMOD );
00772   incidence->setLastModified( QDateTime::currentDateTime() );
00773   // we should probably update the revision number here,
00774   // or internally in the Event itself when certain things change.
00775   // need to verify with ical documentation.
00776 
00777   // The static_cast is ok as the CalendarLocal only observes Incidence objects
00778   notifyIncidenceChanged( static_cast<Incidence *>( incidence ) );
00779 
00780   setModified( true );
00781 }
00782 
00783 void Calendar::notifyIncidenceAdded( Incidence *i )
00784 {
00785   if ( !mObserversEnabled )
00786     return;
00787 
00788   Observer *observer;
00789   for ( observer = mObservers.first(); observer;
00790         observer = mObservers.next() ) {
00791     observer->calendarIncidenceAdded( i );
00792   }
00793 }
00794 
00795 void Calendar::notifyIncidenceChanged( Incidence *i )
00796 {
00797   if ( !mObserversEnabled )
00798     return;
00799 
00800   Observer *observer;
00801   for ( observer = mObservers.first(); observer;
00802         observer = mObservers.next() ) {
00803     observer->calendarIncidenceChanged( i );
00804   }
00805 }
00806 
00807 void Calendar::notifyIncidenceDeleted( Incidence *i )
00808 {
00809   if ( !mObserversEnabled )
00810     return;
00811 
00812   Observer *observer;
00813   for ( observer = mObservers.first(); observer;
00814         observer = mObservers.next() ) {
00815     observer->calendarIncidenceDeleted( i );
00816   }
00817 }
00818 
00819 void Calendar::customPropertyUpdated()
00820 {
00821   setModified( true );
00822 }
00823 
00824 void Calendar::setProductId( const QString &productId )
00825 {
00826   mProductId = productId;
00827 }
00828 
00829 QString Calendar::productId()
00830 {
00831   return mProductId;
00832 }
00833 
00834 Incidence::List Calendar::mergeIncidenceList( const Event::List &events,
00835                                               const Todo::List &todos,
00836                                               const Journal::List &journals )
00837 {
00838   Incidence::List incidences;
00839 
00840   Event::List::ConstIterator it1;
00841   for ( it1 = events.begin(); it1 != events.end(); ++it1 )
00842     incidences.append( *it1 );
00843 
00844   Todo::List::ConstIterator it2;
00845   for ( it2 = todos.begin(); it2 != todos.end(); ++it2 )
00846     incidences.append( *it2 );
00847 
00848   Journal::List::ConstIterator it3;
00849   for ( it3 = journals.begin(); it3 != journals.end(); ++it3 )
00850     incidences.append( *it3 );
00851 
00852   return incidences;
00853 }
00854 
00855 bool Calendar::beginChange( Incidence * )
00856 {
00857   return true;
00858 }
00859 
00860 bool Calendar::endChange( Incidence * )
00861 {
00862   return true;
00863 }
00864 
00865 void Calendar::setObserversEnabled( bool enabled )
00866 {
00867   mObserversEnabled = enabled;
00868 }
00869 
00870 #include "calendar.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys