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