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>
49 class ResourceCached::Private
53 : mCalendar( QLatin1String(
"UTC" ) ),
55 mReloadInterval( 10 ),
56 mInhibitReload( false ),
58 mSavePending( false ),
61 mIdMapper(
"kcal/uidmaps/" )
80 QMap<KCal::Incidence *,bool> mAddedIncidences;
81 QMap<KCal::Incidence *,bool> mChangedIncidences;
82 QMap<KCal::Incidence *,bool> mDeletedIncidences;
88 ResourceCached::ResourceCached()
92 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
93 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
96 ResourceCached::ResourceCached(
const KConfigGroup &group )
100 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
101 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
104 ResourceCached::~ResourceCached()
111 return &d->mCalendar;
114 bool ResourceCached::defaultReloadInhibited()
const
116 return d->mInhibitReload;
131 d->mReloadPolicy = i;
138 return d->mReloadPolicy;
143 d->mReloadInterval = minutes;
148 return d->mReloadInterval;
153 if ( inhibit == d->mInhibitReload ) {
156 d->mInhibitReload = inhibit;
169 return d->mSavePolicy;
174 d->mSaveInterval = minutes;
179 return d->mSaveInterval;
182 void ResourceCached::readConfig(
const KConfigGroup &group )
184 d->mReloadPolicy = group.readEntry(
"ReloadPolicy",
int(ReloadNever) );
185 d->mReloadInterval = group.readEntry(
"ReloadInterval", 10 );
187 d->mSaveInterval = group.readEntry(
"SaveInterval", 10 );
188 d->mSavePolicy = group.readEntry(
"SavePolicy",
int(SaveNever) );
190 QDateTime curDt = QDateTime::currentDateTime();
191 QDateTime dt = group.readEntry(
"LastLoad", curDt );
192 d->mLastLoad = KDateTime( dt, KDateTime::UTC );
193 dt = group.readEntry(
"LastSave", curDt );
194 d->mLastSave = KDateTime( dt, KDateTime::UTC );
200 void ResourceCached::setupSaveTimer()
202 if ( d->mSavePolicy == SaveInterval ) {
203 kDebug() <<
"start save timer (interval " << d->mSaveInterval <<
"mins)";
204 d->mSaveTimer.start( d->mSaveInterval * 60 * 1000 );
206 d->mSaveTimer.stop();
210 void ResourceCached::setupReloadTimer()
212 if ( d->mReloadPolicy == ReloadInterval ) {
213 kDebug() <<
"start reload timer (interval " << d->mReloadInterval <<
"mins)";
214 d->mReloadTimer.start( d->mReloadInterval * 60 * 1000 );
216 d->mReloadTimer.stop();
220 void ResourceCached::writeConfig( KConfigGroup &group )
222 group.writeEntry(
"ReloadPolicy", d->mReloadPolicy );
223 group.writeEntry(
"ReloadInterval", d->mReloadInterval );
225 group.writeEntry(
"SavePolicy", d->mSavePolicy );
226 group.writeEntry(
"SaveInterval", d->mSaveInterval );
228 group.writeEntry(
"LastLoad", d->mLastLoad.toUtc().dateTime() );
229 group.writeEntry(
"LastSave", d->mLastSave.toUtc().dateTime() );
234 return d->mCalendar.addEvent( event );
242 return d->mCalendar.deleteEvent( event );
247 d->mCalendar.deleteAllEvents();
252 return d->mCalendar.event( uid );
259 Event::List list = d->mCalendar.rawEventsForDate( qd, timeSpec, sortField, sortDirection );
265 const KDateTime::Spec &timeSpec,
bool inclusive )
267 return d->mCalendar.rawEvents( start, end, timeSpec, inclusive );
272 return d->mCalendar.rawEventsForDate( kdt );
277 return d->mCalendar.rawEvents( sortField, sortDirection );
282 return d->mCalendar.addTodo( todo );
287 return d->mCalendar.deleteTodo( todo );
292 d->mCalendar.deleteAllTodos();
297 return d->mCalendar.deleteJournal( journal );
302 d->mCalendar.deleteAllJournals();
307 return d->mCalendar.rawTodos( sortField, sortDirection );
312 return d->mCalendar.todo( uid );
317 return d->mCalendar.rawTodosForDate( date );
322 return d->mCalendar.addJournal( journal );
327 return d->mCalendar.journal( uid );
332 return d->mCalendar.rawJournals( sortField, sortDirection );
337 return d->mCalendar.rawJournalsForDate( date );
342 return d->mCalendar.alarmsTo( to );
347 return d->mCalendar.alarms( from, to );
352 d->mCalendar.setTimeSpec( timeSpec );
357 return d->mCalendar.timeSpec();
362 d->mCalendar.setTimeZoneId( tzid );
367 return d->mCalendar.timeZoneId();
372 d->mCalendar.shiftTimes( oldSpec, newSpec );
375 void ResourceCached::clearChanges()
377 d->mAddedIncidences.clear();
378 d->mChangedIncidences.clear();
379 d->mDeletedIncidences.clear();
384 kDebug() << resourceName();
386 setReceivedLoadError(
false );
396 if ( !d->mReloaded && !d->mInhibitReload ) {
397 update = checkForReload();
406 success = doLoad( update );
408 if ( !success && !receivedLoadError() ) {
415 if ( !noReadOnlyOnLoad() && readOnly() ) {
417 Incidence::List::Iterator it;
418 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
419 (*it)->setReadOnly(
true );
423 kDebug() <<
"Done loading resource" << resourceName();
426 emit resourceLoaded(
this );
434 return load( SyncCache );
439 setIdMapperIdentifier();
442 if ( !KStandardDirs::exists( cacheFile() ) ) {
445 d->mCalendar.load( cacheFile() );
446 if ( !noReadOnlyOnLoad() && readOnly() ) {
448 Incidence::List::Iterator it;
449 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
450 (*it)->setReadOnly(
true );
458 if ( !incidence && ( d->mSavePolicy == SaveAlways || d->mSavePolicy == SaveDelayed ) ) {
459 d->mSaveTimer.stop();
461 d->mSavePending =
false;
462 if ( saveInhibited() ) {
466 kDebug() <<
"Save resource" << resourceName();
468 setReceivedSaveError(
false );
476 upload = checkForSave();
484 bool success = incidence ? doSave( upload, incidence ) : doSave( upload );
485 if ( !success && !receivedSaveError() ) {
488 emit resourceSaved(
this );
493 kDebug() <<
"Don't save read-only resource" << resourceName();
500 return save( SyncCache, incidence );
505 Q_UNUSED( incidence );
506 return doSave( syncCache );
511 kDebug() << cacheFile();
513 setIdMapperIdentifier();
516 d->mCalendar.save( cacheFile() );
519 void ResourceCached::setIdMapperIdentifier()
521 d->mIdMapper.setIdentifier( type() +
'_' + identifier() );
526 d->mCalendar.close();
529 void ResourceCached::cleanUpEventCache(
const Event::List &eventList )
533 if ( KStandardDirs::exists( cacheFile() ) ) {
534 calendar.load( cacheFile() );
540 Event::List::ConstIterator cacheIt, it;
541 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
543 for ( it = eventList.begin(); it != eventList.end(); ++it ) {
544 if ( (*it)->uid() == (*cacheIt)->uid() ) {
551 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
552 Event *
event = d->mCalendar.event( (*cacheIt)->uid() );
554 d->mCalendar.deleteEvent( event );
562 void ResourceCached::cleanUpTodoCache(
const Todo::List &todoList )
566 if ( KStandardDirs::exists( cacheFile() ) ) {
567 calendar.load( cacheFile() );
573 Todo::List::ConstIterator cacheIt, it;
574 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
577 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
578 if ( (*it)->uid() == (*cacheIt)->uid() ) {
584 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
585 Todo *todo = d->mCalendar.todo( (*cacheIt)->uid() );
587 d->mCalendar.deleteTodo( todo );
602 return KStandardDirs::locateLocal(
"cache",
"kcal/kresources/" + identifier() );
607 return KStandardDirs::locateLocal(
"cache",
"kcal/changescache/" + identifier() +
'_' + type );
610 void ResourceCached::saveChangesCache(
const QMap<Incidence *, bool> &map,
const QString &type )
615 QMap<Incidence *,bool>::ConstIterator it;
616 for ( it = map.begin(); it != map.end(); ++it ) {
618 calendar.addIncidence( it.key()->clone() );
622 calendar.save( changesCacheFile( type ) );
624 QFile file( changesCacheFile( type ) );
631 void ResourceCached::saveChangesCache()
633 saveChangesCache( d->mAddedIncidences,
"added" );
634 saveChangesCache( d->mDeletedIncidences,
"deleted" );
635 saveChangesCache( d->mChangedIncidences,
"changed" );
638 void ResourceCached::loadChangesCache( QMap<Incidence *, bool> &map,
const QString &type )
642 if ( KStandardDirs::exists( changesCacheFile( type ) ) ) {
643 calendar.load( changesCacheFile( type ) );
649 Incidence::List::ConstIterator it;
650 for ( it = list.begin(); it != list.end(); ++it ) {
651 map.insert( (*it)->clone(), true );
657 void ResourceCached::loadChangesCache()
659 loadChangesCache( d->mAddedIncidences,
"added" );
660 loadChangesCache( d->mDeletedIncidences,
"deleted" );
661 loadChangesCache( d->mChangedIncidences,
"changed" );
666 kDebug() << i->
uid();
668 QMap<Incidence *,bool>::ConstIterator it;
669 it = d->mAddedIncidences.constFind( i );
670 if ( it == d->mAddedIncidences.constEnd() ) {
671 d->mAddedIncidences.insert( i,
true );
674 checkForAutomaticSave();
679 kDebug() << i->
uid();
681 QMap<Incidence *,bool>::ConstIterator it;
682 it = d->mChangedIncidences.constFind( i );
684 if ( it == d->mChangedIncidences.constEnd() ) {
685 d->mChangedIncidences.insert( i,
true );
688 checkForAutomaticSave();
693 kDebug() << i->
uid();
695 QMap<Incidence *,bool>::ConstIterator it;
696 it = d->mDeletedIncidences.constFind( i );
697 if ( it == d->mDeletedIncidences.constEnd() ) {
698 d->mDeletedIncidences.insert( i,
true );
701 checkForAutomaticSave();
707 QMap<Incidence *,bool>::ConstIterator it;
708 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
709 added.append( it.key() );
717 QMap<Incidence *,bool>::ConstIterator it;
718 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
719 changed.append( it.key() );
727 QMap<Incidence *,bool>::ConstIterator it;
728 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
729 deleted.append( it.key() );
737 QMap<Incidence *,bool>::ConstIterator it;
738 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
739 changes.append( it.key() );
741 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
742 changes.append( it.key() );
744 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
745 changes.append( it.key() );
750 bool ResourceCached::hasChanges()
const
752 return !( d->mAddedIncidences.isEmpty() && d->mChangedIncidences.isEmpty() &&
753 d->mDeletedIncidences.isEmpty() );
756 void ResourceCached::clearChange(
Incidence *incidence )
758 clearChange( incidence->
uid() );
761 void ResourceCached::clearChange(
const QString &uid )
763 QMap<Incidence *, bool>::Iterator it;
765 for ( it = d->mAddedIncidences.begin(); it != d->mAddedIncidences.end(); ++it ) {
766 if ( it.key()->uid() == uid ) {
767 d->mAddedIncidences.erase( it );
772 for ( it = d->mChangedIncidences.begin(); it != d->mChangedIncidences.end(); ++it ) {
773 if ( it.key()->uid() == uid ) {
774 d->mChangedIncidences.erase( it );
779 for ( it = d->mDeletedIncidences.begin(); it != d->mDeletedIncidences.end(); ++it ) {
780 if ( it.key()->uid() == uid ) {
781 d->mDeletedIncidences.erase( it );
787 void ResourceCached::enableChangeNotification()
789 d->mCalendar.registerObserver(
this );
792 void ResourceCached::disableChangeNotification()
794 d->mCalendar.unregisterObserver(
this );
797 void ResourceCached::slotReload()
808 void ResourceCached::slotSave()
819 void ResourceCached::checkForAutomaticSave()
821 if ( d->mSavePolicy == SaveAlways ) {
822 kDebug() <<
"save now";
823 d->mSavePending =
true;
824 d->mSaveTimer.setSingleShot(
true );
825 d->mSaveTimer.start( 1 * 1000 );
826 }
else if ( d->mSavePolicy == SaveDelayed ) {
827 kDebug() <<
"save delayed";
828 d->mSavePending =
true;
829 d->mSaveTimer.setSingleShot(
true );
830 d->mSaveTimer.start( 15 * 1000 );
836 if ( d->mReloadPolicy == ReloadNever ) {
839 if ( d->mReloadPolicy == ReloadOnStartup ) {
840 return !d->mReloaded;
847 if ( d->mSavePolicy == SaveNever ) {
855 if ( d->mLastLoad.isValid() ) {
857 txt += i18n(
"Last loaded: %1",
858 KGlobal::locale()->formatDateTime( d->mLastLoad.toUtc().dateTime() ) );
860 if ( d->mLastSave.isValid() ) {
862 txt += i18n(
"Last saved: %1",
863 KGlobal::locale()->formatDateTime( d->mLastSave.toUtc().dateTime() ) );
869 if ( d->mSavePending ) {
870 d->mSaveTimer.stop();
872 if ( d->mSavePending || d->mSavePolicy == SaveOnExit || d->mSavePolicy == SaveInterval ) {
875 d->mCalendar.close();
880 kDebug() <<
"Opening resource" << resourceName();
886 d->mCalendar.setOwner( owner );
891 return d->mCalendar.owner();