libkcal
scheduler.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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 )
00217 {
00218 if (newIncBase->type()=="FreeBusy") {
00219
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
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 )
00249 {
00250 deleteTransaction(incidence);
00251 return false;
00252 }
00253
00254 bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status )
00255 {
00256 bool ret = false;
00257 const IncidenceBase *toDelete = mCalendar->incidenceFromSchedulingID( incidence->uid() );
00258 if ( toDelete ) {
00259 Event *even = mCalendar->event(toDelete->uid());
00260 if (even) {
00261 mCalendar->deleteEvent(even);
00262 ret = true;
00263 } else {
00264 Todo *todo = mCalendar->todo(toDelete->uid());
00265 if (todo) {
00266 mCalendar->deleteTodo(todo);
00267 ret = true;
00268 }
00269 }
00270 }
00271 deleteTransaction(incidence);
00272 return ret;
00273 }
00274
00275 bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status )
00276 {
00277 deleteTransaction(incidence);
00278 return false;
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status , Method method)
00288 {
00289 if(incidence->type()=="FreeBusy") {
00290 return acceptFreeBusy(incidence, method);
00291 }
00292 bool ret = false;
00293 Event *ev = mCalendar->event(incidence->uid());
00294 Todo *to = mCalendar->todo(incidence->uid());
00295 if (ev || to) {
00296
00297 kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl;
00298 Attendee::List attendeesIn = incidence->attendees();
00299 Attendee::List attendeesEv;
00300 if (ev) attendeesEv = ev->attendees();
00301 if (to) attendeesEv = to->attendees();
00302 Attendee::List::ConstIterator inIt;
00303 Attendee::List::ConstIterator evIt;
00304 for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
00305 Attendee *attIn = *inIt;
00306 for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
00307 Attendee *attEv = *evIt;
00308 if (attIn->email().lower()==attEv->email().lower()) {
00309
00310 kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl;
00311 attEv->setStatus(attIn->status());
00312 ret = true;
00313 }
00314 }
00315 }
00316 if ( ret ) {
00317
00318
00319 if ( ev )
00320 ev->updated();
00321 else if ( to )
00322 to->updated();
00323 }
00324 if ( to ) {
00325
00326
00327 Todo *update = dynamic_cast<Todo*> ( incidence );
00328 Q_ASSERT( update );
00329 if ( update && ( to->percentComplete() != update->percentComplete() ) ) {
00330 to->setPercentComplete( update->percentComplete() );
00331 to->updated();
00332 }
00333 }
00334 } else
00335 kdError(5800) << "No incidence for scheduling\n";
00336 if (ret) deleteTransaction(incidence);
00337 return ret;
00338 }
00339
00340 bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status )
00341 {
00342
00343 deleteTransaction(incidence);
00344 return false;
00345 }
00346
00347 bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status )
00348 {
00349 deleteTransaction(incidence);
00350 return false;
00351 }
00352
00353 bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method)
00354 {
00355 if ( !d->mFreeBusyCache ) {
00356 kdError() << "KCal::Scheduler: no FreeBusyCache." << endl;
00357 return false;
00358 }
00359
00360 FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
00361
00362 kdDebug(5800) << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDir() << endl;
00363
00364 Person from;
00365 if(method == Scheduler::Publish) {
00366 from = freebusy->organizer();
00367 }
00368 if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) {
00369 Attendee *attendee = freebusy->attendees().first();
00370 from = attendee->email();
00371 }
00372
00373 if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) return false;
00374
00375 deleteTransaction(incidence);
00376 return true;
00377 }
|