libkcal

resourcecached.cpp

00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@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 <qdatastream.h>
00023 #include <qdatetime.h>
00024 #include <qfile.h>
00025 #include <qstring.h>
00026 #include <qptrlist.h>
00027 
00028 #include <kdebug.h>
00029 #include <klocale.h>
00030 #include <kurl.h>
00031 #include <kstandarddirs.h>
00032 
00033 #include "event.h"
00034 #include "exceptions.h"
00035 #include "incidence.h"
00036 #include "journal.h"
00037 #include "todo.h"
00038 
00039 
00040 #include "resourcecached.h"
00041 
00042 using namespace KCal;
00043 
00044 ResourceCached::ResourceCached( const KConfig* config )
00045   : ResourceCalendar( config ), mCalendar( QString::fromLatin1( "UTC" ) ),
00046     mReloadPolicy( ReloadNever ),  mReloadInterval( 10 ), mReloaded( false ),
00047     mSavePolicy( SaveNever ), mSaveInterval( 10 ),
00048     mIdMapper( "kcal/uidmaps/" )
00049 {
00050   connect( &mReloadTimer, SIGNAL( timeout() ), SLOT( slotReload() ) );
00051   connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( slotSave() ) );
00052 }
00053 
00054 ResourceCached::~ResourceCached()
00055 {
00056 }
00057 
00058 void ResourceCached::setReloadPolicy( int i )
00059 {
00060   mReloadPolicy = i;
00061 
00062   setupReloadTimer();
00063 }
00064 
00065 int ResourceCached::reloadPolicy() const
00066 {
00067   return mReloadPolicy;
00068 }
00069 
00070 void ResourceCached::setReloadInterval( int minutes )
00071 {
00072   mReloadInterval = minutes;
00073 }
00074 
00075 int ResourceCached::reloadInterval() const
00076 {
00077   return mReloadInterval;
00078 }
00079 
00080 void ResourceCached::setSavePolicy( int i )
00081 {
00082   mSavePolicy = i;
00083 
00084   setupSaveTimer();
00085 }
00086 
00087 int ResourceCached::savePolicy() const
00088 {
00089   return mSavePolicy;
00090 }
00091 
00092 void ResourceCached::setSaveInterval( int minutes )
00093 {
00094   mSaveInterval = minutes;
00095 }
00096 
00097 int ResourceCached::saveInterval() const
00098 {
00099   return mSaveInterval;
00100 }
00101 
00102 void ResourceCached::readConfig( const KConfig *config )
00103 {
00104   mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever );
00105   mReloadInterval = config->readNumEntry( "ReloadInterval", 10 );
00106 
00107   mSaveInterval = config->readNumEntry( "SaveInterval", 10 );
00108   mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever );
00109 
00110   mLastLoad = config->readDateTimeEntry( "LastLoad" );
00111   mLastSave = config->readDateTimeEntry( "LastSave" );
00112 
00113   setupSaveTimer();
00114   setupReloadTimer();
00115 }
00116 
00117 void ResourceCached::setupSaveTimer()
00118 {
00119   if ( mSavePolicy == SaveInterval ) {
00120     kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval "
00121               << mSaveInterval << " minutes)." << endl;
00122     mSaveTimer.start( mSaveInterval * 60 * 1000 ); // n minutes
00123   } else {
00124     mSaveTimer.stop();
00125   }
00126 }
00127 
00128 void ResourceCached::setupReloadTimer()
00129 {
00130   if ( mReloadPolicy == ReloadInterval ) {
00131     kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer "
00132                  "(interval " << mReloadInterval << " minutes)" << endl;
00133     mReloadTimer.start( mReloadInterval * 60 * 1000 ); // n minutes
00134   } else {
00135     mReloadTimer.stop();
00136   }
00137 }
00138 
00139 void ResourceCached::writeConfig( KConfig *config )
00140 {
00141   config->writeEntry( "ReloadPolicy", mReloadPolicy );
00142   config->writeEntry( "ReloadInterval", mReloadInterval );
00143 
00144   config->writeEntry( "SavePolicy", mSavePolicy );
00145   config->writeEntry( "SaveInterval", mSaveInterval );
00146 
00147   config->writeEntry( "LastLoad", mLastLoad );
00148   config->writeEntry( "LastSave", mLastSave );
00149 }
00150 
00151 bool ResourceCached::addEvent(Event *event)
00152 {
00153   return mCalendar.addEvent( event );
00154 }
00155 
00156 // probably not really efficient, but...it works for now.
00157 bool ResourceCached::deleteEvent( Event *event )
00158 {
00159   kdDebug(5800) << "ResourceCached::deleteEvent" << endl;
00160 
00161   return mCalendar.deleteEvent( event );
00162 }
00163 
00164 
00165 Event *ResourceCached::event( const QString &uid )
00166 {
00167   return mCalendar.event( uid );
00168 }
00169 
00170 Event::List ResourceCached::rawEventsForDate( const QDate &qd,
00171                                               EventSortField sortField,
00172                                               SortDirection sortDirection )
00173 {
00174   Event::List list = mCalendar.rawEventsForDate( qd, sortField, sortDirection );
00175 
00176   return list;
00177 }
00178 
00179 Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end,
00180                                        bool inclusive )
00181 {
00182   return mCalendar.rawEvents( start, end, inclusive );
00183 }
00184 
00185 Event::List ResourceCached::rawEventsForDate( const QDateTime &qdt )
00186 {
00187   return mCalendar.rawEventsForDate( qdt.date() );
00188 }
00189 
00190 Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
00191 {
00192   return mCalendar.rawEvents( sortField, sortDirection );
00193 }
00194 
00195 bool ResourceCached::addTodo( Todo *todo )
00196 {
00197   return mCalendar.addTodo( todo );
00198 }
00199 
00200 bool ResourceCached::deleteTodo( Todo *todo )
00201 {
00202   return mCalendar.deleteTodo( todo );
00203 }
00204 
00205 bool ResourceCached::deleteJournal( Journal *journal )
00206 {
00207   return mCalendar.deleteJournal( journal );
00208 }
00209 
00210 
00211 Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
00212 {
00213   return mCalendar.rawTodos( sortField, sortDirection );
00214 }
00215 
00216 Todo *ResourceCached::todo( const QString &uid )
00217 {
00218   return mCalendar.todo( uid );
00219 }
00220 
00221 Todo::List ResourceCached::rawTodosForDate( const QDate &date )
00222 {
00223   return mCalendar.rawTodosForDate( date );
00224 }
00225 
00226 
00227 bool ResourceCached::addJournal( Journal *journal )
00228 {
00229   kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;
00230 
00231   return mCalendar.addJournal( journal );
00232 }
00233 
00234 Journal *ResourceCached::journal( const QString &uid )
00235 {
00236   return mCalendar.journal( uid );
00237 }
00238 
00239 Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
00240 {
00241   return mCalendar.rawJournals( sortField, sortDirection );
00242 }
00243 
00244 Journal::List ResourceCached::rawJournalsForDate( const QDate &date )
00245 {
00246   return mCalendar.rawJournalsForDate( date );
00247 }
00248 
00249 
00250 Alarm::List ResourceCached::alarmsTo( const QDateTime &to )
00251 {
00252   return mCalendar.alarmsTo( to );
00253 }
00254 
00255 Alarm::List ResourceCached::alarms( const QDateTime &from, const QDateTime &to )
00256 {
00257 //  kdDebug(5800) << "ResourceCached::alarms(" << from.toString() << " - " << to.toString() << ")\n";
00258 
00259   return mCalendar.alarms( from, to );
00260 }
00261 
00262 
00263 void ResourceCached::setTimeZoneId( const QString& tzid )
00264 {
00265   mCalendar.setTimeZoneId( tzid );
00266 }
00267 
00268 QString ResourceCached::timeZoneId() const
00269 {
00270   return mCalendar.timeZoneId();
00271 }
00272 
00273 void ResourceCached::clearChanges()
00274 {
00275   mAddedIncidences.clear();
00276   mChangedIncidences.clear();
00277   mDeletedIncidences.clear();
00278 }
00279 
00280 void ResourceCached::loadCache()
00281 {
00282   setIdMapperIdentifier();
00283   mIdMapper.load();
00284 
00285   if ( KStandardDirs::exists( cacheFile() ) ) {
00286     mCalendar.load( cacheFile() );
00287     if ( readOnly() ) {
00288       Incidence::List incidences( rawIncidences() );
00289       Incidence::List::Iterator it;
00290       for ( it = incidences.begin(); it != incidences.end(); ++it ) {
00291         (*it)->setReadOnly( true );
00292       }
00293     }
00294   }
00295 }
00296 
00297 void ResourceCached::saveCache()
00298 {
00299   kdDebug(5800) << "ResourceCached::saveCache(): " << cacheFile() << endl;
00300 
00301   setIdMapperIdentifier();
00302   mIdMapper.save();
00303 
00304   mCalendar.save( cacheFile() );
00305 }
00306 
00307 void ResourceCached::setIdMapperIdentifier()
00308 {
00309   mIdMapper.setIdentifier( type() + "_" + identifier() );
00310 }
00311 
00312 void ResourceCached::clearCache()
00313 {
00314   mCalendar.close();
00315 }
00316 
00317 void ResourceCached::cleanUpEventCache( const Event::List &eventList )
00318 {
00319   CalendarLocal calendar ( QString::fromLatin1( "UTC" ) );
00320 
00321   if ( KStandardDirs::exists( cacheFile() ) )
00322     calendar.load( cacheFile() );
00323   else
00324     return;
00325 
00326   Event::List list = calendar.events();
00327   Event::List::ConstIterator cacheIt, it;
00328   for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
00329     bool found = false;
00330     for ( it = eventList.begin(); it != eventList.end(); ++it ) {
00331       if ( (*it)->uid() == (*cacheIt)->uid() )
00332         found = true;
00333     }
00334 
00335     if ( !found ) {
00336       mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
00337       Event *event = mCalendar.event( (*cacheIt)->uid() );
00338       if ( event )
00339         mCalendar.deleteEvent( event );
00340     }
00341   }
00342 
00343   calendar.close();
00344 }
00345 
00346 void ResourceCached::cleanUpTodoCache( const Todo::List &todoList )
00347 {
00348   CalendarLocal calendar ( QString::fromLatin1( "UTC" ) );
00349 
00350   if ( KStandardDirs::exists( cacheFile() ) )
00351     calendar.load( cacheFile() );
00352   else
00353     return;
00354 
00355   Todo::List list = calendar.todos();
00356   Todo::List::ConstIterator cacheIt, it;
00357   for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
00358 
00359     bool found = false;
00360     for ( it = todoList.begin(); it != todoList.end(); ++it ) {
00361       if ( (*it)->uid() == (*cacheIt)->uid() )
00362         found = true;
00363     }
00364 
00365     if ( !found ) {
00366       mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
00367       Todo *todo = mCalendar.todo( (*cacheIt)->uid() );
00368       if ( todo )
00369         mCalendar.deleteTodo( todo );
00370     }
00371   }
00372 
00373   calendar.close();
00374 }
00375 
00376 KPIM::IdMapper& ResourceCached::idMapper()
00377 {
00378   return mIdMapper;
00379 }
00380 
00381 QString ResourceCached::cacheFile() const
00382 {
00383   return locateLocal( "cache", "kcal/kresources/" + identifier() );
00384 }
00385 
00386 QString ResourceCached::changesCacheFile( const QString &type ) const
00387 {
00388   return locateLocal( "cache", "kcal/changescache/" + identifier() + "_" + type );
00389 }
00390 
00391 void ResourceCached::saveChangesCache( const QMap<Incidence*, bool> &map, const QString &type )
00392 {
00393   CalendarLocal calendar ( QString::fromLatin1( "UTC" ) );
00394 
00395   bool isEmpty = true;
00396   QMap<Incidence *,bool>::ConstIterator it;
00397   for ( it = map.begin(); it != map.end(); ++it ) {
00398     isEmpty = false;
00399     calendar.addIncidence( it.key()->clone() );
00400   }
00401 
00402   if ( !isEmpty ) {
00403     calendar.save( changesCacheFile( type ) );
00404   } else {
00405     QFile file( changesCacheFile( type ) );
00406     file.remove();
00407   }
00408 
00409   calendar.close();
00410 }
00411 
00412 void ResourceCached::saveChangesCache()
00413 {
00414   saveChangesCache( mAddedIncidences, "added" );
00415   saveChangesCache( mDeletedIncidences, "deleted" );
00416   saveChangesCache( mChangedIncidences, "changed" );
00417 }
00418 
00419 void ResourceCached::loadChangesCache( QMap<Incidence*, bool> &map, const QString &type )
00420 {
00421   CalendarLocal calendar ( QString::fromLatin1( "UTC" ) );
00422 
00423   if ( KStandardDirs::exists( changesCacheFile( type ) ) )
00424     calendar.load( changesCacheFile( type ) );
00425   else
00426     return;
00427 
00428   const Incidence::List list = calendar.incidences();
00429   Incidence::List::ConstIterator it;
00430   for ( it = list.begin(); it != list.end(); ++it )
00431     map.insert( (*it)->clone(), true );
00432 
00433   calendar.close();
00434 }
00435 
00436 void ResourceCached::loadChangesCache()
00437 {
00438   loadChangesCache( mAddedIncidences, "added" );
00439   loadChangesCache( mDeletedIncidences, "deleted" );
00440   loadChangesCache( mChangedIncidences, "changed" );
00441 }
00442 
00443 void ResourceCached::calendarIncidenceAdded( Incidence *i )
00444 {
00445 #if 1
00446   kdDebug(5800) << "ResourceCached::calendarIncidenceAdded(): "
00447             << i->uid() << endl;
00448 #endif
00449 
00450   QMap<Incidence *,bool>::ConstIterator it;
00451   it = mAddedIncidences.find( i );
00452   if ( it == mAddedIncidences.end() ) {
00453     mAddedIncidences.insert( i, true );
00454   }
00455 
00456   checkForAutomaticSave();
00457 }
00458 
00459 void ResourceCached::calendarIncidenceChanged( Incidence *i )
00460 {
00461 #if 1
00462   kdDebug(5800) << "ResourceCached::calendarIncidenceChanged(): "
00463             << i->uid() << endl;
00464 #endif
00465 
00466   QMap<Incidence *,bool>::ConstIterator it;
00467   it = mChangedIncidences.find( i );
00468   // FIXME: If you modify an added incidence, there's no need to add it to mChangedIncidences!
00469   if ( it == mChangedIncidences.end() ) {
00470     mChangedIncidences.insert( i, true );
00471   }
00472 
00473   checkForAutomaticSave();
00474 }
00475 
00476 void ResourceCached::calendarIncidenceDeleted( Incidence *i )
00477 {
00478 #if 1
00479   kdDebug(5800) << "ResourceCached::calendarIncidenceDeleted(): "
00480             << i->uid() << endl;
00481 #endif
00482 
00483   QMap<Incidence *,bool>::ConstIterator it;
00484   it = mDeletedIncidences.find( i );
00485   if ( it == mDeletedIncidences.end() ) {
00486     mDeletedIncidences.insert( i, true );
00487   }
00488 
00489   checkForAutomaticSave();
00490 }
00491 
00492 Incidence::List ResourceCached::addedIncidences() const
00493 {
00494   Incidence::List added;
00495   QMap<Incidence *,bool>::ConstIterator it;
00496   for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
00497     added.append( it.key() );
00498   }
00499   return added;
00500 }
00501 
00502 Incidence::List ResourceCached::changedIncidences() const
00503 {
00504   Incidence::List changed;
00505   QMap<Incidence *,bool>::ConstIterator it;
00506   for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
00507     changed.append( it.key() );
00508   }
00509   return changed;
00510 }
00511 
00512 Incidence::List ResourceCached::deletedIncidences() const
00513 {
00514   Incidence::List deleted;
00515   QMap<Incidence *,bool>::ConstIterator it;
00516   for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
00517     deleted.append( it.key() );
00518   }
00519   return deleted;
00520 }
00521 
00522 Incidence::List ResourceCached::allChanges() const
00523 {
00524   Incidence::List changes;
00525   QMap<Incidence *,bool>::ConstIterator it;
00526   for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
00527     changes.append( it.key() );
00528   }
00529   for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
00530     changes.append( it.key() );
00531   }
00532   for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
00533     changes.append( it.key() );
00534   }
00535   return changes;
00536 }
00537 
00538 bool ResourceCached::hasChanges() const
00539 {
00540   return !( mAddedIncidences.isEmpty() && mChangedIncidences.isEmpty() &&
00541             mDeletedIncidences.isEmpty() );
00542 }
00543 
00544 void ResourceCached::clearChange( Incidence *incidence )
00545 {
00546   clearChange( incidence->uid() );
00547 }
00548 
00549 void ResourceCached::clearChange( const QString &uid )
00550 {
00551   QMap<Incidence*, bool>::Iterator it;
00552 
00553   for ( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it )
00554     if ( it.key()->uid() == uid ) {
00555       mAddedIncidences.remove( it );
00556       break;
00557     }
00558 
00559   for ( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it )
00560     if ( it.key()->uid() == uid ) {
00561       mChangedIncidences.remove( it );
00562       break;
00563     }
00564 
00565   for ( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it )
00566     if ( it.key()->uid() == uid ) {
00567       mDeletedIncidences.remove( it );
00568       break;
00569     }
00570 }
00571 
00572 void ResourceCached::enableChangeNotification()
00573 {
00574   mCalendar.registerObserver( this );
00575 }
00576 
00577 void ResourceCached::disableChangeNotification()
00578 {
00579   mCalendar.unregisterObserver( this );
00580 }
00581 
00582 void ResourceCached::slotReload()
00583 {
00584   if ( !isActive() ) return;
00585 
00586   kdDebug(5800) << "ResourceCached::slotReload()" << endl;
00587 
00588   load();
00589 }
00590 
00591 void ResourceCached::slotSave()
00592 {
00593   if ( !isActive() ) return;
00594 
00595   kdDebug(5800) << "ResourceCached::slotSave()" << endl;
00596 
00597   save();
00598 }
00599 
00600 void ResourceCached::checkForAutomaticSave()
00601 {
00602   if ( mSavePolicy == SaveAlways )  {
00603     kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save now" << endl;
00604     mSaveTimer.start( 1 * 1000, true ); // 1 second
00605   } else if ( mSavePolicy == SaveDelayed ) {
00606     kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed"
00607               << endl;
00608     mSaveTimer.start( 15 * 1000, true ); // 15 seconds
00609   }
00610 }
00611 
00612 bool ResourceCached::checkForReload()
00613 {
00614   if ( mReloadPolicy == ReloadNever ) return false;
00615   if ( mReloadPolicy == ReloadOnStartup ) return !mReloaded;
00616   return true;
00617 }
00618 
00619 bool ResourceCached::checkForSave()
00620 {
00621   if ( mSavePolicy == SaveNever ) return false;
00622   return true;
00623 }
00624 
00625 void ResourceCached::addInfoText( QString &txt ) const
00626 {
00627   if ( mLastLoad.isValid() ) {
00628     txt += "<br>";
00629     txt += i18n("Last loaded: %1")
00630            .arg( KGlobal::locale()->formatDateTime( mLastLoad ) );
00631   }
00632   if ( mLastSave.isValid() ) {
00633     txt += "<br>";
00634     txt += i18n("Last saved: %1")
00635            .arg( KGlobal::locale()->formatDateTime( mLastSave ) );
00636   }
00637 }
00638 
00639 void ResourceCached::doClose()
00640 {
00641   mCalendar.close();
00642 }
00643 
00644 bool ResourceCached::doOpen()
00645 {
00646   kdDebug(5800) << "Opening resource " << resourceName() << endl;
00647   return true;
00648 }
00649 
00650 void KCal::ResourceCached::setOwner( const Person &owner )
00651 {
00652   mCalendar.setOwner( owner );
00653 }
00654 
00655 const Person & KCal::ResourceCached::getOwner() const
00656 {
00657   return mCalendar.getOwner();
00658 }
00659 
00660 #include "resourcecached.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys