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 <kstandarddirs.h>
00026 
00027 #include "event.h"
00028 #include "todo.h"
00029 #include "freebusy.h"
00030 #include "icalformat.h"
00031 #include "calendar.h"
00032 #include "freebusycache.h"
00033 
00034 #include "scheduler.h"
00035 
00036 using namespace KCal;
00037 
00038 ScheduleMessage::ScheduleMessage(IncidenceBase *incidence,int method,ScheduleMessage::Status status)
00039 {
00040   mIncidence = incidence;
00041   mMethod = method;
00042   mStatus = status;
00043 }
00044 
00045 QString ScheduleMessage::statusName(ScheduleMessage::Status status)
00046 {
00047   switch (status) {
00048     case PublishUpdate:
00049       return i18n("Updated Publish");
00050     case PublishNew:
00051       return i18n("Publish");
00052     case Obsolete:
00053       return i18n("Obsolete");
00054     case RequestNew:
00055       return i18n("New Request");
00056     case RequestUpdate:
00057       return i18n("Updated Request");
00058     default:
00059       return i18n("Unknown Status: %1").arg(QString::number(status));
00060   }
00061 }
00062 
00063 struct Scheduler::Private
00064 {
00065   Private() : mFreeBusyCache( 0 ) {}
00066 
00067   FreeBusyCache *mFreeBusyCache;
00068 };
00069 
00070 Scheduler::Scheduler(Calendar *calendar)
00071 {
00072   mCalendar = calendar;
00073   mFormat = new ICalFormat();
00074   mFormat->setTimeZone( calendar->timeZoneId(), !calendar->isLocalTime() );
00075 
00076   d = new Private;
00077 }
00078 
00079 Scheduler::~Scheduler()
00080 {
00081   delete d;
00082 
00083   delete mFormat;
00084 }
00085 
00086 void Scheduler::setFreeBusyCache( FreeBusyCache *c )
00087 {
00088   d->mFreeBusyCache = c;
00089 }
00090 
00091 FreeBusyCache *Scheduler::freeBusyCache() const
00092 {
00093   return d->mFreeBusyCache;
00094 }
00095 
00096 bool Scheduler::acceptTransaction(IncidenceBase *incidence,Method method,ScheduleMessage::Status status)
00097 {
00098   kdDebug(5800) << "Scheduler::acceptTransaction, method="
00099                 << methodName( method ) << endl;
00100 
00101   switch (method) {
00102     case Publish:
00103       return acceptPublish(incidence, status, method);
00104     case Request:
00105       return acceptRequest(incidence, status);
00106     case Add:
00107       return acceptAdd(incidence, status);
00108     case Cancel:
00109       return acceptCancel(incidence, status);
00110     case Declinecounter:
00111       return acceptDeclineCounter(incidence, status);
00112     case Reply:
00113       return acceptReply(incidence, status, method);
00114     case Refresh:
00115       return acceptRefresh(incidence, status);
00116     case Counter:
00117       return acceptCounter(incidence, status);
00118     default:
00119       break;
00120   }
00121   deleteTransaction(incidence);
00122   return false;
00123 }
00124 
00125 QString Scheduler::methodName(Method method)
00126 {
00127   switch (method) {
00128     case Publish:
00129       return QString::fromLatin1("Publish");
00130     case Request:
00131       return QString::fromLatin1("Request");
00132     case Refresh:
00133       return QString::fromLatin1("Refresh");
00134     case Cancel:
00135       return QString::fromLatin1("Cancel");
00136     case Add:
00137       return QString::fromLatin1("Add");
00138     case Reply:
00139       return QString::fromLatin1("Reply");
00140     case Counter:
00141       return QString::fromLatin1("Counter");
00142     case Declinecounter:
00143       return QString::fromLatin1("Decline Counter");
00144     default:
00145       return QString::fromLatin1("Unknown");
00146   }
00147 }
00148 
00149 QString Scheduler::translatedMethodName(Method method)
00150 {
00151   switch (method) {
00152     case Publish:
00153       return i18n("Publish");
00154     case Request:
00155       return i18n("Request");
00156     case Refresh:
00157       return i18n("Refresh");
00158     case Cancel:
00159       return i18n("Cancel");
00160     case Add:
00161       return i18n("Add");
00162     case Reply:
00163       return i18n("Reply");
00164     case Counter:
00165       return i18n("counter proposal","Counter");
00166     case Declinecounter:
00167       return i18n("decline counter proposal","Decline Counter");
00168     default:
00169       return i18n("Unknown");
00170   }
00171 }
00172 
00173 bool Scheduler::deleteTransaction(IncidenceBase *)
00174 {
00175   return true;
00176 }
00177 
00178 bool Scheduler::acceptPublish( IncidenceBase *newIncBase,
00179                                ScheduleMessage::Status status, Method method )
00180 {
00181   if( newIncBase->type() == "FreeBusy" ) {
00182     return acceptFreeBusy( newIncBase, method );
00183   }
00184 
00185   bool res = false;
00186   kdDebug(5800) << "Scheduler::acceptPublish, status="
00187             << ScheduleMessage::statusName( status ) << endl;
00188   Incidence *newInc = static_cast<Incidence *>( newIncBase );
00189   Incidence *calInc = mCalendar->incidence( newIncBase->uid() );
00190   switch ( status ) {
00191     case ScheduleMessage::Unknown:
00192     case ScheduleMessage::PublishNew:
00193     case ScheduleMessage::PublishUpdate:
00194       res = true;
00195       if ( calInc ) {
00196         if ( (newInc->revision() > calInc->revision()) ||
00197              (newInc->revision() == calInc->revision() &&
00198                newInc->lastModified() > calInc->lastModified() ) ) {
00199           mCalendar->deleteIncidence( calInc );
00200         } else
00201           res = false;
00202       }
00203       if ( res )
00204         mCalendar->addIncidence( newInc );
00205       break;
00206     case ScheduleMessage::Obsolete:
00207       res = true;
00208       break;
00209     default:
00210       break;
00211   }
00212   deleteTransaction( newIncBase );
00213   return res;
00214 }
00215 
00216 bool Scheduler::acceptRequest(IncidenceBase *newIncBase, ScheduleMessage::Status /* status */)
00217 {
00218   if (newIncBase->type()=="FreeBusy") {
00219     // reply to this request is handled in korganizer's incomingdialog
00220     return true;
00221   }
00222   Incidence *newInc = dynamic_cast<Incidence *>( newIncBase );
00223   if ( newInc ) {
00224     bool res = true;
00225     Incidence *exInc = mCalendar->incidenceFromSchedulingID( newIncBase->uid() );
00226     if ( exInc ) {
00227       res = false;
00228       if ( (newInc->revision() > exInc->revision()) ||
00229            (newInc->revision() == exInc->revision() &&
00230              newInc->lastModified()>exInc->lastModified()) ) {
00231         mCalendar->deleteIncidence( exInc );
00232         res = true;
00233       }
00234     }
00235     if ( res ) {
00236       // Move the uid to be the schedulingID and make a unique UID
00237       newInc->setSchedulingID( newInc->uid() );
00238       newInc->setUid( CalFormat::createUniqueId() );
00239 
00240       mCalendar->addIncidence(newInc);
00241     }
00242     deleteTransaction( newIncBase );
00243     return res;
00244   }
00245   return false;
00246 }
00247 
00248 bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00249 {
00250   deleteTransaction(incidence);
00251   return false;
00252 }
00253 
00254 bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00255 {
00256   bool ret = false;
00257   Incidence *inc = mCalendar->incidence( incidence->uid() );
00258   if ( inc ) {
00259     mCalendar->deleteIncidence( inc );
00260     ret = true;
00261   }
00262   deleteTransaction(incidence);
00263   return ret;
00264 }
00265 
00266 bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00267 {
00268   deleteTransaction(incidence);
00269   return false;
00270 }
00271 
00272 //bool Scheduler::acceptFreeBusy(Incidence *incidence,ScheduleMessage::Status status)
00273 //{
00274 //  deleteTransaction(incidence);
00275 //  return false;
00276 //}
00277 
00278 bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status /* status */, Method method)
00279 {
00280   if(incidence->type()=="FreeBusy") {
00281     return acceptFreeBusy(incidence, method);
00282   }
00283   bool ret = false;
00284   Event *ev = mCalendar->event(incidence->uid());
00285   Todo *to = mCalendar->todo(incidence->uid());
00286   if (ev || to) {
00287     //get matching attendee in calendar
00288     kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl;
00289     Attendee::List attendeesIn = incidence->attendees();
00290     Attendee::List attendeesEv;
00291     if (ev) attendeesEv = ev->attendees();
00292     if (to) attendeesEv = to->attendees();
00293     Attendee::List::ConstIterator inIt;
00294     Attendee::List::ConstIterator evIt;
00295     for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
00296       Attendee *attIn = *inIt;
00297       for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
00298         Attendee *attEv = *evIt;
00299         if (attIn->email().lower()==attEv->email().lower()) {
00300           //update attendee-info
00301           kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl;
00302           attEv->setStatus(attIn->status());
00303           ret = true;
00304         }
00305       }
00306     }
00307     if ( ret ) {
00308       // We set at least one of the attendees, so the incidence changed
00309       // Note: This should not result in a sequence number bump
00310       if ( ev )
00311         ev->updated();
00312       else if ( to )
00313         to->updated();
00314     }
00315     if ( to ) {
00316       // for VTODO a REPLY can be used to update the completion status of 
00317       // a task. see RFC2446 3.4.3
00318       Todo *update = dynamic_cast<Todo*> ( incidence );
00319       Q_ASSERT( update );
00320       if ( update && ( to->percentComplete() != update->percentComplete() ) ) {
00321         to->setPercentComplete( update->percentComplete() );
00322         to->updated();
00323       }
00324     }
00325   } else
00326     kdError(5800) << "No incidence for scheduling\n";
00327   if (ret) deleteTransaction(incidence);
00328   return ret;
00329 }
00330 
00331 bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00332 {
00333   // handled in korganizer's IncomingDialog
00334   deleteTransaction(incidence);
00335   return false;
00336 }
00337 
00338 bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
00339 {
00340   deleteTransaction(incidence);
00341   return false;
00342 }
00343 
00344 bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method)
00345 {
00346   if ( !d->mFreeBusyCache ) {
00347     kdError() << "KCal::Scheduler: no FreeBusyCache." << endl;
00348     return false;
00349   }
00350 
00351   FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
00352 
00353   kdDebug(5800) << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDir() << endl;
00354 
00355   Person from;
00356   if(method == Scheduler::Publish) {
00357     from = freebusy->organizer();
00358   }
00359   if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) {
00360     Attendee *attendee = freebusy->attendees().first();
00361     from = attendee->email();
00362   }
00363 
00364   if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) return false;
00365 
00366   deleteTransaction(incidence);
00367   return true;
00368 }
KDE Home | KDE Accessibility Home | Description of Access Keys