korganizer

koattendeeeditor.cpp
1/*
2 Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
3 Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
4 Copyright (c) 2007 Volker Krause <vkrause@kde.org>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19*/
20
21#include <config.h> // for TDEPIM_NEW_DISTRLISTS
22
23#include "koattendeeeditor.h"
24#include "koprefs.h"
25#include "koglobals.h"
26
27#ifndef KORG_NOKABC
28#include <tdeabc/addresseedialog.h>
29#include <libtdepim/addressesdialog.h>
30#include <libtdepim/addresseelineedit.h>
31#endif
32
33#include <libkcal/incidence.h>
34
35#include <libemailfunctions/email.h>
36
37#ifdef TDEPIM_NEW_DISTRLISTS
38#include "distributionlist.h"
39#else
40#include <tdeabc/distributionlist.h>
41#endif
42#include <tdeabc/stdaddressbook.h>
43
44#include <kiconloader.h>
45#include <tdelocale.h>
46#include <tdemessagebox.h>
47
48#include <tqcheckbox.h>
49#include <tqcombobox.h>
50#include <tqhbox.h>
51#include <tqlabel.h>
52#include <tqlayout.h>
53#include <tqpushbutton.h>
54#include <tqwhatsthis.h>
55
56using namespace KCal;
57
58KOAttendeeEditor::KOAttendeeEditor( TQWidget * parent, const char *name ) :
59 TQWidget( parent, name ),
60 mDisableItemUpdate( true )
61{
62}
63
64void KOAttendeeEditor::initOrganizerWidgets(TQWidget * parent, TQBoxLayout * layout)
65{
66 mOrganizerHBox = new TQHBox( parent );
67 layout->addWidget( mOrganizerHBox );
68 // If creating a new event, then the user is the organizer -> show the
69 // identity combo
70 // readEvent will delete it and set another label text instead, if the user
71 // isn't the organizer.
72 // Note that the i18n text below is duplicated in readEvent
73 TQString whatsThis = i18n("Sets the identity corresponding to "
74 "the organizer of this to-do or event. "
75 "Identities can be set in the 'Personal' "
76 "section of the KOrganizer configuration, or in the "
77 "'Security & Privacy'->'Password & User Account' "
78 "section of the Trinity Control Center. In addition, "
79 "identities are gathered from your KMail settings "
80 "and from your address book. If you choose "
81 "to set it globally for TDE in the Control Center, "
82 "be sure to check 'Use email settings from "
83 "Control Center' in the 'Personal' section of the "
84 "KOrganizer configuration.");
85 mOrganizerLabel = new TQLabel( i18n( "Identity as organizer:" ),
86 mOrganizerHBox );
87 mOrganizerCombo = new TQComboBox( mOrganizerHBox );
88 TQWhatsThis::add( mOrganizerLabel, whatsThis );
89 TQWhatsThis::add( mOrganizerCombo, whatsThis );
90 fillOrganizerCombo();
91 mOrganizerHBox->setStretchFactor( mOrganizerCombo, 100 );
92}
93
94void KOAttendeeEditor::initEditWidgets(TQWidget * parent, TQBoxLayout * layout)
95{
96 TQGridLayout *topLayout = new TQGridLayout();
97 layout->addLayout( topLayout );
98
99 TQString whatsThis = i18n("Edits the name of the attendee selected in the list "
100 "above, or adds a new attendee if there are no attendees"
101 "in the list.");
102 TQLabel *attendeeLabel = new TQLabel( parent );
103 TQWhatsThis::add( attendeeLabel, whatsThis );
104 attendeeLabel->setText( i18n("Na&me:") );
105 topLayout->addWidget( attendeeLabel, 0, 0 );
106
107 mNameEdit = new KPIM::AddresseeLineEdit( parent );
108 TQWhatsThis::add( mNameEdit, whatsThis );
109 mNameEdit->setClickMessage( i18n("Click to add a new attendee") );
110 attendeeLabel->setBuddy( mNameEdit );
111 mNameEdit->installEventFilter( this );
112 connect( mNameEdit, TQ_SIGNAL( textChanged( const TQString & ) ),
113 TQ_SLOT( updateAttendee() ) );
114 connect( mNameEdit, TQ_SIGNAL(returnPressed()), TQ_SLOT(expandAttendee()) );
115 topLayout->addMultiCellWidget( mNameEdit, 0, 0, 1, 2 );
116
117 whatsThis = i18n("Edits the role of the attendee selected "
118 "in the list above.");
119 TQLabel *attendeeRoleLabel = new TQLabel( parent );
120 TQWhatsThis::add( attendeeRoleLabel, whatsThis );
121 attendeeRoleLabel->setText( i18n("Ro&le:") );
122 topLayout->addWidget( attendeeRoleLabel, 1, 0 );
123
124 mRoleCombo = new TQComboBox( false, parent );
125 TQWhatsThis::add( mRoleCombo, whatsThis );
126 mRoleCombo->insertStringList( Attendee::roleList() );
127 attendeeRoleLabel->setBuddy( mRoleCombo );
128 connect( mRoleCombo, TQ_SIGNAL( activated( int ) ),
129 TQ_SLOT( updateAttendee() ) );
130 topLayout->addWidget( mRoleCombo, 1, 1 );
131
132 mDelegateLabel = new TQLabel( parent );
133 topLayout->addWidget( mDelegateLabel, 1, 2 );
134
135 whatsThis = i18n("Edits the current attendance status of the attendee "
136 "selected in the list above.");
137 TQLabel *statusLabel = new TQLabel( parent );
138 TQWhatsThis::add( statusLabel, whatsThis );
139 statusLabel->setText( i18n("Stat&us:") );
140 topLayout->addWidget( statusLabel, 2, 0 );
141
142 mStatusCombo = new TQComboBox( false, parent );
143 TQWhatsThis::add( mStatusCombo, whatsThis );
144// mStatusCombo->insertStringList( Attendee::statusList() );
145 mStatusCombo->insertItem( SmallIcon( "help" ), Attendee::statusName( Attendee::NeedsAction ) );
146 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "ok" ), Attendee::statusName( Attendee::Accepted ) );
147 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "no" ), Attendee::statusName( Attendee::Declined ) );
148 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "apply" ), Attendee::statusName( Attendee::Tentative ) );
149 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "mail-forward" ), Attendee::statusName( Attendee::Delegated ) );
150 mStatusCombo->insertItem( Attendee::statusName( Attendee::Completed ) );
151 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "help" ), Attendee::statusName( Attendee::InProcess ) );
152
153 statusLabel->setBuddy( mStatusCombo );
154 connect( mStatusCombo, TQ_SIGNAL( activated( int ) ),
155 TQ_SLOT( updateAttendee() ) );
156 topLayout->addWidget( mStatusCombo, 2, 1 );
157
158 topLayout->setColStretch( 2, 1 );
159
160 mRsvpButton = new TQCheckBox( parent );
161 TQWhatsThis::add( mRsvpButton,
162 i18n("Edits whether to send an email to the attendee "
163 "selected in the list above to request "
164 "a response concerning attendance.") );
165 mRsvpButton->setText( i18n("Re&quest response") );
166 connect( mRsvpButton, TQ_SIGNAL( clicked() ), TQ_SLOT( updateAttendee() ) );
167 topLayout->addWidget( mRsvpButton, 2, 2 );
168
169 TQWidget *buttonBox = new TQWidget( parent );
170 TQVBoxLayout *buttonLayout = new TQVBoxLayout( buttonBox );
171
172 mAddButton = new TQPushButton( i18n("&New"), buttonBox );
173 TQWhatsThis::add( mAddButton,
174 i18n("Adds a new attendee to the list. Once the "
175 "attendee is added, you will be able to "
176 "edit the attendee's name, role, attendance "
177 "status, and whether or not the attendee is required "
178 "to respond to the invitation. To select an attendee "
179 "from your addressbook, click the 'Select Addressee' "
180 "button instead.") );
181 buttonLayout->addWidget( mAddButton );
182 connect( mAddButton, TQ_SIGNAL( clicked() ), TQ_SLOT( addNewAttendee() ) );
183
184 mRemoveButton = new TQPushButton( i18n("&Remove"), buttonBox );
185 TQWhatsThis::add( mRemoveButton,
186 i18n("Removes the attendee selected in "
187 "the list above.") );
188 buttonLayout->addWidget( mRemoveButton );
189
190 mAddressBookButton = new TQPushButton( i18n("Select Addressee..."),
191 buttonBox );
192 TQWhatsThis::add( mAddressBookButton,
193 i18n("Opens your address book, allowing you to select "
194 "new attendees from it.") );
195 buttonLayout->addWidget( mAddressBookButton );
196 connect( mAddressBookButton, TQ_SIGNAL( clicked() ), TQ_SLOT( openAddressBook() ) );
197
198 topLayout->addMultiCellWidget( buttonBox, 0, 3, 3, 3 );
199
200#ifdef KORG_NOKABC
201 mAddressBookButton->hide();
202#endif
203}
204
205void KOAttendeeEditor::openAddressBook()
206{
207#ifndef KORG_NOKABC
208 KPIM::AddressesDialog *dia = new KPIM::AddressesDialog( this, "adddialog" );
209 dia->setShowCC( false );
210 dia->setShowBCC( false );
211 if ( dia->exec() ) {
212 TDEABC::Addressee::List aList = dia->allToAddressesNoDuplicates();
213 for ( TDEABC::Addressee::List::iterator itr = aList.begin();
214 itr != aList.end(); ++itr ) {
216 }
217 }
218 delete dia;
219 return;
220#endif
221}
222
223void KOAttendeeEditor::insertAttendeeFromAddressee(const TDEABC::Addressee &a, const Attendee * at)
224{
225 bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
226 bool sameAsOrganizer = mOrganizerCombo &&
227 KPIM::compareEmail( a.preferredEmail(), mOrganizerCombo->currentText(), false );
228 KCal::Attendee::PartStat partStat = at? at->status() : KCal::Attendee::NeedsAction;
229 bool rsvp = at? at->RSVP() : true;
230
231 if ( myself && sameAsOrganizer ) {
232 partStat = KCal::Attendee::Accepted;
233 rsvp = false;
234 }
235 Attendee *newAt = new Attendee( a.realName(),
236 a.preferredEmail(),
237 !myself, partStat,
238 at ? at->role() : Attendee::ReqParticipant,
239 a.uid() );
240 newAt->setRSVP( rsvp );
241 insertAttendee( newAt, true );
242 mnewAttendees.append( newAt );
243}
244
245void KOAttendeeEditor::fillOrganizerCombo()
246{
247 Q_ASSERT( mOrganizerCombo );
248 // Get all emails from KOPrefs (coming from various places),
249 // and insert them - removing duplicates
250 const TQStringList lst = KOPrefs::instance()->fullEmails();
251 TQStringList uniqueList;
252 for( TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
253 if ( uniqueList.find( *it ) == uniqueList.end() )
254 uniqueList << *it;
255 }
256 mOrganizerCombo->insertStringList( uniqueList );
257}
258
259void KOAttendeeEditor::addNewAttendee()
260{
261 // check if there's still an unchanged example entry, and if so
262 // suggest to edit that first
263 if ( TQListViewItem* item = hasExampleAttendee() ) {
264 KMessageBox::information( this,
265 i18n( "Please edit the example attendee, before adding more." ), TQString(),
266 "EditExistingExampleAttendeeFirst" );
267 // make sure the example attendee is selected
268 item->setSelected( true );
269 item->listView()->setCurrentItem( item );
270 return;
271 }
272 Attendee *a = new Attendee( i18n("Firstname Lastname"),
273 i18n("name") + "@example.net", true );
274 insertAttendee( a, false );
275 mnewAttendees.append( a );
276 updateAttendeeInput();
277 // We don't want the hint again
278 mNameEdit->setClickMessage( "" );
279 mNameEdit->setFocus();
280 TQTimer::singleShot( 0, mNameEdit, TQ_SLOT( selectAll() ) );
281}
282
283void KOAttendeeEditor::readEvent(KCal::Incidence * incidence)
284{
285 mdelAttendees.clear();
286 mnewAttendees.clear();
287 if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) || incidence->organizer().isEmpty() ) {
288 if ( !mOrganizerCombo ) {
289 mOrganizerCombo = new TQComboBox( mOrganizerHBox );
290 fillOrganizerCombo();
291 }
292 mOrganizerLabel->setText( i18n( "Identity as organizer:" ) );
293
294 int found = -1;
295 TQString fullOrganizer = incidence->organizer().fullName();
296 for ( int i = 0 ; i < mOrganizerCombo->count(); ++i ) {
297 if ( mOrganizerCombo->text( i ) == fullOrganizer ) {
298 found = i;
299 mOrganizerCombo->setCurrentItem( i );
300 break;
301 }
302 }
303 if ( found < 0 ) {
304 mOrganizerCombo->insertItem( fullOrganizer, 0 );
305 mOrganizerCombo->setCurrentItem( 0 );
306 }
307 } else { // someone else is the organizer
308 if ( mOrganizerCombo ) {
309 delete mOrganizerCombo;
310 mOrganizerCombo = 0;
311 }
312 mOrganizerLabel->setText( i18n( "Organizer: %1" ).arg( incidence->organizer().fullName() ) );
313 }
314
315 Attendee::List al = incidence->attendees();
316 Attendee::List::ConstIterator it;
317 Attendee *first = 0;
318 for( it = al.begin(); it != al.end(); ++it ) {
319 Attendee *a = new Attendee( **it );
320 if ( !first ) {
321 first = a;
322 }
323 insertAttendee( a, true );
324 }
325
326 // Set the initial editing values to the first attendee in the list.
327 if ( first ) {
328 // Don't update the item here, the user didn't edit it, so it's not needed.
329 // Also, AttendeeEditor's subclasses didn't set the current Item at this point
330 // so if updateAttendee is called now what will happen is that a random item
331 // will get the text of "first".
332 mDisableItemUpdate = true;
333
334 setSelected( 0 );
335 mNameEdit->setText( first->fullName() );
336 mUid = first->uid();
337 mRoleCombo->setCurrentItem( first->role() );
338 if ( first->status() != KCal::Attendee::None ) {
339 mStatusCombo->setCurrentItem( first->status() );
340 } else {
341 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
342 }
343 mRsvpButton->setChecked( first->RSVP() );
344 mRsvpButton->setEnabled( true );
345 mDisableItemUpdate = false;
346 }
347}
348
349void KOAttendeeEditor::writeEvent(KCal::Incidence * incidence)
350{
351 if ( mOrganizerCombo ) {
352 // TODO: Don't take a string and split it up... Is there a better way?
353 incidence->setOrganizer( mOrganizerCombo->currentText() );
354 }
355}
356
357void KOAttendeeEditor::setEnableAttendeeInput(bool enabled)
358{
359 //mNameEdit->setEnabled( enabled );
360 mRoleCombo->setEnabled( enabled );
361 mStatusCombo->setEnabled( enabled );
362 mRsvpButton->setEnabled( enabled );
363
364 mRemoveButton->setEnabled( enabled );
365}
366
367void KOAttendeeEditor::clearAttendeeInput()
368{
369 mNameEdit->setText("");
370 mUid = TQString();
371 mRoleCombo->setCurrentItem(0);
372 mStatusCombo->setCurrentItem(0);
373 mRsvpButton->setChecked(true);
374 setEnableAttendeeInput( false );
375 mDelegateLabel->setText( TQString() );
376}
377
378void KOAttendeeEditor::expandAttendee()
379{
380 TDEABC::Addressee::List aList = expandDistList( mNameEdit->text() );
381 if ( !aList.isEmpty() ) {
382 int index = selectedIndex();
383 for ( TDEABC::Addressee::List::iterator itr = aList.begin(); itr != aList.end(); ++itr ) {
385 }
386 setSelected( index );
387 removeAttendee( currentAttendee() );
388 }
389}
390
391void KOAttendeeEditor::updateAttendee()
392{
393 Attendee *a = currentAttendee();
394 if ( !a || mDisableItemUpdate )
395 return;
396
397 TQString text = mNameEdit->text();
398 if ( !mNameEdit->text().startsWith( "\"" ) ) {
399 // Quote the text as it might contain commas and other quotable chars.
400 text = KPIM::quoteNameIfNecessary( text );
401 }
402
403 TQString name, email;
404 if ( KPIM::getNameAndMail( text, name, email ) ) {
405 name.remove( '"' );
406 email.remove( '"' ).remove( '>' );
407 } else {
408 name = TQString();
409 email = mNameEdit->text();
410 }
411
412 bool iAmTheOrganizer = mOrganizerCombo &&
413 KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() );
414 if ( iAmTheOrganizer ) {
415 bool myself =
416 KPIM::compareEmail( email, mOrganizerCombo->currentText(), false );
417 bool wasMyself =
418 KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false );
419 if ( myself ) {
420 mRsvpButton->setChecked( false );
421 mRsvpButton->setEnabled( false );
422 } else if ( wasMyself ) {
423 // this was me, but is no longer, reset
424 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
425 mRsvpButton->setChecked( true );
426 mRsvpButton->setEnabled( true );
427 }
428 }
429 a->setName( name );
430 a->setUid( mUid );
431 a->setEmail( email );
432 a->setRole( Attendee::Role( mRoleCombo->currentItem() ) );
433 a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) );
434 a->setRSVP( mRsvpButton->isChecked() );
435
436 updateCurrentItem();
437}
438
439void KOAttendeeEditor::fillAttendeeInput( KCal::Attendee *a )
440{
441 mDisableItemUpdate = true;
442
443 TQString tname, temail;
444 TQString username = a->name();
445 if ( !a->email().isEmpty() ) {
446 username = KPIM::quoteNameIfNecessary( username );
447
448 KPIM::getNameAndMail( username, tname, temail ); // ignore return value
449 // which is always false
450 tname += " <" + a->email() + '>';
451 }
452
453 bool myself = KOPrefs::instance()->thatIsMe( a->email() );
454 bool sameAsOrganizer = mOrganizerCombo &&
455 KPIM::compareEmail( a->email(),
456 mOrganizerCombo->currentText(), false );
457 KCal::Attendee::PartStat partStat = a->status();
458 bool rsvp = a->RSVP();
459
460 if ( myself && sameAsOrganizer && a->status() == KCal::Attendee::None ) {
461 partStat = KCal::Attendee::Accepted;
462 rsvp = false;
463 }
464
465 mNameEdit->setText(tname);
466 mUid = a->uid();
467 mRoleCombo->setCurrentItem(a->role());
468 if ( partStat != KCal::Attendee::None ) {
469 mStatusCombo->setCurrentItem( partStat );
470 } else {
471 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
472 }
473 mRsvpButton->setChecked( rsvp );
474
475 mDisableItemUpdate = false;
476 setEnableAttendeeInput( true );
477
478 if ( a->status() == Attendee::Delegated ) {
479 if ( !a->delegate().isEmpty() )
480 mDelegateLabel->setText( i18n( "Delegated to %1" ).arg( a->delegate() ) );
481 else if ( !a->delegator().isEmpty() )
482 mDelegateLabel->setText( i18n( "Delegated from %1" ).arg( a->delegator() ) );
483 else
484 mDelegateLabel->setText( i18n( "Not delegated" ) );
485 }
486 if( myself )
487 mRsvpButton->setEnabled( false );
488
489}
490
491void KOAttendeeEditor::updateAttendeeInput()
492{
493 setEnableAttendeeInput(!mNameEdit->text().isEmpty());
494 Attendee* a = currentAttendee();
495 if ( a ) {
496 fillAttendeeInput( a );
497 } else {
498 clearAttendeeInput();
499 }
500}
501
503{
504 incidence->clearAttendees();
505
506 if ( mdelAttendees.isEmpty() ) {
507 return;
508 }
509
510 Attendee *att;
511 for ( att = mdelAttendees.first(); att; att = mdelAttendees.next() ) {
512 bool isNewAttendee = false;
513 if ( !mnewAttendees.isEmpty() ) {
514 for ( Attendee *newAtt = mnewAttendees.first(); newAtt; newAtt = mnewAttendees.next() ) {
515 if ( *att == *newAtt ) {
516 isNewAttendee = true;
517 break;
518 }
519 }
520 }
521 if ( !isNewAttendee ) {
522 incidence->addAttendee( new Attendee( *att ) );
523 }
524 }
525 mdelAttendees.clear();
526}
527
528void KOAttendeeEditor::acceptForMe()
529{
530 changeStatusForMe( Attendee::Accepted );
531}
532
533void KOAttendeeEditor::declineForMe()
534{
535 changeStatusForMe( Attendee::Declined );
536}
537
538bool KOAttendeeEditor::eventFilter(TQObject *watched, TQEvent *ev)
539{
540 if ( watched && watched == mNameEdit && ev->type() == TQEvent::FocusIn &&
541 currentAttendee() == 0 ) {
542 addNewAttendee();
543 }
544
545 return TQWidget::eventFilter( watched, ev );
546}
547
548bool KOAttendeeEditor::isExampleAttendee( const KCal::Attendee* attendee ) const
549{
550 if ( !attendee ) return false;
551 if ( attendee->name() == i18n( "Firstname Lastname" )
552 && attendee->email().endsWith( "example.net" ) ) {
553 return true;
554 }
555 return false;
556}
557
558TDEABC::Addressee::List KOAttendeeEditor::expandDistList( const TQString &text ) const
559{
560 TDEABC::Addressee::List aList;
561 TDEABC::AddressBook *abook = TDEABC::StdAddressBook::self( true );
562
563#ifdef TDEPIM_NEW_DISTRLISTS
564 const TQValueList<KPIM::DistributionList::Entry> eList =
565 KPIM::DistributionList::findByName( abook, text ).entries( abook );
566 TQValueList<KPIM::DistributionList::Entry>::ConstIterator eit;
567 for ( eit = eList.begin(); eit != eList.end(); ++eit ) {
568 TDEABC::Addressee a = (*eit).addressee;
569 if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
570 aList.append( a ) ;
571 }
572 }
573
574#else
575 TDEABC::DistributionListManager manager( abook );
576 manager.load();
577 const TQStringList dList = manager.listNames();
578 for ( TQStringList::ConstIterator it = dList.begin(); it != dList.end(); ++it ) {
579 if ( (*it) == text ) {
580 const TQValueList<TDEABC::DistributionList::Entry> eList = manager.list( *it )->entries();
581 TQValueList<TDEABC::DistributionList::Entry>::ConstIterator eit;
582 for ( eit = eList.begin(); eit != eList.end(); ++eit ) {
583 TDEABC::Addressee a = (*eit).addressee;
584 if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
585 aList.append( a ) ;
586 }
587 }
588 }
589 }
590#endif
591 return aList;
592}
593
594
595#include "koattendeeeditor.moc"
void setRole(Role)
void setRSVP(bool r)
TQString uid() const
void setUid(const TQString &)
TQString delegate() const
Role role() const
TQString delegator() const
void setStatus(PartStat s)
bool RSVP() const
PartStat status() const
void setOrganizer(const Person &o)
const Attendee::List & attendees() const
void addAttendee(Attendee *attendee, bool doUpdate=true)
void insertAttendeeFromAddressee(const TDEABC::Addressee &a, const KCal::Attendee *at=0)
Reads values from a TDEABC::Addressee and inserts a new Attendee item into the listview with those it...
void cancelAttendeeEvent(KCal::Incidence *incidence)
return a clone of the event with attendees to be canceld