libkcal

scheduler.cpp

00001 /*
00002     This file is part of libkcal.
00003 
00004     Copyright (c) 2001,2004 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This library is free software; you can redistribute it and/or
00008     modify it under the terms of the GNU Library General Public
00009     License as published by the Free Software Foundation; either
00010     version 2 of the License, or (at your option) any later version.
00011 
00012     This library is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     Library General Public License for more details.
00016 
00017     You should have received a copy of the GNU Library General Public License
00018     along with this library; see the file COPYING.LIB.  If not, write to
00019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00020     Boston, MA 02110-1301, USA.
00021 */
00022 
00023 #include <klocale.h>
00024 #include <kdebug.h>
00025 #include <kmessagebox.h>
00026 #include <kstandarddirs.h>
00027 
00028 #include "event.h"
00029 #include "todo.h"
00030 #include "freebusy.h"
00031 #include "icalformat.h"
00032 #include "calendar.h"
00033 #include "calendarresources.h"
00034 #include "freebusycache.h"
00035 #include "assignmentvisitor.h"
00036 
00037 #include "scheduler.h"
00038 
00039 using namespace KCal;
00040 
00041 ScheduleMessage::ScheduleMessage(IncidenceBase *incidence,int method,ScheduleMessage::Status status)
00042 {
00043   mIncidence = incidence;
00044   mMethod = method;
00045   mStatus = status;
00046 }
00047 
00048 QString ScheduleMessage::statusName(ScheduleMessage::Status status)
00049 {
00050   switch (status) {
00051     case PublishUpdate:
00052       return i18n("Updated Publish");
00053     case PublishNew:
00054       return i18n("Publish");
00055     case Obsolete:
00056       return i18n("Obsolete");
00057     case RequestNew:
00058       return i18n("New Request");
00059     case RequestUpdate:
00060       return i18n("Updated Request");
00061     default:
00062       return i18n("Unknown Status: %1").arg(QString::number(status));
00063   }
00064 }
00065 
00066 struct Scheduler::Private
00067 {
00068   Private() : mFreeBusyCache( 0 ) {}
00069 
00070   FreeBusyCache *mFreeBusyCache;
00071 };
00072 
00073 Scheduler::Scheduler(Calendar *calendar)
00074 {
00075   mCalendar = calendar;
00076   mFormat = new ICalFormat();
00077   mFormat->setTimeZone( calendar->timeZoneId(), !calendar->isLocalTime() );
00078 
00079   d = new Private;
00080 }
00081 
00082 Scheduler::~Scheduler()
00083 {
00084   delete d;
00085 
00086   delete mFormat;
00087 }
00088 
00089 void Scheduler::setFreeBusyCache( FreeBusyCache *c )
00090 {
00091   d->mFreeBusyCache = c;
00092 }
00093 
00094 FreeBusyCache *Scheduler::freeBusyCache() const
00095 {
00096   return d->mFreeBusyCache;
00097 }
00098 
00099 bool Scheduler::acceptTransaction( IncidenceBase *incidence,
00100                                    Method method,
00101                                    ScheduleMessage::Status status,
00102                                    const QString &attendee )
00103 {
00104   kdDebug(5800) << "Scheduler::acceptTransaction, method="
00105                 << methodName( method ) << endl;
00106 
00107   switch (method) {
00108     case Publish:
00109       return acceptPublish(incidence, status, method);
00110     case Request:
00111       return acceptRequest( incidence, status, attendee );
00112     case Add:
00113       return acceptAdd(incidence, status);
00114     case Cancel:
00115       return acceptCancel(incidence, status,  attendee );
00116     case Declinecounter:
00117       return acceptDeclineCounter(incidence, status);
00118     case Reply:
00119       return acceptReply(incidence, status, method);
00120     case Refresh:
00121       return acceptRefresh(incidence, status);
00122     case Counter:
00123       return acceptCounter(incidence, status);
00124     default:
00125       break;
00126   }
00127   deleteTransaction(incidence);
00128   return false;
00129 }
00130 
00131 QString Scheduler::methodName(Method method)
00132 {
00133   switch (method) {
00134     case Publish:
00135       return QString::fromLatin1("Publish");
00136     case Request:
00137       return QString::fromLatin1("Request");
00138     case Refresh:
00139       return QString::fromLatin1("Refresh");
00140     case Cancel:
00141       return QString::fromLatin1("Cancel");
00142     case Add:
00143       return QString::fromLatin1("Add");
00144     case Reply:
00145       return QString::fromLatin1("Reply");
00146     case Counter:
00147       return QString::fromLatin1("Counter");
00148     case Declinecounter:
00149       return QString::fromLatin1("Decline Counter");
00150     default:
00151       return QString::fromLatin1("Unknown");
00152   }
00153 }
00154 
00155 QString Scheduler::translatedMethodName(Method method)
00156 {
00157   switch (method) {
00158     case Publish:
00159       return i18n("Publish");
00160     case Request:
00161       return i18n("Request");
00162     case Refresh:
00163       return i18n("Refresh");
00164     case Cancel:
00165       return i18n("Cancel");
00166     case Add:
00167       return i18n("Add");
00168     case Reply:
00169       return i18n("Reply");
00170     case Counter:
00171       return i18n("counter proposal","Counter");
00172     case Declinecounter:
00173       return i18n("decline counter proposal","Decline Counter");
00174     default:
00175       return i18n("Unknown");
00176   }
00177 }
00178 
00179 bool Scheduler::deleteTransaction(IncidenceBase *)
00180 {
00181   return true;
00182 }
00183 
00184 bool Scheduler::acceptPublish( IncidenceBase *newIncBase,
00185                                ScheduleMessage::Status status, Method method )
00186 {
00187   if( newIncBase->type() == "FreeBusy" ) {
00188     return acceptFreeBusy( newIncBase, method );
00189   }
00190 
00191   bool res = false;
00192   kdDebug(5800) << "Scheduler::acceptPublish, status="
00193                 << ScheduleMessage::statusName( status ) << endl;
00194   Incidence *newInc = static_cast<Incidence *>( newIncBase );
00195   Incidence *calInc = mCalendar->incidence( newIncBase->uid() );
00196   switch ( status ) {
00197     case ScheduleMessage::Unknown:
00198     case ScheduleMessage::PublishNew:
00199     case ScheduleMessage::PublishUpdate:
00200       if ( calInc && newInc ) {
00201         if ( (newInc->revision() > calInc->revision()) ||
00202              (newInc->revision() == calInc->revision() &&
00203                newInc->lastModified() > calInc->lastModified() ) ) {
00204           AssignmentVisitor visitor;
00205           const QString oldUid = calInc->uid();
00206           if ( !visitor.assign( calInc, newInc ) ) {
00207             kdError(5800) << "assigning different incidence types" << endl;
00208           } else {
00209             calInc->setUid( oldUid );
00210             calInc->setSchedulingID( newInc->uid() );
00211             res = true;
00212           }
00213         }
00214       }
00215       break;
00216     case ScheduleMessage::Obsolete:
00217       res = true;
00218       break;
00219     default:
00220       break;
00221   }
00222   deleteTransaction( newIncBase );
00223   return res;
00224 }
00225 
00226 bool Scheduler::acceptRequest( IncidenceBase *incidence,
00227                                ScheduleMessage::Status status,
00228                                const QString &attendee )
00229 {
00230   Incidence *inc = static_cast<Incidence *>(incidence);
00231   if ( !inc )
00232     return false;
00233   if (inc->type()=="FreeBusy") {
00234     // reply to this request is handled in korganizer's incomingdialog
00235     return true;
00236   }
00237 
00238   const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->uid() );
00239   kdDebug(5800) << "Scheduler::acceptRequest status=" << ScheduleMessage::statusName( status ) << ": found " << existingIncidences.count() << " incidences with schedulingID " << inc->schedulingID() << endl;
00240   Incidence::List::ConstIterator incit = existingIncidences.begin();
00241   for ( ; incit != existingIncidences.end() ; ++incit ) {
00242     Incidence* const i = *incit;
00243     kdDebug(5800) << "Considering this found event ("
00244                   << ( i->isReadOnly() ? "readonly" : "readwrite" )
00245                   << ") :" << mFormat->toString( i ) << endl;
00246     // If it's readonly, we can't possible update it.
00247     if ( i->isReadOnly() )
00248       continue;
00249     if ( i->revision() <= inc->revision() ) {
00250       // The new incidence might be an update for the found one
00251       bool isUpdate = true;
00252       // Code for new invitations:
00253       // If you think we could check the value of "status" to be RequestNew: we can't.
00254       // It comes from a similar check inside libical, where the event is compared to
00255       // other events in the calendar. But if we have another version of the event around
00256       // (e.g. shared folder for a group), the status could be RequestNew, Obsolete or Updated.
00257       kdDebug(5800) << "looking in " << i->uid() << "'s attendees" << endl;
00258       // This is supposed to be a new request, not an update - however we want to update
00259       // the existing one to handle the "clicking more than once on the invitation" case.
00260       // So check the attendee status of the attendee.
00261       const KCal::Attendee::List attendees = i->attendees();
00262       KCal::Attendee::List::ConstIterator ait;
00263       for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
00264         if( (*ait)->email() == attendee && (*ait)->status() == Attendee::NeedsAction ) {
00265           // This incidence wasn't created by me - it's probably in a shared folder
00266           // and meant for someone else, ignore it.
00267           kdDebug(5800) << "ignoring " << i->uid() << " since I'm still NeedsAction there" << endl;
00268           isUpdate = false;
00269           break;
00270         }
00271       }
00272       if ( isUpdate ) {
00273         if ( i->revision() == inc->revision() &&
00274              i->lastModified() > inc->lastModified() ) {
00275           // This isn't an update - the found incidence was modified more recently
00276           kdDebug(5800) << "This isn't an update - the found incidence was modified more recently" << endl;
00277           deleteTransaction(incidence);
00278           return false;
00279         }
00280         kdDebug(5800) << "replacing existing incidence " << i->uid() << endl;
00281         bool res = true;
00282         AssignmentVisitor visitor;
00283         const QString oldUid = i->uid();
00284         if ( !visitor.assign( i, inc ) ) {
00285           kdError(5800) << "assigning different incidence types" << endl;
00286           res = false;
00287         } else {
00288           i->setUid( oldUid );
00289           i->setSchedulingID( inc->uid() );
00290         }
00291         deleteTransaction( incidence );
00292         return res;
00293       }
00294     } else {
00295       // This isn't an update - the found incidence has a bigger revision number
00296       kdDebug(5800) << "This isn't an update - the found incidence has a bigger revision number" << endl;
00297       deleteTransaction(incidence);
00298       return false;
00299     }
00300   }
00301 
00302   // Move the uid to be the schedulingID and make a unique UID
00303   inc->setSchedulingID( inc->uid() );
00304   inc->setUid( CalFormat::createUniqueId() );
00305   // in case this is an update and we didn't find the to-be-updated incidence,
00306   // ask whether we should create a new one, or drop the update
00307   if ( existingIncidences.count() > 0 || inc->revision() == 0 ||
00308           KMessageBox::questionYesNo( 0,
00309               i18n("The event, task or journal to be updated could not be found. "
00310                   "Maybe it has already been deleted, or the calendar that "
00311                   "contains it is disabled. Press 'Store' to create a new "
00312                   "one or 'Throw away' to discard this update." ),
00313               i18n("Discard this update?"), i18n("Store"),
00314               i18n("Throw away"), "AcceptCantFindIncidence" ) == KMessageBox::Yes ) {
00315     kdDebug(5800) << "Storing new incidence with scheduling uid=" << inc->schedulingID() << " and uid=" << inc->uid() << endl;
00316 
00317     CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
00318     if( stdcal && !stdcal->hasCalendarResources() ) {
00319       KMessageBox::sorry(
00320         0,
00321         i18n( "No calendars found, unable to save the invitation." ) );
00322       return false;
00323     }
00324 
00325     // FIXME: This is a nasty hack, since we need to set a parent for the
00326     //        resource selection dialog. However, we don't have any UI methods
00327     //        in the calendar, only in the CalendarResources::DestinationPolicy
00328     //        So we need to type-cast it and extract it from the CalendarResources
00329     QWidget *tmpparent = 0;
00330     if ( stdcal ) {
00331       tmpparent = stdcal->dialogParentWidget();
00332       stdcal->setDialogParentWidget( 0 );
00333     }
00334 
00335     bool success = false;
00336     if ( stdcal ) {
00337       success = stdcal->addIncidence( inc );
00338     } else {
00339       success = mCalendar->addIncidence( inc );
00340     }
00341 
00342     if ( !success ) {
00343       // We can have a failure if the user pressed [cancel] in the resource
00344       // selectdialog, so check the exception.
00345       ErrorFormat *e = stdcal ? stdcal->exception() : 0;
00346       if ( !e ||
00347            ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel &&
00348                     e->errorCode() != KCal::ErrorFormat::NoWritableFound ) ) ) {
00349         QString errMessage = i18n( "Unable to save %1 \"%2\"." ).
00350                              arg( i18n( inc->type() ) ).
00351                              arg( inc->summary() );
00352         KMessageBox::sorry( 0, errMessage );
00353       }
00354       return false;
00355     }
00356   }
00357   deleteTransaction(incidence);
00358   return true;
00359 }
00360 
00361 bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00362 {
00363   deleteTransaction(incidence);
00364   return false;
00365 }
00366 
00367 bool Scheduler::acceptCancel( IncidenceBase *incidence,
00368                               ScheduleMessage::Status status,
00369                               const QString &attendee )
00370 {
00371   Incidence *inc = static_cast<Incidence *>( incidence );
00372   if ( !inc ) {
00373     return false;
00374   }
00375 
00376   if ( inc->type() == "FreeBusy" ) {
00377     // reply to this request is handled in korganizer's incomingdialog
00378     return true;
00379   }
00380 
00381   const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->uid() );
00382   kdDebug(5800) << "Scheduler::acceptCancel="
00383                 << ScheduleMessage::statusName( status )
00384                 << ": found " << existingIncidences.count()
00385                 << " incidences with schedulingID " << inc->schedulingID()
00386                 << endl;
00387 
00388   bool ret = false;
00389   Incidence::List::ConstIterator incit = existingIncidences.begin();
00390   for ( ; incit != existingIncidences.end() ; ++incit ) {
00391     Incidence *i = *incit;
00392     kdDebug(5800) << "Considering this found event ("
00393                   << ( i->isReadOnly() ? "readonly" : "readwrite" )
00394                   << ") :" << mFormat->toString( i ) << endl;
00395 
00396     // If it's readonly, we can't possible remove it.
00397     if ( i->isReadOnly() ) {
00398       continue;
00399     }
00400 
00401     // Code for new invitations:
00402     // We cannot check the value of "status" to be RequestNew because
00403     // "status" comes from a similar check inside libical, where the event
00404     // is compared to other events in the calendar. But if we have another
00405     // version of the event around (e.g. shared folder for a group), the
00406     // status could be RequestNew, Obsolete or Updated.
00407     kdDebug(5800) << "looking in " << i->uid() << "'s attendees" << endl;
00408 
00409     // This is supposed to be a new request, not an update - however we want
00410     // to update the existing one to handle the "clicking more than once
00411     // on the invitation" case. So check the attendee status of the attendee.
00412     bool isMine = true;
00413     const KCal::Attendee::List attendees = i->attendees();
00414     KCal::Attendee::List::ConstIterator ait;
00415     for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
00416       if ( (*ait)->email() == attendee &&
00417            (*ait)->status() == Attendee::NeedsAction ) {
00418         // This incidence wasn't created by me - it's probably in a shared
00419         // folder and meant for someone else, ignore it.
00420         kdDebug(5800) << "ignoring " << i->uid()
00421                       << " since I'm still NeedsAction there" << endl;
00422         isMine = false;
00423         break;
00424       }
00425     }
00426 
00427     if ( isMine ) {
00428       kdDebug(5800) << "removing existing incidence " << i->uid() << endl;
00429       if ( i->type() == "Event" ) {
00430         Event *event = mCalendar->event( i->uid() );
00431         ret = ( event && mCalendar->deleteEvent( event ) );
00432       } else if ( i->type() == "Todo" ) {
00433         Todo *todo = mCalendar->todo( i->uid() );
00434         ret = ( todo && mCalendar->deleteTodo( todo ) );
00435       }
00436       deleteTransaction( incidence );
00437       return ret;
00438     }
00439   }
00440 
00441   // in case we didn't find the to-be-removed incidence
00442   if ( existingIncidences.count() > 0 && inc->revision() > 0 ) {
00443     KMessageBox::information(
00444       0,
00445       i18n( "The event or task could not be removed from your calendar. "
00446             "Maybe it has already been deleted or is not owned by you. "
00447             "Or it might belong to a read-only or disabled calendar." ) );
00448   }
00449   deleteTransaction( incidence );
00450   return ret;
00451 }
00452 
00453 bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00454 {
00455   const IncidenceBase *toDelete = mCalendar->incidenceFromSchedulingID( incidence->uid() );
00456 
00457   bool ret = true;
00458   if ( toDelete ) {
00459     if ( toDelete->type() == "Event" ) {
00460       Event *event = mCalendar->event( toDelete->uid() );
00461       ret = ( event && mCalendar->deleteEvent( event ) );
00462     } else if ( toDelete->type() == "Todo" ) {
00463       Todo *todo = mCalendar->todo( toDelete->uid() );
00464       ret = ( todo && mCalendar->deleteTodo( todo ) );
00465     }
00466   } else {
00467     // only complain if we failed to determine the toDelete incidence
00468     // on non-initial request.
00469     Incidence *inc = static_cast<Incidence *>( incidence );
00470     if ( inc->revision() > 0 ) {
00471       ret = false;
00472     }
00473   }
00474 
00475   if ( !ret ) {
00476     KMessageBox::information(
00477       0,
00478       i18n( "The event or task to be canceled could not be removed from your calendar. "
00479             "Maybe it has already been deleted or is not owned by you. "
00480             "Or it might belong to a read-only or disabled calendar." ) );
00481   }
00482   deleteTransaction(incidence);
00483   return ret;
00484 }
00485 
00486 bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00487 {
00488   deleteTransaction(incidence);
00489   return false;
00490 }
00491 
00492 //bool Scheduler::acceptFreeBusy(Incidence *incidence,ScheduleMessage::Status status)
00493 //{
00494 //  deleteTransaction(incidence);
00495 //  return false;
00496 //}
00497 
00498 bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status /* status */, Method method)
00499 {
00500   if(incidence->type()=="FreeBusy") {
00501     return acceptFreeBusy(incidence, method);
00502   }
00503   bool ret = false;
00504   Event *ev = mCalendar->event(incidence->uid());
00505   Todo *to = mCalendar->todo(incidence->uid());
00506 
00507   // try harder to find the correct incidence
00508   if ( !ev && !to ) {
00509     const Incidence::List list = mCalendar->incidences();
00510     for ( Incidence::List::ConstIterator it = list.begin(), end = list.end(); it != end; ++it ) {
00511       if ( (*it)->schedulingID() == incidence->uid() ) {
00512         ev = dynamic_cast<Event*>( *it );
00513         to = dynamic_cast<Todo*>( *it );
00514         break;
00515       }
00516     }
00517   }
00518 
00519   if (ev || to) {
00520     //get matching attendee in calendar
00521     kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl;
00522     Attendee::List attendeesIn = incidence->attendees();
00523     Attendee::List attendeesEv;
00524     Attendee::List attendeesNew;
00525     if (ev) attendeesEv = ev->attendees();
00526     if (to) attendeesEv = to->attendees();
00527     Attendee::List::ConstIterator inIt;
00528     Attendee::List::ConstIterator evIt;
00529     for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
00530       Attendee *attIn = *inIt;
00531       bool found = false;
00532       for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
00533         Attendee *attEv = *evIt;
00534         if (attIn->email().lower()==attEv->email().lower()) {
00535           //update attendee-info
00536           kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl;
00537           attEv->setStatus(attIn->status());
00538           attEv->setDelegate(attIn->delegate());
00539           attEv->setDelegator(attIn->delegator());
00540           ret = true;
00541           found = true;
00542         }
00543       }
00544       if ( !found && attIn->status() != Attendee::Declined )
00545         attendeesNew.append( attIn );
00546     }
00547 
00548     bool attendeeAdded = false;
00549     for ( Attendee::List::ConstIterator it = attendeesNew.constBegin(); it != attendeesNew.constEnd(); ++it ) {
00550       Attendee* attNew = *it;
00551       QString msg = i18n("%1 wants to attend %2 but was not invited.").arg( attNew->fullName() )
00552           .arg( ev ? ev->summary() : to->summary() );
00553       if ( !attNew->delegator().isEmpty() )
00554         msg = i18n("%1 wants to attend %2 on behalf of %3.").arg( attNew->fullName() )
00555             .arg( ev ? ev->summary() : to->summary() )
00556             .arg( attNew->delegator() );
00557       if ( KMessageBox::questionYesNo( 0, msg, i18n("Uninvited attendee"),
00558            KGuiItem(i18n("Accept Attendance")), KGuiItem(i18n("Reject Attendance")) )
00559            != KMessageBox::Yes )
00560       {
00561         KCal::Incidence *cancel = dynamic_cast<Incidence*>( incidence );
00562         if ( cancel )
00563           cancel->addComment( i18n( "The organizer rejected your attendance at this meeting." ) );
00564         performTransaction( cancel ? cancel : incidence, Scheduler::Cancel, attNew->fullName() );
00565         delete cancel;
00566         continue;
00567       }
00568 
00569       Attendee *a = new Attendee( attNew->name(), attNew->email(), attNew->RSVP(),
00570                                   attNew->status(), attNew->role(), attNew->uid() );
00571       a->setDelegate( attNew->delegate() );
00572       a->setDelegator( attNew->delegator() );
00573       if ( ev )
00574         ev->addAttendee( a );
00575       else if ( to )
00576         to->addAttendee( a );
00577       ret = true;
00578       attendeeAdded = true;
00579     }
00580 
00581     // send update about new participants
00582     if ( attendeeAdded ) {
00583       bool sendMail = false;
00584       if ( ev || to ) {
00585         if ( KMessageBox::questionYesNo( 0, i18n( "An attendee was added to the incidence. "
00586                                                   "Do you want to email the attendees an update message?" ),
00587                                          i18n( "Attendee Added" ), i18n( "Send Messages" ),
00588                                          i18n( "Do Not Send" ) ) == KMessageBox::Yes ) {
00589           sendMail = true;
00590         }
00591       }
00592 
00593       if ( ev ) {
00594         ev->setRevision( ev->revision() + 1 );
00595         if ( sendMail )
00596           performTransaction( ev, Scheduler::Request );
00597       }
00598       if ( to ) {
00599         to->setRevision( to->revision() + 1 );
00600         if ( sendMail )
00601           performTransaction( to, Scheduler::Request );
00602       }
00603     }
00604 
00605     if ( ret ) {
00606       // We set at least one of the attendees, so the incidence changed
00607       // Note: This should not result in a sequence number bump
00608       if ( ev )
00609         ev->updated();
00610       else if ( to )
00611         to->updated();
00612     }
00613     if ( to ) {
00614       // for VTODO a REPLY can be used to update the completion status of
00615       // a task. see RFC2446 3.4.3
00616       Todo *update = dynamic_cast<Todo*> ( incidence );
00617       Q_ASSERT( update );
00618       if ( update && ( to->percentComplete() != update->percentComplete() ) ) {
00619         to->setPercentComplete( update->percentComplete() );
00620         to->updated();
00621       }
00622     }
00623   } else
00624     kdError(5800) << "No incidence for scheduling\n";
00625   if (ret) deleteTransaction(incidence);
00626   return ret;
00627 }
00628 
00629 bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00630 {
00631   // handled in korganizer's IncomingDialog
00632   deleteTransaction(incidence);
00633   return false;
00634 }
00635 
00636 bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00637 {
00638   deleteTransaction(incidence);
00639   return false;
00640 }
00641 
00642 bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method)
00643 {
00644   if ( !d->mFreeBusyCache ) {
00645     kdError() << "KCal::Scheduler: no FreeBusyCache." << endl;
00646     return false;
00647   }
00648 
00649   FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
00650 
00651   kdDebug(5800) << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDir() << endl;
00652 
00653   Person from;
00654   if(method == Scheduler::Publish) {
00655     from = freebusy->organizer();
00656   }
00657   if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) {
00658     Attendee *attendee = freebusy->attendees().first();
00659     from = attendee->email();
00660   }
00661 
00662   if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) return false;
00663 
00664   deleteTransaction(incidence);
00665   return true;
00666 }
KDE Home | KDE Accessibility Home | Description of Access Keys