1/*
2 This file is part of the kcal library.
3
4 Copyright (c) 2003 Cornelius Schumacher <schumacher@kde.org>
5 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
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 @file
24 This file is part of the API for handling calendar data and
25 defines the CalendarResources class.
26
27 @brief
28 This class provides a Calendar which is composed of other Calendars
29 known as "Resources".
30
31 @author Cornelius Schumacher \<schumacher@kde.org\>
32 @author Reinhold Kainhofer \<reinhold@kainhofer.com\>
33*/
34
35#include "calendarresources.h"
36#include "incidence.h"
37#include "journal.h"
38#include "resourcecalendar.h"
39
40#include "kresources/manager.h"
41#include "kresources/selectdialog.h"
42#include "kabc/lock.h"
43
44#include <kdebug.h>
45#include <kdatetime.h>
46#include <kstandarddirs.h>
47#include <klocalizedstring.h>
48
49#include <QtCore/QString>
50#include <QtCore/QList>
51
52#include <stdlib.h>
53
54using namespace KCal;
55
56/**
57 Private classes that helps to provide binary compatibility between releases.
58 @internal
59*/
60//@cond PRIVATE
61class KCal::CalendarResources::Private
62{
63 public:
64 Private( const QString &family )
65 : mAddingInProgress( false ),
66 mLastUsedResource( 0 ),
67 mManager( new CalendarResourceManager( family ) ),
68 mStandardPolicy( new StandardDestinationPolicy( mManager ) ),
69 mDestinationPolicy( mStandardPolicy ),
70 mAskPolicy( new AskDestinationPolicy( mManager ) ),
71 mException( 0 ),
72 mPendingDeleteFromResourceMap( false )
73 {}
74 ~Private()
75 {
76 delete mManager;
77 delete mStandardPolicy;
78 delete mAskPolicy;
79 }
80 bool mAddingInProgress;
81 ResourceCalendar *mLastUsedResource;
82
83 bool mOpen; //flag that indicates if the resources are "open"
84
85 KRES::Manager<ResourceCalendar>* mManager;
86 QMap <Incidence*, ResourceCalendar*> mResourceMap;
87
88 StandardDestinationPolicy *mStandardPolicy;
89 DestinationPolicy *mDestinationPolicy;
90 AskDestinationPolicy *mAskPolicy;
91
92 QMap<ResourceCalendar *, Ticket *> mTickets;
93 QMap<ResourceCalendar *, int> mChangeCounts;
94
95 ErrorFormat *mException;
96
97 bool mPendingDeleteFromResourceMap;
98
99 template< class IncidenceList >
100 void appendIncidences( IncidenceList &result, const IncidenceList &extra,
101 ResourceCalendar * );
102};
103
104class KCal::CalendarResources::DestinationPolicy::Private
105{
106 public:
107 Private( CalendarResourceManager *manager, QWidget *parent )
108 : mManager( manager ),
109 mParent( parent )
110 {}
111 CalendarResourceManager *mManager;
112 QWidget *mParent;
113};
114
115class KCal::CalendarResources::StandardDestinationPolicy::Private
116{
117 public:
118 Private()
119 {}
120};
121
122class KCal::CalendarResources::AskDestinationPolicy::Private
123{
124 public:
125 Private()
126 {}
127};
128
129class KCal::CalendarResources::Ticket::Private
130{
131 public:
132 Private( ResourceCalendar *resource )
133 : mResource( resource )
134 {}
135 ResourceCalendar *mResource;
136};
137//@endcond
138
139CalendarResources::DestinationPolicy::DestinationPolicy(
140 CalendarResourceManager *manager, QWidget *parent )
141 : d( new KCal::CalendarResources::DestinationPolicy::Private( manager, parent ) )
142{
143}
144
145CalendarResources::DestinationPolicy::~DestinationPolicy()
146{
147 delete d;
148}
149
150QWidget *CalendarResources::DestinationPolicy::parent()
151{
152 return d->mParent;
153}
154
155void CalendarResources::DestinationPolicy::setParent( QWidget *parent )
156{
157 d->mParent = parent;
158}
159
160CalendarResourceManager *CalendarResources::DestinationPolicy::resourceManager()
161{
162 return d->mManager;
163}
164
165bool CalendarResources::DestinationPolicy::hasCalendarResources()
166{
167 CalendarResourceManager::ActiveIterator it;
168 for ( it = resourceManager()->activeBegin();
169 it != resourceManager()->activeEnd(); ++it ) {
170 if ( !(*it)->readOnly() ) {
171 if ( resourceManager()->standardResource() == *it ) {
172 return true;
173 } else {
174 return true;
175 }
176 }
177 }
178 return false;
179}
180
181CalendarResources::StandardDestinationPolicy::StandardDestinationPolicy(
182 CalendarResourceManager *manager, QWidget *parent )
183 : DestinationPolicy( manager, parent ),
184 d( new KCal::CalendarResources::StandardDestinationPolicy::Private )
185{
186}
187
188CalendarResources::StandardDestinationPolicy::~StandardDestinationPolicy()
189{
190 delete d;
191}
192
193ResourceCalendar *CalendarResources::StandardDestinationPolicy::destination( Incidence *incidence )
194{
195 Q_UNUSED( incidence );
196 return resourceManager()->standardResource();
197}
198
199CalendarResources::AskDestinationPolicy::AskDestinationPolicy(
200 CalendarResourceManager *manager, QWidget *parent )
201 : DestinationPolicy( manager, parent ),
202 d( new KCal::CalendarResources::AskDestinationPolicy::Private )
203{
204}
205
206CalendarResources::AskDestinationPolicy::~AskDestinationPolicy()
207{
208 delete d;
209}
210
211ResourceCalendar *CalendarResources::AskDestinationPolicy::destination( Incidence *incidence )
212{
213 Q_UNUSED( incidence );
214 QList<KRES::Resource*> list;
215
216 CalendarResourceManager::ActiveIterator it;
217 for ( it = resourceManager()->activeBegin();
218 it != resourceManager()->activeEnd(); ++it ) {
219 if ( !(*it)->readOnly() ) {
220 //Insert the first the Standard resource to get be the default selected.
221 if ( resourceManager()->standardResource() == *it ) {
222 list.insert( 0, *it );
223 } else {
224 list.append( *it );
225 }
226 }
227 }
228
229 KRES::Resource *r;
230 r = KRES::SelectDialog::getResource( list, parent() );
231 return static_cast<ResourceCalendar *>( r );
232}
233
234CalendarResources::CalendarResources( const KDateTime::Spec &timeSpec,
235 const QString &family )
236 : Calendar( timeSpec ),
237 d( new KCal::CalendarResources::Private( family ) )
238{
239
240 connect( this, SIGNAL(batchAddingBegins()), this, SLOT(beginAddingIncidences()) );
241 connect( this, SIGNAL(batchAddingEnds()), this, SLOT(endAddingIncidences()) );
242
243 d->mManager->addObserver( this );
244}
245
246CalendarResources::CalendarResources( const QString &timeZoneId,
247 const QString &family )
248 : Calendar( timeZoneId ),
249 d( new KCal::CalendarResources::Private( family ) )
250{
251 connect( this, SIGNAL(batchAddingBegins()), this, SLOT(beginAddingIncidences()) );
252 connect( this, SIGNAL(batchAddingEnds()), this, SLOT(endAddingIncidences()) );
253
254 d->mManager->addObserver( this );
255}
256
257CalendarResources::~CalendarResources()
258{
259 close();
260 clearException();
261 delete d;
262}
263
264void CalendarResources::clearException()
265{
266 delete d->mException;
267 d->mException = 0;
268}
269
270ErrorFormat *CalendarResources::exception()
271{
272 return d->mException;
273}
274
275void CalendarResources::readConfig( KConfig *config )
276{
277 d->mManager->readConfig( config );
278
279 CalendarResourceManager::Iterator it;
280 for ( it = d->mManager->begin(); it != d->mManager->end(); ++it ) {
281 connectResource( *it );
282 }
283}
284
285void CalendarResources::load()
286{
287 if ( !d->mManager->standardResource() ) {
288 kDebug() << "Warning! No standard resource yet.";
289 }
290
291 // set the timezone for all resources. Otherwise we'll have those terrible tz
292 // troubles ;-((
293 CalendarResourceManager::Iterator i1;
294 for ( i1 = d->mManager->begin(); i1 != d->mManager->end(); ++i1 ) {
295 (*i1)->setTimeSpec( timeSpec() );
296 }
297
298 QList<ResourceCalendar *> failed;
299
300 // Open all active resources
301 CalendarResourceManager::ActiveIterator it;
302 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
303 if ( !(*it)->load() ) {
304 failed.append( *it );
305 }
306 Incidence::List incidences = (*it)->rawIncidences();
307 Incidence::List::Iterator incit;
308 for ( incit = incidences.begin(); incit != incidences.end(); ++incit ) {
309 (*incit)->registerObserver( this );
310 notifyIncidenceAdded( *incit );
311 }
312 }
313
314 QList<ResourceCalendar *>::ConstIterator it2;
315 for ( it2 = failed.constBegin(); it2 != failed.constEnd(); ++it2 ) {
316 (*it2)->setActive( false );
317 emit signalResourceModified( *it2 );
318 }
319
320 d->mOpen = true;
321 emit calendarLoaded();
322}
323
324bool CalendarResources::reload()
325{
326 save();
327 close();
328 load();
329 return true;
330}
331
332CalendarResourceManager *CalendarResources::resourceManager() const
333{
334 return d->mManager;
335}
336
337void CalendarResources::setStandardDestinationPolicy()
338{
339 d->mDestinationPolicy = d->mStandardPolicy;
340}
341
342void CalendarResources::setAskDestinationPolicy()
343{
344 d->mDestinationPolicy = d->mAskPolicy;
345}
346
347QWidget *CalendarResources::dialogParentWidget()
348{
349 return d->mDestinationPolicy->parent();
350}
351
352void CalendarResources::setDialogParentWidget( QWidget *parent )
353{
354 d->mDestinationPolicy->setParent( parent );
355}
356
357void CalendarResources::close()
358{
359 if ( d->mOpen ) {
360 CalendarResourceManager::ActiveIterator it;
361 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
362 (*it)->close();
363 }
364
365 setModified( false );
366 d->mOpen = false;
367 }
368}
369
370bool CalendarResources::save()
371{
372 bool status = true;
373 if ( d->mOpen && isModified() ) {
374 status = false;
375 CalendarResourceManager::ActiveIterator it;
376 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
377 status = (*it)->save() || status;
378 }
379 setModified( false );
380 }
381
382 return status;
383}
384
385bool CalendarResources::isSaving()
386{
387 CalendarResourceManager::ActiveIterator it;
388 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
389 if ( (*it)->isSaving() ) {
390 return true;
391 }
392 }
393 return false;
394}
395
396bool CalendarResources::addIncidence( Incidence *incidence,
397 ResourceCalendar *resource )
398{
399 // FIXME: Use proper locking via begin/endChange!
400 bool validRes = false;
401 CalendarResourceManager::ActiveIterator it;
402 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
403 if ( (*it) == resource ) {
404 validRes = true;
405 }
406 }
407
408 ResourceCalendar *oldResource = 0;
409 if ( d->mResourceMap.contains( incidence ) ) {
410 oldResource = d->mResourceMap[incidence];
411 }
412 d->mResourceMap[incidence] = resource;
413 if ( validRes && beginChange( incidence ) &&
414 resource->addIncidence( incidence ) ) {
415// d->mResourceMap[incidence] = resource;
416 incidence->registerObserver( this );
417 notifyIncidenceAdded( incidence );
418 setModified( true );
419 endChange( incidence );
420 return true;
421 } else {
422 if ( oldResource ) {
423 d->mResourceMap[incidence] = oldResource;
424 } else {
425 d->mResourceMap.remove( incidence );
426 }
427 }
428
429 return false;
430}
431
432bool CalendarResources::addIncidence( Incidence *incidence )
433{
434 clearException();
435
436 ResourceCalendar *resource = d->mLastUsedResource;
437
438 if ( !d->mAddingInProgress || d->mLastUsedResource == 0 ) {
439 resource = d->mDestinationPolicy->destination( incidence );
440 d->mLastUsedResource = resource;
441 }
442
443 if ( resource ) {
444 d->mResourceMap[ incidence ] = resource;
445
446 if ( beginChange( incidence ) && resource->addIncidence( incidence ) ) {
447 incidence->registerObserver( this );
448 notifyIncidenceAdded( incidence );
449
450 d->mResourceMap[ incidence ] = resource;
451 setModified( true );
452 endChange( incidence );
453 return true;
454 } else {
455 d->mResourceMap.remove( incidence );
456 }
457 } else {
458 d->mException = new ErrorFormat( ErrorFormat::UserCancel );
459 }
460
461 return false;
462}
463
464bool CalendarResources::addEvent( Event *event )
465{
466 return addIncidence( event );
467}
468
469bool CalendarResources::addEvent( Event *Event, ResourceCalendar *resource )
470{
471 return addIncidence( Event, resource );
472}
473
474bool CalendarResources::deleteEvent( Event *event )
475{
476 bool status;
477 if ( d->mResourceMap.find( event ) != d->mResourceMap.end() ) {
478 status = d->mResourceMap[event]->deleteEvent( event );
479 if ( status ) {
480 d->mPendingDeleteFromResourceMap = true;
481 }
482 } else {
483 status = false;
484 CalendarResourceManager::ActiveIterator it;
485 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
486 status = (*it)->deleteEvent( event ) || status;
487 }
488 }
489 if ( status ) {
490 notifyIncidenceDeleted( event );
491 }
492
493 setModified( status );
494 return status;
495}
496
497void CalendarResources::deleteAllEvents()
498{
499 CalendarResourceManager::ActiveIterator it;
500 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
501 (*it)->deleteAllEvents();
502 }
503}
504
505Event *CalendarResources::event( const QString &uid )
506{
507 CalendarResourceManager::ActiveIterator it;
508 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
509 Event *event = (*it)->event( uid );
510 if ( event ) {
511 d->mResourceMap[event] = *it;
512 return event;
513 }
514 }
515
516 // Not found
517 return 0;
518}
519
520bool CalendarResources::addTodo( Todo *todo )
521{
522 return addIncidence( todo );
523}
524
525bool CalendarResources::addTodo( Todo *todo, ResourceCalendar *resource )
526{
527 return addIncidence( todo, resource );
528}
529
530bool CalendarResources::deleteTodo( Todo *todo )
531{
532 bool status;
533 if ( d->mResourceMap.find( todo ) != d->mResourceMap.end() ) {
534 status = d->mResourceMap[todo]->deleteTodo( todo );
535 if ( status ) {
536 d->mPendingDeleteFromResourceMap = true;
537 }
538 } else {
539 CalendarResourceManager::ActiveIterator it;
540 status = false;
541 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
542 status = (*it)->deleteTodo( todo ) || status;
543 }
544 }
545
546 setModified( status );
547 return status;
548}
549
550void CalendarResources::deleteAllTodos()
551{
552 CalendarResourceManager::ActiveIterator it;
553 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
554 (*it)->deleteAllTodos();
555 }
556}
557
558Todo::List CalendarResources::rawTodos( TodoSortField sortField,
559 SortDirection sortDirection )
560{
561 Todo::List result;
562
563 CalendarResourceManager::ActiveIterator it;
564 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
565 d->appendIncidences<Todo::List>( result,
566 (*it)->rawTodos( TodoSortUnsorted ), *it );
567 }
568 return sortTodos( &result, sortField, sortDirection );
569}
570
571Todo *CalendarResources::todo( const QString &uid )
572{
573 CalendarResourceManager::ActiveIterator it;
574 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
575 Todo *todo = (*it)->todo( uid );
576 if ( todo ) {
577 d->mResourceMap[todo] = *it;
578 return todo;
579 }
580 }
581
582 // Not found
583 return 0;
584}
585
586Todo::List CalendarResources::rawTodosForDate( const QDate &date )
587{
588 Todo::List result;
589
590 CalendarResourceManager::ActiveIterator it;
591 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
592 d->appendIncidences<Todo::List>( result,
593 (*it)->rawTodosForDate( date ), *it );
594 }
595 return result;
596}
597
598Alarm::List CalendarResources::alarmsTo( const KDateTime &to )
599{
600 Alarm::List result;
601 CalendarResourceManager::ActiveIterator it;
602 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
603 result += (*it)->alarmsTo( to );
604 }
605 return result;
606}
607
608Alarm::List CalendarResources::alarms( const KDateTime &from,
609 const KDateTime &to )
610{
611 Alarm::List result;
612 CalendarResourceManager::ActiveIterator it;
613 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
614 result += (*it)->alarms( from, to );
615 }
616 return result;
617}
618
619bool CalendarResources::hasCalendarResources()
620{
621 return d->mDestinationPolicy->hasCalendarResources();
622}
623
624/****************************** PROTECTED METHODS ****************************/
625
626Event::List CalendarResources::rawEventsForDate( const QDate &date,
627 const KDateTime::Spec &timeSpec,
628 EventSortField sortField,
629 SortDirection sortDirection )
630{
631 Event::List result;
632 CalendarResourceManager::ActiveIterator it;
633 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
634 d->appendIncidences<Event::List>( result,
635 (*it)->rawEventsForDate( date, timeSpec ), *it );
636 }
637 return sortEventsForDate( &result, date, timeSpec, sortField, sortDirection );
638}
639
640Event::List CalendarResources::rawEvents( const QDate &start, const QDate &end,
641 const KDateTime::Spec &timeSpec, bool inclusive )
642{
643 Event::List result;
644 CalendarResourceManager::ActiveIterator it;
645 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
646 d->appendIncidences<Event::List>( result,
647 (*it)->rawEvents( start, end, timeSpec, inclusive ), *it );
648 }
649 return result;
650}
651
652Event::List CalendarResources::rawEventsForDate( const KDateTime &kdt )
653{
654 // @TODO: Remove the code duplication by the resourcemap iteration block.
655 Event::List result;
656 CalendarResourceManager::ActiveIterator it;
657 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
658 d->appendIncidences<Event::List>( result,
659 (*it)->rawEventsForDate( kdt ), *it );
660 }
661 return result;
662}
663
664Event::List CalendarResources::rawEvents( EventSortField sortField,
665 SortDirection sortDirection )
666{
667 Event::List result;
668 CalendarResourceManager::ActiveIterator it;
669 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
670 d->appendIncidences<Event::List>( result,
671 (*it)->rawEvents( EventSortUnsorted ), *it );
672 }
673 return sortEvents( &result, sortField, sortDirection );
674}
675
676bool CalendarResources::addJournal( Journal *journal )
677{
678 return addIncidence( journal );
679}
680
681bool CalendarResources::addJournal( Journal *journal, ResourceCalendar *resource )
682{
683 return addIncidence( journal, resource );
684}
685
686bool CalendarResources::deleteJournal( Journal *journal )
687{
688 bool status;
689 if ( d->mResourceMap.find( journal ) != d->mResourceMap.end() ) {
690 status = d->mResourceMap[journal]->deleteJournal( journal );
691 if ( status ) {
692 d->mPendingDeleteFromResourceMap = true;
693 }
694 } else {
695 CalendarResourceManager::ActiveIterator it;
696 status = false;
697 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
698 status = (*it)->deleteJournal( journal ) || status;
699 }
700 }
701
702 setModified( status );
703 return status;
704}
705
706void CalendarResources::deleteAllJournals()
707{
708 CalendarResourceManager::ActiveIterator it;
709 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
710 (*it)->deleteAllJournals();
711 }
712}
713
714Journal *CalendarResources::journal( const QString &uid )
715{
716 CalendarResourceManager::ActiveIterator it;
717 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
718 Journal *journal = (*it)->journal( uid );
719 if ( journal ) {
720 d->mResourceMap[journal] = *it;
721 return journal;
722 }
723 }
724
725 // Not found
726 return 0;
727}
728
729Journal::List CalendarResources::rawJournals( JournalSortField sortField,
730 SortDirection sortDirection )
731{
732 Journal::List result;
733 CalendarResourceManager::ActiveIterator it;
734 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
735 d->appendIncidences<Journal::List>( result,
736 (*it)->rawJournals( JournalSortUnsorted ), *it );
737 }
738 return sortJournals( &result, sortField, sortDirection );
739}
740
741Journal::List CalendarResources::rawJournalsForDate( const QDate &date )
742{
743
744 Journal::List result;
745
746 CalendarResourceManager::ActiveIterator it;
747 for ( it = d->mManager->activeBegin(); it != d->mManager->activeEnd(); ++it ) {
748 d->appendIncidences<Journal::List>( result,
749 (*it)->rawJournalsForDate( date ), *it );
750 }
751 return result;
752}
753
754//@cond PRIVATE
755template< class IncidenceList >
756void CalendarResources::Private::appendIncidences( IncidenceList &result,
757 const IncidenceList &extra,
758 ResourceCalendar *resource )
759{
760 result += extra;
761 for ( typename IncidenceList::ConstIterator it = extra.begin();
762 it != extra.end();
763 ++it ) {
764 mResourceMap[ *it ] = resource;
765 }
766}
767//@endcond
768
769void CalendarResources::connectResource( ResourceCalendar *resource )
770{
771 connect( resource, SIGNAL(resourceChanged(ResourceCalendar*)),
772 SIGNAL(calendarChanged()) );
773 connect( resource, SIGNAL(resourceSaved(ResourceCalendar*)),
774 SIGNAL(calendarSaved()) );
775
776 connect( resource, SIGNAL(resourceLoadError(ResourceCalendar*,QString)),
777 SLOT(slotLoadError(ResourceCalendar*,QString)) );
778 connect( resource, SIGNAL(resourceSaveError(ResourceCalendar*,QString)),
779 SLOT(slotSaveError(ResourceCalendar*,QString)) );
780}
781
782ResourceCalendar *CalendarResources::resource( Incidence *incidence )
783{
784 if ( d->mResourceMap.find( incidence ) != d->mResourceMap.end() ) {
785 return d->mResourceMap[ incidence ];
786 }
787 return 0;
788}
789
790void CalendarResources::resourceAdded( ResourceCalendar *resource )
791{
792 if ( !resource->isActive() ) {
793 return;
794 }
795
796 if ( resource->open() ) {
797 resource->load();
798 }
799
800 connectResource( resource );
801
802 emit signalResourceAdded( resource );
803}
804
805void CalendarResources::resourceModified( ResourceCalendar *resource )
806{
807 emit signalResourceModified( resource );
808}
809
810void CalendarResources::resourceDeleted( ResourceCalendar *resource )
811{
812 emit signalResourceDeleted( resource );
813}
814
815void CalendarResources::doSetTimeSpec( const KDateTime::Spec &timeSpec )
816{
817 // set the timezone for all resources. Otherwise we'll have those terrible
818 // tz troubles ;-((
819 CalendarResourceManager::Iterator i1;
820 for ( i1 = d->mManager->begin(); i1 != d->mManager->end(); ++i1 ) {
821 (*i1)->setTimeSpec( timeSpec );
822 }
823}
824
825CalendarResources::Ticket::Ticket( ResourceCalendar *resource )
826 : d( new KCal::CalendarResources::Ticket::Private( resource ) )
827{
828}
829
830CalendarResources::Ticket::~Ticket()
831{
832 delete d;
833}
834
835CalendarResources::Ticket *CalendarResources::requestSaveTicket( ResourceCalendar *resource )
836{
837 KABC::Lock *lock = resource->lock();
838 if ( !lock ) {
839 return 0;
840 }
841 if ( lock->lock() ) {
842 return new Ticket( resource );
843 } else {
844 return 0;
845 }
846}
847
848ResourceCalendar *CalendarResources::Ticket::resource() const
849{
850 return d->mResource;
851}
852
853bool CalendarResources::save( Ticket *ticket, Incidence *incidence )
854{
855 if ( !ticket || !ticket->resource() ) {
856 return false;
857 }
858
859 // @TODO: Check if the resource was changed at all. If not, don't save.
860 if ( ticket->resource()->save( incidence ) ) {
861 releaseSaveTicket( ticket );
862 return true;
863 }
864
865 return false;
866}
867
868void CalendarResources::releaseSaveTicket( Ticket *ticket )
869{
870 ticket->resource()->lock()->unlock();
871 delete ticket;
872}
873
874bool CalendarResources::beginChange( Incidence *incidence )
875{
876 ResourceCalendar *r = resource( incidence );
877 if ( !r ) {
878 r = d->mDestinationPolicy->destination( incidence );
879 if ( !r ) {
880 kError() << "Unable to get destination resource.";
881 return false;
882 }
883 d->mResourceMap[ incidence ] = r;
884 }
885 d->mPendingDeleteFromResourceMap = false;
886
887 int count = incrementChangeCount( r );
888 if ( count == 1 ) {
889 Ticket *ticket = requestSaveTicket( r );
890 if ( !ticket ) {
891 kDebug() << "unable to get ticket.";
892 decrementChangeCount( r );
893 return false;
894 } else {
895 d->mTickets[ r ] = ticket;
896 }
897 }
898
899 return true;
900}
901
902bool CalendarResources::endChange( Incidence *incidence )
903{
904 ResourceCalendar *r = resource( incidence );
905 if ( !r ) {
906 return false;
907 }
908
909 int count = decrementChangeCount( r );
910
911 if ( d->mPendingDeleteFromResourceMap ) {
912 d->mResourceMap.remove( incidence );
913 d->mPendingDeleteFromResourceMap = false;
914 }
915
916 if ( count == 0 ) {
917 bool ok = save( d->mTickets[ r ], incidence );
918 if ( ok ) {
919 d->mTickets.remove( r );
920 } else {
921 return false;
922 }
923 }
924
925 return true;
926}
927
928void CalendarResources::beginAddingIncidences()
929{
930 d->mAddingInProgress = true;
931}
932
933void CalendarResources::endAddingIncidences()
934{
935 d->mAddingInProgress = false;
936 d->mLastUsedResource = 0;
937}
938
939int CalendarResources::incrementChangeCount( ResourceCalendar *r )
940{
941 if ( !d->mChangeCounts.contains( r ) ) {
942 d->mChangeCounts.insert( r, 0 );
943 }
944
945 int count = d->mChangeCounts[ r ];
946 ++count;
947 d->mChangeCounts[ r ] = count;
948
949 return count;
950}
951
952int CalendarResources::decrementChangeCount( ResourceCalendar *r )
953{
954 if ( !d->mChangeCounts.contains( r ) ) {
955 kError() << "No change count for resource.";
956 return 0;
957 }
958
959 int count = d->mChangeCounts[ r ];
960 --count;
961 if ( count < 0 ) {
962 kError() << "Can't decrement change count. It already is 0.";
963 count = 0;
964 }
965 d->mChangeCounts[ r ] = count;
966
967 return count;
968}
969
970void CalendarResources::slotLoadError( ResourceCalendar *r, const QString &err )
971{
972 Q_UNUSED( r );
973 emit signalErrorMessage( err );
974}
975
976void CalendarResources::slotSaveError( ResourceCalendar *r, const QString &err )
977{
978 Q_UNUSED( r );
979 emit signalErrorMessage( err );
980}
981