libkcal

scheduler.cpp
1 /*
2  This file is part of libkcal.
3 
4  Copyright (c) 2001,2004 Cornelius Schumacher <schumacher@kde.org>
5  Copyright (C) 2004 Reinhold Kainhofer <reinhold@kainhofer.com>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Library General Public License for more details.
16 
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB. If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21 */
22 
23 #include <tdelocale.h>
24 #include <kdebug.h>
25 #include <tdemessagebox.h>
26 #include <kstandarddirs.h>
27 
28 #include "calhelper.h"
29 #include "event.h"
30 #include "todo.h"
31 #include "freebusy.h"
32 #include "icalformat.h"
33 #include "calendar.h"
34 #include "calendarresources.h"
35 #include "freebusycache.h"
36 #include "assignmentvisitor.h"
37 
38 #include "scheduler.h"
39 
40 using namespace KCal;
41 
43 {
44  mIncidence = incidence;
45  mMethod = method;
46  mStatus = status;
47 }
48 
50 {
51  switch (status) {
52  case PublishUpdate:
53  return i18n("Updated Publish");
54  case PublishNew:
55  return i18n("Publish");
56  case Obsolete:
57  return i18n("Obsolete");
58  case RequestNew:
59  return i18n("New Request");
60  case RequestUpdate:
61  return i18n("Updated Request");
62  default:
63  return i18n("Unknown Status: %1").arg(TQString::number(status));
64  }
65 }
66 
67 struct Scheduler::Private
68 {
69  Private() : mFreeBusyCache( 0 ) {}
70 
71  FreeBusyCache *mFreeBusyCache;
72 };
73 
75 {
76  mCalendar = calendar;
77  mFormat = new ICalFormat();
78  mFormat->setTimeZone( calendar->timeZoneId(), !calendar->isLocalTime() );
79 
80  d = new Private;
81 }
82 
83 Scheduler::~Scheduler()
84 {
85  delete d;
86 
87  delete mFormat;
88 }
89 
90 void Scheduler::setFreeBusyCache( FreeBusyCache *c )
91 {
92  d->mFreeBusyCache = c;
93 }
94 
95 FreeBusyCache *Scheduler::freeBusyCache() const
96 {
97  return d->mFreeBusyCache;
98 }
99 
101  Method method,
103  const TQString &attendee )
104 {
105  kdDebug(5800) << "Scheduler::acceptTransaction, method="
106  << methodName( method ) << endl;
107 
108  switch (method) {
109  case Publish:
110  return acceptPublish(incidence, status, method);
111  case Request:
112  return acceptRequest( incidence, status, attendee );
113  case Add:
114  return acceptAdd(incidence, status);
115  case Cancel:
116  return acceptCancel(incidence, status, attendee );
117  case Declinecounter:
118  return acceptDeclineCounter(incidence, status);
119  case Reply:
120  return acceptReply(incidence, status, method);
121  case Refresh:
122  return acceptRefresh(incidence, status);
123  case Counter:
124  return acceptCounter(incidence, status);
125  default:
126  break;
127  }
128  deleteTransaction(incidence);
129  return false;
130 }
131 
133 {
134  switch (method) {
135  case Publish:
136  return TQString::fromLatin1("Publish");
137  case Request:
138  return TQString::fromLatin1("Request");
139  case Refresh:
140  return TQString::fromLatin1("Refresh");
141  case Cancel:
142  return TQString::fromLatin1("Cancel");
143  case Add:
144  return TQString::fromLatin1("Add");
145  case Reply:
146  return TQString::fromLatin1("Reply");
147  case Counter:
148  return TQString::fromLatin1("Counter");
149  case Declinecounter:
150  return TQString::fromLatin1("Decline Counter");
151  default:
152  return TQString::fromLatin1("Unknown");
153  }
154 }
155 
157 {
158  switch (method) {
159  case Publish:
160  return i18n("Publish");
161  case Request:
162  return i18n("Request");
163  case Refresh:
164  return i18n("Refresh");
165  case Cancel:
166  return i18n("Cancel");
167  case Add:
168  return i18n("Add");
169  case Reply:
170  return i18n("Reply");
171  case Counter:
172  return i18n("counter proposal","Counter");
173  case Declinecounter:
174  return i18n("decline counter proposal","Decline Counter");
175  default:
176  return i18n("Unknown");
177  }
178 }
179 
180 bool Scheduler::deleteTransaction(IncidenceBase *)
181 {
182  return true;
183 }
184 
185 bool Scheduler::acceptPublish( IncidenceBase *newIncBase,
186  ScheduleMessage::Status status, Method method )
187 {
188  if( newIncBase->type() == "FreeBusy" ) {
189  return acceptFreeBusy( newIncBase, method );
190  }
191 
192  bool res = false;
193  kdDebug(5800) << "Scheduler::acceptPublish, status="
194  << ScheduleMessage::statusName( status ) << endl;
195  Incidence *newInc = static_cast<Incidence *>( newIncBase );
196  Incidence *calInc = mCalendar->incidence( newIncBase->uid() );
197  switch ( status ) {
198  case ScheduleMessage::Unknown:
199  case ScheduleMessage::PublishNew:
200  case ScheduleMessage::PublishUpdate:
201  if ( calInc && newInc ) {
202  if ( (newInc->revision() > calInc->revision()) ||
203  (newInc->revision() == calInc->revision() &&
204  newInc->lastModified() > calInc->lastModified() ) ) {
205  AssignmentVisitor visitor;
206  const TQString oldUid = calInc->uid();
207  if ( !visitor.assign( calInc, newInc ) ) {
208  kdError(5800) << "assigning different incidence types" << endl;
209  } else {
210  calInc->setUid( oldUid );
211  calInc->setSchedulingID( newInc->uid() );
212  res = true;
213  }
214  }
215  }
216  break;
217  case ScheduleMessage::Obsolete:
218  res = true;
219  break;
220  default:
221  break;
222  }
223  deleteTransaction( newIncBase );
224  return res;
225 }
226 
227 bool Scheduler::acceptRequest( IncidenceBase *incidence,
229  const TQString &attendee )
230 {
231  Incidence *inc = static_cast<Incidence *>(incidence);
232  if ( !inc )
233  return false;
234  if (inc->type()=="FreeBusy") {
235  // reply to this request is handled in korganizer's incomingdialog
236  return true;
237  }
238 
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;
247  // If it's readonly, we can't possible update it.
248  if ( i->isReadOnly() )
249  continue;
250  if ( i->revision() <= inc->revision() ) {
251  // The new incidence might be an update for the found one
252  bool isUpdate = true;
253  // Code for new invitations:
254  // If you think we could check the value of "status" to be RequestNew: we can't.
255  // It comes from a similar check inside libical, where the event is compared to
256  // other events in the calendar. But if we have another version of the event around
257  // (e.g. shared folder for a group), the status could be RequestNew, Obsolete or Updated.
258  kdDebug(5800) << "looking in " << i->uid() << "'s attendees" << endl;
259  // This is supposed to be a new request, not an update - however we want to update
260  // the existing one to handle the "clicking more than once on the invitation" case.
261  // So check the attendee status of the attendee.
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 ) {
266  // This incidence wasn't created by me - it's probably in a shared folder
267  // and meant for someone else, ignore it.
268  kdDebug(5800) << "ignoring " << i->uid() << " since I'm still NeedsAction there" << endl;
269  isUpdate = false;
270  break;
271  }
272  }
273  if ( isUpdate ) {
274  if ( i->revision() == inc->revision() &&
275  i->lastModified() > inc->lastModified() ) {
276  // This isn't an update - the found incidence was modified more recently
277  kdDebug(5800) << "This isn't an update - the found incidence was modified more recently" << endl;
278  deleteTransaction(incidence);
279  return false;
280  }
281  kdDebug(5800) << "replacing existing incidence " << i->uid() << endl;
282  bool res = true;
283  AssignmentVisitor visitor;
284  const TQString oldUid = i->uid();
285  if ( !visitor.assign( i, inc ) ) {
286  kdError(5800) << "assigning different incidence types" << endl;
287  res = false;
288  } else {
289  i->setUid( oldUid );
290  i->setSchedulingID( inc->uid() );
291  }
292  deleteTransaction( incidence );
293  return res;
294  }
295  } else {
296  // This isn't an update - the found incidence has a bigger revision number
297  kdDebug(5800) << "This isn't an update - the found incidence has a bigger revision number" << endl;
298  deleteTransaction(incidence);
299  return false;
300  }
301  }
302 
303  // Move the uid to be the schedulingID and make a unique UID
304  inc->setSchedulingID( inc->uid() );
306  // notify the user in case this is an update and we didn't find the to-be-updated incidence
307  if ( existingIncidences.count() == 0 && inc->revision() > 0 ) {
308  KMessageBox::information(
309  0,
310  i18n( "<qt>"
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>"
318  "</ul>"
319  "This is not a problem, but we thought you should know.</qt>" ),
320  i18n( "Cannot find invitation to be updated" ), "AcceptCantFindIncidence" );
321  }
322  kdDebug(5800) << "Storing new incidence with scheduling uid=" << inc->schedulingID()
323  << " and uid=" << inc->uid() << endl;
324 
325  CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
326  if( stdcal && !stdcal->hasCalendarResources() ) {
327  KMessageBox::sorry(
328  0,
329  i18n( "No calendars found, unable to save the invitation." ) );
330  return false;
331  }
332 
333  // FIXME: This is a nasty hack, since we need to set a parent for the
334  // resource selection dialog. However, we don't have any UI methods
335  // in the calendar, only in the CalendarResources::DestinationPolicy
336  // So we need to type-cast it and extract it from the CalendarResources
337  TQWidget *tmpparent = 0;
338  if ( stdcal ) {
339  tmpparent = stdcal->dialogParentWidget();
340  stdcal->setDialogParentWidget( 0 );
341  }
342 
343 TryAgain:
344  bool success = false;
345  if ( stdcal ) {
346  success = stdcal->addIncidence( inc );
347  } else {
348  success = mCalendar->addIncidence( inc );
349  }
350 
351  if ( !success ) {
352  ErrorFormat *e = stdcal ? stdcal->exception() : 0;
353 
354  if ( e && e->errorCode() == KCal::ErrorFormat::UserCancel &&
355  KMessageBox::warningYesNo(
356  0,
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(
363  0,
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 );
370  return true;
371  } else {
372  goto TryAgain;
373  }
374 
375  // We can have a failure if the user pressed [cancel] in the resource
376  // selectdialog, so check the exception.
377  if ( !e ||
378  ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel &&
380  TQString errMessage = i18n( "Unable to save %1 \"%2\"." ).
381  arg( i18n( inc->type() ) ).
382  arg( inc->summary() );
383  KMessageBox::sorry( 0, errMessage );
384  }
385  return false;
386  }
387 
388  deleteTransaction( incidence );
389  return true;
390 }
391 
392 bool Scheduler::acceptAdd(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
393 {
394  deleteTransaction(incidence);
395  return false;
396 }
397 
398 bool Scheduler::acceptCancel( IncidenceBase *incidence,
400  const TQString &attendee )
401 {
402  Incidence *inc = static_cast<Incidence *>( incidence );
403  if ( !inc ) {
404  return false;
405  }
406 
407  if ( inc->type() == "FreeBusy" ) {
408  // reply to this request is handled in korganizer's incomingdialog
409  return true;
410  }
411 
412  const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->uid() );
413  kdDebug(5800) << "Scheduler::acceptCancel="
414  << ScheduleMessage::statusName( status )
415  << ": found " << existingIncidences.count()
416  << " incidences with schedulingID " << inc->schedulingID()
417  << endl;
418 
419  // Remove existing incidences that aren't stored in my calendar as we
420  // will never attempt to remove those -- even if we have write-access.
421  Incidence::List myExistingIncidences;
422  Incidence::List::ConstIterator incit = existingIncidences.begin();
423  for ( ; incit != existingIncidences.end() ; ++incit ) {
424  Incidence *i = *incit;
425  if ( CalHelper::isMyCalendarIncidence( mCalendar, i ) ) {
426  myExistingIncidences.append( i );
427  }
428  }
429 
430  bool ret = false;
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;
437 
438  // If it's readonly, we can't possible remove it.
439  if ( i->isReadOnly() ) {
440  continue;
441  }
442 
443  // Code for new invitations:
444  // We cannot check the value of "status" to be RequestNew because
445  // "status" comes from a similar check inside libical, where the event
446  // is compared to other events in the calendar. But if we have another
447  // version of the event around (e.g. shared folder for a group), the
448  // status could be RequestNew, Obsolete or Updated.
449  kdDebug(5800) << "looking in " << i->uid() << "'s attendees" << endl;
450 
451  // This is supposed to be a new request, not an update - however we want
452  // to update the existing one to handle the "clicking more than once
453  // on the invitation" case. So check the attendee status of the attendee.
454  bool isMine = true;
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 ) {
460  // This incidence wasn't created by me - it's probably in a shared
461  // folder and meant for someone else, ignore it.
462  kdDebug(5800) << "ignoring " << i->uid()
463  << " since I'm still NeedsAction there" << endl;
464  isMine = false;
465  break;
466  }
467  }
468 
469  if ( isMine ) {
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 ) );
477  }
478  deleteTransaction( incidence );
479  return ret;
480  }
481  }
482 
483  // in case we didn't find the to-be-removed incidence
484  if ( myExistingIncidences.count() > 0 && inc->revision() > 0 ) {
485  KMessageBox::information(
486  0,
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." ) );
490  }
491  deleteTransaction( incidence );
492  return ret;
493 }
494 
495 bool Scheduler::acceptCancel(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
496 {
497  const IncidenceBase *toDelete = mCalendar->incidenceFromSchedulingID( incidence->uid() );
498 
499  bool ret = true;
500  if ( toDelete ) {
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 ) );
507  }
508  } else {
509  // only complain if we failed to determine the toDelete incidence
510  // on non-initial request.
511  Incidence *inc = static_cast<Incidence *>( incidence );
512  if ( inc->revision() > 0 ) {
513  ret = false;
514  }
515  }
516 
517  if ( !ret ) {
518  KMessageBox::information(
519  0,
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." ) );
523  }
524  deleteTransaction(incidence);
525  return ret;
526 }
527 
528 bool Scheduler::acceptDeclineCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
529 {
530  deleteTransaction(incidence);
531  return false;
532 }
533 
534 //bool Scheduler::acceptFreeBusy(Incidence *incidence,ScheduleMessage::Status status)
535 //{
536 // deleteTransaction(incidence);
537 // return false;
538 //}
539 
540 bool Scheduler::acceptReply(IncidenceBase *incidence,ScheduleMessage::Status /* status */, Method method)
541 {
542  if(incidence->type()=="FreeBusy") {
543  return acceptFreeBusy(incidence, method);
544  }
545  bool ret = false;
546  Event *ev = mCalendar->event(incidence->uid());
547  Todo *to = mCalendar->todo(incidence->uid());
548 
549  // try harder to find the correct incidence
550  if ( !ev && !to ) {
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 );
556  break;
557  }
558  }
559  }
560 
561  if (ev || to) {
562  //get matching attendee in calendar
563  kdDebug(5800) << "Scheduler::acceptTransaction match found!" << endl;
564  Attendee::List attendeesIn = incidence->attendees();
565  Attendee::List attendeesEv;
566  Attendee::List attendeesNew;
567  if (ev) attendeesEv = ev->attendees();
568  if (to) attendeesEv = to->attendees();
569  Attendee::List::ConstIterator inIt;
570  Attendee::List::ConstIterator evIt;
571  for ( inIt = attendeesIn.begin(); inIt != attendeesIn.end(); ++inIt ) {
572  Attendee *attIn = *inIt;
573  bool found = false;
574  for ( evIt = attendeesEv.begin(); evIt != attendeesEv.end(); ++evIt ) {
575  Attendee *attEv = *evIt;
576  if (attIn->email().lower()==attEv->email().lower()) {
577  //update attendee-info
578  kdDebug(5800) << "Scheduler::acceptTransaction update attendee" << endl;
579  attEv->setStatus(attIn->status());
580  attEv->setDelegate(attIn->delegate());
581  attEv->setDelegator(attIn->delegator());
582  ret = true;
583  found = true;
584  }
585  }
586  if ( !found && attIn->status() != Attendee::Declined )
587  attendeesNew.append( attIn );
588  }
589 
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() )
594  .arg( ev ? ev->summary() : to->summary() );
595  if ( !attNew->delegator().isEmpty() )
596  msg = i18n("%1 wants to attend %2 on behalf of %3.").arg( attNew->fullName() )
597  .arg( ev ? ev->summary() : to->summary() )
598  .arg( attNew->delegator() );
599  if ( KMessageBox::questionYesNo( 0, msg, i18n("Uninvited attendee"),
600  KGuiItem(i18n("Accept Attendance")), KGuiItem(i18n("Reject Attendance")) )
601  != KMessageBox::Yes )
602  {
603  KCal::Incidence *cancel = dynamic_cast<Incidence*>( incidence );
604  if ( cancel )
605  cancel->addComment( i18n( "The organizer rejected your attendance at this meeting." ) );
606  performTransaction( cancel ? cancel : incidence, Scheduler::Cancel, attNew->fullName() );
607  delete cancel;
608  continue;
609  }
610 
611  Attendee *a = new Attendee( attNew->name(), attNew->email(), attNew->RSVP(),
612  attNew->status(), attNew->role(), attNew->uid() );
613  a->setDelegate( attNew->delegate() );
614  a->setDelegator( attNew->delegator() );
615  if ( ev )
616  ev->addAttendee( a );
617  else if ( to )
618  to->addAttendee( a );
619  ret = true;
620  attendeeAdded = true;
621  }
622 
623  // send update about new participants
624  if ( attendeeAdded ) {
625  bool sendMail = false;
626  if ( ev || to ) {
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 ) {
631  sendMail = true;
632  }
633  }
634 
635  if ( ev ) {
636  ev->setRevision( ev->revision() + 1 );
637  if ( sendMail )
638  performTransaction( ev, Scheduler::Request );
639  }
640  if ( to ) {
641  to->setRevision( to->revision() + 1 );
642  if ( sendMail )
643  performTransaction( to, Scheduler::Request );
644  }
645  }
646 
647  if ( ret ) {
648  // We set at least one of the attendees, so the incidence changed
649  // Note: This should not result in a sequence number bump
650  if ( ev )
651  ev->updated();
652  else if ( to )
653  to->updated();
654  }
655  if ( to ) {
656  // for VTODO a REPLY can be used to update the completion status of
657  // a task. see RFC2446 3.4.3
658  Todo *update = dynamic_cast<Todo*> ( incidence );
659  Q_ASSERT( update );
660  if ( update && ( to->percentComplete() != update->percentComplete() ) ) {
661  to->setPercentComplete( update->percentComplete() );
662  to->updated();
663  }
664  }
665  } else
666  kdError(5800) << "No incidence for scheduling\n";
667  if (ret) deleteTransaction(incidence);
668  return ret;
669 }
670 
671 bool Scheduler::acceptRefresh(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
672 {
673  // handled in korganizer's IncomingDialog
674  deleteTransaction(incidence);
675  return false;
676 }
677 
678 bool Scheduler::acceptCounter(IncidenceBase *incidence,ScheduleMessage::Status /* status */)
679 {
680  deleteTransaction(incidence);
681  return false;
682 }
683 
684 bool Scheduler::acceptFreeBusy(IncidenceBase *incidence, Method method)
685 {
686  if ( !d->mFreeBusyCache ) {
687  kdError() << "KCal::Scheduler: no FreeBusyCache." << endl;
688  return false;
689  }
690 
691  FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
692 
693  kdDebug(5800) << "acceptFreeBusy:: freeBusyDirName: " << freeBusyDir() << endl;
694 
695  Person from;
696  if(method == Scheduler::Publish) {
697  from = freebusy->organizer();
698  }
699  if((method == Scheduler::Reply) && (freebusy->attendeeCount() == 1)) {
700  Attendee *attendee = freebusy->attendees().first();
701  from = attendee->email();
702  }
703 
704  if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) return false;
705 
706  deleteTransaction(incidence);
707  return true;
708 }
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.
Definition: attendee.h:37
void setDelegator(const TQString &delegator)
Sets the delegator.
Definition: attendee.h:140
void setDelegate(const TQString &delegate)
Sets the delegate.
Definition: attendee.h:131
TQString uid() const
Return unique id of the attendee.
Definition: attendee.cpp:137
TQString delegate() const
Returns the delegate.
Definition: attendee.h:135
Role role() const
Return role of Attendee.
Definition: attendee.cpp:122
TQString delegator() const
Returns the delegator.
Definition: attendee.h:144
void setStatus(PartStat s)
Set status.
Definition: attendee.cpp:56
bool RSVP() const
Return, if Attendee is asked to reply.
Definition: attendee.h:126
PartStat status() const
Return status.
Definition: attendee.cpp:61
static TQString createUniqueId()
Create a unique id string.
Definition: calformat.cpp:67
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.
Definition: calendar.h:171
virtual bool addIncidence(Incidence *incidence)
Insert an Incidence into the Calendar.
Definition: calendar.cpp:466
bool isLocalTime() const
Determine if Calendar Incidences are to be written without a time zone.
Definition: calendar.cpp:125
virtual Incidence::List incidences()
Return a filtered list of all Incidences for this Calendar.
Definition: calendar.cpp:178
Incidence * incidenceFromSchedulingID(const TQString &sid)
Returns the Incidence associated with the given scheduling identifier.
Definition: calendar.cpp:599
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.
Definition: calendar.cpp:80
virtual bool deleteEvent(Event *event)=0
Remove an Event from the Calendar.
TQString timeZoneId() const
Get the Time Zone ID for the Calendar.
Definition: calendar.cpp:112
Incidence::List incidencesFromSchedulingID(const TQString &UID)
Searches all events and todos for (an incidence with this scheduling ID.
Definition: calendar.cpp:588
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.
Definition: calendar.cpp:576
Calendar format related error class.
Definition: exceptions.h:65
@ NoWritableFound
No writable resource is available.
Definition: exceptions.h:80
@ UserCancel
User canceled the operation.
Definition: exceptions.h:81
ErrorCodeFormat errorCode()
Return format error code.
Definition: exceptions.cpp:101
This class provides an Event in the sense of RFC2445.
Definition: event.h:33
This class provides information about free/busy time of a calendar user.
Definition: freebusy.h:41
This class implements the iCalendar format.
Definition: icalformat.h:44
void setTimeZone(const TQString &id, bool utc)
Set id of used time zone and whether this time zone is UTC or not.
Definition: icalformat.cpp:611
TQString toString(Calendar *)
Return calendar information as string.
Definition: icalformat.cpp:225
This class provides the base class common to all calendar components.
Definition: incidencebase.h:46
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.
Definition: incidence.h:48
void setSchedulingID(const TQString &sid)
Set the event's/todo's scheduling ID.
Definition: incidence.cpp:880
int revision() const
Return the number of revisions this event has seen.
Definition: incidence.cpp:259
TQString schedulingID() const
Return the event's/todo's scheduling ID.
Definition: incidence.cpp:885
TQString summary() const
Return short summary.
Definition: incidence.cpp:293
void setRevision(int rev)
Set the number of revisions this event has seen.
Definition: incidence.cpp:251
This class represents a person.
Definition: person.h:35
ScheduleMessage(IncidenceBase *, int method, Status status)
Create a scheduling message with method as defined in Scheduler::Method and a status.
Definition: scheduler.cpp:42
int method()
Return iTIP method associated with this message.
Definition: scheduler.h:67
Status status()
Return status of this message.
Definition: scheduler.h:71
Status
Message status.
Definition: scheduler.h:50
static TQString statusName(Status status)
Return a human-readable name for an iTIP message status.
Definition: scheduler.cpp:49
virtual TQString freeBusyDir()=0
Returns the directory where the free-busy information is stored.
FreeBusyCache * freeBusyCache() const
Return free/busy cache.
Definition: scheduler.cpp:95
bool acceptTransaction(IncidenceBase *, Method method, ScheduleMessage::Status status, const TQString &attendee=TQString())
Accept transaction.
Definition: scheduler.cpp:100
static TQString translatedMethodName(Method)
Return a translated human-readable name for a iTIP method.
Definition: scheduler.cpp:156
Scheduler(Calendar *calendar)
Create scheduler for calendar specified as argument.
Definition: scheduler.cpp:74
Method
iTIP methods.
Definition: scheduler.h:103
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.
Definition: scheduler.cpp:132
void setFreeBusyCache(FreeBusyCache *)
Set free/busy cache used to store free/busy information.
Definition: scheduler.cpp:90
This class provides a Todo in the sense of RFC2445.
Definition: todo.h:32
int percentComplete() const
Returns how many percent of the task are completed.
Definition: todo.cpp:263
void setPercentComplete(int)
Set how many percent of the task are completed.
Definition: todo.cpp:268
bool isMyCalendarIncidence(Calendar *calendar, Incidence *incidence)
Determine if the specified incidence is likely owned by the the user, independent of the Resource typ...
Definition: calhelper.cpp:55
Namespace KCal is for global classes, objects and/or functions in libkcal.
Definition: alarm.h:38