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