diff options
Diffstat (limited to 'libkcal/resourcecached.cpp')
-rw-r--r-- | libkcal/resourcecached.cpp | 661 |
1 files changed, 661 insertions, 0 deletions
diff --git a/libkcal/resourcecached.cpp b/libkcal/resourcecached.cpp new file mode 100644 index 000000000..09862b25a --- /dev/null +++ b/libkcal/resourcecached.cpp @@ -0,0 +1,661 @@ +/* + This file is part of libkcal. + + Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qdatastream.h> +#include <qdatetime.h> +#include <qfile.h> +#include <qstring.h> +#include <qptrlist.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kurl.h> +#include <kstandarddirs.h> + +#include "event.h" +#include "exceptions.h" +#include "incidence.h" +#include "journal.h" +#include "todo.h" +#include <unistd.h> + + +#include "resourcecached.h" + +using namespace KCal; + +ResourceCached::ResourceCached( const KConfig* config ) + : ResourceCalendar( config ), mCalendar( QString::fromLatin1( "UTC" ) ), + mReloadPolicy( ReloadNever ), mReloadInterval( 10 ), + mReloadTimer( 0, "mReloadTimer" ), mReloaded( false ), + mSavePolicy( SaveNever ), mSaveInterval( 10 ), + mSaveTimer( 0, "mSaveTimer" ), mIdMapper( "kcal/uidmaps/" ) +{ + connect( &mReloadTimer, SIGNAL( timeout() ), SLOT( slotReload() ) ); + connect( &mSaveTimer, SIGNAL( timeout() ), SLOT( slotSave() ) ); +} + +ResourceCached::~ResourceCached() +{ +} + +void ResourceCached::setReloadPolicy( int i ) +{ + mReloadPolicy = i; + + setupReloadTimer(); +} + +int ResourceCached::reloadPolicy() const +{ + return mReloadPolicy; +} + +void ResourceCached::setReloadInterval( int minutes ) +{ + mReloadInterval = minutes; +} + +int ResourceCached::reloadInterval() const +{ + return mReloadInterval; +} + +void ResourceCached::setSavePolicy( int i ) +{ + mSavePolicy = i; + + setupSaveTimer(); +} + +int ResourceCached::savePolicy() const +{ + return mSavePolicy; +} + +void ResourceCached::setSaveInterval( int minutes ) +{ + mSaveInterval = minutes; +} + +int ResourceCached::saveInterval() const +{ + return mSaveInterval; +} + +void ResourceCached::readConfig( const KConfig *config ) +{ + mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever ); + mReloadInterval = config->readNumEntry( "ReloadInterval", 10 ); + + mSaveInterval = config->readNumEntry( "SaveInterval", 10 ); + mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever ); + + mLastLoad = config->readDateTimeEntry( "LastLoad" ); + mLastSave = config->readDateTimeEntry( "LastSave" ); + + setupSaveTimer(); + setupReloadTimer(); +} + +void ResourceCached::setupSaveTimer() +{ + if ( mSavePolicy == SaveInterval ) { + kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval " + << mSaveInterval << " minutes)." << endl; + mSaveTimer.start( mSaveInterval * 60 * 1000 ); // n minutes + } else { + mSaveTimer.stop(); + } +} + +void ResourceCached::setupReloadTimer() +{ + if ( mReloadPolicy == ReloadInterval ) { + kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer " + "(interval " << mReloadInterval << " minutes)" << endl; + mReloadTimer.start( mReloadInterval * 60 * 1000 ); // n minutes + } else { + mReloadTimer.stop(); + } +} + +void ResourceCached::writeConfig( KConfig *config ) +{ + config->writeEntry( "ReloadPolicy", mReloadPolicy ); + config->writeEntry( "ReloadInterval", mReloadInterval ); + + config->writeEntry( "SavePolicy", mSavePolicy ); + config->writeEntry( "SaveInterval", mSaveInterval ); + + config->writeEntry( "LastLoad", mLastLoad ); + config->writeEntry( "LastSave", mLastSave ); +} + +bool ResourceCached::addEvent(Event *event) +{ + return mCalendar.addEvent( event ); +} + +// probably not really efficient, but...it works for now. +bool ResourceCached::deleteEvent( Event *event ) +{ + kdDebug(5800) << "ResourceCached::deleteEvent" << endl; + + return mCalendar.deleteEvent( event ); +} + + +Event *ResourceCached::event( const QString &uid ) +{ + return mCalendar.event( uid ); +} + +Event::List ResourceCached::rawEventsForDate( const QDate &qd, + EventSortField sortField, + SortDirection sortDirection ) +{ + Event::List list = mCalendar.rawEventsForDate( qd, sortField, sortDirection ); + + return list; +} + +Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end, + bool inclusive ) +{ + return mCalendar.rawEvents( start, end, inclusive ); +} + +Event::List ResourceCached::rawEventsForDate( const QDateTime &qdt ) +{ + return mCalendar.rawEventsForDate( qdt.date() ); +} + +Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection ) +{ + return mCalendar.rawEvents( sortField, sortDirection ); +} + +bool ResourceCached::addTodo( Todo *todo ) +{ + return mCalendar.addTodo( todo ); +} + +bool ResourceCached::deleteTodo( Todo *todo ) +{ + return mCalendar.deleteTodo( todo ); +} + +bool ResourceCached::deleteJournal( Journal *journal ) +{ + return mCalendar.deleteJournal( journal ); +} + + +Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection ) +{ + return mCalendar.rawTodos( sortField, sortDirection ); +} + +Todo *ResourceCached::todo( const QString &uid ) +{ + return mCalendar.todo( uid ); +} + +Todo::List ResourceCached::rawTodosForDate( const QDate &date ) +{ + return mCalendar.rawTodosForDate( date ); +} + + +bool ResourceCached::addJournal( Journal *journal ) +{ + kdDebug(5800) << "Adding Journal on " << journal->dtStart().toString() << endl; + + return mCalendar.addJournal( journal ); +} + +Journal *ResourceCached::journal( const QString &uid ) +{ + return mCalendar.journal( uid ); +} + +Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection ) +{ + return mCalendar.rawJournals( sortField, sortDirection ); +} + +Journal::List ResourceCached::rawJournalsForDate( const QDate &date ) +{ + return mCalendar.rawJournalsForDate( date ); +} + + +Alarm::List ResourceCached::alarmsTo( const QDateTime &to ) +{ + return mCalendar.alarmsTo( to ); +} + +Alarm::List ResourceCached::alarms( const QDateTime &from, const QDateTime &to ) +{ + // kdDebug(5800) << "ResourceCached::alarms(" << from.toString() << " - " << to.toString() << ")\n"; + return mCalendar.alarms( from, to ); +} + + +void ResourceCached::setTimeZoneId( const QString& tzid ) +{ + mCalendar.setTimeZoneId( tzid ); +} + +QString ResourceCached::timeZoneId() const +{ + return mCalendar.timeZoneId(); +} + +void ResourceCached::clearChanges() +{ + mAddedIncidences.clear(); + mChangedIncidences.clear(); + mDeletedIncidences.clear(); +} + +void ResourceCached::loadCache() +{ + setIdMapperIdentifier(); + mIdMapper.load(); + + if ( KStandardDirs::exists( cacheFile() ) ) { + mCalendar.load( cacheFile() ); + if ( readOnly() ) { + Incidence::List incidences( rawIncidences() ); + Incidence::List::Iterator it; + for ( it = incidences.begin(); it != incidences.end(); ++it ) { + (*it)->setReadOnly( true ); + } + } + } +} + +void ResourceCached::saveCache() +{ + kdDebug(5800) << "ResourceCached::saveCache(): " << cacheFile() << endl; + + setIdMapperIdentifier(); + mIdMapper.save(); + + mCalendar.save( cacheFile() ); +} + +void ResourceCached::setIdMapperIdentifier() +{ + mIdMapper.setIdentifier( type() + "_" + identifier() ); +} + +void ResourceCached::clearCache() +{ + mCalendar.close(); +} + +void ResourceCached::cleanUpEventCache( const Event::List &eventList ) +{ + CalendarLocal calendar ( QString::fromLatin1( "UTC" ) ); + + if ( KStandardDirs::exists( cacheFile() ) ) + calendar.load( cacheFile() ); + else + return; + + Event::List list = calendar.events(); + Event::List::ConstIterator cacheIt, it; + for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) { + bool found = false; + for ( it = eventList.begin(); it != eventList.end(); ++it ) { + if ( (*it)->uid() == (*cacheIt)->uid() ) + found = true; + } + + if ( !found ) { + mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) ); + Event *event = mCalendar.event( (*cacheIt)->uid() ); + if ( event ) + mCalendar.deleteEvent( event ); + } + } + + calendar.close(); +} + +void ResourceCached::cleanUpTodoCache( const Todo::List &todoList ) +{ + CalendarLocal calendar ( QString::fromLatin1( "UTC" ) ); + + if ( KStandardDirs::exists( cacheFile() ) ) + calendar.load( cacheFile() ); + else + return; + + Todo::List list = calendar.todos(); + Todo::List::ConstIterator cacheIt, it; + for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) { + + bool found = false; + for ( it = todoList.begin(); it != todoList.end(); ++it ) { + if ( (*it)->uid() == (*cacheIt)->uid() ) + found = true; + } + + if ( !found ) { + mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) ); + Todo *todo = mCalendar.todo( (*cacheIt)->uid() ); + if ( todo ) + mCalendar.deleteTodo( todo ); + } + } + + calendar.close(); +} + +KPIM::IdMapper& ResourceCached::idMapper() +{ + return mIdMapper; +} + +QString ResourceCached::cacheFile() const +{ + return locateLocal( "cache", "kcal/kresources/" + identifier() ); +} + +QString ResourceCached::changesCacheFile( const QString &type ) const +{ + return locateLocal( "cache", "kcal/changescache/" + identifier() + "_" + type ); +} + +void ResourceCached::saveChangesCache( const QMap<Incidence*, bool> &map, const QString &type ) +{ + CalendarLocal calendar ( QString::fromLatin1( "UTC" ) ); + + bool isEmpty = true; + QMap<Incidence *,bool>::ConstIterator it; + for ( it = map.begin(); it != map.end(); ++it ) { + isEmpty = false; + calendar.addIncidence( it.key()->clone() ); + } + + if ( !isEmpty ) { + calendar.save( changesCacheFile( type ) ); + } else { + QFile file( changesCacheFile( type ) ); + file.remove(); + } + + calendar.close(); +} + +void ResourceCached::saveChangesCache() +{ + saveChangesCache( mAddedIncidences, "added" ); + saveChangesCache( mDeletedIncidences, "deleted" ); + saveChangesCache( mChangedIncidences, "changed" ); +} + +void ResourceCached::loadChangesCache( QMap<Incidence*, bool> &map, const QString &type ) +{ + CalendarLocal calendar ( QString::fromLatin1( "UTC" ) ); + + if ( KStandardDirs::exists( changesCacheFile( type ) ) ) + calendar.load( changesCacheFile( type ) ); + else + return; + + const Incidence::List list = calendar.incidences(); + Incidence::List::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + map.insert( (*it)->clone(), true ); + + calendar.close(); +} + +void ResourceCached::loadChangesCache() +{ + loadChangesCache( mAddedIncidences, "added" ); + loadChangesCache( mDeletedIncidences, "deleted" ); + loadChangesCache( mChangedIncidences, "changed" ); +} + +void ResourceCached::calendarIncidenceAdded( Incidence *i ) +{ +#if 1 + kdDebug(5800) << "ResourceCached::calendarIncidenceAdded(): " + << i->uid() << endl; +#endif + + QMap<Incidence *,bool>::ConstIterator it; + it = mAddedIncidences.find( i ); + if ( it == mAddedIncidences.end() ) { + mAddedIncidences.insert( i, true ); + } + + checkForAutomaticSave(); +} + +void ResourceCached::calendarIncidenceChanged( Incidence *i ) +{ +#if 1 + kdDebug(5800) << "ResourceCached::calendarIncidenceChanged(): " + << i->uid() << endl; +#endif + + QMap<Incidence *,bool>::ConstIterator it; + it = mChangedIncidences.find( i ); + // FIXME: If you modify an added incidence, there's no need to add it to mChangedIncidences! + if ( it == mChangedIncidences.end() ) { + mChangedIncidences.insert( i, true ); + } + + checkForAutomaticSave(); +} + +void ResourceCached::calendarIncidenceDeleted( Incidence *i ) +{ +#if 1 + kdDebug(5800) << "ResourceCached::calendarIncidenceDeleted(): " + << i->uid() << endl; +#endif + + QMap<Incidence *,bool>::ConstIterator it; + it = mDeletedIncidences.find( i ); + if ( it == mDeletedIncidences.end() ) { + mDeletedIncidences.insert( i, true ); + } + + checkForAutomaticSave(); +} + +Incidence::List ResourceCached::addedIncidences() const +{ + Incidence::List added; + QMap<Incidence *,bool>::ConstIterator it; + for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) { + added.append( it.key() ); + } + return added; +} + +Incidence::List ResourceCached::changedIncidences() const +{ + Incidence::List changed; + QMap<Incidence *,bool>::ConstIterator it; + for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) { + changed.append( it.key() ); + } + return changed; +} + +Incidence::List ResourceCached::deletedIncidences() const +{ + Incidence::List deleted; + QMap<Incidence *,bool>::ConstIterator it; + for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) { + deleted.append( it.key() ); + } + return deleted; +} + +Incidence::List ResourceCached::allChanges() const +{ + Incidence::List changes; + QMap<Incidence *,bool>::ConstIterator it; + for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) { + changes.append( it.key() ); + } + for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) { + changes.append( it.key() ); + } + for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) { + changes.append( it.key() ); + } + return changes; +} + +bool ResourceCached::hasChanges() const +{ + return !( mAddedIncidences.isEmpty() && mChangedIncidences.isEmpty() && + mDeletedIncidences.isEmpty() ); +} + +void ResourceCached::clearChange( Incidence *incidence ) +{ + clearChange( incidence->uid() ); +} + +void ResourceCached::clearChange( const QString &uid ) +{ + QMap<Incidence*, bool>::Iterator it; + + for ( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) + if ( it.key()->uid() == uid ) { + mAddedIncidences.remove( it ); + break; + } + + for ( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) + if ( it.key()->uid() == uid ) { + mChangedIncidences.remove( it ); + break; + } + + for ( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) + if ( it.key()->uid() == uid ) { + mDeletedIncidences.remove( it ); + break; + } +} + +void ResourceCached::enableChangeNotification() +{ + mCalendar.registerObserver( this ); +} + +void ResourceCached::disableChangeNotification() +{ + mCalendar.unregisterObserver( this ); +} + +void ResourceCached::slotReload() +{ + if ( !isActive() ) return; + + kdDebug(5800) << "ResourceCached::slotReload()" << endl; + + load(); +} + +void ResourceCached::slotSave() +{ + if ( !isActive() ) return; + + kdDebug(5800) << "ResourceCached::slotSave()" << endl; + + save(); +} + +void ResourceCached::checkForAutomaticSave() +{ + if ( mSavePolicy == SaveAlways ) { + kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save now" << endl; + mSaveTimer.start( 1 * 1000, true ); // 1 second + } else if ( mSavePolicy == SaveDelayed ) { + kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed" + << endl; + mSaveTimer.start( 15 * 1000, true ); // 15 seconds + } +} + +bool ResourceCached::checkForReload() +{ + if ( mReloadPolicy == ReloadNever ) return false; + if ( mReloadPolicy == ReloadOnStartup ) return !mReloaded; + return true; +} + +bool ResourceCached::checkForSave() +{ + if ( mSavePolicy == SaveNever ) return false; + return true; +} + +void ResourceCached::addInfoText( QString &txt ) const +{ + if ( mLastLoad.isValid() ) { + txt += "<br>"; + txt += i18n("Last loaded: %1") + .arg( KGlobal::locale()->formatDateTime( mLastLoad ) ); + } + if ( mLastSave.isValid() ) { + txt += "<br>"; + txt += i18n("Last saved: %1") + .arg( KGlobal::locale()->formatDateTime( mLastSave ) ); + } +} + +void ResourceCached::doClose() +{ + mCalendar.close(); +} + +bool ResourceCached::doOpen() +{ + kdDebug(5800) << "Opening resource " << resourceName() << endl; + return true; +} + +void KCal::ResourceCached::setOwner( const Person &owner ) +{ + mCalendar.setOwner( owner ); +} + +const Person & KCal::ResourceCached::getOwner() const +{ + return mCalendar.getOwner(); +} + +#include "resourcecached.moc" |