25#include <tdemessagebox.h>
26#include <kstandarddirs.h>
32#include "icalformat.h"
35#include "freebusycache.h"
36#include "assignmentvisitor.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));
67struct Scheduler::Private
69 Private() : mFreeBusyCache( 0 ) {}
71 FreeBusyCache *mFreeBusyCache;
83Scheduler::~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="
195 Incidence *newInc =
static_cast<Incidence *
>( newIncBase );
196 Incidence *calInc = mCalendar->incidence( newIncBase->
uid() );
198 case ScheduleMessage::Unknown:
199 case ScheduleMessage::PublishNew:
200 case ScheduleMessage::PublishUpdate:
201 if ( calInc && newInc ) {
205 AssignmentVisitor visitor;
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 )
231 Incidence *inc =
static_cast<Incidence *
>(incidence);
234 if (inc->type()==
"FreeBusy") {
239 const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->
uid() );
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 ) {
243 Incidence*
const i = *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;
262 const KCal::Attendee::List attendees = i->
attendees();
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;
283 AssignmentVisitor visitor;
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;
325 CalendarResources *stdcal =
dynamic_cast<CalendarResources *
>( mCalendar );
326 if( stdcal && !stdcal->hasCalendarResources() ) {
329 i18n(
"No calendars found, unable to save the invitation." ) );
337 TQWidget *tmpparent = 0;
344 bool success =
false;
348 success = mCalendar->addIncidence( inc );
352 ErrorFormat *e = stdcal ? stdcal->
exception() : 0;
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 )
402 Incidence *inc =
static_cast<Incidence *
>( incidence );
407 if ( inc->type() ==
"FreeBusy" ) {
412 const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->
uid() );
413 kdDebug(5800) <<
"Scheduler::acceptCancel="
415 <<
": found " << existingIncidences.count()
416 <<
" incidences with schedulingID " << inc->
schedulingID()
421 Incidence::List myExistingIncidences;
422 Incidence::List::ConstIterator incit = existingIncidences.begin();
423 for ( ; incit != existingIncidences.end() ; ++incit ) {
424 Incidence *i = *incit;
426 myExistingIncidences.append( i );
431 incit = myExistingIncidences.begin();
432 for ( ; incit != myExistingIncidences.end() ; ++incit ) {
433 Incidence *i = *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;
455 const KCal::Attendee::List attendees = i->
attendees();
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" ) {
472 Event *
event = mCalendar->event( i->
uid() );
473 ret = (
event && mCalendar->deleteEvent( event ) );
474 }
else if ( i->type() ==
"Todo" ) {
475 Todo *todo = mCalendar->todo( i->
uid() );
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 );
497 const IncidenceBase *toDelete = mCalendar->incidenceFromSchedulingID( incidence->
uid() );
501 if ( toDelete->type() ==
"Event" ) {
502 Event *
event = mCalendar->event( toDelete->
uid() );
503 ret = (
event && mCalendar->deleteEvent( event ) );
504 }
else if ( toDelete->type() ==
"Todo" ) {
505 Todo *todo = mCalendar->todo( toDelete->
uid() );
506 ret = ( todo && mCalendar->deleteTodo( todo ) );
511 Incidence *inc =
static_cast<Incidence *
>( incidence );
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);
546 Event *ev = mCalendar->event(incidence->
uid());
547 Todo *to = mCalendar->todo(incidence->
uid());
551 const Incidence::List list = mCalendar->incidences();
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;
564 Attendee::List attendeesIn = incidence->
attendees();
565 Attendee::List attendeesEv;
566 Attendee::List attendeesNew;
569 Attendee::List::ConstIterator inIt;
570 Attendee::List::ConstIterator evIt;
571 for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
572 Attendee *attIn = *inIt;
574 for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
575 Attendee *attEv = *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 ) {
592 Attendee* attNew = *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 )
603 KCal::Incidence *cancel =
dynamic_cast<Incidence*
>( incidence );
605 cancel->
addComment( i18n(
"The organizer rejected your attendance at this meeting." ) );
606 performTransaction( cancel ? cancel : incidence, Scheduler::Cancel, attNew->fullName() );
611 Attendee *a =
new Attendee( attNew->name(), attNew->email(), attNew->
RSVP(),
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);
684bool Scheduler::acceptFreeBusy(
IncidenceBase *incidence, Method method)
686 if ( !d->mFreeBusyCache ) {
687 kdError() <<
"KCal::Scheduler: no FreeBusyCache." << endl;
691 FreeBusy *freebusy =
static_cast<FreeBusy *
>(incidence);
693 kdDebug(5800) <<
"acceptFreeBusy:: freeBusyDirName: " <<
freeBusyDir() << endl;
696 if(method == Scheduler::Publish) {
697 from = freebusy->organizer();
699 if((method == Scheduler::Reply) && (freebusy->
attendeeCount() == 1)) {
700 Attendee *attendee = freebusy->
attendees().first();
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...
bool assign(IncidenceBase *target, const IncidenceBase *source)
Assigns the incidence referenced by source to the incidence referenced by target, first ensuring that...
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.
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.
bool isLocalTime() const
Determine if Calendar Incidences are to be written without a time zone.
ErrorFormat * exception() const
Returns an exception, if there is any, containing information about the last error that occurred.
TQString timeZoneId() const
Get the Time Zone ID for the Calendar.
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.
TQString uid() const
Return the unique id for the event.
const Attendee::List & attendees() const
Return list of attendees.
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.
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.
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.
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.