00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include "koattendeeeditor.h"
00024 #include "koprefs.h"
00025 #include "koglobals.h"
00026
00027 #ifndef KORG_NOKABC
00028 #include <kabc/addresseedialog.h>
00029 #include <libkdepim/addressesdialog.h>
00030 #include <libkdepim/addresseelineedit.h>
00031 #endif
00032
00033 #include <libkcal/incidence.h>
00034
00035 #include <libemailfunctions/email.h>
00036
00037 #ifdef KDEPIM_NEW_DISTRLISTS
00038 #include "distributionlist.h"
00039 #else
00040 #include <kabc/distributionlist.h>
00041 #endif
00042 #include <kabc/stdaddressbook.h>
00043
00044 #include <kiconloader.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047
00048 #include <tqcheckbox.h>
00049 #include <tqcombobox.h>
00050 #include <tqhbox.h>
00051 #include <tqlabel.h>
00052 #include <tqlayout.h>
00053 #include <tqpushbutton.h>
00054 #include <tqwhatsthis.h>
00055
00056 using namespace KCal;
00057
00058 KOAttendeeEditor::KOAttendeeEditor( TQWidget * parent, const char *name ) :
00059 TQWidget( parent, name ),
00060 mDisableItemUpdate( true )
00061 {
00062 }
00063
00064 void KOAttendeeEditor::initOrganizerWidgets(TQWidget * parent, TQBoxLayout * layout)
00065 {
00066 mOrganizerHBox = new TQHBox( parent );
00067 layout->addWidget( mOrganizerHBox );
00068
00069
00070
00071
00072
00073 TQString whatsThis = i18n("Sets the identity corresponding to "
00074 "the organizer of this to-do or event. "
00075 "Identities can be set in the 'Personal' "
00076 "section of the KOrganizer configuration, or in the "
00077 "'Security & Privacy'->'Password & User Account' "
00078 "section of the KDE Control Center. In addition, "
00079 "identities are gathered from your KMail settings "
00080 "and from your address book. If you choose "
00081 "to set it globally for KDE in the Control Center, "
00082 "be sure to check 'Use email settings from "
00083 "Control Center' in the 'Personal' section of the "
00084 "KOrganizer configuration.");
00085 mOrganizerLabel = new TQLabel( i18n( "Identity as organizer:" ),
00086 mOrganizerHBox );
00087 mOrganizerCombo = new TQComboBox( mOrganizerHBox );
00088 TQWhatsThis::add( mOrganizerLabel, whatsThis );
00089 TQWhatsThis::add( mOrganizerCombo, whatsThis );
00090 fillOrganizerCombo();
00091 mOrganizerHBox->setStretchFactor( mOrganizerCombo, 100 );
00092 }
00093
00094 void KOAttendeeEditor::initEditWidgets(TQWidget * parent, TQBoxLayout * layout)
00095 {
00096 TQGridLayout *topLayout = new TQGridLayout();
00097 layout->addLayout( topLayout );
00098
00099 TQString whatsThis = i18n("Edits the name of the attendee selected in the list "
00100 "above, or adds a new attendee if there are no attendees"
00101 "in the list.");
00102 TQLabel *attendeeLabel = new TQLabel( parent );
00103 TQWhatsThis::add( attendeeLabel, whatsThis );
00104 attendeeLabel->setText( i18n("Na&me:") );
00105 topLayout->addWidget( attendeeLabel, 0, 0 );
00106
00107 mNameEdit = new KPIM::AddresseeLineEdit( parent );
00108 TQWhatsThis::add( mNameEdit, whatsThis );
00109 mNameEdit->setClickMessage( i18n("Click to add a new attendee") );
00110 attendeeLabel->setBuddy( mNameEdit );
00111 mNameEdit->installEventFilter( this );
00112 connect( mNameEdit, TQT_SIGNAL( textChanged( const TQString & ) ),
00113 TQT_SLOT( updateAttendee() ) );
00114 connect( mNameEdit, TQT_SIGNAL(returnPressed()), TQT_SLOT(expandAttendee()) );
00115 topLayout->addMultiCellWidget( mNameEdit, 0, 0, 1, 2 );
00116
00117 whatsThis = i18n("Edits the role of the attendee selected "
00118 "in the list above.");
00119 TQLabel *attendeeRoleLabel = new TQLabel( parent );
00120 TQWhatsThis::add( attendeeRoleLabel, whatsThis );
00121 attendeeRoleLabel->setText( i18n("Ro&le:") );
00122 topLayout->addWidget( attendeeRoleLabel, 1, 0 );
00123
00124 mRoleCombo = new TQComboBox( false, parent );
00125 TQWhatsThis::add( mRoleCombo, whatsThis );
00126 mRoleCombo->insertStringList( Attendee::roleList() );
00127 attendeeRoleLabel->setBuddy( mRoleCombo );
00128 connect( mRoleCombo, TQT_SIGNAL( activated( int ) ),
00129 TQT_SLOT( updateAttendee() ) );
00130 topLayout->addWidget( mRoleCombo, 1, 1 );
00131
00132 mDelegateLabel = new TQLabel( parent );
00133 topLayout->addWidget( mDelegateLabel, 1, 2 );
00134
00135 whatsThis = i18n("Edits the current attendance status of the attendee "
00136 "selected in the list above.");
00137 TQLabel *statusLabel = new TQLabel( parent );
00138 TQWhatsThis::add( statusLabel, whatsThis );
00139 statusLabel->setText( i18n("Stat&us:") );
00140 topLayout->addWidget( statusLabel, 2, 0 );
00141
00142 mStatusCombo = new TQComboBox( false, parent );
00143 TQWhatsThis::add( mStatusCombo, whatsThis );
00144
00145 mStatusCombo->insertItem( SmallIcon( "help" ), Attendee::statusName( Attendee::NeedsAction ) );
00146 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "ok" ), Attendee::statusName( Attendee::Accepted ) );
00147 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "no" ), Attendee::statusName( Attendee::Declined ) );
00148 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "apply" ), Attendee::statusName( Attendee::Tentative ) );
00149 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "mail_forward" ), Attendee::statusName( Attendee::Delegated ) );
00150 mStatusCombo->insertItem( Attendee::statusName( Attendee::Completed ) );
00151 mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "help" ), Attendee::statusName( Attendee::InProcess ) );
00152
00153 statusLabel->setBuddy( mStatusCombo );
00154 connect( mStatusCombo, TQT_SIGNAL( activated( int ) ),
00155 TQT_SLOT( updateAttendee() ) );
00156 topLayout->addWidget( mStatusCombo, 2, 1 );
00157
00158 topLayout->setColStretch( 2, 1 );
00159
00160 mRsvpButton = new TQCheckBox( parent );
00161 TQWhatsThis::add( mRsvpButton,
00162 i18n("Edits whether to send an email to the attendee "
00163 "selected in the list above to request "
00164 "a response concerning attendance.") );
00165 mRsvpButton->setText( i18n("Re&quest response") );
00166 connect( mRsvpButton, TQT_SIGNAL( clicked() ), TQT_SLOT( updateAttendee() ) );
00167 topLayout->addWidget( mRsvpButton, 2, 2 );
00168
00169 TQWidget *buttonBox = new TQWidget( parent );
00170 TQVBoxLayout *buttonLayout = new TQVBoxLayout( buttonBox );
00171
00172 mAddButton = new TQPushButton( i18n("&New"), buttonBox );
00173 TQWhatsThis::add( mAddButton,
00174 i18n("Adds a new attendee to the list. Once the "
00175 "attendee is added, you will be able to "
00176 "edit the attendee's name, role, attendance "
00177 "status, and whether or not the attendee is required "
00178 "to respond to the invitation. To select an attendee "
00179 "from your addressbook, click the 'Select Addressee' "
00180 "button instead.") );
00181 buttonLayout->addWidget( mAddButton );
00182 connect( mAddButton, TQT_SIGNAL( clicked() ), TQT_SLOT( addNewAttendee() ) );
00183
00184 mRemoveButton = new TQPushButton( i18n("&Remove"), buttonBox );
00185 TQWhatsThis::add( mRemoveButton,
00186 i18n("Removes the attendee selected in "
00187 "the list above.") );
00188 buttonLayout->addWidget( mRemoveButton );
00189
00190 mAddressBookButton = new TQPushButton( i18n("Select Addressee..."),
00191 buttonBox );
00192 TQWhatsThis::add( mAddressBookButton,
00193 i18n("Opens your address book, allowing you to select "
00194 "new attendees from it.") );
00195 buttonLayout->addWidget( mAddressBookButton );
00196 connect( mAddressBookButton, TQT_SIGNAL( clicked() ), TQT_SLOT( openAddressBook() ) );
00197
00198 topLayout->addMultiCellWidget( buttonBox, 0, 3, 3, 3 );
00199
00200 #ifdef KORG_NOKABC
00201 mAddressBookButton->hide();
00202 #endif
00203 }
00204
00205 void KOAttendeeEditor::openAddressBook()
00206 {
00207 #ifndef KORG_NOKABC
00208 KPIM::AddressesDialog *dia = new KPIM::AddressesDialog( this, "adddialog" );
00209 dia->setShowCC( false );
00210 dia->setShowBCC( false );
00211 if ( dia->exec() ) {
00212 KABC::Addressee::List aList = dia->allToAddressesNoDuplicates();
00213 for ( KABC::Addressee::List::iterator itr = aList.begin();
00214 itr != aList.end(); ++itr ) {
00215 insertAttendeeFromAddressee( (*itr) );
00216 }
00217 }
00218 delete dia;
00219 return;
00220 #endif
00221 }
00222
00223 void KOAttendeeEditor::insertAttendeeFromAddressee(const KABC::Addressee &a, const Attendee * at)
00224 {
00225 bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
00226 bool sameAsOrganizer = mOrganizerCombo &&
00227 KPIM::compareEmail( a.preferredEmail(), mOrganizerCombo->currentText(), false );
00228 KCal::Attendee::PartStat partStat = at? at->status() : KCal::Attendee::NeedsAction;
00229 bool rsvp = at? at->RSVP() : true;
00230
00231 if ( myself && sameAsOrganizer ) {
00232 partStat = KCal::Attendee::Accepted;
00233 rsvp = false;
00234 }
00235 Attendee *newAt = new Attendee( a.realName(),
00236 a.preferredEmail(),
00237 !myself, partStat,
00238 at ? at->role() : Attendee::ReqParticipant,
00239 a.uid() );
00240 newAt->setRSVP( rsvp );
00241 insertAttendee( newAt, true );
00242 mnewAttendees.append( newAt );
00243 }
00244
00245 void KOAttendeeEditor::fillOrganizerCombo()
00246 {
00247 Q_ASSERT( mOrganizerCombo );
00248
00249
00250 const TQStringList lst = KOPrefs::instance()->fullEmails();
00251 TQStringList uniqueList;
00252 for( TQStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
00253 if ( uniqueList.find( *it ) == uniqueList.end() )
00254 uniqueList << *it;
00255 }
00256 mOrganizerCombo->insertStringList( uniqueList );
00257 }
00258
00259 void KOAttendeeEditor::addNewAttendee()
00260 {
00261
00262
00263 if ( TQListViewItem* item = hasExampleAttendee() ) {
00264 KMessageBox::information( this,
00265 i18n( "Please edit the example attendee, before adding more." ), TQString::null,
00266 "EditExistingExampleAttendeeFirst" );
00267
00268 item->setSelected( true );
00269 item->listView()->setCurrentItem( item );
00270 return;
00271 }
00272 Attendee *a = new Attendee( i18n("Firstname Lastname"),
00273 i18n("name") + "@example.net", true );
00274 insertAttendee( a, false );
00275 mnewAttendees.append( a );
00276 updateAttendeeInput();
00277
00278 mNameEdit->setClickMessage( "" );
00279 mNameEdit->setFocus();
00280 TQTimer::singleShot( 0, mNameEdit, TQT_SLOT( selectAll() ) );
00281 }
00282
00283 void KOAttendeeEditor::readEvent(KCal::Incidence * incidence)
00284 {
00285 mdelAttendees.clear();
00286 mnewAttendees.clear();
00287 if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) || incidence->organizer().isEmpty() ) {
00288 if ( !mOrganizerCombo ) {
00289 mOrganizerCombo = new TQComboBox( mOrganizerHBox );
00290 fillOrganizerCombo();
00291 }
00292 mOrganizerLabel->setText( i18n( "Identity as organizer:" ) );
00293
00294 int found = -1;
00295 TQString fullOrganizer = incidence->organizer().fullName();
00296 for ( int i = 0 ; i < mOrganizerCombo->count(); ++i ) {
00297 if ( mOrganizerCombo->text( i ) == fullOrganizer ) {
00298 found = i;
00299 mOrganizerCombo->setCurrentItem( i );
00300 break;
00301 }
00302 }
00303 if ( found < 0 ) {
00304 mOrganizerCombo->insertItem( fullOrganizer, 0 );
00305 mOrganizerCombo->setCurrentItem( 0 );
00306 }
00307 } else {
00308 if ( mOrganizerCombo ) {
00309 delete mOrganizerCombo;
00310 mOrganizerCombo = 0;
00311 }
00312 mOrganizerLabel->setText( i18n( "Organizer: %1" ).arg( incidence->organizer().fullName() ) );
00313 }
00314
00315 Attendee::List al = incidence->attendees();
00316 Attendee::List::ConstIterator it;
00317 Attendee *first = 0;
00318 for( it = al.begin(); it != al.end(); ++it ) {
00319 Attendee *a = new Attendee( **it );
00320 if ( !first ) {
00321 first = a;
00322 }
00323 insertAttendee( a, true );
00324 }
00325
00326
00327 if ( first ) {
00328
00329
00330
00331
00332 mDisableItemUpdate = true;
00333
00334 setSelected( 0 );
00335 mNameEdit->setText( first->fullName() );
00336 mUid = first->uid();
00337 mRoleCombo->setCurrentItem( first->role() );
00338 if ( first->status() != KCal::Attendee::None ) {
00339 mStatusCombo->setCurrentItem( first->status() );
00340 } else {
00341 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
00342 }
00343 mRsvpButton->setChecked( first->RSVP() );
00344 mRsvpButton->setEnabled( true );
00345 mDisableItemUpdate = false;
00346 }
00347 }
00348
00349 void KOAttendeeEditor::writeEvent(KCal::Incidence * incidence)
00350 {
00351 if ( mOrganizerCombo ) {
00352
00353 incidence->setOrganizer( mOrganizerCombo->currentText() );
00354 }
00355 }
00356
00357 void KOAttendeeEditor::setEnableAttendeeInput(bool enabled)
00358 {
00359
00360 mRoleCombo->setEnabled( enabled );
00361 mStatusCombo->setEnabled( enabled );
00362 mRsvpButton->setEnabled( enabled );
00363
00364 mRemoveButton->setEnabled( enabled );
00365 }
00366
00367 void KOAttendeeEditor::clearAttendeeInput()
00368 {
00369 mNameEdit->setText("");
00370 mUid = TQString::null;
00371 mRoleCombo->setCurrentItem(0);
00372 mStatusCombo->setCurrentItem(0);
00373 mRsvpButton->setChecked(true);
00374 setEnableAttendeeInput( false );
00375 mDelegateLabel->setText( TQString() );
00376 }
00377
00378 void KOAttendeeEditor::expandAttendee()
00379 {
00380 KABC::Addressee::List aList = expandDistList( mNameEdit->text() );
00381 if ( !aList.isEmpty() ) {
00382 int index = selectedIndex();
00383 for ( KABC::Addressee::List::iterator itr = aList.begin(); itr != aList.end(); ++itr ) {
00384 insertAttendeeFromAddressee( (*itr) );
00385 }
00386 setSelected( index );
00387 removeAttendee( currentAttendee() );
00388 }
00389 }
00390
00391 void KOAttendeeEditor::updateAttendee()
00392 {
00393 Attendee *a = currentAttendee();
00394 if ( !a || mDisableItemUpdate )
00395 return;
00396
00397 TQString text = mNameEdit->text();
00398 if ( !mNameEdit->text().startsWith( "\"" ) ) {
00399
00400 text = KPIM::quoteNameIfNecessary( text );
00401 }
00402
00403 TQString name, email;
00404 if ( KPIM::getNameAndMail( text, name, email ) ) {
00405 name.remove( '"' );
00406 email.remove( '"' ).remove( '>' );
00407 } else {
00408 name = TQString();
00409 email = mNameEdit->text();
00410 }
00411
00412 bool iAmTheOrganizer = mOrganizerCombo &&
00413 KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() );
00414 if ( iAmTheOrganizer ) {
00415 bool myself =
00416 KPIM::compareEmail( email, mOrganizerCombo->currentText(), false );
00417 bool wasMyself =
00418 KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false );
00419 if ( myself ) {
00420 mRsvpButton->setChecked( false );
00421 mRsvpButton->setEnabled( false );
00422 } else if ( wasMyself ) {
00423
00424 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
00425 mRsvpButton->setChecked( true );
00426 mRsvpButton->setEnabled( true );
00427 }
00428 }
00429 a->setName( name );
00430 a->setUid( mUid );
00431 a->setEmail( email );
00432 a->setRole( Attendee::Role( mRoleCombo->currentItem() ) );
00433 a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) );
00434 a->setRSVP( mRsvpButton->isChecked() );
00435
00436 updateCurrentItem();
00437 }
00438
00439 void KOAttendeeEditor::fillAttendeeInput( KCal::Attendee *a )
00440 {
00441 mDisableItemUpdate = true;
00442
00443 TQString tname, temail;
00444 TQString username = a->name();
00445 if ( !a->email().isEmpty() ) {
00446 username = KPIM::quoteNameIfNecessary( username );
00447
00448 KPIM::getNameAndMail( username, tname, temail );
00449
00450 tname += " <" + a->email() + '>';
00451 }
00452
00453 bool myself = KOPrefs::instance()->thatIsMe( a->email() );
00454 bool sameAsOrganizer = mOrganizerCombo &&
00455 KPIM::compareEmail( a->email(),
00456 mOrganizerCombo->currentText(), false );
00457 KCal::Attendee::PartStat partStat = a->status();
00458 bool rsvp = a->RSVP();
00459
00460 if ( myself && sameAsOrganizer && a->status() == KCal::Attendee::None ) {
00461 partStat = KCal::Attendee::Accepted;
00462 rsvp = false;
00463 }
00464
00465 mNameEdit->setText(tname);
00466 mUid = a->uid();
00467 mRoleCombo->setCurrentItem(a->role());
00468 if ( partStat != KCal::Attendee::None ) {
00469 mStatusCombo->setCurrentItem( partStat );
00470 } else {
00471 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
00472 }
00473 mRsvpButton->setChecked( rsvp );
00474
00475 mDisableItemUpdate = false;
00476 setEnableAttendeeInput( true );
00477
00478 if ( a->status() == Attendee::Delegated ) {
00479 if ( !a->delegate().isEmpty() )
00480 mDelegateLabel->setText( i18n( "Delegated to %1" ).arg( a->delegate() ) );
00481 else if ( !a->delegator().isEmpty() )
00482 mDelegateLabel->setText( i18n( "Delegated from %1" ).arg( a->delegator() ) );
00483 else
00484 mDelegateLabel->setText( i18n( "Not delegated" ) );
00485 }
00486 if( myself )
00487 mRsvpButton->setEnabled( false );
00488
00489 }
00490
00491 void KOAttendeeEditor::updateAttendeeInput()
00492 {
00493 setEnableAttendeeInput(!mNameEdit->text().isEmpty());
00494 Attendee* a = currentAttendee();
00495 if ( a ) {
00496 fillAttendeeInput( a );
00497 } else {
00498 clearAttendeeInput();
00499 }
00500 }
00501
00502 void KOAttendeeEditor::cancelAttendeeEvent( KCal::Incidence *incidence )
00503 {
00504 incidence->clearAttendees();
00505
00506 if ( mdelAttendees.isEmpty() ) {
00507 return;
00508 }
00509
00510 Attendee *att;
00511 for ( att = mdelAttendees.first(); att; att = mdelAttendees.next() ) {
00512 bool isNewAttendee = false;
00513 if ( !mnewAttendees.isEmpty() ) {
00514 for ( Attendee *newAtt = mnewAttendees.first(); newAtt; newAtt = mnewAttendees.next() ) {
00515 if ( *att == *newAtt ) {
00516 isNewAttendee = true;
00517 break;
00518 }
00519 }
00520 }
00521 if ( !isNewAttendee ) {
00522 incidence->addAttendee( new Attendee( *att ) );
00523 }
00524 }
00525 mdelAttendees.clear();
00526 }
00527
00528 void KOAttendeeEditor::acceptForMe()
00529 {
00530 changeStatusForMe( Attendee::Accepted );
00531 }
00532
00533 void KOAttendeeEditor::declineForMe()
00534 {
00535 changeStatusForMe( Attendee::Declined );
00536 }
00537
00538 bool KOAttendeeEditor::eventFilter(TQObject *watched, TQEvent *ev)
00539 {
00540 if ( watched && watched == mNameEdit && ev->type() == TQEvent::FocusIn &&
00541 currentAttendee() == 0 ) {
00542 addNewAttendee();
00543 }
00544
00545 return TQWidget::eventFilter( watched, ev );
00546 }
00547
00548 bool KOAttendeeEditor::isExampleAttendee( const KCal::Attendee* attendee ) const
00549 {
00550 if ( !attendee ) return false;
00551 if ( attendee->name() == i18n( "Firstname Lastname" )
00552 && attendee->email().endsWith( "example.net" ) ) {
00553 return true;
00554 }
00555 return false;
00556 }
00557
00558 KABC::Addressee::List KOAttendeeEditor::expandDistList( const TQString &text ) const
00559 {
00560 KABC::Addressee::List aList;
00561 KABC::AddressBook *abook = KABC::StdAddressBook::self( true );
00562
00563 #ifdef KDEPIM_NEW_DISTRLISTS
00564 const TQValueList<KPIM::DistributionList::Entry> eList =
00565 KPIM::DistributionList::findByName( abook, text ).entries( abook );
00566 TQValueList<KPIM::DistributionList::Entry>::ConstIterator eit;
00567 for ( eit = eList.begin(); eit != eList.end(); ++eit ) {
00568 KABC::Addressee a = (*eit).addressee;
00569 if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
00570 aList.append( a ) ;
00571 }
00572 }
00573
00574 #else
00575 KABC::DistributionListManager manager( abook );
00576 manager.load();
00577 const TQStringList dList = manager.listNames();
00578 for ( TQStringList::ConstIterator it = dList.begin(); it != dList.end(); ++it ) {
00579 if ( (*it) == text ) {
00580 const TQValueList<KABC::DistributionList::Entry> eList = manager.list( *it )->entries();
00581 TQValueList<KABC::DistributionList::Entry>::ConstIterator eit;
00582 for ( eit = eList.begin(); eit != eList.end(); ++eit ) {
00583 KABC::Addressee a = (*eit).addressee;
00584 if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
00585 aList.append( a ) ;
00586 }
00587 }
00588 }
00589 }
00590 #endif
00591 return aList;
00592 }
00593
00594
00595 #include "koattendeeeditor.moc"