00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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 #include <unistd.h>
00039
00040
00041 #include "resourcecached.h"
00042
00043 using namespace KCal;
00044
00045 ResourceCached::ResourceCached( const KConfig* config )
00046 : ResourceCalendar( config ), mCalendar( QString::fromLatin1( "UTC" ) ),
00047 mReloadPolicy( ReloadNever ), mReloadInterval( 10 ), mReloaded( false ),
00048 mSavePolicy( SaveNever ), mSaveInterval( 10 ),
00049 mIdMapper( "kcal/uidmaps/" )
00050 {
00051 connect( &mReloadTimer, SIGNAL( timeout() ), SLOT( slotReload() ) );
00052 connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( slotSave() ) );
00053 }
00054
00055 ResourceCached::~ResourceCached()
00056 {
00057 }
00058
00059 void ResourceCached::setReloadPolicy( int i )
00060 {
00061 mReloadPolicy = i;
00062
00063 setupReloadTimer();
00064 }
00065
00066 int ResourceCached::reloadPolicy() const
00067 {
00068 return mReloadPolicy;
00069 }
00070
00071 void ResourceCached::setReloadInterval( int minutes )
00072 {
00073 mReloadInterval = minutes;
00074 }
00075
00076 int ResourceCached::reloadInterval() const
00077 {
00078 return mReloadInterval;
00079 }
00080
00081 void ResourceCached::setSavePolicy( int i )
00082 {
00083 mSavePolicy = i;
00084
00085 setupSaveTimer();
00086 }
00087
00088 int ResourceCached::savePolicy() const
00089 {
00090 return mSavePolicy;
00091 }
00092
00093 void ResourceCached::setSaveInterval( int minutes )
00094 {
00095 mSaveInterval = minutes;
00096 }
00097
00098 int ResourceCached::saveInterval() const
00099 {
00100 return mSaveInterval;
00101 }
00102
00103 void ResourceCached::readConfig( const KConfig *config )
00104 {
00105 mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever );
00106 mReloadInterval = config->readNumEntry( "ReloadInterval", 10 );
00107
00108 mSaveInterval = config->readNumEntry( "SaveInterval", 10 );
00109 mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever );
00110
00111 mLastLoad = config->readDateTimeEntry( "LastLoad" );
00112 mLastSave = config->readDateTimeEntry( "LastSave" );
00113
00114 setupSaveTimer();
00115 setupReloadTimer();
00116 }
00117
00118 void ResourceCached::setupSaveTimer()
00119 {
00120 if ( mSavePolicy == SaveInterval ) {
00121 kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval "
00122 << mSaveInterval << " minutes)." << endl;
00123 mSaveTimer.start( mSaveInterval * 60 * 1000 );
00124 } else {
00125 mSaveTimer.stop();
00126 }
00127 }
00128
00129 void ResourceCached::setupReloadTimer()
00130 {
00131 if ( mReloadPolicy == ReloadInterval ) {
00132 kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer "
00133 "(interval " << mReloadInterval << " minutes)" << endl;
00134 mReloadTimer.start( mReloadInterval * 60 * 1000 );
00135 } else {
00136 mReloadTimer.stop();
00137 }
00138 }
00139
00140 void ResourceCached::writeConfig( KConfig *config )
00141 {
00142 config->writeEntry( "ReloadPolicy", mReloadPolicy );
00143 config->writeEntry( "ReloadInterval", mReloadInterval );
00144
00145 config->writeEntry( "SavePolicy", mSavePolicy );
00146 config->writeEntry( "SaveInterval", mSaveInterval );
00147
00148 config->writeEntry( "LastLoad", mLastLoad );
00149 config->writeEntry( "LastSave", mLastSave );
00150 }
00151
00152 bool ResourceCached::addEvent(Event *event)
00153 {
00154 return mCalendar.addEvent( event );
00155 }
00156
00157
00158 bool ResourceCached::deleteEvent( Event *event )
00159 {
00160 kdDebug(5800) << "ResourceCached::deleteEvent" << endl;
00161
00162 return mCalendar.deleteEvent( event );
00163 }
00164
00165
00166 Event *ResourceCached::event( const QString &uid )
00167 {
00168 return mCalendar.event( uid );
00169 }
00170
00171 Event::List ResourceCached::rawEventsForDate( const QDate &qd,
00172 EventSortField sortField,
00173 SortDirection sortDirection )
00174 {
00175 Event::List list = mCalendar.rawEventsForDate( qd, sortField, sortDirection );
00176
00177 return list;
00178 }
00179
00180 Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end,
00181 bool inclusive )
00182 {
00183 return mCalendar.rawEvents( start, end, inclusive );
00184 }
00185
00186 Event::List ResourceCached::rawEventsForDate( const QDateTime &qdt )
00187 {
00188 return mCalendar.rawEventsForDate( qdt.date() );
00189 }
00190
00191 Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
00192 {
00193 return mCalendar.rawEvents( sortField, sortDirection );
00194 }
00195
00196 bool ResourceCached::addTodo( Todo *todo )
00197 {
00198 return mCalendar.addTodo( todo );
00199 }
00200
00201 bool ResourceCached::deleteTodo( Todo *todo )
00202 {
00203 return mCalendar.deleteTodo( todo );
00204 }
00205
00206 bool ResourceCached::deleteJournal( Journal *journal )
00207 {
00208 return mCalendar.deleteJournal( journal );
00209 }
00210
00211
00212 Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
00213 {
00214 return mCalendar.rawTodos( sortField, sortDirection );
00215 }
00216
00217 Todo *ResourceCached::todo( const QString &uid )
00218 {
00219 return mCalendar.todo( uid );
00220 }
00221
00222 Todo::List ResourceCached::rawTodosForDate( const QDate &date )
00223 {
00224 return mCalendar.rawTodosForDate( date );
00225 }
00226
00227
00228 bool ResourceCached::addJournal( Journal *journal )
00229 {
00230 kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl;
00231
00232 return mCalendar.addJournal( journal );
00233 }
00234
00235 Journal *ResourceCached::journal( const QString &uid )
00236 {
00237 return mCalendar.journal( uid );
00238 }
00239
00240 Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
00241 {
00242 return mCalendar.rawJournals( sortField, sortDirection );
00243 }
00244
00245 Journal::List ResourceCached::rawJournalsForDate( const QDate &date )
00246 {
00247 return mCalendar.rawJournalsForDate( date );
00248 }
00249
00250
00251 Alarm::List ResourceCached::alarmsTo( const QDateTime &to )
00252 {
00253 return mCalendar.alarmsTo( to );
00254 }
00255
00256 Alarm::List ResourceCached::alarms( const QDateTime &from, const QDateTime &to )
00257 {
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
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 );
00605 } else if ( mSavePolicy == SaveDelayed ) {
00606 kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed"
00607 << endl;
00608 mSaveTimer.start( 15 * 1000, true );
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"