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 TQt, and distribute the resulting executable, 00023 without including the source code for TQt in the source distribution. 00024 */ 00025 00026 #include "koeditordetails.h" 00027 00028 #include <tqbuttongroup.h> 00029 #include <tqcheckbox.h> 00030 #include <tqcombobox.h> 00031 #include <tqdatetime.h> 00032 #include <tqdragobject.h> 00033 #include <tqfiledialog.h> 00034 #include <tqgroupbox.h> 00035 #include <tqlabel.h> 00036 #include <tqlayout.h> 00037 #include <tqlineedit.h> 00038 #include <tqpushbutton.h> 00039 #include <tqradiobutton.h> 00040 #include <tqregexp.h> 00041 #include <tqtooltip.h> 00042 #include <tqvbox.h> 00043 #include <tqvgroupbox.h> 00044 #include <tqwhatsthis.h> 00045 #include <tqwidgetstack.h> 00046 #include <tqvaluevector.h> 00047 00048 #include <kdebug.h> 00049 #include <tdelocale.h> 00050 #include <kiconloader.h> 00051 #include <tdemessagebox.h> 00052 #ifndef KORG_NOKABC 00053 #include <tdeabc/addresseedialog.h> 00054 #include <tdeabc/vcardconverter.h> 00055 #include <libtdepim/addressesdialog.h> 00056 #include <libtdepim/addresseelineedit.h> 00057 #include <libtdepim/distributionlist.h> 00058 #include <tdeabc/stdaddressbook.h> 00059 #endif 00060 #include <libtdepim/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 // do not delete mData here 00076 // delete mData; 00077 } 00078 00079 template <> 00080 void CustomListViewItem<KCal::Attendee *>::updateItem() 00081 { 00082 setText(0,mData->name()); 00083 setText(1,mData->email()); 00084 setText(2,mData->roleStr()); 00085 setText(3,mData->statusStr()); 00086 if (mData->RSVP() && !mData->email().isEmpty()) 00087 setPixmap(4,KOGlobals::self()->smallIcon("mailappt")); 00088 else 00089 setPixmap(4,KOGlobals::self()->smallIcon("nomailappt")); 00090 setText(5, mData->delegate()); 00091 setText(6, mData->delegator()); 00092 } 00093 00094 KOAttendeeListView::KOAttendeeListView ( TQWidget *parent, const char *name ) 00095 : TDEListView(parent, name) 00096 { 00097 setAcceptDrops( true ); 00098 setAllColumnsShowFocus( true ); 00099 setSorting( -1 ); 00100 } 00101 00107 KOAttendeeListView::~KOAttendeeListView() 00108 { 00109 } 00110 00111 void KOAttendeeListView::contentsDragEnterEvent( TQDragEnterEvent *e ) 00112 { 00113 dragEnterEvent(e); 00114 } 00115 00116 void KOAttendeeListView::contentsDragMoveEvent( TQDragMoveEvent *e ) 00117 { 00118 #ifndef KORG_NODND 00119 if ( KVCardDrag::canDecode( e ) || TQTextDrag::canDecode( e ) ) { 00120 e->accept(); 00121 } else { 00122 e->ignore(); 00123 } 00124 #endif 00125 } 00126 00127 void KOAttendeeListView::dragEnterEvent( TQDragEnterEvent *e ) 00128 { 00129 #ifndef KORG_NODND 00130 if ( KVCardDrag::canDecode( e ) || TQTextDrag::canDecode( e ) ) { 00131 e->accept(); 00132 } else { 00133 e->ignore(); 00134 } 00135 #endif 00136 } 00137 00138 void KOAttendeeListView::addAttendee( const TQString &newAttendee ) 00139 { 00140 kdDebug(5850) << " Email: " << newAttendee << endl; 00141 TQString name; 00142 TQString email; 00143 KPIM::getNameAndMail( newAttendee, name, email ); 00144 emit dropped( new Attendee( name, email, true ) ); 00145 } 00146 00147 void KOAttendeeListView::contentsDropEvent( TQDropEvent *e ) 00148 { 00149 dropEvent(e); 00150 } 00151 00152 void KOAttendeeListView::dropEvent( TQDropEvent *e ) 00153 { 00154 #ifndef KORG_NODND 00155 TQString text; 00156 00157 #ifndef KORG_NOKABC 00158 TDEABC::Addressee::List list; 00159 if ( KVCardDrag::decode( e, list ) ) { 00160 TDEABC::Addressee::List::Iterator it; 00161 for ( it = list.begin(); it != list.end(); ++it ) { 00162 TQString em( (*it).fullEmail() ); 00163 if ( em.isEmpty() ) { 00164 em = (*it).realName(); 00165 } 00166 addAttendee( em ); 00167 } 00168 } else 00169 #endif // KORG_NOKABC 00170 if (TQTextDrag::decode(e,text)) { 00171 kdDebug(5850) << "Dropped : " << text << endl; 00172 TQStringList emails = TQStringList::split(",",text); 00173 for(TQStringList::ConstIterator it = emails.begin();it!=emails.end();++it) { 00174 addAttendee(*it); 00175 } 00176 } 00177 #endif //KORG_NODND 00178 } 00179 00180 00181 KOEditorDetails::KOEditorDetails( int spacing, TQWidget *parent, 00182 const char *name ) 00183 : KOAttendeeEditor( parent, name), mDisableItemUpdate( false ) 00184 { 00185 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00186 topLayout->setSpacing( spacing ); 00187 00188 initOrganizerWidgets( this, topLayout ); 00189 00190 mListView = new KOAttendeeListView( this, "mListView" ); 00191 TQWhatsThis::add( mListView, 00192 i18n("Displays information about current attendees. " 00193 "To edit an attendee, select it in this list " 00194 "and modify the values in the area below. " 00195 "Clicking on a column title will sort the list " 00196 "according to that column. The RSVP column " 00197 "indicates whether or not a response is requested " 00198 "from the attendee.") ); 00199 mListView->addColumn( i18n("Name"), 200 ); 00200 mListView->addColumn( i18n("Email"), 200 ); 00201 mListView->addColumn( i18n("Role"), 80 ); 00202 mListView->addColumn( i18n("Status"), 100 ); 00203 mListView->addColumn( i18n("RSVP"), 55 ); 00204 mListView->addColumn( i18n("Delegated to"), 120 ); 00205 mListView->addColumn( i18n("Delegated from" ), 120 ); 00206 mListView->setResizeMode( TQListView::LastColumn ); 00207 if ( KOPrefs::instance()->mCompactDialogs ) { 00208 mListView->setFixedHeight( 78 ); 00209 } 00210 00211 connect( mListView, TQT_SIGNAL( selectionChanged( TQListViewItem * ) ), 00212 TQT_SLOT( updateAttendeeInput() ) ); 00213 #ifndef KORG_NODND 00214 connect( mListView, TQT_SIGNAL( dropped( Attendee * ) ), 00215 TQT_SLOT( slotInsertAttendee( Attendee * ) ) ); 00216 #endif 00217 topLayout->addWidget( mListView ); 00218 00219 initEditWidgets( this, topLayout ); 00220 00221 connect( mRemoveButton, TQT_SIGNAL(clicked()), TQT_SLOT(removeAttendee()) ); 00222 00223 updateAttendeeInput(); 00224 } 00225 00226 KOEditorDetails::~KOEditorDetails() 00227 { 00228 } 00229 00230 bool KOEditorDetails::hasAttendees() 00231 { 00232 return mListView->childCount() > 0; 00233 } 00234 00235 void KOEditorDetails::removeAttendee() 00236 { 00237 AttendeeListItem *aItem = 00238 static_cast<AttendeeListItem *>( mListView->selectedItem() ); 00239 if ( !aItem ) return; 00240 00241 AttendeeListItem *nextSelectedItem = static_cast<AttendeeListItem*>( aItem->nextSibling() ); 00242 if( mListView->childCount() == 1 ) 00243 nextSelectedItem = 0; 00244 if( mListView->childCount() > 1 && aItem == mListView->lastItem() ) 00245 nextSelectedItem = static_cast<AttendeeListItem*>( mListView->firstChild() ); 00246 00247 Attendee *attendee = aItem->data(); 00248 Attendee *delA = new Attendee( attendee->name(), attendee->email(), 00249 attendee->RSVP(), attendee->status(), 00250 attendee->role(), attendee->uid() ); 00251 mdelAttendees.append( delA ); 00252 delete aItem; 00253 00254 if( nextSelectedItem ) { 00255 mListView->setSelected( nextSelectedItem, true ); 00256 } 00257 updateAttendeeInput(); 00258 emit updateAttendeeSummary( mListView->childCount() ); 00259 } 00260 00261 00262 void KOEditorDetails::insertAttendee( Attendee *a, bool goodEmailAddress ) 00263 { 00264 Q_UNUSED( goodEmailAddress ); 00265 00266 // lastItem() is O(n), but for n very small that should be fine 00267 AttendeeListItem *item = new AttendeeListItem( 00268 a, mListView, static_cast<TDEListViewItem*>( mListView->lastItem() ) ); 00269 mListView->setSelected( item, true ); 00270 emit updateAttendeeSummary( mListView->childCount() ); 00271 } 00272 00273 void KOEditorDetails::removeAttendee( Attendee *attendee ) 00274 { 00275 TQListViewItem *item; 00276 for ( item = mListView->firstChild(); item; item = item->nextSibling() ) { 00277 AttendeeListItem *anItem = static_cast<AttendeeListItem *>( item ); 00278 Attendee *att = anItem->data(); 00279 if ( att == attendee ) { 00280 delete anItem; 00281 break; 00282 } 00283 } 00284 } 00285 00286 void KOEditorDetails::setDefaults() 00287 { 00288 mRsvpButton->setChecked( true ); 00289 } 00290 00291 void KOEditorDetails::readEvent( Incidence *event ) 00292 { 00293 mListView->clear(); 00294 KOAttendeeEditor::readEvent( event ); 00295 00296 mListView->setSelected( mListView->firstChild(), true ); 00297 00298 emit updateAttendeeSummary( mListView->childCount() ); 00299 } 00300 00301 void KOEditorDetails::writeEvent(Incidence *event) 00302 { 00303 event->clearAttendees(); 00304 TQValueVector<TQListViewItem*> toBeDeleted; 00305 TQListViewItem *item; 00306 AttendeeListItem *a; 00307 for (item = mListView->firstChild(); item; 00308 item = item->nextSibling()) { 00309 a = (AttendeeListItem *)item; 00310 Attendee *attendee = a->data(); 00311 Q_ASSERT( attendee ); 00312 /* Check if the attendee is a distribution list and expand it */ 00313 if ( attendee->email().isEmpty() ) { 00314 KPIM::DistributionList list = 00315 KPIM::DistributionList::findByName( TDEABC::StdAddressBook::self(), attendee->name() ); 00316 if ( !list.isEmpty() ) { 00317 toBeDeleted.push_back( item ); // remove it once we are done expanding 00318 KPIM::DistributionList::Entry::List entries = list.entries( TDEABC::StdAddressBook::self() ); 00319 KPIM::DistributionList::Entry::List::Iterator it( entries.begin() ); 00320 while ( it != entries.end() ) { 00321 KPIM::DistributionList::Entry &e = ( *it ); 00322 ++it; 00323 // this calls insertAttendee, which appends 00324 insertAttendeeFromAddressee( e.addressee, attendee ); 00325 // TODO: duplicate check, in case it was already added manually 00326 } 00327 } 00328 } else { 00329 bool skip = false; 00330 if ( attendee->email().endsWith( "example.net" ) ) { 00331 if ( KMessageBox::warningYesNo( this, i18n("%1 does not look like a valid email address. " 00332 "Are you sure you want to invite this participant?").arg( attendee->email() ), 00333 i18n("Invalid email address") ) != KMessageBox::Yes ) { 00334 skip = true; 00335 } 00336 } 00337 if ( !skip ) { 00338 event->addAttendee( new Attendee( *attendee ) ); 00339 } 00340 } 00341 } 00342 00343 KOAttendeeEditor::writeEvent( event ); 00344 00345 // cleanup 00346 TQValueVector<TQListViewItem*>::iterator it; 00347 for( it = toBeDeleted.begin(); it != toBeDeleted.end(); ++it ) { 00348 delete *it; 00349 } 00350 } 00351 00352 bool KOEditorDetails::validateInput() 00353 { 00354 return true; 00355 } 00356 00357 KCal::Attendee * KOEditorDetails::currentAttendee() const 00358 { 00359 TQListViewItem *item = mListView->selectedItem(); 00360 AttendeeListItem *aItem = static_cast<AttendeeListItem *>( item ); 00361 if ( !aItem ) 00362 return 0; 00363 return aItem->data(); 00364 } 00365 00366 void KOEditorDetails::updateCurrentItem() 00367 { 00368 AttendeeListItem *item = static_cast<AttendeeListItem*>( mListView->selectedItem() ); 00369 if ( item ) 00370 item->updateItem(); 00371 } 00372 00373 void KOEditorDetails::slotInsertAttendee( Attendee *a ) 00374 { 00375 insertAttendee( a ); 00376 mnewAttendees.append( a ); 00377 } 00378 00379 void KOEditorDetails::setSelected( int index ) 00380 { 00381 int count = 0; 00382 for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { 00383 if ( count == index ) { 00384 mListView->setSelected( *it, true ); 00385 return; 00386 } 00387 count++; 00388 } 00389 } 00390 00391 int KOEditorDetails::selectedIndex() 00392 { 00393 int index = 0; 00394 for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { 00395 if ( mListView->isSelected( *it ) ) { 00396 break; 00397 } 00398 index++; 00399 } 00400 return index; 00401 } 00402 00403 void KOEditorDetails::changeStatusForMe(Attendee::PartStat status) 00404 { 00405 const TQStringList myEmails = KOPrefs::instance()->allEmails(); 00406 for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { 00407 AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() ); 00408 for ( TQStringList::ConstIterator it2( myEmails.begin() ), end( myEmails.end() ); it2 != end; ++it2 ) { 00409 if ( item->data()->email() == *it2 ) { 00410 item->data()->setStatus( status ); 00411 item->updateItem(); 00412 } 00413 } 00414 } 00415 } 00416 00417 TQListViewItem* KOEditorDetails::hasExampleAttendee() const 00418 { 00419 for ( TQListViewItemIterator it( mListView ); it.current(); ++it ) { 00420 AttendeeListItem *item = static_cast<AttendeeListItem*>( it.current() ); 00421 Attendee *attendee = item->data(); 00422 Q_ASSERT( attendee ); 00423 if ( isExampleAttendee( attendee ) ) 00424 return item; 00425 } 00426 return 0; 00427 } 00428 00429 #include "koeditordetails.moc"