00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "koeditordetails.h"
00026
00027 #include <qtooltip.h>
00028 #include <qfiledialog.h>
00029 #include <qlayout.h>
00030 #include <qvbox.h>
00031 #include <qbuttongroup.h>
00032 #include <qvgroupbox.h>
00033 #include <qwidgetstack.h>
00034 #include <qdatetime.h>
00035 #include <qdragobject.h>
00036 #include <qcombobox.h>
00037 #include <qlineedit.h>
00038 #include <qlabel.h>
00039 #include <qcheckbox.h>
00040 #include <qpushbutton.h>
00041 #include <qgroupbox.h>
00042 #include <qradiobutton.h>
00043 #include <qregexp.h>
00044
00045 #include <kdebug.h>
00046 #include <klocale.h>
00047 #include <kiconloader.h>
00048 #include <kmessagebox.h>
00049 #ifndef KORG_NOKABC
00050 #include <kabc/addresseedialog.h>
00051 #include <kabc/vcardconverter.h>
00052 #include <libkdepim/addressesdialog.h>
00053 #include <libkdepim/addresseelineedit.h>
00054 #include <kabc/distributionlist.h>
00055 #include <kabc/stdaddressbook.h>
00056 #endif
00057 #include <libkdepim/kvcarddrag.h>
00058 #include <libkdepim/email.h>
00059
00060 #include <libkcal/incidence.h>
00061
00062 #include "koprefs.h"
00063 #include "koglobals.h"
00064
00065 #include "koeditorfreebusy.h"
00066
00067 #include "kocore.h"
00068
00069 template <>
00070 CustomListViewItem<KCal::Attendee *>::~CustomListViewItem()
00071 {
00072 delete mData;
00073 }
00074
00075 template <>
00076 void CustomListViewItem<KCal::Attendee *>::updateItem()
00077 {
00078 setText(0,mData->name());
00079 setText(1,mData->email());
00080 setText(2,mData->roleStr());
00081 setText(3,mData->statusStr());
00082 if (mData->RSVP() && !mData->email().isEmpty())
00083 setPixmap(4,KOGlobals::self()->smallIcon("mailappt"));
00084 else
00085 setPixmap(4,KOGlobals::self()->smallIcon("nomailappt"));
00086 }
00087
00088 KOAttendeeListView::KOAttendeeListView ( QWidget *parent, const char *name )
00089 : KListView(parent, name)
00090 {
00091 setAcceptDrops( true );
00092 setAllColumnsShowFocus( true );
00093 setSorting( -1 );
00094 }
00095
00101 KOAttendeeListView::~KOAttendeeListView()
00102 {
00103 }
00104
00105 void KOAttendeeListView::contentsDragEnterEvent( QDragEnterEvent *e )
00106 {
00107 dragEnterEvent(e);
00108 }
00109
00110 void KOAttendeeListView::contentsDragMoveEvent( QDragMoveEvent *e )
00111 {
00112 #ifndef KORG_NODND
00113 if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) ) {
00114 e->accept();
00115 } else {
00116 e->ignore();
00117 }
00118 #endif
00119 }
00120
00121 void KOAttendeeListView::dragEnterEvent( QDragEnterEvent *e )
00122 {
00123 #ifndef KORG_NODND
00124 if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) ) {
00125 e->accept();
00126 } else {
00127 e->ignore();
00128 }
00129 #endif
00130 }
00131
00132 void KOAttendeeListView::addAttendee( const QString &newAttendee )
00133 {
00134 kdDebug(5850) << " Email: " << newAttendee << endl;
00135 QString name;
00136 QString email;
00137 KPIM::getNameAndMail( newAttendee, name, email );
00138 emit dropped( new Attendee( name, email, true ) );
00139 }
00140
00141 void KOAttendeeListView::contentsDropEvent( QDropEvent *e )
00142 {
00143 dropEvent(e);
00144 }
00145
00146 void KOAttendeeListView::dropEvent( QDropEvent *e )
00147 {
00148 #ifndef KORG_NODND
00149 QString text;
00150 QString vcards;
00151
00152 #ifndef KORG_NOKABC
00153 if ( KVCardDrag::decode( e, vcards ) ) {
00154 KABC::VCardConverter converter;
00155
00156 KABC::Addressee::List list = converter.parseVCards( vcards );
00157 KABC::Addressee::List::Iterator it;
00158 for ( it = list.begin(); it != list.end(); ++it ) {
00159 QString em( (*it).fullEmail() );
00160 if (em.isEmpty()) {
00161 em=(*it).realName();
00162 }
00163 addAttendee( em );
00164 }
00165 } else
00166 #endif // KORG_NOKABC
00167 if (QTextDrag::decode(e,text)) {
00168 kdDebug(5850) << "Dropped : " << text << endl;
00169 QStringList emails = QStringList::split(",",text);
00170 for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
00171 addAttendee(*it);
00172 }
00173 }
00174 #endif //KORG_NODND
00175 }
00176
00177
00178 KOEditorDetails::KOEditorDetails( int spacing, QWidget *parent,
00179 const char *name )
00180 : QWidget( parent, name), mDisableItemUpdate( false ), mFreeBusy( 0 )
00181 {
00182 QGridLayout *topLayout = new QGridLayout( this );
00183 topLayout->setSpacing( spacing );
00184
00185 mOrganizerHBox = new QHBox( this );
00186
00187
00188
00189
00190
00191 mOrganizerLabel = new QLabel( i18n( "Identity as organizer:" ),
00192 mOrganizerHBox );
00193 mOrganizerCombo = new QComboBox( mOrganizerHBox );
00194 fillOrganizerCombo();
00195 mOrganizerHBox->setStretchFactor( mOrganizerCombo, 100 );
00196
00197 mListView = new KOAttendeeListView( this, "mListView" );
00198 mListView->addColumn( i18n("Name"), 200 );
00199 mListView->addColumn( i18n("Email"), 200 );
00200 mListView->addColumn( i18n("Role"), 60 );
00201 mListView->addColumn( i18n("Status"), 100 );
00202 mListView->addColumn( i18n("RSVP"), 35 );
00203 mListView->setResizeMode( QListView::LastColumn );
00204 if ( KOPrefs::instance()->mCompactDialogs ) {
00205 mListView->setFixedHeight( 78 );
00206 }
00207
00208 connect( mListView, SIGNAL( selectionChanged( QListViewItem * ) ),
00209 SLOT( updateAttendeeInput() ) );
00210 #ifndef KORG_NODND
00211 connect( mListView, SIGNAL( dropped( Attendee * ) ),
00212 SLOT( insertAttendee( Attendee * ) ) );
00213 #endif
00214
00215 QLabel *attendeeLabel = new QLabel( this );
00216 attendeeLabel->setText( i18n("Na&me:") );
00217
00218 mNameEdit = new KPIM::AddresseeLineEdit( this );
00219 mNameEdit->setClickMessage( i18n("Click to add a new attendee") );
00220 attendeeLabel->setBuddy( mNameEdit );
00221 mNameEdit->installEventFilter( this );
00222 connect( mNameEdit, SIGNAL( textChanged( const QString & ) ),
00223 SLOT( updateAttendeeItem() ) );
00224
00225 mUidEdit = new QLineEdit( 0 );
00226 mUidEdit->setText( "" );
00227
00228 QLabel *attendeeRoleLabel = new QLabel( this );
00229 attendeeRoleLabel->setText( i18n("Ro&le:") );
00230
00231 mRoleCombo = new QComboBox( false, this );
00232 mRoleCombo->insertStringList( Attendee::roleList() );
00233 attendeeRoleLabel->setBuddy( mRoleCombo );
00234 connect( mRoleCombo, SIGNAL( activated( int ) ),
00235 SLOT( updateAttendeeItem() ) );
00236
00237 QLabel *statusLabel = new QLabel( this );
00238 statusLabel->setText( i18n("Stat&us:") );
00239
00240 mStatusCombo = new QComboBox( false, this );
00241 mStatusCombo->insertStringList( Attendee::statusList() );
00242 statusLabel->setBuddy( mStatusCombo );
00243 connect( mStatusCombo, SIGNAL( activated( int ) ),
00244 SLOT( updateAttendeeItem() ) );
00245
00246 mRsvpButton = new QCheckBox( this );
00247 mRsvpButton->setText( i18n("Re&quest response") );
00248 connect( mRsvpButton, SIGNAL( clicked() ), SLOT( updateAttendeeItem() ) );
00249
00250 QWidget *buttonBox = new QWidget( this );
00251 QVBoxLayout *buttonLayout = new QVBoxLayout( buttonBox );
00252
00253 QPushButton *newButton = new QPushButton( i18n("&New"), buttonBox );
00254 buttonLayout->addWidget( newButton );
00255 connect( newButton, SIGNAL( clicked() ), SLOT( addNewAttendee() ) );
00256
00257 mRemoveButton = new QPushButton( i18n("&Remove"), buttonBox );
00258 buttonLayout->addWidget( mRemoveButton );
00259 connect( mRemoveButton, SIGNAL( clicked() ), SLOT( removeAttendee() ) );
00260
00261 mAddressBookButton = new QPushButton( i18n("Select Addressee..."),
00262 buttonBox );
00263 buttonLayout->addWidget( mAddressBookButton );
00264 connect( mAddressBookButton, SIGNAL( clicked() ), SLOT( openAddressBook() ) );
00265
00266 topLayout->addMultiCellWidget( mOrganizerHBox, 0, 0, 0, 5 );
00267 topLayout->addMultiCellWidget( mListView, 1, 1, 0, 5 );
00268 topLayout->addWidget( attendeeLabel, 2, 0 );
00269 topLayout->addMultiCellWidget( mNameEdit, 2, 2, 1, 1 );
00270
00271 topLayout->addWidget( attendeeRoleLabel, 3, 0 );
00272 topLayout->addWidget( mRoleCombo, 3, 1 );
00273 #if 0
00274 topLayout->setColStretch( 2, 1 );
00275 topLayout->addWidget( statusLabel, 3, 3 );
00276 topLayout->addWidget( mStatusCombo, 3, 4 );
00277 #else
00278 topLayout->addWidget( statusLabel, 4, 0 );
00279 topLayout->addWidget( mStatusCombo, 4, 1 );
00280 #endif
00281 topLayout->addMultiCellWidget( mRsvpButton, 5, 5, 0, 1 );
00282 topLayout->addMultiCellWidget( buttonBox, 2, 4, 5, 5 );
00283
00284 #ifdef KORG_NOKABC
00285 mAddressBookButton->hide();
00286 #endif
00287
00288 updateAttendeeInput();
00289 }
00290
00291 KOEditorDetails::~KOEditorDetails()
00292 {
00293 }
00294
00295 bool KOEditorDetails::eventFilter( QObject *watched, QEvent *ev)
00296 {
00297 if ( watched && watched == mNameEdit && ev->type() == QEvent::FocusIn &&
00298 mListView->childCount() == 0 ) {
00299 addNewAttendee();
00300 }
00301
00302 return QWidget::eventFilter( watched, ev );
00303 }
00304
00305 void KOEditorDetails::removeAttendee()
00306 {
00307 AttendeeListItem *aItem =
00308 static_cast<AttendeeListItem *>( mListView->selectedItem() );
00309 if ( !aItem ) return;
00310
00311 Attendee *delA = new Attendee( aItem->data()->name(), aItem->data()->email(),
00312 aItem->data()->RSVP(), aItem->data()->status(),
00313 aItem->data()->role(), aItem->data()->uid() );
00314 mdelAttendees.append( delA );
00315
00316 if ( mFreeBusy ) mFreeBusy->removeAttendee( aItem->data() );
00317 delete aItem;
00318
00319 updateAttendeeInput();
00320 }
00321
00322
00323 void KOEditorDetails::openAddressBook()
00324 {
00325 #ifndef KORG_NOKABC
00326 KPIM::AddressesDialog *dia = new KPIM::AddressesDialog( this, "adddialog" );
00327 dia->setShowCC( false );
00328 dia->setShowBCC( false );
00329 if ( dia->exec() ) {
00330 KABC::Addressee::List aList = dia->allToAddressesNoDuplicates();
00331 for ( KABC::Addressee::List::iterator itr = aList.begin();
00332 itr != aList.end(); ++itr ) {
00333 KABC::Addressee a = (*itr);
00334 bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
00335 bool sameAsOrganizer = mOrganizerCombo &&
00336 KPIM::compareEmail( a.preferredEmail(), mOrganizerCombo->currentText(), false );
00337 KCal::Attendee::PartStat partStat;
00338 if ( myself && sameAsOrganizer )
00339 partStat = KCal::Attendee::Accepted;
00340 else
00341 partStat = KCal::Attendee::NeedsAction;
00342 insertAttendee( new Attendee( a.realName(), a.preferredEmail(),
00343 !myself, partStat,
00344 KCal::Attendee::ReqParticipant, a.uid() ),
00345 true );
00346 }
00347 }
00348 delete dia;
00349 return;
00350 #if 0
00351
00352 KABC::Addressee a = KABC::AddresseeDialog::getAddressee(this);
00353 if (!a.isEmpty()) {
00354
00355
00356 bool myself = KOPrefs::instance()->thatIsMe( a.preferredEmail() );
00357 KCal::Attendee::PartStat partStat =
00358 myself ? KCal::Attendee::Accepted : KCal::Attendee::NeedsAction;
00359 insertAttendee( new Attendee( a.realName(), a.preferredEmail(),
00360 !myself, partStat,
00361 KCal::Attendee::ReqParticipant, a.uid() ) );
00362 }
00363 #endif
00364 #endif
00365 }
00366
00367
00368 void KOEditorDetails::addNewAttendee()
00369 {
00370 Attendee *a = new Attendee( i18n("Firstname Lastname"),
00371 i18n("name@domain.com"), true );
00372 insertAttendee( a, false );
00373
00374 mNameEdit->setClickMessage( "" );
00375 mNameEdit->setFocus();
00376 QTimer::singleShot( 0, mNameEdit, SLOT( selectAll() ) );
00377 }
00378
00379
00380 void KOEditorDetails::insertAttendee( Attendee *a )
00381 {
00382 insertAttendee( a, true );
00383 }
00384
00385 void KOEditorDetails::insertAttendee( Attendee *a, bool goodEmailAddress )
00386 {
00387
00388 AttendeeListItem *item = new AttendeeListItem( a, mListView,
00389 static_cast<KListViewItem*>( mListView->lastItem() ) );
00390 mListView->setSelected( item, true );
00391 if( mFreeBusy ) mFreeBusy->insertAttendee( a, goodEmailAddress );
00392 }
00393
00394 void KOEditorDetails::setDefaults()
00395 {
00396 mRsvpButton->setChecked( true );
00397 }
00398
00399 void KOEditorDetails::readEvent( Incidence *event )
00400 {
00401
00402 bool block = false;
00403 if( mFreeBusy ) {
00404 block = mFreeBusy->updateEnabled();
00405 mFreeBusy->setUpdateEnabled( false );
00406 mFreeBusy->clearAttendees();
00407 }
00408
00409 mListView->clear();
00410 mdelAttendees.clear();
00411 Attendee::List al = event->attendees();
00412 Attendee::List::ConstIterator it;
00413 for( it = al.begin(); it != al.end(); ++it )
00414 insertAttendee( new Attendee( **it ), true );
00415
00416 mListView->setSelected( mListView->firstChild(), true );
00417
00418 if ( KOPrefs::instance()->thatIsMe( event->organizer().email() ) ) {
00419 if ( !mOrganizerCombo ) {
00420 mOrganizerCombo = new QComboBox( mOrganizerHBox );
00421 fillOrganizerCombo();
00422 }
00423 mOrganizerLabel->setText( i18n( "Identity as organizer:" ) );
00424
00425
00426
00427 for ( int i = 0 ; i < mOrganizerCombo->count(); ++i ) {
00428 QString itemTxt = KPIM::getEmailAddr( mOrganizerCombo->text( i ) );
00429 if ( KPIM::compareEmail( event->organizer().email(), itemTxt, false ) ) {
00430
00431 mOrganizerCombo->changeItem( event->organizer().fullName(), i );
00432 mOrganizerCombo->setCurrentItem( i );
00433 break;
00434 }
00435 }
00436 } else {
00437 if ( mOrganizerCombo ) {
00438 delete mOrganizerCombo;
00439 mOrganizerCombo = 0;
00440 }
00441 mOrganizerLabel->setText( i18n( "Organizer: %1" ).arg( event->organizer().fullName() ) );
00442 }
00443
00444
00445 if( mFreeBusy ) mFreeBusy->setUpdateEnabled( block );
00446 }
00447
00448 void KOEditorDetails::writeEvent(Incidence *event)
00449 {
00450 event->clearAttendees();
00451 QListViewItem *item;
00452 AttendeeListItem *a;
00453 for (item = mListView->firstChild(); item;
00454 item = item->nextSibling()) {
00455 a = (AttendeeListItem *)item;
00456 event->addAttendee(new Attendee(*(a->data())));
00457 }
00458 if ( mOrganizerCombo ) {
00459
00460 event->setOrganizer( mOrganizerCombo->currentText() );
00461 }
00462 }
00463
00464 void KOEditorDetails::cancelAttendeeEvent(Incidence *event)
00465 {
00466 event->clearAttendees();
00467 Attendee * att;
00468 for (att=mdelAttendees.first();att;att=mdelAttendees.next()) {
00469 event->addAttendee(new Attendee(*att));
00470 }
00471 mdelAttendees.clear();
00472 }
00473
00474 bool KOEditorDetails::validateInput()
00475 {
00476 return true;
00477 }
00478
00479 void KOEditorDetails::updateAttendeeInput()
00480 {
00481
00482 setEnableAttendeeInput(!mNameEdit->text().isEmpty());
00483 QListViewItem *item = mListView->selectedItem();
00484 AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item );
00485 if (aItem) {
00486 fillAttendeeInput( aItem );
00487 } else {
00488 clearAttendeeInput();
00489 }
00490 }
00491
00492 void KOEditorDetails::clearAttendeeInput()
00493 {
00494 mNameEdit->setText("");
00495 mUidEdit->setText("");
00496 mRoleCombo->setCurrentItem(0);
00497 mStatusCombo->setCurrentItem(0);
00498 mRsvpButton->setChecked(true);
00499 setEnableAttendeeInput( false );
00500 }
00501
00502 void KOEditorDetails::fillAttendeeInput( AttendeeListItem *aItem )
00503 {
00504 Attendee *a = aItem->data();
00505 mDisableItemUpdate = true;
00506 QString name = a->name();
00507 if (!a->email().isEmpty()) {
00508
00509 QRegExp needQuotes( "[^ 0-9A-Za-z\\x0080-\\xFFFF]" );
00510 if ( name.find( needQuotes ) != -1 )
00511 name = "\"" + name + "\" <" + a->email() + ">";
00512 else
00513 name += " <" + a->email() + ">";
00514 }
00515 mNameEdit->setText(name);
00516 mUidEdit->setText(a->uid());
00517 mRoleCombo->setCurrentItem(a->role());
00518 mStatusCombo->setCurrentItem(a->status());
00519 mRsvpButton->setChecked(a->RSVP());
00520
00521 mDisableItemUpdate = false;
00522
00523 setEnableAttendeeInput( true );
00524 }
00525
00526 void KOEditorDetails::setEnableAttendeeInput( bool enabled )
00527 {
00528
00529 mRoleCombo->setEnabled( enabled );
00530 mStatusCombo->setEnabled( enabled );
00531 mRsvpButton->setEnabled( enabled );
00532
00533 mRemoveButton->setEnabled( enabled );
00534 }
00535
00536 void KOEditorDetails::updateAttendeeItem()
00537 {
00538 if (mDisableItemUpdate) return;
00539
00540 QListViewItem *item = mListView->selectedItem();
00541 AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item );
00542 if ( !aItem ) return;
00543
00544 Attendee *a = aItem->data();
00545 QString name;
00546 QString email;
00547 KPIM::getNameAndMail(mNameEdit->text(), name, email);
00548
00549 bool iAmTheOrganizer = mOrganizerCombo &&
00550 KOPrefs::instance()->thatIsMe( mOrganizerCombo->currentText() );
00551 if ( iAmTheOrganizer ) {
00552 bool myself =
00553 KPIM::compareEmail( email, mOrganizerCombo->currentText(), false );
00554 bool wasMyself =
00555 KPIM::compareEmail( a->email(), mOrganizerCombo->currentText(), false );
00556 if ( myself ) {
00557 mStatusCombo->setCurrentItem( KCal::Attendee::Accepted );
00558 mRsvpButton->setChecked( false );
00559 mRsvpButton->setEnabled( false );
00560 } else if ( wasMyself ) {
00561
00562 mStatusCombo->setCurrentItem( KCal::Attendee::NeedsAction );
00563 mRsvpButton->setChecked( true );
00564 mRsvpButton->setEnabled( true );
00565 }
00566 }
00567 a->setName( name );
00568 a->setUid( mUidEdit->text() );
00569 a->setEmail( email );
00570 a->setRole( Attendee::Role( mRoleCombo->currentItem() ) );
00571 a->setStatus( Attendee::PartStat( mStatusCombo->currentItem() ) );
00572 a->setRSVP( mRsvpButton->isChecked() );
00573 aItem->updateItem();
00574 if ( mFreeBusy ) mFreeBusy->updateAttendee( a );
00575 }
00576
00577 void KOEditorDetails::setFreeBusyWidget( KOEditorFreeBusy *v )
00578 {
00579 mFreeBusy = v;
00580 }
00581
00582 void KOEditorDetails::fillOrganizerCombo()
00583 {
00584 Q_ASSERT( mOrganizerCombo );
00585
00586
00587 const QStringList lst = KOPrefs::instance()->fullEmails();
00588 QStringList uniqueList;
00589 for( QStringList::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
00590 if ( uniqueList.find( *it ) == uniqueList.end() )
00591 uniqueList << *it;
00592 }
00593 mOrganizerCombo->insertStringList( uniqueList );
00594 }
00595
00596 #include "koeditordetails.moc"