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