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