korganizer

koattendeeeditor.cpp

00001 /*
00002     Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org>
00003     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00004     Copyright (c) 2007 Volker Krause <vkrause@kde.org>
00005 
00006         This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
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 
00038 #include <qcheckbox.h>
00039 #include <qcombobox.h>
00040 #include <qhbox.h>
00041 #include <qlabel.h>
00042 #include <qlayout.h>
00043 #include <qpushbutton.h>
00044 #include <qwhatsthis.h>
00045 
00046 using namespace KCal;
00047 
00048 KOAttendeeEditor::KOAttendeeEditor( QWidget * parent, const char *name ) :
00049     QWidget( parent, name ),
00050     mDisableItemUpdate( true )
00051 {
00052 }
00053 
00054 void KOAttendeeEditor::initOrganizerWidgets(QWidget * parent, QBoxLayout * layout)
00055 {
00056   mOrganizerHBox = new QHBox( parent );
00057   layout->addWidget( mOrganizerHBox );
00058   // If creating a new event, then the user is the organizer -> show the
00059   // identity combo
00060   // readEvent will delete it and set another label text instead, if the user
00061   // isn't the organizer.
00062   // Note that the i18n text below is duplicated in readEvent
00063   QString whatsThis = i18n("Sets the identity corresponding to "
00064                            "the organizer of this to-do or event. "
00065                            "Identities can be set in the 'Personal' "
00066                            "section of the KOrganizer configuration, or in the "
00067                            "'Security & Privacy'->'Password & User Account' "
00068                            "section of the KDE Control Center. In addition, "
00069                            "identities are gathered from your KMail settings "
00070                            "and from your address book. If you choose "
00071                            "to set it globally for KDE in the Control Center, "
00072                            "be sure to check 'Use email settings from "
00073                            "Control Center' in the 'Personal' section of the "
00074                            "KOrganizer configuration.");
00075   mOrganizerLabel = new QLabel( i18n( "Identity as organizer:" ),
00076                                 mOrganizerHBox );
00077   mOrganizerCombo = new QComboBox( mOrganizerHBox );
00078   QWhatsThis::add( mOrganizerLabel, whatsThis );
00079   QWhatsThis::add( mOrganizerCombo, whatsThis );
00080   fillOrganizerCombo();
00081   mOrganizerHBox->setStretchFactor( mOrganizerCombo, 100 );
00082 }
00083 
00084 void KOAttendeeEditor::initEditWidgets(QWidget * parent, QBoxLayout * layout)
00085 {
00086   QGridLayout *topLayout = new QGridLayout();
00087   layout->addLayout( topLayout );
00088 
00089   QString whatsThis = i18n("Edits the name of the attendee selected in the list "
00090                            "above, or adds a new attendee if there are no attendees"
00091                            "in the list.");
00092   QLabel *attendeeLabel = new QLabel( parent );
00093   QWhatsThis::add( attendeeLabel, whatsThis );
00094   attendeeLabel->setText( i18n("Na&me:") );
00095   topLayout->addWidget( attendeeLabel, 0, 0 );
00096 
00097   mNameEdit = new KPIM::AddresseeLineEdit( parent );
00098   QWhatsThis::add( mNameEdit, whatsThis );
00099   mNameEdit->setClickMessage( i18n("Click to add a new attendee") );
00100   attendeeLabel->setBuddy( mNameEdit );
00101   mNameEdit->installEventFilter( this );
00102   connect( mNameEdit, SIGNAL( textChanged( const QString & ) ),
00103            SLOT( updateAttendee() ) );
00104   topLayout->addMultiCellWidget( mNameEdit, 0, 0, 1, 2 );
00105 
00106   whatsThis = i18n("Edits the role of the attendee selected "
00107                    "in the list above.");
00108   QLabel *attendeeRoleLabel = new QLabel( parent );
00109   QWhatsThis::add( attendeeRoleLabel, whatsThis );
00110   attendeeRoleLabel->setText( i18n("Ro&le:") );
00111   topLayout->addWidget( attendeeRoleLabel, 1, 0 );
00112 
00113   mRoleCombo = new QComboBox( false, parent );
00114   QWhatsThis::add( mRoleCombo, whatsThis );
00115   mRoleCombo->insertStringList( Attendee::roleList() );
00116   attendeeRoleLabel->setBuddy( mRoleCombo );
00117   connect( mRoleCombo, SIGNAL( activated( int ) ),
00118            SLOT( updateAttendee() ) );
00119   topLayout->addWidget( mRoleCombo, 1, 1 );
00120 
00121   mDelegateLabel = new QLabel( parent );
00122   topLayout->addWidget( mDelegateLabel, 1, 2 );
00123 
00124   whatsThis = i18n("Edits the current attendance status of the attendee "
00125                    "selected in the list above.");
00126   QLabel *statusLabel = new QLabel( parent );
00127   QWhatsThis::add( statusLabel, whatsThis );
00128   statusLabel->setText( i18n("Stat&us:") );
00129   topLayout->addWidget( statusLabel, 2, 0 );
00130 
00131   mStatusCombo = new QComboBox( false, parent );
00132   QWhatsThis::add( mStatusCombo, whatsThis );
00133 //   mStatusCombo->insertStringList( Attendee::statusList() );
00134   mStatusCombo->insertItem( SmallIcon( "help" ), Attendee::statusName( Attendee::NeedsAction ) );
00135   mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "ok" ), Attendee::statusName( Attendee::Accepted ) );
00136   mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "no" ), Attendee::statusName( Attendee::Declined ) );
00137   mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "apply" ), Attendee::statusName( Attendee::Tentative ) );
00138   mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "mail_forward" ), Attendee::statusName( Attendee::Delegated ) );
00139   mStatusCombo->insertItem( Attendee::statusName( Attendee::Completed ) );
00140   mStatusCombo->insertItem( KOGlobals::self()->smallIcon( "help" ), Attendee::statusName( Attendee::InProcess ) );
00141 
00142   statusLabel->setBuddy( mStatusCombo );
00143   connect( mStatusCombo, SIGNAL( activated( int ) ),
00144            SLOT( updateAttendee() ) );
00145   topLayout->addWidget( mStatusCombo, 2, 1 );
00146 
00147   topLayout->setColStretch( 2, 1 );
00148 
00149   mRsvpButton = new QCheckBox( parent );
00150   QWhatsThis::add( mRsvpButton,
00151            i18n("Edits whether to send an email to the attendee "
00152             "selected in the list above to request "
00153             "a response concerning attendance.") );
00154   mRsvpButton->setText( i18n("Re&quest response") );
00155   connect( mRsvpButton, SIGNAL( clicked() ), SLOT( updateAttendee() ) );
00156   topLayout->addWidget( mRsvpButton, 2, 2 );
00157 
00158   QWidget *buttonBox = new QWidget( parent );
00159   QVBoxLayout *buttonLayout = new QVBoxLayout( buttonBox );
00160 
00161   mAddButton = new QPushButton( i18n("&New"), buttonBox );
00162   QWhatsThis::add( mAddButton,
00163            i18n("Adds a new attendee to the list. Once the "
00164             "attendee is added, you will be able to "
00165             "edit the attendee's name, role, attendance "
00166             "status, and whether or not the attendee is required "
00167             "to respond to the invitation. To select an attendee "
00168             "from your addressbook, click the 'Select Addressee' "
00169             "button instead.") );
00170   buttonLayout->addWidget( mAddButton );
00171   connect( mAddButton, SIGNAL( clicked() ), SLOT( addNewAttendee() ) );
00172 
00173   mRemoveButton = new QPushButton( i18n("&Remove"), buttonBox );
00174   QWhatsThis::add( mRemoveButton,
00175            i18n("Removes the attendee selected in "
00176             "the list above.") );
00177   buttonLayout->addWidget( mRemoveButton );
00178 
00179   mAddressBookButton = new QPushButton( i18n("Select Addressee..."),
00180                                         buttonBox );
00181   QWhatsThis::add( mAddressBookButton,
00182            i18n("Opens your address book, allowing you to select "
00183             "new attendees from it.") );
00184   buttonLayout->addWidget( mAddressBookButton );
00185   connect( mAddressBookButton, SIGNAL( clicked() ), SLOT( openAddressBook() ) );
00186 
00187   topLayout->addMultiCellWidget( buttonBox, 0, 3, 3, 3 );
00188 
00189 #ifdef KORG_NOKABC
00190   mAddressBookButton->hide();
00191 #endif
00192 }
00193 
00194 void KOAttendeeEditor::openAddressBook()
00195 {
00196 #ifndef KORG_NOKABC
00197   KPIM::AddressesDialog *dia = new KPIM::AddressesDialog( this, "adddialog" );
00198   dia->setShowCC( false );
00199   dia->setShowBCC( false );
00200   if ( dia->exec() ) {
00201     KABC::Addressee::List aList = dia->allToAddressesNoDuplicates();
00202     for ( KABC::Addressee::List::iterator itr = aList.begin();
00203           itr != aList.end(); ++itr ) {
00204       insertAttendeeFromAddressee( (*itr) );
00205     }
00206   }
00207   delete dia;
00208   return;
00209 #if 0
00210     // old code
00211     KABC::Addressee a = KABC::AddresseeDialog::getAddressee(this);
00212     if (!a.isEmpty()) {
00213         // If this is myself, I don't want to get a response but instead
00214         // assume I will be available
00215         bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
00216         KCal::Attendee::PartStat partStat =
00217             myself ? KCal::Attendee::Accepted : KCal::Attendee::NeedsAction;
00218         insertAttendee( new Attendee( a.realName(), a.preferredEmail(),
00219                                       !myself, partStat,
00220                                       KCal::Attendee::ReqParticipant, a.uid() ) );
00221     }
00222 #endif
00223 #endif
00224 }
00225 
00226 void KOAttendeeEditor::insertAttendeeFromAddressee(const KABC::Addressee &a, const Attendee * at)
00227 {
00228   bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
00229   bool sameAsOrganizer = mOrganizerCombo &&
00230   KPIM::compareEmail( a.preferredEmail(), mOrganizerCombo->currentText(), false );
00231   KCal::Attendee::PartStat partStat = at? at->status() : KCal::Attendee::NeedsAction;
00232   bool rsvp = at? at->RSVP() : true;
00233 
00234   if ( myself && sameAsOrganizer ) {
00235     partStat = KCal::Attendee::Accepted;
00236     rsvp = false;
00237   }
00238   Attendee *newAt = new Attendee( a.realName(),
00239                                a.preferredEmail(),
00240                                !myself, partStat,
00241                                at ? at->role() : Attendee::ReqParticipant,
00242                                a.uid() );
00243   newAt->setRSVP( rsvp );
00244   insertAttendee( newAt, true );
00245 }
00246 
00247 void KOAttendeeEditor::fillOrganizerCombo()
00248 {
00249   Q_ASSERT( mOrganizerCombo );
00250   // Get all emails from KOPrefs (coming from various places),
00251   // and insert them - removing duplicates
00252   const QStringList lst = KOPrefs::instance()->fullEmails();
00253   QStringList uniqueList;
00254   for( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
00255     if ( uniqueList.find( *it ) == uniqueList.end() )
00256       uniqueList << *it;
00257   }
00258   mOrganizerCombo->insertStringList( uniqueList );
00259 }
00260 
00261 void KOAttendeeEditor::addNewAttendee()
00262 {
00263   Attendee *a = new Attendee( i18n("Firstname Lastname"),
00264                               i18n("name") + "@example.net", true );
00265   insertAttendee( a, false );
00266   mnewAttendees.append(a);
00267   updateAttendeeInput();
00268   // We don't want the hint again
00269   mNameEdit->setClickMessage( "" );
00270   mNameEdit->setFocus();
00271   QTimer::singleShot( 0, mNameEdit, SLOT( selectAll() ) );
00272 }
00273 
00274 void KOAttendeeEditor::readEvent(KCal::Incidence * incidence)
00275 {
00276   mdelAttendees.clear();
00277   mnewAttendees.clear();
00278   if ( KOPrefs::instance()->thatIsMe( incidence->organizer().email() ) ) {
00279     if ( !mOrganizerCombo ) {
00280       mOrganizerCombo = new QComboBox( mOrganizerHBox );
00281       fillOrganizerCombo();
00282     }
00283     mOrganizerLabel->setText( i18n( "Identity as organizer:" ) );
00284 
00285     int found = -1;
00286     QString fullOrganizer = incidence->organizer().fullName();
00287     for ( int i = 0 ; i < mOrganizerCombo->count(); ++i ) {
00288       if ( mOrganizerCombo->text( i ) == fullOrganizer ) {
00289         found = i;
00290         mOrganizerCombo->setCurrentItem( i );
00291         break;
00292       }
00293     }
00294     if ( found < 0 ) {
00295       mOrganizerCombo->insertItem( fullOrganizer, 0 );
00296       mOrganizerCombo->setCurrentItem( 0 );
00297     }
00298   } else { // someone else is the organizer
00299     if ( mOrganizerCombo ) {
00300       delete mOrganizerCombo;
00301       mOrganizerCombo = 0;
00302     }
00303     mOrganizerLabel->setText( i18n( "Organizer: %1" ).arg( incidence->organizer().fullName() ) );
00304   }
00305 
00306   Attendee::List al = incidence->attendees();
00307   Attendee::List::ConstIterator it;
00308   for( it = al.begin(); it != al.end(); ++it )
00309     insertAttendee( new Attendee( **it ), true );
00310 }
00311 
00312 void KOAttendeeEditor::writeEvent(KCal::Incidence * incidence)
00313 {
00314   if ( mOrganizerCombo ) {
00315     // TODO: Don't take a string and split it up... Is there a better way?
00316     incidence->setOrganizer( mOrganizerCombo->currentText() );
00317   }
00318 }
00319 
00320 void KOAttendeeEditor::setEnableAttendeeInput(bool enabled)
00321 {
00322   //mNameEdit->setEnabled( enabled );
00323   mRoleCombo->setEnabled( enabled );
00324   mStatusCombo->setEnabled( enabled );
00325   mRsvpButton->setEnabled( enabled );
00326 
00327   mRemoveButton->setEnabled( enabled );
00328 }
00329 
00330 void KOAttendeeEditor::clearAttendeeInput()
00331 {
00332   mNameEdit->setText("");
00333   mUid = QString::null;
00334   mRoleCombo->setCurrentItem(0);
00335   mStatusCombo->setCurrentItem(0);
00336   mRsvpButton->setChecked(true);
00337   setEnableAttendeeInput( false );
00338   mDelegateLabel->setText( QString() );
00339 }
00340 
00341 void KOAttendeeEditor::updateAttendee()
00342 {
00343   Attendee *a = currentAttendee();
00344   if ( !a || mDisableItemUpdate )
00345     return;
00346 
00347   QString name;
00348   QString email;
00349   KPIM::getNameAndMail(mNameEdit->text(), name, email);
00350 
00351   bool iAmTheOrganizer = mOrganizerCombo &&
00352     KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() );
00353   if ( iAmTheOrganizer ) {
00354     bool myself =
00355       KPIM::compareEmail( email, mOrganizerCombo->currentText(), false );
00356     bool wasMyself =
00357       KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false );
00358     if ( myself ) {
00359       mStatusCombo->setCurrentItem( KCal::Attendee::Accepted );
00360       mRsvpButton->setChecked( false );
00361       mRsvpButton->setEnabled( false );
00362     } else if ( wasMyself ) {
00363       // this was me, but is no longer, reset
00364       mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
00365       mRsvpButton->setChecked( true );
00366       mRsvpButton->setEnabled( true );
00367     }
00368   }
00369   a->setName( name );
00370   a->setUid( mUid );
00371   a->setEmail( email );
00372   a->setRole( Attendee::Role( mRoleCombo->currentItem() ) );
00373   a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) );
00374   a->setRSVP( mRsvpButton->isChecked() );
00375 
00376   updateCurrentItem();
00377 }
00378 
00379 void KOAttendeeEditor::fillAttendeeInput( KCal::Attendee *a )
00380 {
00381   mDisableItemUpdate = true;
00382 
00383   QString name = a->name();
00384   if (!a->email().isEmpty()) {
00385     name = KPIM::quoteNameIfNecessary( name );
00386     name += " <" + a->email() + ">";
00387   }
00388   mNameEdit->setText(name);
00389   mUid = a->uid();
00390   mRoleCombo->setCurrentItem(a->role());
00391   mStatusCombo->setCurrentItem(a->status());
00392   mRsvpButton->setChecked(a->RSVP());
00393 
00394   mDisableItemUpdate = false;
00395   setEnableAttendeeInput( true );
00396 
00397   if ( a->status() == Attendee::Delegated ) {
00398     if ( !a->delegate().isEmpty() )
00399       mDelegateLabel->setText( i18n( "Delegated to %1" ).arg( a->delegate() ) );
00400     else if ( !a->delegator().isEmpty() )
00401       mDelegateLabel->setText( i18n( "Delegated from %1" ).arg( a->delegator() ) );
00402     else
00403       mDelegateLabel->setText( i18n( "Not delegated" ) );
00404   }
00405 }
00406 
00407 void KOAttendeeEditor::updateAttendeeInput()
00408 {
00409   setEnableAttendeeInput(!mNameEdit->text().isEmpty());
00410   Attendee* a = currentAttendee();
00411   if ( a ) {
00412     fillAttendeeInput( a );
00413   } else {
00414     clearAttendeeInput();
00415   }
00416 }
00417 
00418 void KOAttendeeEditor::cancelAttendeeEvent( KCal::Incidence *incidence )
00419 {
00420   incidence->clearAttendees();
00421   Attendee * att;
00422   for (att=mdelAttendees.first();att;att=mdelAttendees.next()) {
00423     bool isNewAttendee = false;
00424     for (Attendee *newAtt=mnewAttendees.first();newAtt;newAtt=mnewAttendees.next()) {
00425       if (*att==*newAtt) {
00426         isNewAttendee = true;
00427         break;
00428       }
00429     }
00430     if (!isNewAttendee) {
00431       incidence->addAttendee(new Attendee(*att));
00432     }
00433   }
00434   mdelAttendees.clear();
00435 }
00436 
00437 void KOAttendeeEditor::acceptForMe()
00438 {
00439   changeStatusForMe( Attendee::Accepted );
00440 }
00441 
00442 void KOAttendeeEditor::declineForMe()
00443 {
00444   changeStatusForMe( Attendee::Declined );
00445 }
00446 
00447 bool KOAttendeeEditor::eventFilter(QObject *watched, QEvent *ev)
00448 {
00449   if ( watched && watched == mNameEdit && ev->type() == QEvent::FocusIn &&
00450        currentAttendee() == 0 ) {
00451     addNewAttendee();
00452   }
00453 
00454   return QWidget::eventFilter( watched, ev );
00455 }
00456 
00457 #include "koattendeeeditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys