addresseeselector.cpp
00001 /* 00002 This file is part of libkdepim. 00003 00004 Copyright (c) 2004 Tobias Koenig <tokoe@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library 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 GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include <tqheader.h> 00023 #include <tqlabel.h> 00024 #include <tqlayout.h> 00025 #include <tqsignalmapper.h> 00026 #include <tqtoolbutton.h> 00027 00028 #include <kabc/stdaddressbook.h> 00029 #include <kcombobox.h> 00030 #include <kdialog.h> 00031 #include <kglobal.h> 00032 #include <kiconloader.h> 00033 #include <klineedit.h> 00034 #include <klistview.h> 00035 #include <klocale.h> 00036 00037 #include "addresseeselector.h" 00038 00039 using namespace KPIM; 00040 00041 class AddresseeSelector::AddressBookManager 00042 { 00043 public: 00044 TQStringList titles() const; 00045 00046 void addResource( KABC::Resource* ); 00047 void addAddressBook( const TQString &title, SelectionItem::List &list ); 00048 00049 void clear(); 00050 bool contains( uint index, const SelectionItem& ); 00051 00052 private: 00053 struct AddressBookEntry { 00054 TQString title; 00055 SelectionItem::List list; 00056 }; 00057 00058 TQValueList<KABC::Resource*> mResources; 00059 TQValueList<AddressBookEntry> mAddressBooks; 00060 }; 00061 00062 TQStringList AddresseeSelector::AddressBookManager::titles() const 00063 { 00064 TQStringList titles; 00065 00066 // we've always an 'all' entry 00067 titles.append( i18n( "All" ) ); 00068 00069 TQValueList<KABC::Resource*>::ConstIterator resIt; 00070 for ( resIt = mResources.begin(); resIt != mResources.end(); ++resIt ) 00071 titles.append( (*resIt)->resourceName() ); 00072 00073 TQValueList<AddressBookEntry>::ConstIterator abIt; 00074 for ( abIt = mAddressBooks.begin(); abIt != mAddressBooks.end(); ++abIt ) 00075 titles.append( (*abIt).title ); 00076 00077 return titles; 00078 } 00079 00080 void AddresseeSelector::AddressBookManager::addResource( KABC::Resource *resource ) 00081 { 00082 if ( mResources.find( resource ) == mResources.end() ) 00083 mResources.append( resource ); 00084 } 00085 00086 void AddresseeSelector::AddressBookManager::addAddressBook( const TQString &title, 00087 SelectionItem::List &list ) 00088 { 00089 AddressBookEntry entry; 00090 entry.title = title; 00091 entry.list = list; 00092 00093 00094 // TODO: check for duplicates 00095 mAddressBooks.append( entry ); 00096 } 00097 00098 void AddresseeSelector::AddressBookManager::clear() 00099 { 00100 mResources.clear(); 00101 mAddressBooks.clear(); 00102 } 00103 00104 bool AddresseeSelector::AddressBookManager::contains( uint index, const SelectionItem &item ) 00105 { 00106 if ( index == 0 ) // the 'all' entry 00107 return true; 00108 00109 if ( mResources.count() > 0 ) { 00110 if ( index <= mResources.count() ) { 00111 index--; 00112 if ( item.addressee().resource() == mResources[ index ] ) 00113 return true; 00114 else 00115 return false; 00116 } 00117 } 00118 00119 index = index - mResources.count(); 00120 00121 if ( mAddressBooks.count() > 0 ) { 00122 if ( index <= mAddressBooks.count() ) { 00123 index--; 00124 AddressBookEntry entry = mAddressBooks[ index ]; 00125 SelectionItem::List::ConstIterator it; 00126 for ( it = entry.list.begin(); it != entry.list.end(); ++it ) 00127 if ( (*it).addressee() == item.addressee() ) 00128 return true; 00129 00130 return false; 00131 } 00132 } 00133 00134 return false; 00135 } 00136 00137 00138 SelectionItem::SelectionItem( const KABC::Addressee &addressee, uint index ) 00139 : mAddressee( addressee ), mDistributionList( 0 ), mIndex( index ) 00140 { 00141 mField.fill( false, 10 ); 00142 } 00143 00144 SelectionItem::SelectionItem( KABC::DistributionList *list, uint index ) 00145 : mDistributionList( list ), mIndex( index ) 00146 { 00147 mField.fill( false, 10 ); 00148 } 00149 00150 SelectionItem::SelectionItem() 00151 : mDistributionList( 0 ), mIndex( 0 ) 00152 { 00153 mField.fill( false, 10 ); 00154 } 00155 00156 void SelectionItem::addToField( int index ) 00157 { 00158 mField.setBit( index ); 00159 } 00160 00161 void SelectionItem::removeFromField( int index ) 00162 { 00163 mField.clearBit( index ); 00164 } 00165 00166 bool SelectionItem::isInField( int index ) 00167 { 00168 return mField.testBit( index ); 00169 } 00170 00171 KABC::Addressee SelectionItem::addressee() const 00172 { 00173 return mAddressee; 00174 } 00175 00176 KABC::DistributionList* SelectionItem::distributionList() const 00177 { 00178 return mDistributionList; 00179 } 00180 00181 uint SelectionItem::index() const 00182 { 00183 return mIndex; 00184 } 00185 00186 00187 class SelectionViewItem : public TQListViewItem 00188 { 00189 public: 00190 SelectionViewItem( TQListView *parent, Selection *selection, 00191 SelectionItem *item ) 00192 : TQListViewItem( parent, "" ), mSelection( selection ), mItem( item ) 00193 { 00194 if ( mItem->distributionList() == 0 ) 00195 mIcon = mSelection->itemIcon( mItem->addressee(), mItem->index() ); 00196 else 00197 mIcon = mSelection->distributionListIcon( mItem->distributionList() ); 00198 } 00199 00200 TQString text( int column ) const 00201 { 00202 if ( column == 0 ) { 00203 if ( mItem->distributionList() == 0 ) 00204 return mSelection->itemText( mItem->addressee(), mItem->index() ); 00205 else 00206 return mSelection->distributionListText( mItem->distributionList() ); 00207 } else 00208 return TQString(); 00209 } 00210 00211 const TQPixmap* pixmap( int column ) const 00212 { 00213 if ( column == 0 ) { 00214 return &mIcon; 00215 } else 00216 return 0; 00217 } 00218 00219 SelectionItem* item() const { return mItem; } 00220 00221 private: 00222 Selection *mSelection; 00223 SelectionItem *mItem; 00224 TQPixmap mIcon; 00225 }; 00226 00227 AddresseeSelector::AddresseeSelector( Selection *selection, TQWidget *parent, const char *name ) 00228 : TQWidget( parent, name ), mSelection( selection ), mManager( 0 ) 00229 { 00230 mMoveMapper = new TQSignalMapper( TQT_TQOBJECT(this) ); 00231 mRemoveMapper = new TQSignalMapper( TQT_TQOBJECT(this) ); 00232 00233 mAddressBookManager = new AddressBookManager(); 00234 00235 initGUI(); 00236 00237 init(); 00238 00239 mSelection->setSelector( this ); 00240 } 00241 00242 AddresseeSelector::~AddresseeSelector() 00243 { 00244 delete mManager; 00245 mManager = 0; 00246 00247 delete mAddressBookManager; 00248 mAddressBookManager = 0; 00249 } 00250 00251 void AddresseeSelector::init() 00252 { 00253 connect( KABC::StdAddressBook::self( true ), TQT_SIGNAL( addressBookChanged( AddressBook* ) ), 00254 this, TQT_SLOT( reloadAddressBook() ) ); 00255 connect( mAddresseeFilter, TQT_SIGNAL( textChanged( const TQString& ) ), 00256 this, TQT_SLOT( updateAddresseeView() ) ); 00257 connect( mAddressBookCombo, TQT_SIGNAL( activated( int ) ), 00258 this, TQT_SLOT( updateAddresseeView() ) ); 00259 00260 connect( mMoveMapper, TQT_SIGNAL( mapped( int ) ), 00261 this, TQT_SLOT( move( int ) ) ); 00262 connect( mRemoveMapper, TQT_SIGNAL( mapped( int ) ), 00263 this, TQT_SLOT( remove( int ) ) ); 00264 00265 reloadAddressBook(); 00266 } 00267 00268 void AddresseeSelector::initGUI() 00269 { 00270 TQGridLayout *layout = new TQGridLayout( this, 2, 3, KDialog::marginHint(), KDialog::spacingHint() ); 00271 TQGridLayout *topLayout = new TQGridLayout( this, 2, 2, KDialog::marginHint() ); 00272 00273 TQLabel *label = new TQLabel( i18n( "Address book:" ), this ); 00274 mAddressBookCombo = new KComboBox( false, this ); 00275 00276 topLayout->addWidget( label, 0, 0 ); 00277 topLayout->addWidget( mAddressBookCombo, 0, 1 ); 00278 00279 label = new TQLabel( i18n( "Search:" ), this ); 00280 mAddresseeFilter = new KLineEdit( this ); 00281 00282 topLayout->addWidget( label, 1, 0 ); 00283 topLayout->addWidget( mAddresseeFilter, 1, 1 ); 00284 00285 topLayout->setColStretch( 1, 1 ); 00286 00287 layout->addMultiCellLayout( topLayout, 0, 0, 0, 2 ); 00288 00289 int row = 1; 00290 00291 TQIconSet moveSet = KGlobal::iconLoader()->loadIconSet( "next", KIcon::Small ); 00292 TQIconSet removeSet = KGlobal::iconLoader()->loadIconSet( "previous", KIcon::Small ); 00293 00294 uint count = mSelection->fieldCount(); 00295 for ( uint i = 0; i < count; ++i, ++row ) { 00296 KListView *listView = new KListView( this ); 00297 listView->addColumn( mSelection->fieldTitle( i ) ); 00298 listView->setFullWidth( true ); 00299 mSelectionViews.append( listView ); 00300 00301 connect( listView, TQT_SIGNAL( doubleClicked( TQListViewItem*, const TQPoint&, int ) ), 00302 mRemoveMapper, TQT_SLOT( map() ) ); 00303 mRemoveMapper->setMapping( TQT_TQOBJECT(listView), i ); 00304 00305 TQVBoxLayout *buttonLayout = new TQVBoxLayout( this ); 00306 buttonLayout->setAlignment( TQt::AlignBottom ); 00307 layout->addLayout( buttonLayout, row, 1 ); 00308 00309 // move button 00310 TQToolButton *moveButton = new TQToolButton( this ); 00311 moveButton->setIconSet( moveSet ); 00312 moveButton->setFixedSize( 30, 30 ); 00313 00314 connect( moveButton, TQT_SIGNAL( clicked() ), 00315 mMoveMapper, TQT_SLOT( map() ) ); 00316 mMoveMapper->setMapping( TQT_TQOBJECT(moveButton), i ); 00317 00318 // remove button 00319 TQToolButton *removeButton = new TQToolButton( this ); 00320 removeButton->setIconSet( removeSet ); 00321 removeButton->setFixedSize( 30, 30 ); 00322 00323 connect( removeButton, TQT_SIGNAL( clicked() ), 00324 mRemoveMapper, TQT_SLOT( map() ) ); 00325 mRemoveMapper->setMapping( TQT_TQOBJECT(removeButton), i ); 00326 00327 buttonLayout->addWidget( moveButton ); 00328 buttonLayout->addWidget( removeButton ); 00329 00330 layout->addWidget( listView, row, 2 ); 00331 } 00332 00333 mAddresseeView = new KListView( this ); 00334 mAddresseeView->addColumn( "" ); 00335 mAddresseeView->header()->hide(); 00336 mAddresseeView->setFullWidth( true ); 00337 00338 layout->addMultiCellWidget( mAddresseeView, 1, row, 0, 0 ); 00339 } 00340 00341 void AddresseeSelector::finish() 00342 { 00343 SelectionItem::List::Iterator it; 00344 00345 for ( uint field = 0; field < mSelection->fieldCount(); ++field ) { 00346 for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) { 00347 if ( (*it).isInField( field ) ) { 00348 if ( (*it).distributionList() == 0 ) 00349 mSelection->addSelectedAddressees( field, (*it).addressee(), (*it).index() ); 00350 else 00351 mSelection->addSelectedDistributionList( field, (*it).distributionList() ); 00352 } 00353 } 00354 } 00355 } 00356 00357 void AddresseeSelector::updateAddresseeView() 00358 { 00359 mAddresseeView->clear(); 00360 00361 int addressBookIndex = mAddressBookCombo->currentItem(); 00362 00363 SelectionItem::List::Iterator it; 00364 for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) { 00365 if ( mAddressBookManager->contains( addressBookIndex, *it ) ) { 00366 if ( (*it).distributionList() == 0 ) { 00367 if ( mAddresseeFilter->text().isEmpty() || 00368 mSelection->itemMatches( (*it).addressee(), (*it).index(), 00369 mAddresseeFilter->text() ) ) 00370 new SelectionViewItem( mAddresseeView, mSelection, &(*it) ); 00371 } else { 00372 if ( mAddresseeFilter->text().isEmpty() || 00373 mSelection->distributionListMatches( (*it).distributionList(), 00374 mAddresseeFilter->text() ) ) 00375 new SelectionViewItem( mAddresseeView, mSelection, &(*it) ); 00376 } 00377 } 00378 } 00379 00380 updateSelectionViews(); 00381 } 00382 00383 void AddresseeSelector::move( int index ) 00384 { 00385 SelectionViewItem *item = dynamic_cast<SelectionViewItem*>( mAddresseeView->selectedItem() ); 00386 if ( item ) { 00387 item->item()->addToField( index ); 00388 updateSelectionView( index ); 00389 } 00390 } 00391 00392 void AddresseeSelector::remove( int index ) 00393 { 00394 KListView *view = mSelectionViews[ index ]; 00395 00396 SelectionViewItem *item = dynamic_cast<SelectionViewItem*>( view->selectedItem() ); 00397 if ( item ) { 00398 item->item()->removeFromField( index ); 00399 updateSelectionView( index ); 00400 } 00401 } 00402 00403 void AddresseeSelector::setItemSelected( uint fieldIndex, const KABC::Addressee &addr, uint itemIndex ) 00404 { 00405 bool found = false; 00406 00407 SelectionItem::List::Iterator it; 00408 for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) { 00409 if ( (*it).addressee() == addr && (*it).index() == itemIndex ) { 00410 (*it).addToField( fieldIndex ); 00411 found = true; 00412 } 00413 } 00414 00415 if ( !found ) { 00416 SelectionItem item( addr, itemIndex ); 00417 item.addToField( fieldIndex ); 00418 00419 mSelectionItems.append( item ); 00420 } 00421 00422 updateSelectionView( fieldIndex ); 00423 } 00424 00425 void AddresseeSelector::setItemSelected( uint fieldIndex, const KABC::Addressee &addr, 00426 uint itemIndex, const TQString &text ) 00427 { 00428 bool found = false; 00429 00430 SelectionItem::List::Iterator it; 00431 for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) { 00432 if ( mSelection->itemEquals( (*it).addressee(), (*it).index(), text ) ) { 00433 (*it).addToField( fieldIndex ); 00434 found = true; 00435 } 00436 } 00437 00438 if ( !found ) { 00439 SelectionItem item( addr, itemIndex ); 00440 item.addToField( fieldIndex ); 00441 00442 mSelectionItems.append( item ); 00443 } 00444 00445 updateSelectionView( fieldIndex ); 00446 } 00447 00448 void AddresseeSelector::updateSelectionView( int index ) 00449 { 00450 KListView *view = mSelectionViews[ index ]; 00451 view->clear(); 00452 00453 SelectionItem::List::Iterator it; 00454 for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) { 00455 if ( (*it).isInField( index ) ) 00456 new SelectionViewItem( view, mSelection, &(*it) ); 00457 } 00458 } 00459 00460 void AddresseeSelector::updateSelectionViews() 00461 { 00462 for ( uint i = 0; i < mSelection->fieldCount(); ++i ) 00463 updateSelectionView( i ); 00464 } 00465 00466 void AddresseeSelector::reloadAddressBook() 00467 { 00468 // load contacts 00469 KABC::Addressee::List list = KABC::StdAddressBook::self( true )->allAddressees(); 00470 KABC::Addressee::List::Iterator it; 00471 00472 SelectionItem::List selectedItems; 00473 00474 SelectionItem::List::Iterator itemIt; 00475 for ( itemIt = mSelectionItems.begin(); itemIt != mSelectionItems.end(); ++itemIt ) { 00476 bool isSelected = false; 00477 for ( uint i = 0; i < mSelection->fieldCount(); ++i ) { 00478 if ( (*itemIt).isInField( i ) ) { 00479 isSelected = true; 00480 break; 00481 } 00482 } 00483 00484 // we don't save distribution lists, since this leads to crashes 00485 if ( isSelected && (*itemIt).distributionList() == 0 ) { 00486 selectedItems.append( *itemIt ); 00487 } 00488 } 00489 00490 mSelectionItems.clear(); 00491 mSelectionItems = selectedItems; 00492 00493 for ( it = list.begin(); it != list.end(); ++it ) { 00494 uint itemCount = mSelection->itemCount( *it ); 00495 for ( uint index = 0; index < itemCount; ++index ) { 00496 bool available = false; 00497 for ( itemIt = mSelectionItems.begin(); itemIt != mSelectionItems.end(); ++itemIt ) { 00498 if ( (*itemIt).addressee() == (*it) && (*itemIt).index() == index ) { 00499 available = true; 00500 break; 00501 } 00502 } 00503 00504 if ( !available ) { 00505 SelectionItem item( *it, index ); 00506 mSelectionItems.append( item ); 00507 } 00508 } 00509 } 00510 00511 // load distribution lists 00512 delete mManager; 00513 mManager = new KABC::DistributionListManager( KABC::StdAddressBook::self( true ) ); 00514 00515 mManager->load(); 00516 00517 TQStringList lists = mManager->listNames(); 00518 00519 TQStringList::Iterator listIt; 00520 for ( listIt = lists.begin(); listIt != lists.end(); ++listIt ) { 00521 KABC::DistributionList *list = mManager->list( *listIt ); 00522 SelectionItem item( list, 0 ); 00523 mSelectionItems.append( item ); 00524 } 00525 00526 mAddressBookManager->clear(); 00527 00528 // update address book combo 00529 mAddressBookCombo->clear(); 00530 00531 TQPtrList<KABC::Resource> resources = KABC::StdAddressBook::self( true )->resources(); 00532 TQPtrListIterator<KABC::Resource> resIt( resources ); 00533 while ( resIt.current() ) { 00534 if ( resIt.current()->isActive() ) 00535 mAddressBookManager->addResource( resIt ); 00536 00537 ++resIt; 00538 } 00539 00540 for ( uint i = 0; i < mSelection->addressBookCount(); ++i ) { 00541 SelectionItem::List itemList; 00542 00543 KABC::Addressee::List addrList = mSelection->addressBookContent( i ); 00544 for ( it = addrList.begin(); it != addrList.end(); ++it ) { 00545 uint itemCount = mSelection->itemCount( *it ); 00546 for ( uint index = 0; index < itemCount; ++index ) { 00547 SelectionItem item( *it, index ); 00548 mSelectionItems.append( item ); 00549 itemList.append( item ); 00550 } 00551 } 00552 00553 mAddressBookManager->addAddressBook( mSelection->addressBookTitle( i ), 00554 itemList ); 00555 } 00556 00557 mAddressBookCombo->insertStringList( mAddressBookManager->titles() ); 00558 00559 updateAddresseeView(); 00560 } 00561 00562 00563 AddresseeSelectorDialog::AddresseeSelectorDialog( Selection *selection, 00564 TQWidget *parent, const char *name ) 00565 : KDialogBase( Plain, "", Ok | Cancel, Ok, parent, name, true ) 00566 { 00567 TQFrame *frame = plainPage(); 00568 TQVBoxLayout *layout = new TQVBoxLayout( frame ); 00569 mSelector = new KPIM::AddresseeSelector( selection, frame ); 00570 layout->addWidget( mSelector ); 00571 00572 resize( 500, 490 ); 00573 } 00574 00575 void AddresseeSelectorDialog::accept() 00576 { 00577 mSelector->finish(); 00578 TQDialog::accept(); 00579 } 00580 00581 #include "addresseeselector.moc"