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);
Scheduler(Calendar *calendar)
Create scheduler for calendar specified as argument.
PartStat status() const
Return status.
This class provides information about free/busy time of a calendar user.
void setStatus(PartStat s)
Set status.
TQString uid() const
Return unique id of the attendee.
Incidence * incidenceFromSchedulingID(const TQString &sid)
Returns the Incidence associated with the given scheduling identifier.
static TQString methodName(Method)
Return a machine-readable name for a iTIP method.
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred.
virtual bool deleteEvent(Event *event)=0
Remove an Event from the Calendar.
void addAttendee(Attendee *attendee, bool doUpdate=true)
Add Attendee to this incidence.
void setUid(const TQString &)
Set the unique id for the event.
TQString timeZoneId() const
Get the Time Zone ID for the Calendar.
virtual bool addIncidence(Incidence *incidence)
Insert an Incidence into the Calendar.
TQDateTime lastModified() const
Return the time the incidence was last modified.
void setDelegator(const TQString &delegator)
Sets the delegator.
Incidence::List incidencesFromSchedulingID(const TQString &UID)
Searches all events and todos for (an incidence with this scheduling ID.
This class represents a person.
TQString delegator() const
Returns the delegator.
bool acceptTransaction(IncidenceBase *, Method method, ScheduleMessage::Status status, const TQString &attendee=TQString())
Accept transaction.
bool assign(IncidenceBase *target, const IncidenceBase *source)
Assigns the incidence referenced by source to the incidence referenced by target, first ensuring that...
Role role() const
Return role of Attendee.
TQWidget * dialogParentWidget()
Returns the current parent for new dialogs.
void setDialogParentWidget(TQWidget *parent)
Set the widget parent for new dialogs.
This class provides an Event in the sense of RFC2445.
void addComment(const TQString &comment)
Add a comment to this incidence.
void setPercentComplete(int)
Set how many percent of the task are completed.
Helper for type correct assignment of incidences via pointers.
FreeBusyCache * freeBusyCache() const
Return free/busy cache.
This class provides a Todo in the sense of RFC2445.
bool isReadOnly() const
Return if the object is read-only.
int attendeeCount() const
Return number of attendees.
virtual Incidence::List incidences()
Return a filtered list of all Incidences for this Calendar.
Status status()
Return status of this message.
bool RSVP() const
Return, if Attendee is asked to reply.
int method()
Return iTIP method associated with this message.
virtual Event * event(const TQString &uid)=0
Returns the Event associated with the given unique identifier.
virtual bool deleteTodo(Todo *todo)=0
Remove a Todo from the Calendar.
bool addIncidence(Incidence *incidence)
Insert an Incidence into the Calendar.
void setDelegate(const TQString &delegate)
Sets the delegate.
static TQString translatedMethodName(Method)
Return a translated human-readable name for a iTIP method.
void setRevision(int rev)
Set the number of revisions this event has seen.
virtual bool performTransaction(IncidenceBase *incidence, Method method)=0
Perform iTIP transaction on incidence.
This class provides the base class common to all calendar components.
This class represents information related to an attendee of an event.
const Attendee::List & attendees() const
Return list of attendees.
virtual TQString freeBusyDir()=0
Returns the directory where the free-busy information is stored.
bool isMyCalendarIncidence(Calendar *calendar, Incidence *incidence)
Determine if the specified incidence is likely owned by the the user, independent of the Resource typ...
TQString delegate() const
Returns the delegate.
int percentComplete() const
Returns how many percent of the task are completed.
bool isLocalTime() const
Determine if Calendar Incidences are to be written without a time zone.
TQString uid() const
Return the unique id for the event.
int revision() const
Return the number of revisions this event has seen.
TQString summary() const
Return short summary.
This class provides the base class common to all calendar components.
TQString schedulingID() const
Return the event's/todo's scheduling ID.
void updated()
Call this to notify the observers after the IncidenceBas object has changed.
void setSchedulingID(const TQString &sid)
Set the event's/todo's scheduling ID.
virtual Todo * todo(const TQString &uid)=0
Returns the Todo associated with the given unique identifier.
static TQString statusName(Status status)
Return a human-readable name for an iTIP message status.
void setFreeBusyCache(FreeBusyCache *)
Set free/busy cache used to store free/busy information.
ScheduleMessage(IncidenceBase *, int method, Status status)
Create a scheduling message with method as defined in Scheduler::Method and a status.
Incidence * incidence(const TQString &uid)
Returns the Incidence associated with the given unique identifier.