• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.14.10 API Reference
  • KDE Home
  • Contact Us
 

KCal Library

  • kcal
scheduler.cpp
1 /*
2  This file is part of the kcal library.
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 "scheduler.h"
24 #include "calendar.h"
25 #ifndef KDEPIM_NO_KRESOURCES
26 #include "calendarresources.h"
27 #endif
28 #include "event.h"
29 #include "todo.h"
30 #include "freebusy.h"
31 #include "freebusycache.h"
32 #include "icalformat.h"
33 #include "assignmentvisitor.h"
34 
35 #include <klocalizedstring.h>
36 #include <kdebug.h>
37 #include <kmessagebox.h>
38 #include <kstandarddirs.h>
39 
40 using namespace KCal;
41 
42 //@cond PRIVATE
43 class KCal::ScheduleMessage::Private
44 {
45  public:
46  Private() {}
47 
48  IncidenceBase *mIncidence;
49  iTIPMethod mMethod;
50  Status mStatus;
51  QString mError;
52 };
53 //@endcond
54 
55 ScheduleMessage::ScheduleMessage( IncidenceBase *incidence,
56  iTIPMethod method,
57  ScheduleMessage::Status status )
58  : d( new KCal::ScheduleMessage::Private )
59 {
60  d->mIncidence = incidence;
61  d->mMethod = method;
62  d->mStatus = status;
63 }
64 
65 ScheduleMessage::~ScheduleMessage()
66 {
67  delete d;
68 }
69 
70 IncidenceBase *ScheduleMessage::event()
71 {
72  return d->mIncidence;
73 }
74 
75 iTIPMethod ScheduleMessage::method()
76 {
77  return d->mMethod;
78 }
79 
80 ScheduleMessage::Status ScheduleMessage::status()
81 {
82  return d->mStatus;
83 }
84 
85 QString ScheduleMessage::statusName( ScheduleMessage::Status status )
86 {
87  switch( status ) {
88  case PublishNew:
89  return i18nc( "@item this is a new scheduling message",
90  "New Scheduling Message" );
91  case PublishUpdate:
92  return i18nc( "@item this is an update to an existing scheduling message",
93  "Updated Scheduling Message" );
94  case Obsolete:
95  return i18nc( "@item obsolete status", "Obsolete" );
96  case RequestNew:
97  return i18nc( "@item this is a request for a new scheduling message",
98  "New Scheduling Message Request" );
99  case RequestUpdate:
100  return i18nc( "@item this is a request for an update to an existing scheduling message",
101  "Updated Scheduling Message Request" );
102  default:
103  return i18nc( "@item unknown status", "Unknown Status: %1", int( status ) );
104  }
105 }
106 
107 QString ScheduleMessage::error()
108 {
109  return d->mError;
110 }
111 
112 //@cond PRIVATE
113 struct KCal::Scheduler::Private
114 {
115  Private()
116  : mFreeBusyCache( 0 )
117  {
118  }
119  FreeBusyCache *mFreeBusyCache;
120 };
121 //@endcond
122 
123 Scheduler::Scheduler( Calendar *calendar ) : d( new KCal::Scheduler::Private )
124 {
125  mCalendar = calendar;
126  mFormat = new ICalFormat();
127  mFormat->setTimeSpec( calendar->timeSpec() );
128 }
129 
130 Scheduler::~Scheduler()
131 {
132  delete mFormat;
133  delete d;
134 }
135 
136 void Scheduler::setFreeBusyCache( FreeBusyCache *c )
137 {
138  d->mFreeBusyCache = c;
139 }
140 
141 FreeBusyCache *Scheduler::freeBusyCache() const
142 {
143  return d->mFreeBusyCache;
144 }
145 
146 bool Scheduler::acceptTransaction( IncidenceBase *incidence,
147  iTIPMethod method,
148  ScheduleMessage::Status status )
149 {
150  return acceptTransaction( incidence, method, status, QString() );
151 }
152 
153 bool Scheduler::acceptTransaction( IncidenceBase *incidence,
154  iTIPMethod method,
155  ScheduleMessage::Status status,
156  const QString &email )
157 {
158  kDebug() << "method=" << methodName( method );
159 
160  switch ( method ) {
161  case iTIPPublish:
162  return acceptPublish( incidence, status, method );
163  case iTIPRequest:
164  return acceptRequest( incidence, status, email );
165  case iTIPAdd:
166  return acceptAdd( incidence, status );
167  case iTIPCancel:
168  return acceptCancel( incidence, status, email );
169  case iTIPDeclineCounter:
170  return acceptDeclineCounter( incidence, status );
171  case iTIPReply:
172  return acceptReply( incidence, status, method );
173  case iTIPRefresh:
174  return acceptRefresh( incidence, status );
175  case iTIPCounter:
176  return acceptCounter( incidence, status );
177  default:
178  break;
179  }
180  deleteTransaction( incidence );
181  return false;
182 }
183 
184 QString Scheduler::methodName( iTIPMethod method )
185 {
186  switch ( method ) {
187  case iTIPPublish:
188  return QLatin1String( "Publish" );
189  case iTIPRequest:
190  return QLatin1String( "Request" );
191  case iTIPRefresh:
192  return QLatin1String( "Refresh" );
193  case iTIPCancel:
194  return QLatin1String( "Cancel" );
195  case iTIPAdd:
196  return QLatin1String( "Add" );
197  case iTIPReply:
198  return QLatin1String( "Reply" );
199  case iTIPCounter:
200  return QLatin1String( "Counter" );
201  case iTIPDeclineCounter:
202  return QLatin1String( "Decline Counter" );
203  default:
204  return QLatin1String( "Unknown" );
205  }
206 }
207 
208 QString Scheduler::translatedMethodName( iTIPMethod method )
209 {
210  switch ( method ) {
211  case iTIPPublish:
212  return i18nc( "@item event, to-do, journal or freebusy posting", "Publish" );
213  case iTIPRequest:
214  return i18nc( "@item event, to-do or freebusy scheduling requests", "Request" );
215  case iTIPReply:
216  return i18nc( "@item event, to-do or freebusy reply to request", "Reply" );
217  case iTIPAdd:
218  return i18nc(
219  "@item event, to-do or journal additional property request", "Add" );
220  case iTIPCancel:
221  return i18nc( "@item event, to-do or journal cancellation notice", "Cancel" );
222  case iTIPRefresh:
223  return i18nc( "@item event or to-do description update request", "Refresh" );
224  case iTIPCounter:
225  return i18nc( "@item event or to-do submit counter proposal", "Counter" );
226  case iTIPDeclineCounter:
227  return i18nc( "@item event or to-do decline a counter proposal", "Decline Counter" );
228  default:
229  return i18nc( "@item no method", "Unknown" );
230  }
231 }
232 
233 bool Scheduler::deleteTransaction( IncidenceBase * )
234 {
235  return true;
236 }
237 
238 bool Scheduler::acceptPublish( IncidenceBase *newIncBase,
239  ScheduleMessage::Status status,
240  iTIPMethod method )
241 {
242  if( newIncBase->type() == "FreeBusy" ) {
243  return acceptFreeBusy( newIncBase, method );
244  }
245 
246  bool res = false;
247 
248  kDebug() << "status=" << ScheduleMessage::statusName( status );
249 
250  Incidence *newInc = static_cast<Incidence *>( newIncBase );
251  Incidence *calInc = mCalendar->incidence( newIncBase->uid() );
252  switch ( status ) {
253  case ScheduleMessage::Unknown:
254  case ScheduleMessage::PublishNew:
255  case ScheduleMessage::PublishUpdate:
256  if ( calInc && newInc ) {
257  if ( ( newInc->revision() > calInc->revision() ) ||
258  ( newInc->revision() == calInc->revision() &&
259  newInc->lastModified() > calInc->lastModified() ) ) {
260  AssignmentVisitor visitor;
261  const QString oldUid = calInc->uid();
262  if ( !visitor.assign( calInc, newInc ) ) {
263  kError() << "assigning different incidence types";
264  } else {
265  calInc->setSchedulingID( newInc->uid() );
266  calInc->setUid( oldUid );
267  res = true;
268  }
269  }
270  }
271  break;
272  case ScheduleMessage::Obsolete:
273  res = true;
274  break;
275  default:
276  break;
277  }
278  deleteTransaction( newIncBase );
279  return res;
280 }
281 
282 bool Scheduler::acceptRequest( IncidenceBase *incidence,
283  ScheduleMessage::Status status )
284 {
285  return acceptRequest( incidence, status, QString() );
286 }
287 
288 bool Scheduler::acceptRequest( IncidenceBase *incidence,
289  ScheduleMessage::Status status,
290  const QString &email )
291 {
292  Incidence *inc = static_cast<Incidence *>( incidence );
293  if ( !inc ) {
294  return false;
295  }
296  if ( inc->type() == "FreeBusy" ) {
297  // reply to this request is handled in korganizer's incomingdialog
298  return true;
299  }
300 
301  const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->uid() );
302  kDebug() << "status=" << ScheduleMessage::statusName( status )
303  << ": found " << existingIncidences.count()
304  << " incidences with schedulingID " << inc->schedulingID();
305  Incidence::List::ConstIterator incit = existingIncidences.begin();
306  for ( ; incit != existingIncidences.end() ; ++incit ) {
307  Incidence *i = *incit;
308  kDebug() << "Considering this found event ("
309  << ( i->isReadOnly() ? "readonly" : "readwrite" )
310  << ") :" << mFormat->toString( i );
311  // If it's readonly, we can't possible update it.
312  if ( i->isReadOnly() ) {
313  continue;
314  }
315  if ( i->revision() <= inc->revision() ) {
316  // The new incidence might be an update for the found one
317  bool isUpdate = true;
318  // Code for new invitations:
319  // If you think we could check the value of "status" to be RequestNew: we can't.
320  // It comes from a similar check inside libical, where the event is compared to
321  // other events in the calendar. But if we have another version of the event around
322  // (e.g. shared folder for a group), the status could be RequestNew, Obsolete or Updated.
323  kDebug() << "looking in " << i->uid() << "'s attendees";
324  // This is supposed to be a new request, not an update - however we want to update
325  // the existing one to handle the "clicking more than once on the invitation" case.
326  // So check the attendee status of the attendee.
327  const KCal::Attendee::List attendees = i->attendees();
328  KCal::Attendee::List::ConstIterator ait;
329  for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
330  if( (*ait)->email() == email && (*ait)->status() == Attendee::NeedsAction ) {
331  // This incidence wasn't created by me - it's probably in a shared folder
332  // and meant for someone else, ignore it.
333  kDebug() << "ignoring " << i->uid() << " since I'm still NeedsAction there";
334  isUpdate = false;
335  break;
336  }
337  }
338  if ( isUpdate ) {
339  if ( i->revision() == inc->revision() &&
340  i->lastModified() > inc->lastModified() ) {
341  // This isn't an update - the found incidence was modified more recently
342  kDebug() << "This isn't an update - the found incidence was modified more recently";
343  deleteTransaction( i );
344  return false;
345  }
346  kDebug() << "replacing existing incidence " << i->uid();
347  bool res = true;
348  AssignmentVisitor visitor;
349  const QString oldUid = i->uid();
350  if ( !visitor.assign( i, inc ) ) {
351  kError() << "assigning different incidence types";
352  res = false;
353  } else {
354  i->setUid( oldUid );
355  i->setSchedulingID( inc->uid() );
356  }
357  deleteTransaction( incidence );
358  return res;
359  }
360  } else {
361  // This isn't an update - the found incidence has a bigger revision number
362  kDebug() << "This isn't an update - the found incidence has a bigger revision number";
363  deleteTransaction( incidence );
364  return false;
365  }
366  }
367 
368  // Move the uid to be the schedulingID and make a unique UID
369  inc->setSchedulingID( inc->uid() );
370  inc->setUid( CalFormat::createUniqueId() );
371  // in case this is an update and we didn't find the to-be-updated incidence,
372  // ask whether we should create a new one, or drop the update
373  if ( existingIncidences.count() > 0 || inc->revision() == 0 ||
374  KMessageBox::questionYesNo(
375  0,
376  i18nc( "@info",
377  "The event, to-do or journal to be updated could not be found. "
378  "Maybe it has already been deleted, or the calendar that "
379  "contains it is disabled. Press 'Store' to create a new "
380  "one or 'Throw away' to discard this update." ),
381  i18nc( "@title", "Discard this update?" ),
382  KGuiItem( i18nc( "@option", "Store" ) ),
383  KGuiItem( i18nc( "@option", "Throw away" ) ),
384  "AcceptCantFindIncidence" ) == KMessageBox::Yes ) {
385  kDebug() << "Storing new incidence with scheduling uid=" << inc->schedulingID()
386  << " and uid=" << inc->uid();
387 
388 #ifndef KDEPIM_NO_KRESOURCES
389  CalendarResources *stdcal = dynamic_cast<CalendarResources *>( mCalendar );
390  if( stdcal && !stdcal->hasCalendarResources() ) {
391  KMessageBox::sorry(
392  0,
393  i18nc( "@info", "No calendars found, unable to save the invitation." ) );
394  return false;
395  }
396 
397  // FIXME: This is a nasty hack, since we need to set a parent for the
398  // resource selection dialog. However, we don't have any UI methods
399  // in the calendar, only in the CalendarResources::DestinationPolicy
400  // So we need to type-cast it and extract it from the CalendarResources
401  if ( stdcal ) {
402  stdcal->setDialogParentWidget( 0 );
403  }
404 #endif
405 
406  TryAgain:
407  bool success = false;
408 #ifndef KDEPIM_NO_KRESOURCES
409  if ( stdcal )
410  success = stdcal->addIncidence( inc );
411  else
412 #endif
413  success = mCalendar->addIncidence( inc );
414 
415  if ( !success ) {
416 #ifndef KDEPIM_NO_KRESOURCES
417  ErrorFormat *e = stdcal ? stdcal->exception() : 0;
418 #else
419  ErrorFormat *e = 0;
420 #endif
421 
422  if ( e && e->errorCode() == KCal::ErrorFormat::UserCancel &&
423  KMessageBox::warningYesNo(
424  0,
425  i18nc( "@info",
426  "You canceled the save operation. Therefore, the appointment will not be "
427  "stored in your calendar even though you accepted the invitation. "
428  "Are you certain you want to discard this invitation? " ),
429  i18nc( "@title", "Discard this invitation?" ),
430  KGuiItem( i18nc( "@option", "Discard" ) ),
431  KGuiItem( i18nc( "@option", "Go Back to Folder Selection" ) ) ) == KMessageBox::Yes ) {
432  KMessageBox::information(
433  0,
434  i18nc( "@info",
435  "The invitation \"%1\" was not saved to your calendar "
436  "but you are still listed as an attendee for that appointment.\n"
437  "If you mistakenly accepted the invitation or do not plan to attend, please "
438  "notify the organizer %2 and ask them to remove you from the attendee list.",
439  inc->summary(), inc->organizer().fullName() ) );
440  deleteTransaction( incidence );
441  return true;
442  } else {
443  goto TryAgain;
444  }
445 
446  // We can have a failure if the user pressed [cancel] in the resource
447  // selectdialog, so check the exception.
448  if ( !e ||
449  ( e && ( e->errorCode() != KCal::ErrorFormat::UserCancel &&
450  e->errorCode() != KCal::ErrorFormat::NoWritableFound ) ) ) {
451  QString errMessage = i18nc( "@info", "Unable to save %1 \"%2\".",
452  i18n( inc->type() ), inc->summary() );
453  KMessageBox::sorry( 0, errMessage );
454  }
455  return false;
456  }
457  }
458  deleteTransaction( incidence );
459  return true;
460 }
461 
462 bool Scheduler::acceptAdd( IncidenceBase *incidence, ScheduleMessage::Status /* status */)
463 {
464  deleteTransaction( incidence );
465  return false;
466 }
467 
468 bool Scheduler::acceptCancel( IncidenceBase *incidence,
469  ScheduleMessage::Status status,
470  const QString &attendee )
471 {
472  Incidence *inc = static_cast<Incidence *>( incidence );
473  if ( !inc ) {
474  return false;
475  }
476 
477  if ( inc->type() == "FreeBusy" ) {
478  // reply to this request is handled in korganizer's incomingdialog
479  return true;
480  }
481 
482  const Incidence::List existingIncidences = mCalendar->incidencesFromSchedulingID( inc->uid() );
483  kDebug() << "Scheduler::acceptCancel="
484  << ScheduleMessage::statusName( status )
485  << ": found " << existingIncidences.count()
486  << " incidences with schedulingID " << inc->schedulingID();
487 
488  bool ret = false;
489  Incidence::List::ConstIterator incit = existingIncidences.begin();
490  for ( ; incit != existingIncidences.end() ; ++incit ) {
491  Incidence *i = *incit;
492  kDebug() << "Considering this found event ("
493  << ( i->isReadOnly() ? "readonly" : "readwrite" )
494  << ") :" << mFormat->toString( i );
495 
496  // If it's readonly, we can't possible remove it.
497  if ( i->isReadOnly() ) {
498  continue;
499  }
500 
501  // Code for new invitations:
502  // We cannot check the value of "status" to be RequestNew because
503  // "status" comes from a similar check inside libical, where the event
504  // is compared to other events in the calendar. But if we have another
505  // version of the event around (e.g. shared folder for a group), the
506  // status could be RequestNew, Obsolete or Updated.
507  kDebug() << "looking in " << i->uid() << "'s attendees";
508 
509  // This is supposed to be a new request, not an update - however we want
510  // to update the existing one to handle the "clicking more than once
511  // on the invitation" case. So check the attendee status of the attendee.
512  bool isMine = true;
513  const KCal::Attendee::List attendees = i->attendees();
514  KCal::Attendee::List::ConstIterator ait;
515  for ( ait = attendees.begin(); ait != attendees.end(); ++ait ) {
516  if ( (*ait)->email() == attendee &&
517  (*ait)->status() == Attendee::NeedsAction ) {
518  // This incidence wasn't created by me - it's probably in a shared
519  // folder and meant for someone else, ignore it.
520  kDebug() << "ignoring " << i->uid()
521  << " since I'm still NeedsAction there";
522  isMine = false;
523  break;
524  }
525  }
526 
527  if ( isMine ) {
528  kDebug() << "removing existing incidence " << i->uid();
529  if ( i->type() == "Event" ) {
530  Event *event = mCalendar->event( i->uid() );
531  ret = ( event && mCalendar->deleteEvent( event ) );
532  } else if ( i->type() == "Todo" ) {
533  Todo *todo = mCalendar->todo( i->uid() );
534  ret = ( todo && mCalendar->deleteTodo( todo ) );
535  }
536  deleteTransaction( incidence );
537  return ret;
538  }
539  }
540 
541  // in case we didn't find the to-be-removed incidence
542  if ( existingIncidences.count() > 0 && inc->revision() > 0 ) {
543  KMessageBox::information(
544  0,
545  i18nc( "@info",
546  "The event or task could not be removed from your calendar. "
547  "Maybe it has already been deleted or is not owned by you. "
548  "Or it might belong to a read-only or disabled calendar." ) );
549  }
550  deleteTransaction( incidence );
551  return ret;
552 }
553 
554 bool Scheduler::acceptCancel( IncidenceBase *incidence,
555  ScheduleMessage::Status status )
556 {
557  Q_UNUSED( status );
558 
559  const IncidenceBase *toDelete = mCalendar->incidenceFromSchedulingID( incidence->uid() );
560 
561  bool ret = true;
562  if ( toDelete ) {
563  if ( toDelete->type() == "Event" ) {
564  Event *event = mCalendar->event( toDelete->uid() );
565  ret = ( event && mCalendar->deleteEvent( event ) );
566  } else if ( toDelete->type() == "Todo" ) {
567  Todo *todo = mCalendar->todo( toDelete->uid() );
568  ret = ( todo && mCalendar->deleteTodo( todo ) );
569  }
570  } else {
571  // only complain if we failed to determine the toDelete incidence
572  // on non-initial request.
573  Incidence *inc = static_cast<Incidence *>( incidence );
574  if ( inc->revision() > 0 ) {
575  ret = false;
576  }
577  }
578 
579  if ( !ret ) {
580  KMessageBox::information(
581  0,
582  i18nc( "@info",
583  "The event or task to be canceled could not be removed from your calendar. "
584  "Maybe it has already been deleted or is not owned by you. "
585  "Or it might belong to a read-only or disabled calendar." ) );
586  }
587  deleteTransaction( incidence );
588  return ret;
589 }
590 
591 bool Scheduler::acceptDeclineCounter( IncidenceBase *incidence,
592  ScheduleMessage::Status status )
593 {
594  Q_UNUSED( status );
595  deleteTransaction( incidence );
596  return false;
597 }
598 
599 bool Scheduler::acceptReply( IncidenceBase *incidence,
600  ScheduleMessage::Status status,
601  iTIPMethod method )
602 {
603  Q_UNUSED( status );
604  if ( incidence->type() == "FreeBusy" ) {
605  return acceptFreeBusy( incidence, method );
606  }
607  bool ret = false;
608  Event *ev = mCalendar->event( incidence->uid() );
609  Todo *to = mCalendar->todo( incidence->uid() );
610 
611  // try harder to find the correct incidence
612  if ( !ev && !to ) {
613  const Incidence::List list = mCalendar->incidences();
614  for ( Incidence::List::ConstIterator it=list.constBegin(), end=list.constEnd();
615  it != end; ++it ) {
616  if ( (*it)->schedulingID() == incidence->uid() ) {
617  ev = dynamic_cast<Event*>( *it );
618  to = dynamic_cast<Todo*>( *it );
619  break;
620  }
621  }
622  }
623 
624  if ( ev || to ) {
625  //get matching attendee in calendar
626  kDebug() << "match found!";
627  Attendee::List attendeesIn = incidence->attendees();
628  Attendee::List attendeesEv;
629  Attendee::List attendeesNew;
630  if ( ev ) {
631  attendeesEv = ev->attendees();
632  }
633  if ( to ) {
634  attendeesEv = to->attendees();
635  }
636  Attendee::List::ConstIterator inIt;
637  Attendee::List::ConstIterator evIt;
638  for ( inIt = attendeesIn.constBegin(); inIt != attendeesIn.constEnd(); ++inIt ) {
639  Attendee *attIn = *inIt;
640  bool found = false;
641  for ( evIt = attendeesEv.constBegin(); evIt != attendeesEv.constEnd(); ++evIt ) {
642  Attendee *attEv = *evIt;
643  if ( attIn->email().toLower() == attEv->email().toLower() ) {
644  //update attendee-info
645  kDebug() << "update attendee";
646  attEv->setStatus( attIn->status() );
647  attEv->setDelegate( attIn->delegate() );
648  attEv->setDelegator( attIn->delegator() );
649  ret = true;
650  found = true;
651  }
652  }
653  if ( !found && attIn->status() != Attendee::Declined ) {
654  attendeesNew.append( attIn );
655  }
656  }
657 
658  bool attendeeAdded = false;
659  for ( Attendee::List::ConstIterator it = attendeesNew.constBegin();
660  it != attendeesNew.constEnd(); ++it ) {
661  Attendee *attNew = *it;
662  QString msg =
663  i18nc( "@info", "%1 wants to attend %2 but was not invited.",
664  attNew->fullName(),
665  ( ev ? ev->summary() : to->summary() ) );
666  if ( !attNew->delegator().isEmpty() ) {
667  msg = i18nc( "@info", "%1 wants to attend %2 on behalf of %3.",
668  attNew->fullName(),
669  ( ev ? ev->summary() : to->summary() ), attNew->delegator() );
670  }
671  if ( KMessageBox::questionYesNo(
672  0, msg, i18nc( "@title", "Uninvited attendee" ),
673  KGuiItem( i18nc( "@option", "Accept Attendance" ) ),
674  KGuiItem( i18nc( "@option", "Reject Attendance" ) ) ) != KMessageBox::Yes ) {
675  KCal::Incidence *cancel = dynamic_cast<Incidence*>( incidence );
676  if ( cancel ) {
677  cancel->addComment(
678  i18nc( "@info",
679  "The organizer rejected your attendance at this meeting." ) );
680  }
681  performTransaction( cancel ? cancel : incidence, iTIPCancel, attNew->fullName() );
682  // ### can't delete cancel here because it is aliased to incidence which
683  // is accessed in the next loop iteration (CID 4232)
684  // delete cancel;
685  continue;
686  }
687 
688  Attendee *a = new Attendee( attNew->name(), attNew->email(), attNew->RSVP(),
689  attNew->status(), attNew->role(), attNew->uid() );
690  a->setDelegate( attNew->delegate() );
691  a->setDelegator( attNew->delegator() );
692  if ( ev ) {
693  ev->addAttendee( a );
694  } else if ( to ) {
695  to->addAttendee( a );
696  }
697  ret = true;
698  attendeeAdded = true;
699  }
700 
701  // send update about new participants
702  if ( attendeeAdded ) {
703  bool sendMail = false;
704  if ( ev || to ) {
705  if ( KMessageBox::questionYesNo(
706  0,
707  i18nc( "@info",
708  "An attendee was added to the incidence. "
709  "Do you want to email the attendees an update message?" ),
710  i18nc( "@title", "Attendee Added" ),
711  KGuiItem( i18nc( "@option", "Send Messages" ) ),
712  KGuiItem( i18nc( "@option", "Do Not Send" ) ) ) == KMessageBox::Yes ) {
713  sendMail = true;
714  }
715  }
716 
717  if ( ev ) {
718  ev->setRevision( ev->revision() + 1 );
719  if ( sendMail ) {
720  performTransaction( ev, iTIPRequest );
721  }
722  }
723  if ( to ) {
724  to->setRevision( to->revision() + 1 );
725  if ( sendMail ) {
726  performTransaction( to, iTIPRequest );
727  }
728  }
729  }
730 
731  if ( ret ) {
732  // We set at least one of the attendees, so the incidence changed
733  // Note: This should not result in a sequence number bump
734  if ( ev ) {
735  ev->updated();
736  } else if ( to ) {
737  to->updated();
738  }
739  }
740  if ( to ) {
741  // for VTODO a REPLY can be used to update the completion status of
742  // a to-do. see RFC2446 3.4.3
743  Todo *update = dynamic_cast<Todo*> ( incidence );
744  Q_ASSERT( update );
745  if ( update && ( to->percentComplete() != update->percentComplete() ) ) {
746  to->setPercentComplete( update->percentComplete() );
747  to->updated();
748  }
749  }
750  } else {
751  kError() << "No incidence for scheduling.";
752  }
753 
754  if ( ret ) {
755  deleteTransaction( incidence );
756  }
757  return ret;
758 }
759 
760 bool Scheduler::acceptRefresh( IncidenceBase *incidence, ScheduleMessage::Status status )
761 {
762  Q_UNUSED( status );
763  // handled in korganizer's IncomingDialog
764  deleteTransaction( incidence );
765  return false;
766 }
767 
768 bool Scheduler::acceptCounter( IncidenceBase *incidence, ScheduleMessage::Status status )
769 {
770  Q_UNUSED( status );
771  deleteTransaction( incidence );
772  return false;
773 }
774 
775 bool Scheduler::acceptFreeBusy( IncidenceBase *incidence, iTIPMethod method )
776 {
777  if ( !d->mFreeBusyCache ) {
778  kError() << "KCal::Scheduler: no FreeBusyCache.";
779  return false;
780  }
781 
782  FreeBusy *freebusy = static_cast<FreeBusy *>(incidence);
783 
784  kDebug() << "freeBusyDirName:" << freeBusyDir();
785 
786  Person from;
787  if( method == iTIPPublish ) {
788  from = freebusy->organizer();
789  }
790  if ( ( method == iTIPReply ) && ( freebusy->attendeeCount() == 1 ) ) {
791  Attendee *attendee = freebusy->attendees().first();
792  from.setName( attendee->name() );
793  from.setEmail( attendee->email() );
794  }
795 
796  if ( !d->mFreeBusyCache->saveFreeBusy( freebusy, from ) ) {
797  return false;
798  }
799 
800  deleteTransaction( incidence );
801  return true;
802 }
calendar.h
This file is part of the API for handling calendar data and defines the Calendar class.
calendarresources.h
This file is part of the API for handling calendar data and defines the CalendarResources class.
KCal::AssignmentVisitor
Helper for type correct assignment of incidences via pointers.
Definition: assignmentvisitor.h:55
KCal::AssignmentVisitor::assign
bool assign(IncidenceBase *target, const IncidenceBase *source)
Assigns the incidence referenced by source to the incidence referenced by target, first ensuring that...
Definition: assignmentvisitor.cpp:49
KCal::Attendee
Represents information related to an attendee of an Calendar Incidence, typically a meeting or task (...
Definition: attendee.h:59
KCal::Attendee::email
QString email() const
Returns the email address for this person.
Definition: person.cpp:144
KCal::Attendee::setStatus
void setStatus(PartStat status)
Sets the PartStat of the attendee to status.
Definition: attendee.cpp:120
KCal::Attendee::setDelegator
void setDelegator(const QString &delegator)
Sets the delegator.
Definition: attendee.cpp:245
KCal::Attendee::RSVP
bool RSVP() const
Returns the attendee RSVP flag.
Definition: attendee.cpp:115
KCal::Attendee::name
QString name() const
Returns the person name string.
Definition: person.cpp:139
KCal::Attendee::NeedsAction
@ NeedsAction
Event, to-do or journal needs action (default)
Definition: attendee.h:72
KCal::Attendee::Declined
@ Declined
Event, to-do or journal declined.
Definition: attendee.h:74
KCal::Attendee::setDelegate
void setDelegate(const QString &delegate)
Sets the delegate.
Definition: attendee.cpp:235
KCal::Attendee::delegate
QString delegate() const
Returns the delegate.
Definition: attendee.cpp:240
KCal::Attendee::fullName
QString fullName() const
Returns the full name of this person.
Definition: person.cpp:114
KCal::Attendee::role
Role role() const
Returns the Role of the attendee.
Definition: attendee.cpp:185
KCal::Attendee::delegator
QString delegator() const
Returns the delegator.
Definition: attendee.cpp:250
KCal::Attendee::uid
QString uid() const
Returns the UID of the attendee.
Definition: attendee.cpp:200
KCal::Attendee::status
PartStat status() const
Returns the PartStat of the attendee.
Definition: attendee.cpp:125
KCal::CalFormat::createUniqueId
static QString createUniqueId()
Creates a unique id string.
Definition: calformat.cpp:115
KCal::CalendarResources
This class provides a Calendar which is composed of other Calendars known as "Resources".
Definition: calendarresources.h:59
KCal::CalendarResources::hasCalendarResources
bool hasCalendarResources()
Return true if we have resources configure.
Definition: calendarresources.cpp:619
KCal::CalendarResources::setDialogParentWidget
void setDialogParentWidget(QWidget *parent)
Set the widget parent for new dialogs.
Definition: calendarresources.cpp:352
KCal::CalendarResources::addIncidence
bool addIncidence(Incidence *incidence)
Inserts an Incidence into the calendar.
Definition: calendarresources.cpp:432
KCal::CalendarResources::exception
ErrorFormat * exception()
Returns an exception, if there is any, containing information about the last error that occurred.
Definition: calendarresources.cpp:270
KCal::Calendar
Represents the main calendar class.
Definition: calendar.h:121
KCal::Calendar::addIncidence
virtual bool addIncidence(Incidence *incidence)
Inserts an Incidence into the calendar.
Definition: calendar.cpp:573
KCal::Calendar::incidences
virtual Incidence::List incidences()
Returns a filtered list of all Incidences for this Calendar.
Definition: calendar.cpp:282
KCal::Calendar::todo
virtual Todo * todo(const QString &uid)=0
Returns the Todo associated with the given unique identifier.
KCal::Calendar::event
virtual Event * event(const QString &uid)=0
Returns the Event associated with the given unique identifier.
KCal::Calendar::deleteEvent
virtual bool deleteEvent(Event *event)=0
Removes an Event from the calendar.
KCal::Calendar::incidencesFromSchedulingID
Incidence::List incidencesFromSchedulingID(const QString &sid)
Searches all events and todos for an incidence with this scheduling identifiere.
Definition: calendar.cpp:685
KCal::Calendar::deleteTodo
virtual bool deleteTodo(Todo *todo)=0
Removes a Todo from the calendar.
KCal::Calendar::incidenceFromSchedulingID
Incidence * incidenceFromSchedulingID(const QString &sid)
Returns the Incidence associated with the given scheduling identifier.
Definition: calendar.cpp:698
KCal::Calendar::incidence
Incidence * incidence(const QString &uid)
Returns the Incidence associated with the given unique identifier.
Definition: calendar.cpp:669
KCal::Calendar::timeSpec
KDateTime::Spec timeSpec() const
Get the time specification (time zone etc.) used for creating or modifying incidences in the Calendar...
Definition: calendar.cpp:145
KCal::ErrorFormat
Calendar format related error class.
Definition: exceptions.h:83
KCal::ErrorFormat::NoWritableFound
@ NoWritableFound
No writable resource is available.
Definition: exceptions.h:99
KCal::ErrorFormat::UserCancel
@ UserCancel
User canceled the operation.
Definition: exceptions.h:98
KCal::ErrorFormat::errorCode
ErrorCodeFormat errorCode()
Returns the format error code.
Definition: exceptions.cpp:131
KCal::Event
This class provides an Event in the sense of RFC2445.
Definition: event.h:42
KCal::FreeBusyCache
An abstract base class to allow different implementations of storing free busy information,...
Definition: freebusycache.h:45
KCal::FreeBusy
Provides information about the free/busy time of a calendar.
Definition: freebusy.h:51
KCal::ICalFormat
iCalendar format implementation.
Definition: icalformat.h:53
KCal::ICalFormat::toString
QString toString(Calendar *calendar)
Definition: icalformat.cpp:229
KCal::ICalFormat::setTimeSpec
void setTimeSpec(const KDateTime::Spec &timeSpec)
Sets the iCalendar time specification (time zone, etc.).
Definition: icalformat.cpp:578
KCal::IncidenceBase
An abstract class that provides a common base for all calendar incidence classes.
Definition: incidencebase.h:103
KCal::IncidenceBase::updated
void updated()
Call this to notify the observers after the IncidenceBase object has changed.
Definition: incidencebase.cpp:475
KCal::IncidenceBase::type
virtual QByteArray type() const =0
Prints the type of Incidence as a string.
KCal::IncidenceBase::addComment
void addComment(const QString &comment)
Adds a comment to thieincidence.
Definition: incidencebase.cpp:332
KCal::IncidenceBase::attendees
const Attendee::List & attendees() const
Returns a list of incidence attendees.
Definition: incidencebase.cpp:378
KCal::IncidenceBase::organizer
Person organizer() const
Returns the Person associated with this incidence.
Definition: incidencebase.cpp:230
KCal::IncidenceBase::uid
QString uid() const
Returns the unique id (uid) for the incidence.
Definition: incidencebase.cpp:184
KCal::IncidenceBase::lastModified
KDateTime lastModified() const
Returns the time the incidence was last modified.
Definition: incidencebase.cpp:203
KCal::IncidenceBase::attendeeCount
int attendeeCount() const
Returns the number of incidence attendees.
Definition: incidencebase.cpp:383
KCal::IncidenceBase::setUid
void setUid(const QString &uid)
Returns the type of Incidence as a translated string.
Definition: incidencebase.cpp:178
KCal::IncidenceBase::isReadOnly
bool isReadOnly() const
Returns true the object is read-only; false otherwise.
Definition: incidencebase.h:318
KCal::IncidenceBase::addAttendee
void addAttendee(Attendee *attendee, bool doUpdate=true)
Add Attendee to this incidence.
Definition: incidencebase.cpp:362
KCal::Incidence
Provides the abstract base class common to non-FreeBusy (Events, To-dos, Journals) calendar component...
Definition: incidence.h:70
KCal::Incidence::schedulingID
QString schedulingID() const
Returns the incidence scheduling ID.
Definition: incidence.cpp:986
KCal::Incidence::setSchedulingID
void setSchedulingID(const QString &sid)
Set the incidence scheduling ID.
Definition: incidence.cpp:981
KCal::Incidence::revision
int revision() const
Returns the number of revisions this incidence has seen.
Definition: incidence.cpp:344
KCal::Incidence::summary
QString summary() const
Returns the incidence summary.
Definition: incidence.cpp:424
KCal::Incidence::setRevision
void setRevision(int rev)
Sets the number of revisions this incidence has seen.
Definition: incidence.cpp:333
KCal::ListBase
This class provides a template for lists of pointers.
Definition: listbase.h:45
KCal::Person
Represents a person, by name ane email address.
Definition: person.h:49
KCal::Person::setEmail
void setEmail(const QString &email)
Sets the email address for this person to email.
Definition: person.cpp:159
KCal::Person::fullName
QString fullName() const
Returns the full name of this person.
Definition: person.cpp:114
KCal::Person::setName
void setName(const QString &name)
Sets the name of the person to name.
Definition: person.cpp:154
KCal::ScheduleMessage
A Scheduling message class.
Definition: scheduler.h:59
KCal::ScheduleMessage::ScheduleMessage
ScheduleMessage(IncidenceBase *incidence, iTIPMethod method, Status status)
Creates a scheduling message with method as defined in iTIPMethod and a status.
Definition: scheduler.cpp:55
KCal::ScheduleMessage::~ScheduleMessage
~ScheduleMessage()
Destructor.
Definition: scheduler.cpp:65
KCal::ScheduleMessage::event
IncidenceBase * event()
Returns the event associated with this message.
Definition: scheduler.cpp:70
KCal::ScheduleMessage::error
QString error()
Returns the error message if there is any.
Definition: scheduler.cpp:107
KCal::ScheduleMessage::method
iTIPMethod method()
Returns the iTIP method associated with this message.
Definition: scheduler.cpp:75
KCal::ScheduleMessage::status
Status status()
Returns the status of this message.
Definition: scheduler.cpp:80
KCal::ScheduleMessage::Status
Status
Message status.
Definition: scheduler.h:64
KCal::ScheduleMessage::RequestUpdate
@ RequestUpdate
Request updated message.
Definition: scheduler.h:69
KCal::ScheduleMessage::PublishNew
@ PublishNew
New message posting.
Definition: scheduler.h:65
KCal::ScheduleMessage::RequestNew
@ RequestNew
Request new message posting.
Definition: scheduler.h:68
KCal::ScheduleMessage::PublishUpdate
@ PublishUpdate
Updated message.
Definition: scheduler.h:66
KCal::ScheduleMessage::Obsolete
@ Obsolete
obsolete
Definition: scheduler.h:67
KCal::ScheduleMessage::Unknown
@ Unknown
No status.
Definition: scheduler.h:70
KCal::ScheduleMessage::statusName
static QString statusName(Status status)
Returns a human-readable name for an iTIP message status.
Definition: scheduler.cpp:85
KCal::Scheduler
This class provides an encapsulation of iTIP transactions (RFC 2446).
Definition: scheduler.h:121
KCal::Scheduler::freeBusyCache
FreeBusyCache * freeBusyCache() const
Returns the free/busy cache.
Definition: scheduler.cpp:141
KCal::Scheduler::Scheduler
Scheduler(Calendar *calendar)
Creates a scheduler for calendar specified as argument.
Definition: scheduler.cpp:123
KCal::Scheduler::acceptTransaction
bool KCAL_DEPRECATED acceptTransaction(IncidenceBase *incidence, iTIPMethod method, ScheduleMessage::Status status)
Definition: scheduler.cpp:146
KCal::Scheduler::acceptRequest
bool KCAL_DEPRECATED acceptRequest(IncidenceBase *, ScheduleMessage::Status status)
Definition: scheduler.cpp:282
KCal::Scheduler::methodName
static QString methodName(iTIPMethod method)
Returns a machine-readable name for a iTIP method.
Definition: scheduler.cpp:184
KCal::Scheduler::freeBusyDir
virtual QString freeBusyDir()=0
Returns the directory where the free-busy information is stored.
KCal::Scheduler::setFreeBusyCache
void setFreeBusyCache(FreeBusyCache *)
Sets the free/busy cache used to store free/busy information.
Definition: scheduler.cpp:136
KCal::Scheduler::performTransaction
virtual bool performTransaction(IncidenceBase *incidence, iTIPMethod method)=0
Performs iTIP transaction on incidence.
KCal::Scheduler::translatedMethodName
static QString translatedMethodName(iTIPMethod method)
Returns a translated human-readable name for a iTIP method.
Definition: scheduler.cpp:208
KCal::Todo
Provides a To-do in the sense of RFC2445.
Definition: todo.h:45
KCal::Todo::setPercentComplete
void setPercentComplete(int percent)
Sets what percentage of the to-do is completed.
Definition: todo.cpp:468
KCal::Todo::percentComplete
int percentComplete() const
Returns what percentage of the to-do is completed.
Definition: todo.cpp:463
event.h
This file is part of the API for handling calendar data and defines the Event class.
freebusy.h
This file is part of the API for handling calendar data and defines the FreeBusy class.
freebusycache.h
This file is part of the API for handling calendar data and defines the FreeBusyCache abstract base c...
icalformat.h
This file is part of the API for handling calendar data and defines the ICalFormat class.
todo.h
This file is part of the API for handling calendar data and defines the Todo class.
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Thu Jan 20 2022 00:00:00 by doxygen 1.9.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KCal Library

Skip menu "KCal Library"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepimlibs-4.14.10 API Reference

Skip menu "kdepimlibs-4.14.10 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal