libkcal

resourcecached.cpp
00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019     Boston, MA 02110-1301, USA.
00020 */
00021 
00022 // TODO [FIXME] IMPORTANT
00023 // If a cached resource initiates a reload while an event editor is active, or an event is locked for editing,
00024 // a big fat crash will ensue.  The reload subroutine must ABORT if ANY korganizer events are locked for editing!!!
00025 
00026 #include <tqdatastream.h>
00027 #include <tqdatetime.h>
00028 #include <tqfile.h>
00029 #include <tqstring.h>
00030 #include <tqptrlist.h>
00031 
00032 #include <kdebug.h>
00033 #include <klocale.h>
00034 #include <kurl.h>
00035 #include <kstandarddirs.h>
00036 
00037 #include "event.h"
00038 #include "exceptions.h"
00039 #include "incidence.h"
00040 #include "journal.h"
00041 #include "todo.h"
00042 #include <unistd.h>
00043 
00044 
00045 #include "resourcecached.h"
00046 
00047 using namespace KCal;
00048 
00049 static bool m_editoropen = false;
00050 
00051 ResourceCached::ResourceCached( const KConfig* config )
00052   : ResourceCalendar( config ), mCalendar( TQString::fromLatin1( "UTC" ) ),
00053     mReloadPolicy( ReloadNever ),  mReloadInterval( 10 ),
00054     mReloadTimer( 0, "mReloadTimer" ), mReloaded( false ),
00055     mSavePolicy( SaveNever ), mSaveInterval( 10 ),
00056     mSaveTimer( 0, "mSaveTimer" ), mIdMapper( "kcal/uidmaps/" )
00057 {
00058   connect( &mReloadTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotReload() ) );
00059   connect( &mSaveTimer, TQT_SIGNAL( timeout() ), TQT_SLOT( slotSave() ) );
00060 }
00061 
00062 ResourceCached::~ResourceCached()
00063 {
00064 }
00065 
00066 void ResourceCached::setReloadPolicy( int i )
00067 {
00068   mReloadPolicy = i;
00069 
00070   setupReloadTimer();
00071 }
00072 
00073 int ResourceCached::reloadPolicy() const
00074 {
00075   return mReloadPolicy;
00076 }
00077 
00078 void ResourceCached::setReloadInterval( int minutes )
00079 {
00080   mReloadInterval = minutes;
00081 }
00082 
00083 int ResourceCached::reloadInterval() const
00084 {
00085   return mReloadInterval;
00086 }
00087 
00088 void ResourceCached::setSavePolicy( int i )
00089 {
00090   mSavePolicy = i;
00091 
00092   setupSaveTimer();
00093 }
00094 
00095 int ResourceCached::savePolicy() const
00096 {
00097   return mSavePolicy;
00098 }
00099 
00100 void ResourceCached::setSaveInterval( int minutes )
00101 {
00102   mSaveInterval = minutes;
00103 }
00104 
00105 int ResourceCached::saveInterval() const
00106 {
00107   return mSaveInterval;
00108 }
00109 
00110 void ResourceCached::readConfig( const KConfig *config )
00111 {
00112   mReloadPolicy = config->readNumEntry( "ReloadPolicy", ReloadNever );
00113   mReloadInterval = config->readNumEntry( "ReloadInterval", 10 );
00114 
00115   mSaveInterval = config->readNumEntry( "SaveInterval", 10 );
00116   mSavePolicy = config->readNumEntry( "SavePolicy", SaveNever );
00117 
00118   mLastLoad = config->readDateTimeEntry( "LastLoad" );
00119   mLastSave = config->readDateTimeEntry( "LastSave" );
00120 
00121   setupSaveTimer();
00122   setupReloadTimer();
00123 }
00124 
00125 void ResourceCached::setupSaveTimer()
00126 {
00127   if ( mSavePolicy == SaveInterval ) {
00128     kdDebug(5800) << "ResourceCached::setSavePolicy(): start save timer (interval "
00129               << mSaveInterval << " minutes)." << endl;
00130     mSaveTimer.start( mSaveInterval * 60 * 1000 ); // n minutes
00131   } else {
00132     mSaveTimer.stop();
00133   }
00134 }
00135 
00136 void ResourceCached::setupReloadTimer()
00137 {
00138   if ( mReloadPolicy == ReloadInterval ) {
00139     kdDebug(5800) << "ResourceCached::setSavePolicy(): start reload timer "
00140                  "(interval " << mReloadInterval << " minutes)" << endl;
00141     mReloadTimer.start( mReloadInterval * 60 * 1000 ); // n minutes
00142   } else {
00143     mReloadTimer.stop();
00144   }
00145 }
00146 
00147 void ResourceCached::writeConfig( KConfig *config )
00148 {
00149   config->writeEntry( "ReloadPolicy", mReloadPolicy );
00150   config->writeEntry( "ReloadInterval", mReloadInterval );
00151 
00152   config->writeEntry( "SavePolicy", mSavePolicy );
00153   config->writeEntry( "SaveInterval", mSaveInterval );
00154 
00155   config->writeEntry( "LastLoad", mLastLoad );
00156   config->writeEntry( "LastSave", mLastSave );
00157 }
00158 
00159 bool ResourceCached::addEvent(Event *event)
00160 {
00161   return mCalendar.addEvent( event );
00162 }
00163 
00164 bool ResourceCached::addEvent(Event *event, const TQString &subresource )
00165 {
00166   Q_UNUSED( subresource ); // CalendarLocal does not support subresources
00167   return mCalendar.addEvent( event );
00168 }
00169 
00170 // probably not really efficient, but...it works for now.
00171 bool ResourceCached::deleteEvent( Event *event )
00172 {
00173   kdDebug(5800) << "ResourceCached::deleteEvent" << endl;
00174 
00175   return mCalendar.deleteEvent( event );
00176 }
00177 
00178 
00179 Event *ResourceCached::event( const TQString &uid )
00180 {
00181   return mCalendar.event( uid );
00182 }
00183 
00184 Event::List ResourceCached::rawEventsForDate( const TQDate &qd,
00185                                               EventSortField sortField,
00186                                               SortDirection sortDirection )
00187 {
00188   Event::List list = mCalendar.rawEventsForDate( qd, sortField, sortDirection );
00189 
00190   return list;
00191 }
00192 
00193 Event::List ResourceCached::rawEvents( const TQDate &start, const TQDate &end,
00194                                        bool inclusive )
00195 {
00196   return mCalendar.rawEvents( start, end, inclusive );
00197 }
00198 
00199 Event::List ResourceCached::rawEventsForDate( const TQDateTime &qdt )
00200 {
00201   return mCalendar.rawEventsForDate( qdt.date() );
00202 }
00203 
00204 Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
00205 {
00206   return mCalendar.rawEvents( sortField, sortDirection );
00207 }
00208 
00209 bool ResourceCached::addTodo( Todo *todo )
00210 {
00211   return mCalendar.addTodo( todo );
00212 }
00213 
00214 bool ResourceCached::addTodo( Todo *todo, const TQString &subresource )
00215 {
00216   Q_UNUSED( subresource ); // CalendarLocal does not support subresources
00217   return mCalendar.addTodo( todo );
00218 }
00219 
00220 bool ResourceCached::deleteTodo( Todo *todo )
00221 {
00222   return mCalendar.deleteTodo( todo );
00223 }
00224 
00225 bool ResourceCached::deleteJournal( Journal *journal )
00226 {
00227   return mCalendar.deleteJournal( journal );
00228 }
00229 
00230 
00231 Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
00232 {
00233   return mCalendar.rawTodos( sortField, sortDirection );
00234 }
00235 
00236 Todo *ResourceCached::todo( const TQString &uid )
00237 {
00238   return mCalendar.todo( uid );
00239 }
00240 
00241 Todo::List ResourceCached::rawTodosForDate( const TQDate &date )
00242 {
00243   return mCalendar.rawTodosForDate( date );
00244 }
00245 
00246 bool ResourceCached::addJournal( Journal *journal )
00247 {
00248   return mCalendar.addJournal( journal );
00249 }
00250 
00251 bool ResourceCached::addJournal( Journal *journal, const TQString &subresource )
00252 {
00253   Q_UNUSED( subresource ); // CalendarLocal does not support subresources
00254   return mCalendar.addJournal( journal );
00255 }
00256 
00257 Journal *ResourceCached::journal( const TQString &uid )
00258 {
00259   return mCalendar.journal( uid );
00260 }
00261 
00262 Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
00263 {
00264   return mCalendar.rawJournals( sortField, sortDirection );
00265 }
00266 
00267 Journal::List ResourceCached::rawJournalsForDate( const TQDate &date )
00268 {
00269   return mCalendar.rawJournalsForDate( date );
00270 }
00271 
00272 
00273 Alarm::List ResourceCached::alarmsTo( const TQDateTime &to )
00274 {
00275   return mCalendar.alarmsTo( to );
00276 }
00277 
00278 Alarm::List ResourceCached::alarms( const TQDateTime &from, const TQDateTime &to )
00279 {
00280   // kdDebug(5800) << "ResourceCached::alarms(" << from.toString() << " - " << to.toString() << ")\n";
00281   return mCalendar.alarms( from, to );
00282 }
00283 
00284 
00285 void ResourceCached::setTimeZoneId( const TQString& tzid )
00286 {
00287   mCalendar.setTimeZoneId( tzid );
00288 }
00289 
00290 TQString ResourceCached::timeZoneId() const
00291 {
00292   return mCalendar.timeZoneId();
00293 }
00294 
00295 void ResourceCached::clearChanges()
00296 {
00297   mAddedIncidences.clear();
00298   mChangedIncidences.clear();
00299   mDeletedIncidences.clear();
00300 }
00301 
00302 void ResourceCached::loadCache()
00303 {
00304   setIdMapperIdentifier();
00305   mIdMapper.load();
00306 
00307   if ( KStandardDirs::exists( cacheFile() ) ) {
00308     mCalendar.load( cacheFile() );
00309     if ( readOnly() ) {
00310       Incidence::List incidences( rawIncidences() );
00311       Incidence::List::Iterator it;
00312       for ( it = incidences.begin(); it != incidences.end(); ++it ) {
00313         (*it)->setReadOnly( true );
00314       }
00315     }
00316   }
00317 }
00318 
00319 void ResourceCached::saveCache()
00320 {
00321   kdDebug(5800) << "ResourceCached::saveCache(): " << cacheFile() << endl;
00322 
00323   setIdMapperIdentifier();
00324   mIdMapper.save();
00325 
00326   mCalendar.save( cacheFile() );
00327 }
00328 
00329 void ResourceCached::setIdMapperIdentifier()
00330 {
00331   mIdMapper.setIdentifier( type() + "_" + identifier() );
00332 }
00333 
00334 void ResourceCached::clearCache()
00335 {
00336   mCalendar.close();
00337 }
00338 
00339 void ResourceCached::clearEventsCache()
00340 {
00341   mCalendar.closeEvents();
00342 }
00343 
00344 void ResourceCached::clearTodosCache()
00345 {
00346   mCalendar.closeTodos();
00347 }
00348 
00349 void ResourceCached::clearJournalsCache()
00350 {
00351   mCalendar.closeJournals();
00352 }
00353 
00354 void ResourceCached::cleanUpEventCache( const Event::List &eventList )
00355 {
00356   CalendarLocal calendar ( TQString::fromLatin1( "UTC" ) );
00357 
00358   if ( KStandardDirs::exists( cacheFile() ) )
00359     calendar.load( cacheFile() );
00360   else
00361     return;
00362 
00363   Event::List list = calendar.events();
00364   Event::List::ConstIterator cacheIt, it;
00365   for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
00366     bool found = false;
00367     for ( it = eventList.begin(); it != eventList.end(); ++it ) {
00368       if ( (*it)->uid() == (*cacheIt)->uid() )
00369         found = true;
00370     }
00371 
00372     if ( !found ) {
00373       mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
00374       Event *event = mCalendar.event( (*cacheIt)->uid() );
00375       if ( event )
00376         mCalendar.deleteEvent( event );
00377     }
00378   }
00379 
00380   calendar.close();
00381 }
00382 
00383 void ResourceCached::cleanUpTodoCache( const Todo::List &todoList )
00384 {
00385   CalendarLocal calendar ( TQString::fromLatin1( "UTC" ) );
00386 
00387   if ( KStandardDirs::exists( cacheFile() ) )
00388     calendar.load( cacheFile() );
00389   else
00390     return;
00391 
00392   Todo::List list = calendar.todos();
00393   Todo::List::ConstIterator cacheIt, it;
00394   for ( cacheIt = list.begin(); cacheIt != list.end(); ++cacheIt ) {
00395 
00396     bool found = false;
00397     for ( it = todoList.begin(); it != todoList.end(); ++it ) {
00398       if ( (*it)->uid() == (*cacheIt)->uid() )
00399         found = true;
00400     }
00401 
00402     if ( !found ) {
00403       mIdMapper.removeRemoteId( mIdMapper.remoteId( (*cacheIt)->uid() ) );
00404       Todo *todo = mCalendar.todo( (*cacheIt)->uid() );
00405       if ( todo )
00406         mCalendar.deleteTodo( todo );
00407     }
00408   }
00409 
00410   calendar.close();
00411 }
00412 
00413 KPIM::IdMapper& ResourceCached::idMapper()
00414 {
00415   return mIdMapper;
00416 }
00417 
00418 TQString ResourceCached::cacheFile() const
00419 {
00420   return locateLocal( "cache", "kcal/kresources/" + identifier() );
00421 }
00422 
00423 TQString ResourceCached::changesCacheFile( const TQString &type ) const
00424 {
00425   return locateLocal( "cache", "kcal/changescache/" + identifier() + "_" + type );
00426 }
00427 
00428 void ResourceCached::saveChangesCache( const TQMap<Incidence*, bool> &map, const TQString &type )
00429 {
00430   CalendarLocal calendar ( TQString::fromLatin1( "UTC" ) );
00431 
00432   bool isEmpty = true;
00433   TQMap<Incidence *,bool>::ConstIterator it;
00434   for ( it = map.begin(); it != map.end(); ++it ) {
00435     isEmpty = false;
00436     calendar.addIncidence( it.key()->clone() );
00437   }
00438 
00439   if ( !isEmpty ) {
00440     calendar.save( changesCacheFile( type ) );
00441   } else {
00442     TQFile file( changesCacheFile( type ) );
00443     file.remove();
00444   }
00445 
00446   calendar.close();
00447 }
00448 
00449 void ResourceCached::saveChangesCache()
00450 {
00451   saveChangesCache( mAddedIncidences, "added" );
00452   saveChangesCache( mDeletedIncidences, "deleted" );
00453   saveChangesCache( mChangedIncidences, "changed" );
00454 }
00455 
00456 void ResourceCached::loadChangesCache( TQMap<Incidence*, bool> &map, const TQString &type )
00457 {
00458   CalendarLocal calendar ( TQString::fromLatin1( "UTC" ) );
00459 
00460   if ( KStandardDirs::exists( changesCacheFile( type ) ) )
00461     calendar.load( changesCacheFile( type ) );
00462   else
00463     return;
00464 
00465   const Incidence::List list = calendar.incidences();
00466   Incidence::List::ConstIterator it;
00467   for ( it = list.begin(); it != list.end(); ++it )
00468     map.insert( (*it)->clone(), true );
00469 
00470   calendar.close();
00471 }
00472 
00473 void ResourceCached::loadChangesCache()
00474 {
00475   loadChangesCache( mAddedIncidences, "added" );
00476   loadChangesCache( mDeletedIncidences, "deleted" );
00477   loadChangesCache( mChangedIncidences, "changed" );
00478 }
00479 
00480 void ResourceCached::calendarIncidenceAdded( Incidence *i )
00481 {
00482 #if 1
00483   kdDebug(5800) << "ResourceCached::calendarIncidenceAdded(): "
00484             << i->uid() << endl;
00485 #endif
00486 
00487   TQMap<Incidence *,bool>::ConstIterator it;
00488   it = mAddedIncidences.find( i );
00489   if ( it == mAddedIncidences.end() ) {
00490     mAddedIncidences.insert( i, true );
00491   }
00492 
00493   checkForAutomaticSave();
00494 }
00495 
00496 void ResourceCached::calendarIncidenceChanged( Incidence *i )
00497 {
00498 #if 1
00499   kdDebug(5800) << "ResourceCached::calendarIncidenceChanged(): "
00500             << i->uid() << endl;
00501 #endif
00502 
00503   TQMap<Incidence *,bool>::ConstIterator it;
00504   it = mChangedIncidences.find( i );
00505   // FIXME: If you modify an added incidence, there's no need to add it to mChangedIncidences!
00506   if ( it == mChangedIncidences.end() ) {
00507     mChangedIncidences.insert( i, true );
00508   }
00509 
00510   checkForAutomaticSave();
00511 }
00512 
00513 void ResourceCached::calendarIncidenceDeleted( Incidence *i )
00514 {
00515 #if 1
00516   kdDebug(5800) << "ResourceCached::calendarIncidenceDeleted(): "
00517             << i->uid() << endl;
00518 #endif
00519 
00520   if (i->hasRecurrenceID()) {
00521     // This incidence has a parent; notify the parent of the child's death and do not destroy the parent!
00522     // Get the parent
00523     IncidenceList il = i->childIncidences();
00524     IncidenceListIterator it;
00525     it = il.begin();
00526     Incidence *parentIncidence;
00527     parentIncidence = this->incidence(*it);
00528     // Remove the child
00529     calendarIncidenceChanged(parentIncidence);
00530   }
00531   else {
00532     TQMap<Incidence *,bool>::ConstIterator it;
00533     it = mDeletedIncidences.find( i );
00534     if ( it == mDeletedIncidences.end() ) {
00535       mDeletedIncidences.insert( i, true );
00536     }
00537   }
00538   checkForAutomaticSave();
00539 }
00540 
00541 Incidence::List ResourceCached::addedIncidences() const
00542 {
00543   Incidence::List added;
00544   TQMap<Incidence *,bool>::ConstIterator it;
00545   for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
00546     added.append( it.key() );
00547   }
00548   return added;
00549 }
00550 
00551 Incidence::List ResourceCached::changedIncidences() const
00552 {
00553   Incidence::List changed;
00554   TQMap<Incidence *,bool>::ConstIterator it;
00555   for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
00556     changed.append( it.key() );
00557   }
00558   return changed;
00559 }
00560 
00561 Incidence::List ResourceCached::deletedIncidences() const
00562 {
00563   Incidence::List deleted;
00564   TQMap<Incidence *,bool>::ConstIterator it;
00565   for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
00566     deleted.append( it.key() );
00567   }
00568   return deleted;
00569 }
00570 
00571 Incidence::List ResourceCached::allChanges() const
00572 {
00573   Incidence::List changes;
00574   TQMap<Incidence *,bool>::ConstIterator it;
00575   for( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it ) {
00576     changes.append( it.key() );
00577   }
00578   for( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it ) {
00579     changes.append( it.key() );
00580   }
00581   for( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it ) {
00582     changes.append( it.key() );
00583   }
00584   return changes;
00585 }
00586 
00587 bool ResourceCached::hasChanges() const
00588 {
00589   return !( mAddedIncidences.isEmpty() && mChangedIncidences.isEmpty() &&
00590             mDeletedIncidences.isEmpty() );
00591 }
00592 
00593 void ResourceCached::clearChange( Incidence *incidence )
00594 {
00595   clearChange( incidence->uid() );
00596 }
00597 
00598 void ResourceCached::clearChange( const TQString &uid )
00599 {
00600   TQMap<Incidence*, bool>::Iterator it;
00601 
00602   for ( it = mAddedIncidences.begin(); it != mAddedIncidences.end(); ++it )
00603     if ( it.key()->uid() == uid ) {
00604       mAddedIncidences.remove( it );
00605       break;
00606     }
00607 
00608   for ( it = mChangedIncidences.begin(); it != mChangedIncidences.end(); ++it )
00609     if ( it.key()->uid() == uid ) {
00610       mChangedIncidences.remove( it );
00611       break;
00612     }
00613 
00614   for ( it = mDeletedIncidences.begin(); it != mDeletedIncidences.end(); ++it )
00615     if ( it.key()->uid() == uid ) {
00616       mDeletedIncidences.remove( it );
00617       break;
00618     }
00619 }
00620 
00621 void ResourceCached::enableChangeNotification()
00622 {
00623   mCalendar.registerObserver( this );
00624 }
00625 
00626 void ResourceCached::disableChangeNotification()
00627 {
00628   mCalendar.unregisterObserver( this );
00629 }
00630 
00631 bool ResourceCached::editorWindowOpen()
00632 {
00633   return m_editoropen;
00634 }
00635 
00636 void ResourceCached::setEditorWindowOpen(bool open)
00637 {
00638   m_editoropen = open;
00639 }
00640 
00641 void ResourceCached::slotReload()
00642 {
00643   if ( !isActive() ) return;
00644 
00645   // Make sure no editor windows are open
00646   if (editorWindowOpen() == true) return;
00647 
00648   kdDebug(5800) << "ResourceCached::slotReload()" << endl;
00649 
00650   load();
00651 }
00652 
00653 void ResourceCached::slotSave()
00654 {
00655   if ( !isActive() ) return;
00656 
00657   kdDebug(5800) << "ResourceCached::slotSave()" << endl;
00658 
00659   save();
00660 }
00661 
00662 void ResourceCached::checkForAutomaticSave()
00663 {
00664   if ( mSavePolicy == SaveAlways )  {
00665     kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save now" << endl;
00666     mSaveTimer.start( 1 * 1000, true ); // 1 second
00667   } else if ( mSavePolicy == SaveDelayed ) {
00668     kdDebug(5800) << "ResourceCached::checkForAutomaticSave(): save delayed"
00669               << endl;
00670     mSaveTimer.start( 15 * 1000, true ); // 15 seconds
00671   }
00672 }
00673 
00674 bool ResourceCached::checkForReload()
00675 {
00676   if ( mReloadPolicy == ReloadNever ) return false;
00677   if ( mReloadPolicy == ReloadOnStartup ) return !mReloaded;
00678   return true;
00679 }
00680 
00681 bool ResourceCached::checkForSave()
00682 {
00683   if ( mSavePolicy == SaveNever ) return false;
00684   return true;
00685 }
00686 
00687 void ResourceCached::addInfoText( TQString &txt ) const
00688 {
00689   if ( mLastLoad.isValid() ) {
00690     txt += "<br>";
00691     txt += i18n("Last loaded: %1")
00692            .arg( KGlobal::locale()->formatDateTime( mLastLoad ) );
00693   }
00694   if ( mLastSave.isValid() ) {
00695     txt += "<br>";
00696     txt += i18n("Last saved: %1")
00697            .arg( KGlobal::locale()->formatDateTime( mLastSave ) );
00698   }
00699 }
00700 
00701 void ResourceCached::doClose()
00702 {
00703   mCalendar.close();
00704 }
00705 
00706 bool ResourceCached::doOpen()
00707 {
00708   kdDebug(5800) << "Opening resource " << resourceName() << endl;
00709   return true;
00710 }
00711 
00712 void KCal::ResourceCached::setOwner( const Person &owner )
00713 {
00714   mCalendar.setOwner( owner );
00715 }
00716 
00717 const Person & KCal::ResourceCached::getOwner() const
00718 {
00719   return mCalendar.getOwner();
00720 }
00721 
00722 #include "resourcecached.moc"