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