23 #include <tdelocale.h>
25 #include <tdemessagebox.h>
26 #include <kstandarddirs.h>
32 #include "icalformat.h"
35 #include "freebusycache.h"
36 #include "assignmentvisitor.h"
38 #include "scheduler.h"
44 mIncidence = incidence;
53 return i18n(
"Updated Publish");
55 return i18n(
"Publish");
57 return i18n(
"Obsolete");
59 return i18n(
"New Request");
61 return i18n(
"Updated Request");
63 return i18n(
"Unknown Status: %1").arg(TQString::number(status));
67 struct Scheduler::Private
69 Private() : mFreeBusyCache( 0 ) {}
71 FreeBusyCache *mFreeBusyCache;
83 Scheduler::~Scheduler()
92 d->mFreeBusyCache = c;
97 return d->mFreeBusyCache;
103 const TQString &attendee )
105 kdDebug(5800) <<
"Scheduler::acceptTransaction, method="
110 return acceptPublish(incidence, status, method);
112 return acceptRequest( incidence, status, attendee );
114 return acceptAdd(incidence, status);
116 return acceptCancel(incidence, status, attendee );
118 return acceptDeclineCounter(incidence, status);
120 return acceptReply(incidence, status, method);
122 return acceptRefresh(incidence, status);
124 return acceptCounter(incidence, status);
128 deleteTransaction(incidence);
136 return TQString::fromLatin1(
"Publish");
138 return TQString::fromLatin1(
"Request");
140 return TQString::fromLatin1(
"Refresh");
142 return TQString::fromLatin1(
"Cancel");
144 return TQString::fromLatin1(
"Add");
146 return TQString::fromLatin1(
"Reply");
148 return TQString::fromLatin1(
"Counter");
150 return TQString::fromLatin1(
"Decline Counter");
152 return TQString::fromLatin1(
"Unknown");
160 return i18n(
"Publish");
162 return i18n(
"Request");
164 return i18n(
"Refresh");
166 return i18n(
"Cancel");
170 return i18n(
"Reply");
172 return i18n(
"counter proposal",
"Counter");
174 return i18n(
"decline counter proposal",
"Decline Counter");
176 return i18n(
"Unknown");
188 if( newIncBase->type() ==
"FreeBusy" ) {
189 return acceptFreeBusy( newIncBase, method );
193 kdDebug(5800) <<
"Scheduler::acceptPublish, status="
198 case ScheduleMessage::Unknown:
199 case ScheduleMessage::PublishNew:
200 case ScheduleMessage::PublishUpdate:
201 if ( calInc && newInc ) {
206 const TQString oldUid = calInc->
uid();
207 if ( !visitor.
assign( calInc, newInc ) ) {
208 kdError(5800) <<
"assigning different incidence types" << endl;
217 case ScheduleMessage::Obsolete:
223 deleteTransaction( newIncBase );
229 const TQString &attendee )
234 if (inc->type()==
"FreeBusy") {
240 kdDebug(5800) <<
"Scheduler::acceptRequest status=" <<
ScheduleMessage::statusName( status ) <<
": found " << existingIncidences.count() <<
" incidences with schedulingID " << inc->
schedulingID() << endl;
241 Incidence::List::ConstIterator incit = existingIncidences.begin();
242 for ( ; incit != existingIncidences.end() ; ++incit ) {
244 kdDebug(5800) <<
"Considering this found event ("
245 << ( i->
isReadOnly() ?
"readonly" :
"readwrite" )
246 <<
") :" << mFormat->
toString( i ) << endl;
252 bool isUpdate =
true;
258 kdDebug(5800) <<
"looking in " << i->
uid() <<
"'s attendees" << endl;
263 KCal::Attendee::List::ConstIterator ait;
264 for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
265 if( (*ait)->email() == attendee && (*ait)->status() == Attendee::NeedsAction ) {
268 kdDebug(5800) <<
"ignoring " << i->
uid() <<
" since I'm still NeedsAction there" << endl;
277 kdDebug(5800) <<
"This isn't an update - the found incidence was modified more recently" << endl;
278 deleteTransaction(incidence);
281 kdDebug(5800) <<
"replacing existing incidence " << i->
uid() << endl;
284 const TQString oldUid = i->
uid();
285 if ( !visitor.
assign( i, inc ) ) {
286 kdError(5800) <<
"assigning different incidence types" << endl;
292 deleteTransaction( incidence );
297 kdDebug(5800) <<
"This isn't an update - the found incidence has a bigger revision number" << endl;
298 deleteTransaction(incidence);
307 if ( existingIncidences.count() == 0 && inc->
revision() > 0 ) {
308 KMessageBox::information(
311 "You accepted an invitation update, but an earlier version of the "
312 "item could not be found in your calendar.<p>"
313 "This may have occurred because:<ul>"
314 "<li>the organizer did not include you in the original invitation</li>"
315 "<li>you did not accept the original invitation yet</li>"
316 "<li>you deleted the original invitation from your calendar</li>"
317 "<li>you no longer have access to the calendar containing the invitation</li>"
319 "This is not a problem, but we thought you should know.</qt>" ),
320 i18n(
"Cannot find invitation to be updated" ),
"AcceptCantFindIncidence" );
322 kdDebug(5800) <<
"Storing new incidence with scheduling uid=" << inc->
schedulingID()
323 <<
" and uid=" << inc->
uid() << endl;
326 if( stdcal && !stdcal->hasCalendarResources() ) {
329 i18n(
"No calendars found, unable to save the invitation." ) );
337 TQWidget *tmpparent = 0;
344 bool success =
false;
355 KMessageBox::warningYesNo(
357 i18n(
"You canceled the save operation. Therefore, the appointment will not be "
358 "stored in your calendar even though you accepted the invitation. "
359 "Are you certain you want to discard this invitation? " ),
360 i18n(
"Discard this invitation?" ),
361 i18n(
"Discard" ), i18n(
"Go Back to Folder Selection" ) ) == KMessageBox::Yes ) {
362 KMessageBox::information(
364 i18n(
"The invitation \"%1\" was not saved to your calendar "
365 "but you are still listed as an attendee for that appointment.\n"
366 "If you mistakenly accepted the invitation or do not plan to attend, please notify "
367 "the organizer %2 and ask them to remove you from the attendee list.").
368 arg( inc->
summary(), inc->organizer().fullName() ) );
369 deleteTransaction( incidence );
380 TQString errMessage = i18n(
"Unable to save %1 \"%2\"." ).
381 arg( i18n( inc->type() ) ).
383 KMessageBox::sorry( 0, errMessage );
388 deleteTransaction( incidence );
394 deleteTransaction(incidence);
400 const TQString &attendee )
407 if ( inc->type() ==
"FreeBusy" ) {
413 kdDebug(5800) <<
"Scheduler::acceptCancel="
415 <<
": found " << existingIncidences.count()
416 <<
" incidences with schedulingID " << inc->
schedulingID()
422 Incidence::List::ConstIterator incit = existingIncidences.begin();
423 for ( ; incit != existingIncidences.end() ; ++incit ) {
426 myExistingIncidences.append( i );
431 incit = myExistingIncidences.begin();
432 for ( ; incit != myExistingIncidences.end() ; ++incit ) {
434 kdDebug(5800) <<
"Considering this found event ("
435 << ( i->
isReadOnly() ?
"readonly" :
"readwrite" )
436 <<
") :" << mFormat->
toString( i ) << endl;
449 kdDebug(5800) <<
"looking in " << i->
uid() <<
"'s attendees" << endl;
456 KCal::Attendee::List::ConstIterator ait;
457 for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
458 if ( (*ait)->email() == attendee &&
459 (*ait)->status() == Attendee::NeedsAction ) {
462 kdDebug(5800) <<
"ignoring " << i->
uid()
463 <<
" since I'm still NeedsAction there" << endl;
470 kdDebug(5800) <<
"removing existing incidence " << i->
uid() << endl;
471 if ( i->type() ==
"Event" ) {
473 ret = (
event && mCalendar->
deleteEvent( event ) );
474 }
else if ( i->type() ==
"Todo" ) {
476 ret = ( todo && mCalendar->
deleteTodo( todo ) );
478 deleteTransaction( incidence );
484 if ( myExistingIncidences.count() > 0 && inc->
revision() > 0 ) {
485 KMessageBox::information(
487 i18n(
"The event or task could not be removed from your calendar. "
488 "Maybe it has already been deleted or is not owned by you. "
489 "Or it might belong to a read-only or disabled calendar." ) );
491 deleteTransaction( incidence );
501 if ( toDelete->type() ==
"Event" ) {
503 ret = (
event && mCalendar->
deleteEvent( event ) );
504 }
else if ( toDelete->type() ==
"Todo" ) {
506 ret = ( todo && mCalendar->
deleteTodo( todo ) );
518 KMessageBox::information(
520 i18n(
"The event or task to be canceled could not be removed from your calendar. "
521 "Maybe it has already been deleted or is not owned by you. "
522 "Or it might belong to a read-only or disabled calendar." ) );
524 deleteTransaction(incidence);
530 deleteTransaction(incidence);
542 if(incidence->type()==
"FreeBusy") {
543 return acceptFreeBusy(incidence, method);
552 for ( Incidence::List::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
553 if ( (*it)->schedulingID() == incidence->
uid() ) {
554 ev =
dynamic_cast<Event*
>( *it );
555 to =
dynamic_cast<Todo*
>( *it );
563 kdDebug(5800) <<
"Scheduler::acceptTransaction match found!" << endl;
569 Attendee::List::ConstIterator inIt;
570 Attendee::List::ConstIterator evIt;
571 for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
574 for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
576 if (attIn->email().lower()==attEv->email().lower()) {
578 kdDebug(5800) <<
"Scheduler::acceptTransaction update attendee" << endl;
586 if ( !found && attIn->
status() != Attendee::Declined )
587 attendeesNew.append( attIn );
590 bool attendeeAdded =
false;
591 for ( Attendee::List::ConstIterator it = attendeesNew.constBegin(); it != attendeesNew.constEnd(); ++it ) {
593 TQString msg = i18n(
"%1 wants to attend %2 but was not invited.").arg( attNew->fullName() )
596 msg = i18n(
"%1 wants to attend %2 on behalf of %3.").arg( attNew->fullName() )
599 if ( KMessageBox::questionYesNo( 0, msg, i18n(
"Uninvited attendee"),
600 KGuiItem(i18n(
"Accept Attendance")), KGuiItem(i18n(
"Reject Attendance")) )
601 != KMessageBox::Yes )
605 cancel->
addComment( i18n(
"The organizer rejected your attendance at this meeting." ) );
606 performTransaction( cancel ? cancel : incidence, Scheduler::Cancel, attNew->fullName() );
620 attendeeAdded =
true;
624 if ( attendeeAdded ) {
625 bool sendMail =
false;
627 if ( KMessageBox::questionYesNo( 0, i18n(
"An attendee was added to the incidence. "
628 "Do you want to email the attendees an update message?" ),
629 i18n(
"Attendee Added" ), i18n(
"Send Messages" ),
630 i18n(
"Do Not Send" ) ) == KMessageBox::Yes ) {
658 Todo *update =
dynamic_cast<Todo*
> ( incidence );
666 kdError(5800) <<
"No incidence for scheduling\n";
667 if (ret) deleteTransaction(incidence);
674 deleteTransaction(incidence);
680 deleteTransaction(incidence);
684 bool Scheduler::acceptFreeBusy(
IncidenceBase *incidence, Method method)
686 if ( !d->mFreeBusyCache ) {
687 kdError() <<
"KCal::Scheduler: no FreeBusyCache." << endl;
693 kdDebug(5800) <<
"acceptFreeBusy:: freeBusyDirName: " <<
freeBusyDir() << endl;
696 if(method == Scheduler::Publish) {
697 from = freebusy->organizer();
699 if((method == Scheduler::Reply) && (freebusy->
attendeeCount() == 1)) {
701 from = attendee->email();
704 if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) )
return false;
706 deleteTransaction(incidence);