1/*
2 This file is part of the kcal library.
3
4 Copyright © 2006 by David Jarvie <software@astrojar.org.uk>
5 Copyright (c) 2003,2004 Cornelius Schumacher <schumacher@kde.org>
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
21*/
22
23#include "resourcecached.h"
24#include "calendarlocal.h"
25#include "event.h"
26#include "exceptions.h"
27#include "incidence.h"
28#include "journal.h"
29#include "todo.h"
30
31#include "kresources/idmapper.h"
32
33#include <kconfiggroup.h>
34#include <kdebug.h>
35#include <klocalizedstring.h>
36#include <kstandarddirs.h>
37#include <kurl.h>
38
39#include <QtCore/QDateTime>
40#include <QtCore/QDataStream>
41#include <QtCore/QFile>
42#include <QtCore/QString>
43#include <QtCore/QTimer>
44
45
46using namespace KCal;
47
48//@cond PRIVATE
49class ResourceCached::Private
50{
51 public:
52 Private()
53 : mCalendar( QLatin1String( "UTC" ) ),
54 mReloadPolicy( ResourceCached::ReloadNever ),
55 mReloadInterval( 10 ),
56 mInhibitReload( false ),
57 mReloaded( false ),
58 mSavePending( false ),
59 mSavePolicy( ResourceCached::SaveNever ),
60 mSaveInterval( 10 ),
61 mIdMapper( "kcal/uidmaps/" )
62 {}
63
64 CalendarLocal mCalendar;
65
66 int mReloadPolicy;
67 int mReloadInterval;
68 QTimer mReloadTimer;
69 bool mInhibitReload; // true to prevent downloads by load(DefaultCache)
70 bool mReloaded; // true once it has been downloaded
71 bool mSavePending; // true if a save of changes has been scheduled on the timer
72
73 int mSavePolicy;
74 int mSaveInterval;
75 QTimer mSaveTimer;
76
77 KDateTime mLastLoad;
78 KDateTime mLastSave;
79
80 QMap<KCal::Incidence *,bool> mAddedIncidences;
81 QMap<KCal::Incidence *,bool> mChangedIncidences;
82 QMap<KCal::Incidence *,bool> mDeletedIncidences;
83
84 KRES::IdMapper mIdMapper;
85};
86//@endcond
87
88ResourceCached::ResourceCached()
89 : ResourceCalendar(),
90 d( new Private )
91{
92 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
93 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
94}
95
96ResourceCached::ResourceCached( const KConfigGroup &group )
97 : ResourceCalendar( group ),
98 d( new Private )
99{
100 connect( &d->mReloadTimer, SIGNAL(timeout()), SLOT(slotReload()) );
101 connect( &d->mSaveTimer, SIGNAL(timeout()), SLOT(slotSave()) );
102}
103
104ResourceCached::~ResourceCached()
105{
106 delete d;
107}
108
109CalendarLocal *ResourceCached::calendar() const
110{
111 return &d->mCalendar;
112}
113
114bool ResourceCached::defaultReloadInhibited() const
115{
116 return d->mInhibitReload;
117}
118
119bool ResourceCached::reloaded() const
120{
121 return d->mReloaded;
122}
123
124void ResourceCached::setReloaded( bool done )
125{
126 d->mReloaded = done;
127}
128
129void ResourceCached::setReloadPolicy( int i )
130{
131 d->mReloadPolicy = i;
132
133 setupReloadTimer();
134}
135
136int ResourceCached::reloadPolicy() const
137{
138 return d->mReloadPolicy;
139}
140
141void ResourceCached::setReloadInterval( int minutes )
142{
143 d->mReloadInterval = minutes;
144}
145
146int ResourceCached::reloadInterval() const
147{
148 return d->mReloadInterval;
149}
150
151bool ResourceCached::inhibitDefaultReload( bool inhibit )
152{
153 if ( inhibit == d->mInhibitReload ) {
154 return false;
155 }
156 d->mInhibitReload = inhibit;
157 return true;
158}
159
160void ResourceCached::setSavePolicy( int i )
161{
162 d->mSavePolicy = i;
163
164 setupSaveTimer();
165}
166
167int ResourceCached::savePolicy() const
168{
169 return d->mSavePolicy;
170}
171
172void ResourceCached::setSaveInterval( int minutes )
173{
174 d->mSaveInterval = minutes;
175}
176
177int ResourceCached::saveInterval() const
178{
179 return d->mSaveInterval;
180}
181
182void ResourceCached::readConfig( const KConfigGroup &group )
183{
184 d->mReloadPolicy = group.readEntry( "ReloadPolicy", int(ReloadNever) );
185 d->mReloadInterval = group.readEntry( "ReloadInterval", 10 );
186
187 d->mSaveInterval = group.readEntry( "SaveInterval", 10 );
188 d->mSavePolicy = group.readEntry( "SavePolicy", int(SaveNever) );
189
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 );
195
196 setupSaveTimer();
197 setupReloadTimer();
198}
199
200void ResourceCached::setupSaveTimer()
201{
202 if ( d->mSavePolicy == SaveInterval ) {
203 kDebug() << "start save timer (interval " << d->mSaveInterval << "mins)";
204 d->mSaveTimer.start( d->mSaveInterval * 60 * 1000 ); // n minutes
205 } else {
206 d->mSaveTimer.stop();
207 }
208}
209
210void ResourceCached::setupReloadTimer()
211{
212 if ( d->mReloadPolicy == ReloadInterval ) {
213 kDebug() << "start reload timer (interval " << d->mReloadInterval << "mins)";
214 d->mReloadTimer.start( d->mReloadInterval * 60 * 1000 ); // n minutes
215 } else {
216 d->mReloadTimer.stop();
217 }
218}
219
220void ResourceCached::writeConfig( KConfigGroup &group )
221{
222 group.writeEntry( "ReloadPolicy", d->mReloadPolicy );
223 group.writeEntry( "ReloadInterval", d->mReloadInterval );
224
225 group.writeEntry( "SavePolicy", d->mSavePolicy );
226 group.writeEntry( "SaveInterval", d->mSaveInterval );
227
228 group.writeEntry( "LastLoad", d->mLastLoad.toUtc().dateTime() );
229 group.writeEntry( "LastSave", d->mLastSave.toUtc().dateTime() );
230}
231
232bool ResourceCached::addEvent( Event *event )
233{
234 return d->mCalendar.addEvent( event );
235}
236
237// probably not really efficient, but...it works for now.
238bool ResourceCached::deleteEvent( Event *event )
239{
240 kDebug();
241
242 return d->mCalendar.deleteEvent( event );
243}
244
245void ResourceCached::deleteAllEvents()
246{
247 d->mCalendar.deleteAllEvents();
248}
249
250Event *ResourceCached::event( const QString &uid )
251{
252 return d->mCalendar.event( uid );
253}
254
255Event::List ResourceCached::rawEventsForDate( const QDate &qd, const KDateTime::Spec &timeSpec,
256 EventSortField sortField,
257 SortDirection sortDirection )
258{
259 Event::List list = d->mCalendar.rawEventsForDate( qd, timeSpec, sortField, sortDirection );
260
261 return list;
262}
263
264Event::List ResourceCached::rawEvents( const QDate &start, const QDate &end,
265 const KDateTime::Spec &timeSpec, bool inclusive )
266{
267 return d->mCalendar.rawEvents( start, end, timeSpec, inclusive );
268}
269
270Event::List ResourceCached::rawEventsForDate( const KDateTime &kdt )
271{
272 return d->mCalendar.rawEventsForDate( kdt );
273}
274
275Event::List ResourceCached::rawEvents( EventSortField sortField, SortDirection sortDirection )
276{
277 return d->mCalendar.rawEvents( sortField, sortDirection );
278}
279
280bool ResourceCached::addTodo( Todo *todo )
281{
282 return d->mCalendar.addTodo( todo );
283}
284
285bool ResourceCached::deleteTodo( Todo *todo )
286{
287 return d->mCalendar.deleteTodo( todo );
288}
289
290void ResourceCached::deleteAllTodos()
291{
292 d->mCalendar.deleteAllTodos();
293}
294
295bool ResourceCached::deleteJournal( Journal *journal )
296{
297 return d->mCalendar.deleteJournal( journal );
298}
299
300void ResourceCached::deleteAllJournals()
301{
302 d->mCalendar.deleteAllJournals();
303}
304
305Todo::List ResourceCached::rawTodos( TodoSortField sortField, SortDirection sortDirection )
306{
307 return d->mCalendar.rawTodos( sortField, sortDirection );
308}
309
310Todo *ResourceCached::todo( const QString &uid )
311{
312 return d->mCalendar.todo( uid );
313}
314
315Todo::List ResourceCached::rawTodosForDate( const QDate &date )
316{
317 return d->mCalendar.rawTodosForDate( date );
318}
319
320bool ResourceCached::addJournal( Journal *journal )
321{
322 return d->mCalendar.addJournal( journal );
323}
324
325Journal *ResourceCached::journal( const QString &uid )
326{
327 return d->mCalendar.journal( uid );
328}
329
330Journal::List ResourceCached::rawJournals( JournalSortField sortField, SortDirection sortDirection )
331{
332 return d->mCalendar.rawJournals( sortField, sortDirection );
333}
334
335Journal::List ResourceCached::rawJournalsForDate( const QDate &date )
336{
337 return d->mCalendar.rawJournalsForDate( date );
338}
339
340Alarm::List ResourceCached::alarmsTo( const KDateTime &to )
341{
342 return d->mCalendar.alarmsTo( to );
343}
344
345Alarm::List ResourceCached::alarms( const KDateTime &from, const KDateTime &to )
346{
347 return d->mCalendar.alarms( from, to );
348}
349
350void ResourceCached::setTimeSpec( const KDateTime::Spec &timeSpec )
351{
352 d->mCalendar.setTimeSpec( timeSpec );
353}
354
355KDateTime::Spec ResourceCached::timeSpec() const
356{
357 return d->mCalendar.timeSpec();
358}
359
360void ResourceCached::setTimeZoneId( const QString &tzid )
361{
362 d->mCalendar.setTimeZoneId( tzid );
363}
364
365QString ResourceCached::timeZoneId() const
366{
367 return d->mCalendar.timeZoneId();
368}
369
370void ResourceCached::shiftTimes( const KDateTime::Spec &oldSpec, const KDateTime::Spec &newSpec )
371{
372 d->mCalendar.shiftTimes( oldSpec, newSpec );
373}
374
375void ResourceCached::clearChanges()
376{
377 d->mAddedIncidences.clear();
378 d->mChangedIncidences.clear();
379 d->mDeletedIncidences.clear();
380}
381
382bool ResourceCached::load( CacheAction action )
383{
384 kDebug() << resourceName();
385
386 setReceivedLoadError( false );
387
388 bool success = true;
389 if ( !isOpen() ) {
390 success = open(); //krazy:exclude=syscalls open is a class method
391 }
392 if ( success ) {
393 bool update = false;
394 switch ( action ) {
395 case DefaultCache:
396 if ( !d->mReloaded && !d->mInhibitReload ) {
397 update = checkForReload();
398 }
399 break;
400 case NoSyncCache:
401 break;
402 case SyncCache:
403 update = true;
404 break;
405 }
406 success = doLoad( update );
407 }
408 if ( !success && !receivedLoadError() ) {
409 loadError();
410 }
411
412 // If the resource is read-only, we need to set its incidences to read-only,
413 // too. This can't be done at a lower-level, since the read-only setting
414 // happens at this level
415 if ( !noReadOnlyOnLoad() && readOnly() ) {
416 Incidence::List incidences( rawIncidences() );
417 Incidence::List::Iterator it;
418 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
419 (*it)->setReadOnly( true );
420 }
421 }
422
423 kDebug() << "Done loading resource" << resourceName();
424
425 if ( success ) {
426 emit resourceLoaded( this );
427 }
428
429 return success;
430}
431
432bool ResourceCached::load()
433{
434 return load( SyncCache );
435}
436
437bool ResourceCached::loadFromCache()
438{
439 setIdMapperIdentifier();
440 d->mIdMapper.load();
441
442 if ( !KStandardDirs::exists( cacheFile() ) ) {
443 return false;
444 }
445 d->mCalendar.load( cacheFile() );
446 if ( !noReadOnlyOnLoad() && readOnly() ) {
447 Incidence::List incidences( rawIncidences() );
448 Incidence::List::Iterator it;
449 for ( it = incidences.begin(); it != incidences.end(); ++it ) {
450 (*it)->setReadOnly( true );
451 }
452 }
453 return true;
454}
455
456bool ResourceCached::save( CacheAction action, Incidence *incidence )
457{
458 if ( !incidence && ( d->mSavePolicy == SaveAlways || d->mSavePolicy == SaveDelayed ) ) {
459 d->mSaveTimer.stop(); // in case it's called manually while save is pending
460 }
461 d->mSavePending = false;
462 if ( saveInhibited() ) {
463 return true;
464 }
465 if ( !readOnly() ) {
466 kDebug() << "Save resource" << resourceName();
467
468 setReceivedSaveError( false );
469
470 if ( !isOpen() ) {
471 return true;
472 }
473 bool upload = false;
474 switch ( action ) {
475 case DefaultCache:
476 upload = checkForSave();
477 break;
478 case NoSyncCache:
479 break;
480 case SyncCache:
481 upload = true;
482 break;
483 }
484 bool success = incidence ? doSave( upload, incidence ) : doSave( upload );
485 if ( !success && !receivedSaveError() ) {
486 saveError();
487 } else {
488 emit resourceSaved( this );
489 }
490 return success;
491 } else {
492 // Read-only, just don't save...
493 kDebug() << "Don't save read-only resource" << resourceName();
494 return true;
495 }
496}
497
498bool ResourceCached::save( Incidence *incidence )
499{
500 return save( SyncCache, incidence );
501}
502
503bool ResourceCached::doSave( bool syncCache, Incidence *incidence )
504{
505 Q_UNUSED( incidence );
506 return doSave( syncCache );
507}
508
509void ResourceCached::saveToCache()
510{
511 kDebug() << cacheFile();
512
513 setIdMapperIdentifier();
514 d->mIdMapper.save();
515
516 d->mCalendar.save( cacheFile() );
517}
518
519void ResourceCached::setIdMapperIdentifier()
520{
521 d->mIdMapper.setIdentifier( type() + '_' + identifier() );
522}
523
524void ResourceCached::clearCache()
525{
526 d->mCalendar.close();
527}
528
529void ResourceCached::cleanUpEventCache( const Event::List &eventList )
530{
531 CalendarLocal calendar ( QLatin1String( "UTC" ) );
532
533 if ( KStandardDirs::exists( cacheFile() ) ) {
534 calendar.load( cacheFile() );
535 } else {
536 return;
537 }
538
539 Event::List list = calendar.events();
540 Event::List::ConstIterator cacheIt, it;
541 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
542 bool found = false;
543 for ( it = eventList.begin(); it != eventList.end(); ++it ) {
544 if ( (*it)->uid() == (*cacheIt)->uid() ) {
545 found = true;
546 break;
547 }
548 }
549
550 if ( !found ) {
551 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
552 Event *event = d->mCalendar.event( (*cacheIt)->uid() );
553 if ( event ) {
554 d->mCalendar.deleteEvent( event );
555 }
556 }
557 }
558
559 calendar.close();
560}
561
562void ResourceCached::cleanUpTodoCache( const Todo::List &todoList )
563{
564 CalendarLocal calendar ( QLatin1String( "UTC" ) );
565
566 if ( KStandardDirs::exists( cacheFile() ) ) {
567 calendar.load( cacheFile() );
568 } else {
569 return;
570 }
571
572 Todo::List list = calendar.todos();
573 Todo::List::ConstIterator cacheIt, it;
574 for ( cacheIt = list.constBegin(); cacheIt != list.constEnd(); ++cacheIt ) {
575
576 bool found = false;
577 for ( it = todoList.constBegin(); it != todoList.constEnd(); ++it ) {
578 if ( (*it)->uid() == (*cacheIt)->uid() ) {
579 found = true;
580 }
581 }
582
583 if ( !found ) {
584 d->mIdMapper.removeRemoteId( d->mIdMapper.remoteId( (*cacheIt)->uid() ) );
585 Todo *todo = d->mCalendar.todo( (*cacheIt)->uid() );
586 if ( todo ) {
587 d->mCalendar.deleteTodo( todo );
588 }
589 }
590 }
591
592 calendar.close();
593}
594
595KRES::IdMapper &ResourceCached::idMapper()
596{
597 return d->mIdMapper;
598}
599
600QString ResourceCached::cacheFile() const
601{
602 return KStandardDirs::locateLocal( "cache", "kcal/kresources/" + identifier() );
603}
604
605QString ResourceCached::changesCacheFile( const QString &type ) const
606{
607 return KStandardDirs::locateLocal( "cache", "kcal/changescache/" + identifier() + '_' + type );
608}
609
610void ResourceCached::saveChangesCache( const QMap<Incidence *, bool> &map, const QString &type )
611{
612 CalendarLocal calendar ( QLatin1String( "UTC" ) );
613
614 bool isEmpty = true;
615 QMap<Incidence *,bool>::ConstIterator it;
616 for ( it = map.begin(); it != map.end(); ++it ) {
617 isEmpty = false;
618 calendar.addIncidence( it.key()->clone() );
619 }
620
621 if ( !isEmpty ) {
622 calendar.save( changesCacheFile( type ) );
623 } else {
624 QFile file( changesCacheFile( type ) );
625 file.remove();
626 }
627
628 calendar.close();
629}
630
631void ResourceCached::saveChangesCache()
632{
633 saveChangesCache( d->mAddedIncidences, "added" );
634 saveChangesCache( d->mDeletedIncidences, "deleted" );
635 saveChangesCache( d->mChangedIncidences, "changed" );
636}
637
638void ResourceCached::loadChangesCache( QMap<Incidence *, bool> &map, const QString &type )
639{
640 CalendarLocal calendar ( QLatin1String( "UTC" ) );
641
642 if ( KStandardDirs::exists( changesCacheFile( type ) ) ) {
643 calendar.load( changesCacheFile( type ) );
644 } else {
645 return;
646 }
647
648 const Incidence::List list = calendar.incidences();
649 Incidence::List::ConstIterator it;
650 for ( it = list.begin(); it != list.end(); ++it ) {
651 map.insert( (*it)->clone(), true );
652 }
653
654 calendar.close();
655}
656
657void ResourceCached::loadChangesCache()
658{
659 loadChangesCache( d->mAddedIncidences, "added" );
660 loadChangesCache( d->mDeletedIncidences, "deleted" );
661 loadChangesCache( d->mChangedIncidences, "changed" );
662}
663
664void ResourceCached::calendarIncidenceAdded( Incidence *i )
665{
666 kDebug() << i->uid();
667
668 QMap<Incidence *,bool>::ConstIterator it;
669 it = d->mAddedIncidences.constFind( i );
670 if ( it == d->mAddedIncidences.constEnd() ) {
671 d->mAddedIncidences.insert( i, true );
672 }
673
674 checkForAutomaticSave();
675}
676
677void ResourceCached::calendarIncidenceChanged( Incidence *i )
678{
679 kDebug() << i->uid();
680
681 QMap<Incidence *,bool>::ConstIterator it;
682 it = d->mChangedIncidences.constFind( i );
683 // FIXME: If you modify an added incidence, there's no need to add it to d->mChangedIncidences!
684 if ( it == d->mChangedIncidences.constEnd() ) {
685 d->mChangedIncidences.insert( i, true );
686 }
687
688 checkForAutomaticSave();
689}
690
691void ResourceCached::calendarIncidenceDeleted( Incidence *i )
692{
693 kDebug() << i->uid();
694
695 QMap<Incidence *,bool>::ConstIterator it;
696 it = d->mDeletedIncidences.constFind( i );
697 if ( it == d->mDeletedIncidences.constEnd() ) {
698 d->mDeletedIncidences.insert( i, true );
699 }
700
701 checkForAutomaticSave();
702}
703
704Incidence::List ResourceCached::addedIncidences() const
705{
706 Incidence::List added;
707 QMap<Incidence *,bool>::ConstIterator it;
708 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
709 added.append( it.key() );
710 }
711 return added;
712}
713
714Incidence::List ResourceCached::changedIncidences() const
715{
716 Incidence::List changed;
717 QMap<Incidence *,bool>::ConstIterator it;
718 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
719 changed.append( it.key() );
720 }
721 return changed;
722}
723
724Incidence::List ResourceCached::deletedIncidences() const
725{
726 Incidence::List deleted;
727 QMap<Incidence *,bool>::ConstIterator it;
728 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
729 deleted.append( it.key() );
730 }
731 return deleted;
732}
733
734Incidence::List ResourceCached::allChanges() const
735{
736 Incidence::List changes;
737 QMap<Incidence *,bool>::ConstIterator it;
738 for ( it = d->mAddedIncidences.constBegin(); it != d->mAddedIncidences.constEnd(); ++it ) {
739 changes.append( it.key() );
740 }
741 for ( it = d->mChangedIncidences.constBegin(); it != d->mChangedIncidences.constEnd(); ++it ) {
742 changes.append( it.key() );
743 }
744 for ( it = d->mDeletedIncidences.constBegin(); it != d->mDeletedIncidences.constEnd(); ++it ) {
745 changes.append( it.key() );
746 }
747 return changes;
748}
749
750bool ResourceCached::hasChanges() const
751{
752 return !( d->mAddedIncidences.isEmpty() && d->mChangedIncidences.isEmpty() &&
753 d->mDeletedIncidences.isEmpty() );
754}
755
756void ResourceCached::clearChange( Incidence *incidence )
757{
758 clearChange( incidence->uid() );
759}
760
761void ResourceCached::clearChange( const QString &uid )
762{
763 QMap<Incidence *, bool>::Iterator it;
764
765 for ( it = d->mAddedIncidences.begin(); it != d->mAddedIncidences.end(); ++it ) {
766 if ( it.key()->uid() == uid ) {
767 d->mAddedIncidences.erase( it );
768 break;
769 }
770 }
771
772 for ( it = d->mChangedIncidences.begin(); it != d->mChangedIncidences.end(); ++it ) {
773 if ( it.key()->uid() == uid ) {
774 d->mChangedIncidences.erase( it );
775 break;
776 }
777 }
778
779 for ( it = d->mDeletedIncidences.begin(); it != d->mDeletedIncidences.end(); ++it ) {
780 if ( it.key()->uid() == uid ) {
781 d->mDeletedIncidences.erase( it );
782 break;
783 }
784 }
785}
786
787void ResourceCached::enableChangeNotification()
788{
789 d->mCalendar.registerObserver( this );
790}
791
792void ResourceCached::disableChangeNotification()
793{
794 d->mCalendar.unregisterObserver( this );
795}
796
797void ResourceCached::slotReload()
798{
799 if ( !isActive() ) {
800 return;
801 }
802
803 kDebug();
804
805 load( SyncCache );
806}
807
808void ResourceCached::slotSave()
809{
810 if ( !isActive() ) {
811 return;
812 }
813
814 kDebug();
815
816 save( SyncCache );
817}
818
819void ResourceCached::checkForAutomaticSave()
820{
821 if ( d->mSavePolicy == SaveAlways ) {
822 kDebug() << "save now";
823 d->mSavePending = true;
824 d->mSaveTimer.setSingleShot( true );
825 d->mSaveTimer.start( 1 * 1000 ); // 1 second
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 ); // 15 seconds
831 }
832}
833
834bool ResourceCached::checkForReload()
835{
836 if ( d->mReloadPolicy == ReloadNever ) {
837 return false;
838 }
839 if ( d->mReloadPolicy == ReloadOnStartup ) {
840 return !d->mReloaded;
841 }
842 return true;
843}
844
845bool ResourceCached::checkForSave()
846{
847 if ( d->mSavePolicy == SaveNever ) {
848 return false;
849 }
850 return true;
851}
852
853void ResourceCached::addInfoText( QString &txt ) const
854{
855 if ( d->mLastLoad.isValid() ) {
856 txt += "<br>";
857 txt += i18n( "Last loaded: %1",
858 KGlobal::locale()->formatDateTime( d->mLastLoad.toUtc().dateTime() ) );
859 }
860 if ( d->mLastSave.isValid() ) {
861 txt += "<br>";
862 txt += i18n( "Last saved: %1",
863 KGlobal::locale()->formatDateTime( d->mLastSave.toUtc().dateTime() ) );
864 }
865}
866
867void ResourceCached::doClose()
868{
869 if ( d->mSavePending ) {
870 d->mSaveTimer.stop();
871 }
872 if ( d->mSavePending || d->mSavePolicy == SaveOnExit || d->mSavePolicy == SaveInterval ) {
873 save( SyncCache );
874 }
875 d->mCalendar.close();
876}
877
878bool ResourceCached::doOpen()
879{
880 kDebug() << "Opening resource" << resourceName();
881 return true;
882}
883
884void KCal::ResourceCached::setOwner( const Person &owner )
885{
886 d->mCalendar.setOwner( owner );
887}
888
889Person KCal::ResourceCached::owner() const
890{
891 return d->mCalendar.owner();
892}
893