kitchensync

calendarmerger.cpp

00001 /*
00002     This file is part of KitchenSync.
00003 
00004     Copyright (C) 2002,2004 Holger Hans Peter Freyther <freyther@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "calendarmerger.h"
00023 
00024 #include "calendarsyncee.h"
00025 
00026 #include <libkcal/event.h>
00027 #include <libkcal/todo.h>
00028 
00029 #include <kstaticdeleter.h>
00030 
00031 #include <qmap.h>
00032 
00033 namespace KSync {
00034 
00041 namespace CalendarMergerInternal {
00042 /* forwards */
00043 template<class T> void mergeOrganizer( T* const, const T* const );
00044 template<class T> void mergeReadOnly( T* const, const T* const );
00045 template<class T> void mergeStartDate( T* const, const T* const );
00046 template<class T> void mergeDuration( T* const, const T* const );
00047 template<class T> void mergeFloat( T* const, const T* const );
00048 template<class T> void mergeAttendee( T* const, const T* const );
00049 template<class T> void mergeCreatedDate( T* const, const T* const );
00050 template<class T> void mergeRevision( T* const, const T* const );
00051 template<class T> void mergeDescription( T* const, const T* const );
00052 template<class T> void mergeSummary( T* const, const T* const );
00053 template<class T> void mergeCategory( T* const, const T* const );
00054 template<class T> void mergeRelations( T* const, const T* const );
00055 template<class T> void mergeExDates( T* const, const T* const );
00056 template<class T> void mergeAttachments( T* const, const T* const );
00057 template<class T> void mergeSecrecy( T* const,  const T* const );
00058 template<class T> void mergeResources( T* const,  const T* const );
00059 template<class T> void mergePriority( T* const, const T* const );
00060 template<class T> void mergeAlarms( T* const, const T* const );
00061 template<class T> void mergeRecurrence( T* const, const T* const );
00062 template<class T> void mergeLocation( T* const, const T* const );
00063 
00064 template<class T> void mergeDtDue( T* const, const T* const);
00065 template<class T> void mergeDtStart( T* const, const T* const );
00066 template<class T> void mergeCompleted(T* const, const T* const );
00067 template<class T> void mergePercent(T* const, const T* const );
00068 template<class T> void mergeDtEnd( T* const, const T* const );
00069 template<class T> void mergeStartDateFloat( T* const, const T* const );
00070 template<class T> void mergeDueDateFloat( T* const, const T* const );
00071 
00072 template <class T>
00073 class MergeBase
00074 {
00075 public:
00076     MergeBase();
00077     virtual ~MergeBase();
00078     typedef void (*merge)(T* const, const T* const );
00079     typedef QMap<int, merge> MergeMap;
00080     typedef typename QMap<int, merge>::Iterator Iterator;
00081     void invoke( int, T* const, const T* const );
00082     void add( int, merge );
00083 protected:
00084     MergeMap map;
00085 };
00086 
00087 typedef MergeBase<KCal::Event> MergeCal;
00088 typedef MergeBase<KCal::Todo> MergeTodo;
00089 
00090 static MergeCal  *mergeEventMap = 0;
00091 static MergeTodo *mergeTodoMap  = 0;
00092 
00093 static KStaticDeleter<MergeCal> mergeEventDeleter;
00094 static KStaticDeleter<MergeTodo> mergeTodoDeleter;
00095 
00096 template <class T> MergeBase<T>::MergeBase()
00097 {
00098   map.insert( CalendarMerger::Organizer,    mergeOrganizer );
00099   map.insert( CalendarMerger::ReadOnly,     mergeReadOnly );
00100   map.insert( CalendarMerger::DtStart,      mergeDtStart );
00101   map.insert( CalendarMerger::Duration,     mergeDuration );
00102   map.insert( CalendarMerger::Float,        mergeFloat );
00103   map.insert( CalendarMerger::Attendee,     mergeAttendee );
00104   map.insert( CalendarMerger::CreatedDate,  mergeCreatedDate );
00105   map.insert( CalendarMerger::Revision,     mergeRevision );
00106   map.insert( CalendarMerger::Description,  mergeDescription );
00107   map.insert( CalendarMerger::Summary,      mergeSummary );
00108   map.insert( CalendarMerger::Category,     mergeCategory );
00109   map.insert( CalendarMerger::Relations,    mergeRelations );
00110   map.insert( CalendarMerger::ExDates,      mergeExDates );
00111   map.insert( CalendarMerger::Attachments,  mergeAttachments );
00112   map.insert( CalendarMerger::Secrecy,      mergeSecrecy );
00113   map.insert( CalendarMerger::Resources,    mergeResources );
00114   map.insert( CalendarMerger::Priority,     mergePriority );
00115   map.insert( CalendarMerger::Alarms,       mergeAlarms );
00116   map.insert( CalendarMerger::Recurrence,   mergeRecurrence );
00117   map.insert( CalendarMerger::Location,     mergeLocation );
00118 }
00119 
00120 template <class T> MergeBase<T>::~MergeBase()
00121 {
00122 }
00123 
00124 template <class T> void MergeBase<T>::invoke(int i, T* const dest, const T* const src)
00125 {
00126   Iterator it= map.find( i );
00127   if ( it != map.end() )
00128     (*it.data())(dest, src );
00129 }
00130 
00131 template<class T>
00132 void MergeBase<T>::add(int res, merge mer )
00133 {
00134   map.insert( res, mer );
00135 }
00136 
00137 void init()
00138 {
00139   if ( mergeTodoMap )
00140     return;
00141 
00142   mergeTodoDeleter. setObject(mergeTodoMap,  new MergeTodo);
00143   mergeEventDeleter.setObject(mergeEventMap, new MergeCal );
00144 
00145   /* todo specefic additional information */
00146   mergeTodoMap->add( CalendarMerger::DtDue,     mergeDtDue   );
00147   mergeTodoMap->add( CalendarMerger::StartDate, mergeStartDate );
00148   mergeTodoMap->add( CalendarMerger::Completed, mergeCompleted  );
00149   mergeTodoMap->add( CalendarMerger::Percent,   mergePercent   );
00150   mergeTodoMap->add( CalendarMerger::StartDateTime, mergeStartDateFloat );
00151   mergeTodoMap->add( CalendarMerger::DueDateTime,   mergeDueDateFloat   );
00152 
00153   /* event specefic additional information */
00154   mergeEventMap->add( CalendarMerger::DtEnd,    mergeDtEnd );
00155 }
00156 
00157 // implementation of the merge functions
00158 /*
00159  * Merge the Organizer Field.
00160  */
00161 template <class Todo> void mergeOrganizer( Todo* const dest, const Todo* const src)
00162 {
00163   dest->setOrganizer( src->organizer() );
00164 }
00165 
00166 /*
00167  * Merge the ReadOnly Field.
00168  */
00169 template <class Todo> void mergeReadOnly( Todo* const dest, const Todo* const src)
00170 {
00171   dest->setReadOnly( src->isReadOnly() );
00172 }
00173 
00174 /*
00175  * Merge the Start Date.
00176  */
00177 template <class Todo> void mergeDtStart( Todo* const dest, const Todo* const src)
00178 {
00179   dest->setDtStart( src->dtStart() );
00180 }
00181 
00182 /*
00183  * Merge the Duration.
00184  */
00185 template <class Todo> void mergeDuration( Todo* const dest, const Todo* const src)
00186 {
00187   dest->setDuration( src->duration() );
00188 }
00189 
00190 /*
00191  * Merge if it is floating.
00192  */
00193 template <class Todo> void mergeFloat( Todo* const dest, const Todo* const src)
00194 {
00195   dest->setFloats( src->doesFloat() );
00196 }
00197 
00198 /*
00199  * Merge in the Attendees.
00200  */
00201 template <class Todo>  void mergeAttendee( Todo* const dest,
00202                                            const Todo* const src)
00203 {
00204   KCal::Attendee::List att = src->attendees();
00205   KCal::Attendee::List::ConstIterator it;
00206   for ( it = att.begin(); it != att.end(); ++it )
00207     dest->addAttendee( new KCal::Attendee( **it ) );
00208 }
00209 
00210 /*
00211  * Merge the Created on field.
00212  */
00213 template <class Todo>  void mergeCreatedDate( Todo* const dest,
00214                                               const Todo* const src)
00215 {
00216   dest->setCreated( src->created() );
00217 }
00218 
00219 /*
00220  * Merge the Revision Field.
00221  */
00222 template <class Todo> void mergeRevision( Todo* const dest,
00223                                           const Todo* const src)
00224 {
00225   dest->setRevision( src->revision() );
00226 }
00227 
00228 /*
00229  * Merge the Description.
00230  */
00231 template <class Todo> void mergeDescription( Todo* const dest,
00232                                              const Todo* const src)
00233 {
00234   dest->setDescription( src->description() );
00235 }
00236 
00237 /*
00238  * Merge the Summary.
00239  */
00240 template <class Todo> void mergeSummary( Todo* const dest,
00241                                          const Todo* const src)
00242 {
00243   dest->setSummary( src->summary() );
00244 }
00245 
00246 /*
00247  * Merge the Category.
00248  */
00249 template <class Todo> void mergeCategory( Todo* const dest,
00250                                           const Todo* const src)
00251 {
00252   dest->setCategories( src->categories() );
00253 }
00254 
00255 /*
00256  * Merge the Relations by cloning.
00257  */
00258 template <class Todo> void mergeRelations( Todo* const dest,
00259                                            const Todo* const src)
00260 {
00261   KCal::Incidence::List rel = src->relations();
00262   KCal::Incidence::List::ConstIterator it;
00263   for ( it = rel.begin(); it != rel.end(); ++it )
00264     dest->addRelation( (*it)->clone() );
00265 
00266 }
00267 
00268 /*
00269  * Merge the EXteded Dates.
00270  */
00271 template <class Todo> void mergeExDates( Todo* const dest,
00272                                          const Todo* const src)
00273 {
00274   dest->recurrence()->setExDates( src->recurrence()->exDates() );
00275 }
00276 
00277 /*
00278  * @todo
00279  */
00280 template <class Todo> void mergeAttachments( Todo* const, const Todo* const )
00281 {
00282 // FIXME!!!
00283 }
00284 
00285 /*
00286  * Merge the secrecy attribute
00287  */
00288 template <class Todo> void mergeSecrecy( Todo* const dest,
00289                                          const Todo* const src)
00290 {
00291   dest->setSecrecy( src->secrecy() );
00292 }
00293 
00297 template <class Todo> void mergeResources( Todo* const dest,
00298                                            const Todo* const src)
00299 {
00300   dest->setResources( src->resources() );
00301 }
00302 
00303 /*
00304  * Merge the Priority.
00305  */
00306 template <class Todo> void mergePriority( Todo* const dest,
00307                                           const Todo* const src)
00308 {
00309     dest->setPriority( src->priority() );
00310 }
00311 
00312 /*
00313  * Merge the Alarms
00314  */
00315 template <class Todo> void mergeAlarms( Todo* const dest,
00316                                         const Todo* const src )
00317 {
00318     KCal::Alarm::List als = src->alarms();
00319     KCal::Alarm::List::ConstIterator it;
00320     for ( it = als.begin(); it != als.end(); ++it )
00321         dest->addAlarm( new KCal::Alarm( **it ) );
00322 
00323 }
00324 
00325 /*
00326  * Merge Recurrence @todo
00327  */
00328 template <class Todo> void mergeRecurrence( Todo* const ,
00329                                             const Todo* const )
00330 {
00331   // not available
00332 }
00333 
00334 /*
00335  * Merget the Location of the Incidence.
00336  */
00337 template <class Todo> void mergeLocation( Todo* const dest ,
00338                                           const Todo* const src)
00339 {
00340     dest->setLocation( src->location() );
00341 }
00342 
00343 
00345 /*
00346  * Merge the Due Date
00347  */
00348 template<class T>
00349 void mergeDtDue( T* const dest, const T* const src)
00350 {
00351  dest->setDtDue( src->dtDue() );
00352 }
00353 
00354 /*
00355  * Merge the Start Date
00356  */
00357 template<class T>
00358 void mergeStartDate( T* const dest, const T* const src)
00359 {
00360   dest->setHasStartDate( src->hasStartDate() );
00361 }
00362 
00363 /*
00364  * Merge if they were completed
00365  */
00366 template<class T>
00367 void mergeCompleted( T* const dest, const T* const src)
00368 {
00369   dest->setCompleted( src->isCompleted() );
00370 }
00371 
00372 /*
00373  * Merge how many percent where completed
00374  */
00375 template<class T>
00376 void mergePercent( T* const dest, const T* const src)
00377 {
00378   dest->setPercentComplete( src->percentComplete() );
00379 }
00380 
00381 // Calendar specefic
00382 
00383 /*
00384  * The End of an Event
00385  */
00386 template<class T>
00387 void mergeDtEnd( T* const dest, const T* src)
00388 {
00389   dest->setDtEnd( src->dtEnd() );
00390 }
00391 
00392 /* merge time attribute */
00393 template<class Todo>
00394 void mergeStartDateFloat( Todo* const dest,  const Todo* const src ) {
00395   /*
00396    * merge the start Time of the src into dest!
00397    * Merge only if both have startDates and finally
00398    * src doesFloat
00399    */
00400   if ( dest->hasStartDate() && src->hasStartDate() && src->doesFloat() ) {
00401     QDateTime dt = dest->dtStart( true );
00402     dt.setTime( src->dtStart( true ).time() );
00403     dest->setDtStart( dt );
00404   }
00405 }
00406 
00407 /*
00408  * same as mergeStartFloat
00409  */
00410 template<class Todo>
00411 void mergeDueDateFloat( Todo* const dest, const Todo* const src ) {
00412   /*
00413    * merge the due Time of the src into dest!
00414    * Merge only if both have dueDates and finally
00415    * src doesFloat
00416    */
00417   if ( dest->hasDueDate() && src->hasDueDate() && src->doesFloat() ) {
00418     QDateTime dt = dest->dtDue( true );
00419     dt.setTime( src->dtDue( true ).time() );
00420     dest->setDtDue( dt, true );
00421   }
00422 }
00423 
00424 }
00425 
00426 // End of the Namespace
00427 
00428 
00429 
00431 // Now the actual and way shorter implementation of ther Merger which
00432 // actually calls the functios above
00433 //
00434 
00435 
00443 CalendarMerger::CalendarMerger( const QBitArray& todo, const QBitArray& event )
00444     : mEvent( event ), mTodo( todo )
00445 {
00446   setSynceeType( QString::fromLatin1("CalendarSyncee") );
00447 }
00448 
00449 CalendarMerger::~CalendarMerger()
00450 {}
00451 
00455 bool CalendarMerger::merge( SyncEntry* _entry, SyncEntry* _other )
00456 {
00457   if ( !sameType( _entry, _other, QString::fromLatin1("CalendarSyncEntry") ) )
00458     return false;
00459 
00460   /*
00461    * Lets cast
00462    */
00463   CalendarSyncEntry *entry, *other;
00464   entry = static_cast<CalendarSyncEntry*>( _entry );
00465   other = static_cast<CalendarSyncEntry*>( _other );
00466 
00467 
00468   /*
00469    * Wouldn't be able to sync two different types successfully right
00470    */
00471   if ( entry->incidence()->type() != other->incidence()->type() )
00472     return false;
00473 
00474   CalendarMergerInternal::init();
00475   if ( entry->incidence()->type() == "Event" )
00476     mergeEvent( entry, other );
00477   else
00478     mergeTodo( entry, other );
00479 
00480   return true;
00481 }
00482 
00483 
00484 void CalendarMerger::mergeTodo( CalendarSyncEntry* entry, CalendarSyncEntry* other )
00485 {
00486   QBitArray otherSup;
00487   if ( other->syncee() && other->syncee()->merger() )
00488     otherSup = otherMerger<CalendarMerger>( other )->mTodo;
00489   else {
00490     otherSup = QBitArray( mTodo.size() );
00491     otherSup.fill( true );
00492   }
00493 
00494 
00495   for ( uint i=0;i < otherSup.size() && i < mTodo.size(); ++i )
00496     if ( otherSup[i] && !mTodo[i] )
00497       CalendarMergerInternal::mergeTodoMap->invoke( i, static_cast<KCal::Todo*>( entry->incidence() ),
00498                                                     static_cast<KCal::Todo*>( other->incidence() ) );
00499 
00500 }
00501 
00502 void CalendarMerger::mergeEvent( CalendarSyncEntry* entry, CalendarSyncEntry* other ) {
00503   QBitArray otherSup;
00504   if ( other->syncee() && other->syncee()->merger() )
00505     otherSup = otherMerger<CalendarMerger>( other )->mEvent;
00506   else {
00507     otherSup = QBitArray( mEvent.size() );
00508     otherSup.fill( true );
00509   }
00510 
00511   for ( uint i=0;i < otherSup.size() && i < mEvent.size(); ++i )
00512     if ( otherSup[i] && !mEvent[i] )
00513       CalendarMergerInternal::mergeEventMap->invoke( i, static_cast<KCal::Event*>( entry->incidence() ),
00514                                                      static_cast<KCal::Event*>( other->incidence() ) );
00515 
00516 }
00517 }
KDE Home | KDE Accessibility Home | Description of Access Keys