libkdepim

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 <qheader.h>
00023 #include <qlabel.h>
00024 #include <qlayout.h>
00025 #include <qsignalmapper.h>
00026 #include <qtoolbutton.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     QStringList titles() const;
00045 
00046     void addResource( KABC::Resource* );
00047     void addAddressBook( const QString &title, SelectionItem::List &list );
00048 
00049     void clear();
00050     bool contains( uint index, const SelectionItem& );
00051 
00052   private:
00053     struct AddressBookEntry {
00054       QString title;
00055       SelectionItem::List list;
00056     };
00057 
00058     QValueList<KABC::Resource*> mResources;
00059     QValueList<AddressBookEntry> mAddressBooks;
00060 };
00061 
00062 QStringList AddresseeSelector::AddressBookManager::titles() const
00063 {
00064   QStringList titles;
00065 
00066   // we've always an 'all' entry
00067   titles.append( i18n( "All" ) );
00068 
00069   QValueList<KABC::Resource*>::ConstIterator resIt;
00070   for ( resIt = mResources.begin(); resIt != mResources.end(); ++resIt )
00071     titles.append( (*resIt)->resourceName() );
00072 
00073   QValueList<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 QString &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 QListViewItem
00188 {
00189   public:
00190     SelectionViewItem( QListView *parent, Selection *selection,
00191                        SelectionItem *item )
00192       : QListViewItem( 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     QString 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 QString::null;
00209     }
00210 
00211     const QPixmap* 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     QPixmap mIcon;
00225 };
00226 
00227 AddresseeSelector::AddresseeSelector( Selection *selection, QWidget *parent, const char *name )
00228   : QWidget( parent, name ), mSelection( selection ), mManager( 0 )
00229 {
00230   mMoveMapper = new QSignalMapper( this );
00231   mRemoveMapper = new QSignalMapper( 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 ), SIGNAL( addressBookChanged( AddressBook* ) ),
00254            this, SLOT( reloadAddressBook() ) );
00255   connect( mAddresseeFilter, SIGNAL( textChanged( const QString& ) ),
00256            this, SLOT( updateAddresseeView() ) );
00257   connect( mAddressBookCombo, SIGNAL( activated( int ) ),
00258            this, SLOT( updateAddresseeView() ) );
00259 
00260   connect( mMoveMapper, SIGNAL( mapped( int ) ),
00261            this, SLOT( move( int ) ) );
00262   connect( mRemoveMapper, SIGNAL( mapped( int ) ),
00263            this, SLOT( remove( int ) ) );
00264 
00265   reloadAddressBook();
00266 }
00267 
00268 void AddresseeSelector::initGUI()
00269 {
00270   QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), KDialog::spacingHint() );
00271   QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint() );
00272 
00273   QLabel *label = new QLabel( 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 QLabel( 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   QIconSet moveSet = KGlobal::iconLoader()->loadIconSet( "next", KIcon::Small );
00292   QIconSet 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, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ),
00302              mRemoveMapper, SLOT( map() ) );
00303     mRemoveMapper->setMapping( listView, i );
00304 
00305     QVBoxLayout *buttonLayout = new QVBoxLayout( this );
00306     buttonLayout->setAlignment( Qt::AlignBottom );
00307     layout->addLayout( buttonLayout, row, 1 );
00308 
00309     // move button
00310     QToolButton *moveButton = new QToolButton( this );
00311     moveButton->setIconSet( moveSet );
00312     moveButton->setFixedSize( 30, 30 );
00313 
00314     connect( moveButton, SIGNAL( clicked() ),
00315              mMoveMapper, SLOT( map() ) );
00316     mMoveMapper->setMapping( moveButton, i );
00317 
00318     // remove button
00319     QToolButton *removeButton = new QToolButton( this );
00320     removeButton->setIconSet( removeSet );
00321     removeButton->setFixedSize( 30, 30 );
00322 
00323     connect( removeButton, SIGNAL( clicked() ),
00324              mRemoveMapper, SLOT( map() ) );
00325     mRemoveMapper->setMapping( 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 QString &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   QStringList lists = mManager->listNames();
00518 
00519   QStringList::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   QPtrList<KABC::Resource> resources = KABC::StdAddressBook::self( true )->resources();
00532   QPtrListIterator<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                                                   QWidget *parent, const char *name )
00565   : KDialogBase( Plain, "", Ok | Cancel, Ok, parent, name, true )
00566 {
00567   QFrame *frame = plainPage();
00568   QVBoxLayout *layout = new QVBoxLayout( 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   QDialog::accept();
00579 }
00580 
00581 #include "addresseeselector.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys