23 #include "resourcecached.h"
33 #include <kconfiggroup.h>
36 #include <kstandarddirs.h>
39 #include <QtCore/QDateTime>
40 #include <QtCore/QDataStream>
41 #include <QtCore/QFile>
42 #include <QtCore/QString>
43 #include <QtCore/QTimer>
45 #include "resourcecached.moc"
50 class ResourceCached::Private
54 : mCalendar( QLatin1String(
"UTC" ) ),
56 mReloadInterval( 10 ),
57 mInhibitReload( false ),
59 mSavePending( false ),
62 mIdMapper(
"kcal/uidmaps/" )
81 QMap<KCal::Incidence *,bool> mAddedIncidences;
82 QMap<KCal::Incidence *,bool> mChangedIncidences;
83 QMap<KCal::Incidence *,bool> mDeletedIncidences;
89 ResourceCached::ResourceCached()
93 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
94 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
97 ResourceCached::ResourceCached(
const KConfigGroup &group )
101 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
102 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
105 ResourceCached::~ResourceCached()
112 return &d->mCalendar;
115 bool ResourceCached::defaultReloadInhibited()
const
117 return d->mInhibitReload;
132 d->mReloadPolicy = i;
139 return d->mReloadPolicy;
144 d->mReloadInterval = minutes;
149 return d->mReloadInterval;
154 if ( inhibit == d->mInhibitReload ) {
157 d->mInhibitReload = inhibit;
170 return d->mSavePolicy;
175 d->mSaveInterval = minutes;
180 return d->mSaveInterval;
183 void ResourceCached::readConfig(
const KConfigGroup &group )
185 d->mReloadPolicy = group.readEntry(
"ReloadPolicy",
int(ReloadNever) );
186 d->mReloadInterval = group.readEntry(
"ReloadInterval", 10 );
188 d->mSaveInterval = group.readEntry(
"SaveInterval", 10 );
189 d->mSavePolicy = group.readEntry(
"SavePolicy",
int(SaveNever) );
191 QDateTime curDt = QDateTime::currentDateTime();
192 QDateTime dt = group.readEntry(
"LastLoad", curDt );
193 d->mLastLoad = KDateTime( dt, KDateTime::UTC );
194 dt = group.readEntry(
"LastSave", curDt );
195 d->mLastSave = KDateTime( dt, KDateTime::UTC );
201 void ResourceCached::setupSaveTimer()
203 if ( d->mSavePolicy == SaveInterval ) {
204 kDebug() <<
"start save timer (interval " << d->mSaveInterval <<
"mins)";
205 d->mSaveTimer.start( d->mSaveInterval * 60 * 1000 );
207 d->mSaveTimer.stop();
211 void ResourceCached::setupReloadTimer()
213 if ( d->mReloadPolicy == ReloadInterval ) {
214 kDebug() <<
"start reload timer (interval " << d->mReloadInterval <<
"mins)";
215 d->mReloadTimer.start( d->mReloadInterval * 60 * 1000 );
217 d->mReloadTimer.stop();
221 void ResourceCached::writeConfig( KConfigGroup &group )
223 group.writeEntry(
"ReloadPolicy", d->mReloadPolicy );
224 group.writeEntry(
"ReloadInterval", d->mReloadInterval );
226 group.writeEntry(
"SavePolicy", d->mSavePolicy );
227 group.writeEntry(
"SaveInterval", d->mSaveInterval );
229 group.writeEntry(
"LastLoad", d->mLastLoad.toUtc().dateTime() );
230 group.writeEntry(
"LastSave", d->mLastSave.toUtc().dateTime() );
235 return d->mCalendar.addEvent( event );
243 return d->mCalendar.deleteEvent( event );
248 d->mCalendar.deleteAllEvents();
253 return d->mCalendar.event( uid );
260 Event::List list = d->mCalendar.rawEventsForDate( qd, timeSpec, sortField, sortDirection );
266 const KDateTime::Spec &timeSpec,
bool inclusive )
268 return d->mCalendar.rawEvents( start, end, timeSpec, inclusive );
273 return d->mCalendar.rawEventsForDate( kdt );
278 return d->mCalendar.rawEvents( sortField, sortDirection );
283 return d->mCalendar.addTodo( todo );
288 return d->mCalendar.deleteTodo( todo );
293 d->mCalendar.deleteAllTodos();
298 return d->mCalendar.deleteJournal( journal );
303 d->mCalendar.deleteAllJournals();
308 return d->mCalendar.rawTodos( sortField, sortDirection );
313 return d->mCalendar.todo( uid );
318 return d->mCalendar.rawTodosForDate( date );
323 return d->mCalendar.addJournal( journal );
328 return d->mCalendar.journal( uid );
333 return d->mCalendar.rawJournals( sortField, sortDirection );
338 return d->mCalendar.rawJournalsForDate( date );
343 return d->mCalendar.alarmsTo( to );
348 return d->mCalendar.alarms( from, to );
353 d->mCalendar.setTimeSpec( timeSpec );
358 return d->mCalendar.timeSpec();
363 d->mCalendar.setTimeZoneId( tzid );
368 return d->mCalendar.timeZoneId();
373 d->mCalendar.shiftTimes( oldSpec, newSpec );
376 void ResourceCached::clearChanges()
378 d->mAddedIncidences.clear();
379 d->mChangedIncidences.clear();
380 d->mDeletedIncidences.clear();
385 kDebug() << resourceName();
387 setReceivedLoadError(
false );
397 if ( !d->mReloaded && !d->mInhibitReload ) {
398 update = checkForReload();
407 success = doLoad( update );
409 if ( !success && !receivedLoadError() ) {
416 if ( !noReadOnlyOnLoad() && readOnly() ) {
418 Incidence::List::Iterator it;
419 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
420 (*it)->setReadOnly(
true );
424 kDebug() <<
"Done loading resource" << resourceName();
427 emit resourceLoaded(
this );
435 return load( SyncCache );
440 setIdMapperIdentifier();
443 if ( !KStandardDirs::exists( cacheFile() ) ) {
446 d->mCalendar.load( cacheFile() );
447 if ( !noReadOnlyOnLoad() && readOnly() ) {
449 Incidence::List::Iterator it;
450 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
451 (*it)->setReadOnly(
true );
459 if ( !incidence && ( d->mSavePolicy == SaveAlways || d->mSavePolicy == SaveDelayed ) ) {
460 d->mSaveTimer.stop();
462 d->mSavePending =
false;
463 if ( saveInhibited() ) {
467 kDebug() <<
"Save resource" << resourceName();
469 setReceivedSaveError(
false );
477 upload = checkForSave();
485 bool success = incidence ? doSave( upload, incidence ) : doSave( upload );
486 if ( !success && !receivedSaveError() ) {
489 emit resourceSaved(
this );
494 kDebug() <<
"Don't save read-only resource" << resourceName();
501 return save( SyncCache, incidence );
506 Q_UNUSED( incidence );
507 return doSave( syncCache );
512 kDebug() << cacheFile();
514 setIdMapperIdentifier();
517 d->mCalendar.save( cacheFile() );
520 void ResourceCached::setIdMapperIdentifier()
522 d->mIdMapper.setIdentifier( type() +
'_' + identifier() );
527 d->mCalendar.close();
530 void ResourceCached::cleanUpEventCache(
const Event::List &eventList )
534 if ( KStandardDirs::exists( cacheFile() ) ) {
535 calendar.load( cacheFile() );
541 Event::List::ConstIterator cacheIt, it;
542 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
544 for ( it = eventList.begin(); it != eventList.end(); ++it ) {
545 if ( (*it)->uid() == (*cacheIt)->uid() ) {
552 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
553 Event *
event = d->mCalendar.event( (*cacheIt)->uid() );
555 d->mCalendar.deleteEvent( event );
563 void ResourceCached::cleanUpTodoCache(
const Todo::List &todoList )
567 if ( KStandardDirs::exists( cacheFile() ) ) {
568 calendar.load( cacheFile() );
574 Todo::List::ConstIterator cacheIt, it;
575 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
578 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
579 if ( (*it)->uid() == (*cacheIt)->uid() ) {
585 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
586 Todo *todo = d->mCalendar.todo( (*cacheIt)->uid() );
588 d->mCalendar.deleteTodo( todo );
603 return KStandardDirs::locateLocal(
"cache",
"kcal/kresources/" + identifier() );
608 return KStandardDirs::locateLocal(
"cache",
"kcal/changescache/" + identifier() +
'_' + type );
611 void ResourceCached::saveChangesCache(
const QMap<Incidence *, bool> &map,
const QString &type )
616 QMap<Incidence *,bool>::ConstIterator it;
617 for ( it = map.begin(); it != map.end(); ++it ) {
619 calendar.addIncidence( it.key()->clone() );
623 calendar.save( changesCacheFile( type ) );
625 QFile file( changesCacheFile( type ) );
632 void ResourceCached::saveChangesCache()
634 saveChangesCache( d->mAddedIncidences,
"added" );
635 saveChangesCache( d->mDeletedIncidences,
"deleted" );
636 saveChangesCache( d->mChangedIncidences,
"changed" );
639 void ResourceCached::loadChangesCache( QMap<Incidence *, bool> &map,
const QString &type )
643 if ( KStandardDirs::exists( changesCacheFile( type ) ) ) {
644 calendar.load( changesCacheFile( type ) );
650 Incidence::List::ConstIterator it;
651 for ( it = list.begin(); it != list.end(); ++it ) {
652 map.insert( (*it)->clone(), true );
658 void ResourceCached::loadChangesCache()
660 loadChangesCache( d->mAddedIncidences,
"added" );
661 loadChangesCache( d->mDeletedIncidences,
"deleted" );
662 loadChangesCache( d->mChangedIncidences,
"changed" );
667 kDebug() << i->
uid();
669 QMap<Incidence *,bool>::ConstIterator it;
670 it = d->mAddedIncidences.constFind( i );
671 if ( it == d->mAddedIncidences.constEnd() ) {
672 d->mAddedIncidences.insert( i,
true );
675 checkForAutomaticSave();
680 kDebug() << i->
uid();
682 QMap<Incidence *,bool>::ConstIterator it;
683 it = d->mChangedIncidences.constFind( i );
685 if ( it == d->mChangedIncidences.constEnd() ) {
686 d->mChangedIncidences.insert( i,
true );
689 checkForAutomaticSave();
694 kDebug() << i->
uid();
696 QMap<Incidence *,bool>::ConstIterator it;
697 it = d->mDeletedIncidences.constFind( i );
698 if ( it == d->mDeletedIncidences.constEnd() ) {
699 d->mDeletedIncidences.insert( i,
true );
702 checkForAutomaticSave();
708 QMap<Incidence *,bool>::ConstIterator it;
709 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
710 added.append( it.key() );
718 QMap<Incidence *,bool>::ConstIterator it;
719 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
720 changed.append( it.key() );
728 QMap<Incidence *,bool>::ConstIterator it;
729 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
730 deleted.append( it.key() );
738 QMap<Incidence *,bool>::ConstIterator it;
739 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
740 changes.append( it.key() );
742 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
743 changes.append( it.key() );
745 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
746 changes.append( it.key() );
751 bool ResourceCached::hasChanges()
const
753 return !( d->mAddedIncidences.isEmpty() && d->mChangedIncidences.isEmpty() &&
754 d->mDeletedIncidences.isEmpty() );
757 void ResourceCached::clearChange(
Incidence *incidence )
759 clearChange( incidence->
uid() );
762 void ResourceCached::clearChange(
const QString &uid )
764 QMap<Incidence *, bool>::Iterator it;
766 for ( it = d->mAddedIncidences.begin(); it != d->mAddedIncidences.end(); ++it ) {
767 if ( it.key()->uid() == uid ) {
768 d->mAddedIncidences.erase( it );
773 for ( it = d->mChangedIncidences.begin(); it != d->mChangedIncidences.end(); ++it ) {
774 if ( it.key()->uid() == uid ) {
775 d->mChangedIncidences.erase( it );
780 for ( it = d->mDeletedIncidences.begin(); it != d->mDeletedIncidences.end(); ++it ) {
781 if ( it.key()->uid() == uid ) {
782 d->mDeletedIncidences.erase( it );
788 void ResourceCached::enableChangeNotification()
790 d->mCalendar.registerObserver(
this );
793 void ResourceCached::disableChangeNotification()
795 d->mCalendar.unregisterObserver(
this );
798 void ResourceCached::slotReload()
809 void ResourceCached::slotSave()
820 void ResourceCached::checkForAutomaticSave()
822 if ( d->mSavePolicy == SaveAlways ) {
823 kDebug() <<
"save now";
824 d->mSavePending =
true;
825 d->mSaveTimer.setSingleShot(
true );
826 d->mSaveTimer.start( 1 * 1000 );
827 }
else if ( d->mSavePolicy == SaveDelayed ) {
828 kDebug() <<
"save delayed";
829 d->mSavePending =
true;
830 d->mSaveTimer.setSingleShot(
true );
831 d->mSaveTimer.start( 15 * 1000 );
837 if ( d->mReloadPolicy == ReloadNever ) {
840 if ( d->mReloadPolicy == ReloadOnStartup ) {
841 return !d->mReloaded;
848 if ( d->mSavePolicy == SaveNever ) {
856 if ( d->mLastLoad.isValid() ) {
858 txt += i18n(
"Last loaded: %1",
859 KGlobal::locale()->formatDateTime( d->mLastLoad.toUtc().dateTime() ) );
861 if ( d->mLastSave.isValid() ) {
863 txt += i18n(
"Last saved: %1",
864 KGlobal::locale()->formatDateTime( d->mLastSave.toUtc().dateTime() ) );
870 if ( d->mSavePending ) {
871 d->mSaveTimer.stop();
873 if ( d->mSavePending || d->mSavePolicy == SaveOnExit || d->mSavePolicy == SaveInterval ) {
876 d->mCalendar.close();
881 kDebug() <<
"Opening resource" << resourceName();
887 d->mCalendar.setOwner( owner );
892 return d->mCalendar.owner();