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