korganizer

koeditordetails.cpp

00001 /*
00002     This file is part of KOrganizer.
00003 
00004     Copyright (c) 2001 Cornelius Schumacher <schumacher@kde.org>
00005     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00006 
00007     This program is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 2 of the License, or
00010     (at your option) any later version.
00011 
00012     This program is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00020 
00021     As a special exception, permission is given to link this program
00022     with any edition of Qt, and distribute the resulting executable,
00023     without including the source code for Qt in the source distribution.
00024 */
00025 
00026 #include "koeditordetails.h"
00027 
00028 #include <qbuttongroup.h>
00029 #include <qcheckbox.h>
00030 #include <qcombobox.h>
00031 #include <qdatetime.h>
00032 #include <qdragobject.h>
00033 #include <qfiledialog.h>
00034 #include <qgroupbox.h>
00035 #include <qlabel.h>
00036 #include <qlayout.h>
00037 #include <qlineedit.h>
00038 #include <qpushbutton.h>
00039 #include <qradiobutton.h>
00040 #include <qregexp.h>
00041 #include <qtooltip.h>
00042 #include <qvbox.h>
00043 #include <qvgroupbox.h>
00044 #include <qwhatsthis.h>
00045 #include <qwidgetstack.h>
00046 #include <qvaluevector.h>
00047 
00048 #include <kdebug.h>
00049 #include <klocale.h>
00050 #include <kiconloader.h>
00051 #include <kmessagebox.h>
00052 #ifndef KORG_NOKABC
00053 #include <kabc/addresseedialog.h>
00054 #include <kabc/vcardconverter.h>
00055 #include <libkdepim/addressesdialog.h>
00056 #include <libkdepim/addresseelineedit.h>
00057 #include <libkdepim/distributionlist.h>
00058 #include <kabc/stdaddressbook.h>
00059 #endif
00060 #include <libkdepim/kvcarddrag.h>
00061 #include <libemailfunctions/email.h>
00062 
00063 #include <libkcal/incidence.h>
00064 
00065 #include "koprefs.h"
00066 #include "koglobals.h"
00067 
00068 #include "koeditorfreebusy.h"
00069 
00070 #include "kocore.h"
00071 
00072 template <>
00073 CustomListViewItem<KCal::Attendee *>::~CustomListViewItem()
00074 {
00075   delete mData;
00076 }
00077 
00078 template <>
00079 void CustomListViewItem<KCal::Attendee *>::updateItem()
00080 {
00081   setText(0,mData->name());
00082   setText(1,mData->email());
00083   setText(2,mData->roleStr());
00084   setText(3,mData->statusStr());
00085   if (mData->RSVP() && !mData->email().isEmpty())
00086     setPixmap(4,KOGlobals::self()->smallIcon("mailappt"));
00087   else
00088     setPixmap(4,KOGlobals::self()->smallIcon("nomailappt"));
00089   setText(5, mData->delegate());
00090   setText(6, mData->delegator());
00091 }
00092 
00093 KOAttendeeListView::KOAttendeeListView ( QWidget *parent, const char *name )
00094   : KListView(parent, name)
00095 {
00096   setAcceptDrops( true );
00097   setAllColumnsShowFocus( true );
00098   setSorting( -1 );
00099 }
00100 
00106 KOAttendeeListView::~KOAttendeeListView()
00107 {
00108 }
00109 
00110 void KOAttendeeListView::contentsDragEnterEvent( QDragEnterEvent *e )
00111 {
00112   dragEnterEvent(e);
00113 }
00114 
00115 void KOAttendeeListView::contentsDragMoveEvent( QDragMoveEvent *e )
00116 {
00117 #ifndef KORG_NODND
00118   if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) ) {
00119     e->accept();
00120   } else {
00121     e->ignore();
00122   }
00123 #endif
00124 }
00125 
00126 void KOAttendeeListView::dragEnterEvent( QDragEnterEvent *e )
00127 {
00128 #ifndef KORG_NODND
00129   if ( KVCardDrag::canDecode( e ) || QTextDrag::canDecode( e ) ) {
00130     e->accept();
00131   } else {
00132     e->ignore();
00133   }
00134 #endif
00135 }
00136 
00137 void KOAttendeeListView::addAttendee( const QString &newAttendee )
00138 {
00139   kdDebug(5850) << " Email: " << newAttendee << endl;
00140   QString name;
00141   QString email;
00142   KPIM::getNameAndMail( newAttendee, name, email );
00143   emit dropped( new Attendee( name, email, true ) );
00144 }
00145 
00146 void KOAttendeeListView::contentsDropEvent( QDropEvent *e )
00147 {
00148   dropEvent(e);
00149 }
00150 
00151 void KOAttendeeListView::dropEvent( QDropEvent *e )
00152 {
00153 #ifndef KORG_NODND
00154   QString text;
00155   QString vcards;
00156 
00157 #ifndef KORG_NOKABC
00158   if ( KVCardDrag::decode( e, vcards ) ) {
00159     KABC::VCardConverter converter;
00160 
00161     KABC::Addressee::List list = converter.parseVCards( vcards );
00162     KABC::Addressee::List::Iterator it;
00163     for ( it = list.begin(); it != list.end(); ++it ) {
00164       QString em( (*it).fullEmail() );
00165       if (em.isEmpty()) {
00166         em=(*it).realName();
00167       }
00168       addAttendee( em );
00169     }
00170   } else
00171 #endif // KORG_NOKABC
00172   if (QTextDrag::decode(e,text)) {
00173     kdDebug(5850) << "Dropped : " << text << endl;
00174     QStringList emails = QStringList::split(",",text);
00175     for(QStringList::ConstIterator it = emails.begin();it!=emails.end();++it) {
00176       addAttendee(*it);
00177     }
00178   }
00179 #endif //KORG_NODND
00180 }
00181 
00182 
00183 KOEditorDetails::KOEditorDetails( int spacing, QWidget *parent,
00184                                   const char *name )
00185   : KOAttendeeEditor( parent, name), mDisableItemUpdate( false )
00186 {
00187   QBoxLayout *topLayout = new QVBoxLayout( this );
00188   topLayout->setSpacing( spacing );
00189 
00190   initOrganizerWidgets( this, topLayout );
00191 
00192   mListView = new KOAttendeeListView( this, "mListView" );
00193   QWhatsThis::add( mListView,
00194            i18n("Displays information about current attendees. "
00195             "To edit an attendee, select it in this list "
00196             "and modify the values in the area below. "
00197             "Clicking on a column title will sort the list "
00198             "according to that column. The RSVP column "
00199             "indicates whether or not a response is requested "
00200             "from the attendee.") );
00201   mListView->addColumn( i18n("Name"), 200 );
00202   mListView->addColumn( i18n("Email"), 200 );
00203   mListView->addColumn( i18n("Role"), 80 );
00204   mListView->addColumn( i18n("Status"), 100 );
00205   mListView->addColumn( i18n("RSVP"), 55 );
00206   mListView->addColumn( i18n("Delegated to"), 120 );
00207   mListView->addColumn( i18n("Delegated from" ), 120 );
00208   mListView->setResizeMode( QListView::LastColumn );
00209   if ( KOPrefs::instance()->mCompactDialogs ) {
00210     mListView->setFixedHeight( 78 );
00211   }
00212 
00213   connect( mListView, SIGNAL( selectionChanged( QListViewItem * ) ),
00214            SLOT( updateAttendeeInput() ) );
00215 #ifndef KORG_NODND
00216   connect( mListView, SIGNAL( dropped( Attendee * ) ),
00217            SLOT( slotInsertAttendee( Attendee * ) ) );
00218 #endif
00219   topLayout->addWidget( mListView );
00220 
00221   initEditWidgets( this, topLayout );
00222 
00223   connect( mRemoveButton, SIGNAL(clicked()), SLOT(removeAttendee()) );
00224 
00225   updateAttendeeInput();
00226 }
00227 
00228 KOEditorDetails::~KOEditorDetails()
00229 {
00230 }
00231 
00232 bool KOEditorDetails::hasAttendees()
00233 {
00234   return mListView->childCount() > 0;
00235 }
00236 
00237 void KOEditorDetails::removeAttendee()
00238 {
00239   AttendeeListItem *aItem =
00240       static_cast<AttendeeListItem *>( mListView->selectedItem() );
00241   if ( !aItem ) return;
00242 
00243   AttendeeListItem *nextSelectedItem = static_cast<AttendeeListItem*>( aItem->nextSibling() );
00244   if( mListView->childCount() == 1 )
00245       nextSelectedItem = 0;
00246   if( mListView->childCount() > 1 && aItem == mListView->lastItem() )
00247       nextSelectedItem = static_cast<AttendeeListItem*>(  mListView->firstChild() );
00248 
00249   Attendee *delA = new Attendee( aItem->data()->name(), aItem->data()->email(),
00250                                  aItem->data()->RSVP(), aItem->data()->status(),
00251                                  aItem->data()->role(), aItem->data()->uid() );
00252   mdelAttendees.append( delA );
00253 
00254   delete aItem;
00255 
00256   if( nextSelectedItem )
00257       mListView->setSelected( nextSelectedItem, true );
00258   updateAttendeeInput();
00259   emit updateAttendeeSummary( mListView->childCount() );
00260 }
00261 
00262 
00263 void KOEditorDetails::insertAttendee( Attendee *a, bool goodEmailAddress )
00264 {
00265   Q_UNUSED( goodEmailAddress );
00266 
00267   // lastItem() is O(n), but for n very small that should be fine
00268   AttendeeListItem *item = new AttendeeListItem( a, mListView,
00269       static_cast<KListViewItem*>( mListView->lastItem() ) );
00270   mListView->setSelected( item, true );
00271   emit updateAttendeeSummary( mListView->childCount() );
00272 }
00273 
00274 void KOEditorDetails::removeAttendee( Attendee *a )
00275 {
00276   Q_UNUSED( a );
00277 }
00278 
00279 void KOEditorDetails::setDefaults()
00280 {
00281   mRsvpButton->setChecked( true );
00282 }
00283 
00284 void KOEditorDetails::readEvent( Incidence *event )
00285 {
00286   mListView->clear();
00287   KOAttendeeEditor::readEvent( event );
00288 
00289   mListView->setSelected( mListView->firstChild(), true );
00290 
00291   emit updateAttendeeSummary( mListView->childCount() );
00292 }
00293 
00294 void KOEditorDetails::writeEvent(Incidence *event)
00295 {
00296   event->clearAttendees();
00297   QValueVector<QListViewItem*> toBeDeleted;
00298   QListViewItem *item;
00299   AttendeeListItem *a;
00300   for (item = mListView->firstChild(); item;
00301        item = item->nextSibling()) {
00302     a = (AttendeeListItem *)item;
00303     Attendee *attendee = a->data();
00304     Q_ASSERT( attendee );
00305     /* Check if the attendee is a distribution list and expand it */
00306     if ( attendee->email().isEmpty() ) {
00307       KPIM::DistributionList list =
00308         KPIM::DistributionList::findByName( KABC::StdAddressBook::self(), attendee->name() );
00309       if ( !list.isEmpty() ) {
00310         toBeDeleted.push_back( item ); // remove it once we are done expanding
00311         KPIM::DistributionList::Entry::List entries = list.entries( KABC::StdAddressBook::self() );
00312         KPIM::DistributionList::Entry::List::Iterator it( entries.begin() );
00313         while ( it != entries.end() ) {
00314           KPIM::DistributionList::Entry &e = ( *it );
00315           ++it;
00316           // this calls insertAttendee, which appends
00317           insertAttendeeFromAddressee( e.addressee, attendee );
00318           // TODO: duplicate check, in case it was already added manually
00319         }
00320       }
00321     } else {
00322       bool skip = false;
00323       if ( attendee->email().endsWith( "example.net" ) ) {
00324         if ( KMessageBox::warningYesNo( this, i18n("%1 does not look like a valid email address. "
00325                 "Are you sure you want to invite this participant?").arg( attendee->email() ),
00326               i18n("Invalid email address") ) != KMessageBox::Yes ) {
00327           skip = true;
00328         }
00329       }
00330       if ( !skip ) {
00331         event->addAttendee( new Attendee( *attendee ) );
00332       }
00333     }
00334   }
00335 
00336   KOAttendeeEditor::writeEvent( event );
00337 
00338   // cleanup
00339   QValueVector<QListViewItem*>::iterator it;
00340   for( it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it ) {
00341     delete *it;
00342   }
00343 }
00344 
00345 bool KOEditorDetails::validateInput()
00346 {
00347   return true;
00348 }
00349 
00350 KCal::Attendee * KOEditorDetails::currentAttendee() const
00351 {
00352   QListViewItem *item = mListView->selectedItem();
00353   AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item );
00354   if ( !aItem )
00355     return 0;
00356   return aItem->data();
00357 }
00358 
00359 void KOEditorDetails::updateCurrentItem()
00360 {
00361   AttendeeListItem *item = static_cast<AttendeeListItem*>( mListView->selectedItem() );
00362   if ( item )
00363     item->updateItem();
00364 }
00365 
00366 void KOEditorDetails::slotInsertAttendee(Attendee * a)
00367 {
00368   insertAttendee( a );
00369 }
00370 
00371 void KOEditorDetails::changeStatusForMe(Attendee::PartStat status)
00372 {
00373   const QStringList myEmails = KOPrefs::instance()->allEmails();
00374   for ( QListViewItemIterator it( mListView ); it.current(); ++it ) {
00375     AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() );
00376     for ( QStringList::ConstIterator it2( myEmails.begin() ), end( myEmails.end() ); it2 != end; ++it2 ) {
00377       if ( item->data()->email() == *it2 ) {
00378         item->data()->setStatus( status );
00379         item->updateItem();
00380       }
00381     }
00382   }
00383 }
00384 
00385 QListViewItem* KOEditorDetails::hasExampleAttendee() const
00386 {
00387   for ( QListViewItemIterator it( mListView ); it.current(); ++it ) {
00388     AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() );
00389     Attendee *attendee = item->data();
00390     Q_ASSERT( attendee );
00391     if ( isExampleAttendee( attendee ) )
00392         return item;
00393   }
00394   return 0;
00395 }
00396 
00397 #include "koeditordetails.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys