kaddressbook Library API Documentation

ldapsearchdialog.cpp

00001 /* ldapsearchdialogimpl.cpp - LDAP access
00002  *      Copyright (C) 2002 Klar�vdalens Datakonsult AB
00003  *
00004  *      Author: Steffen Hansen <hansen@kde.org>
00005  *
00006  * This file is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation; either version 2 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This file 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
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00019  */
00020 
00021 
00022 #include <qcheckbox.h>
00023 #include <qgroupbox.h>
00024 #include <qheader.h>
00025 #include <qlabel.h>
00026 #include <qlayout.h>
00027 #include <qlistview.h>
00028 #include <qpushbutton.h>
00029 
00030 #include <addresseelineedit.h>
00031 #include <kapplication.h>
00032 #include <kcombobox.h>
00033 #include <kconfig.h>
00034 #include <klineedit.h>
00035 #include <klocale.h>
00036 #include <kmessagebox.h>
00037 
00038 #include "kabcore.h"
00039 #include "ldapsearchdialog.h"
00040 #include "kablock.h"
00041 
00042 static QString asUtf8( const QByteArray &val )
00043 {
00044   if ( val.isEmpty() )
00045     return QString::null;
00046 
00047   const char *data = val.data();
00048 
00049   //QString::fromUtf8() bug workaround
00050   if ( data[ val.size() - 1 ] == '\0' ) 
00051     return QString::fromUtf8( data, val.size() - 1 );
00052   else
00053     return QString::fromUtf8( data, val.size() );
00054 }
00055 
00056 static QString join( const KPIM::LdapAttrValue& lst, const QString& sep )
00057 {
00058   QString res;
00059   bool alredy = false;
00060   for ( KPIM::LdapAttrValue::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
00061     if ( alredy )
00062       res += sep;
00063     alredy = TRUE;
00064     res += asUtf8( *it );
00065   }
00066   return res;
00067 }
00068 
00069 static QMap<QString, QString>& adrbookattr2ldap()
00070 {
00071   static QMap<QString, QString> keys;
00072 
00073   if ( keys.isEmpty() ) {
00074     keys[ i18n( "Title" ) ] = "title";
00075     keys[ i18n( "Full Name" ) ] = "cn";
00076     keys[ i18n( "Email" ) ] = "mail";
00077     keys[ i18n( "Home Number" ) ] = "homePhone";
00078     keys[ i18n( "Work Number" ) ] = "telephoneNumber";
00079     keys[ i18n( "Mobile Number" ) ] = "mobile";
00080     keys[ i18n( "Fax Number" ) ] = "facsimileTelephoneNumber";
00081     keys[ i18n( "Pager" ) ] = "pager";
00082     keys[ i18n( "Street") ] = "street";
00083     keys[ i18n( "State" ) ] = "st";
00084     keys[ i18n( "Country" ) ] = "co";
00085     keys[ i18n( "City" ) ] = "l";
00086     keys[ i18n( "Organization" ) ] = "o";
00087     keys[ i18n( "Company" ) ] = "Company";
00088     keys[ i18n( "Department" ) ] = "department";
00089     keys[ i18n( "Zip Code" ) ] = "postalCode";
00090     keys[ i18n( "Postal Address" ) ] = "postalAddress";
00091     keys[ i18n( "Description" ) ] = "description";
00092     keys[ i18n( "User ID" ) ] = "uid";
00093   }
00094   return keys;
00095 }
00096 
00097 class ContactListItem : public QListViewItem
00098 {
00099   public:
00100     ContactListItem( QListView* parent, const KPIM::LdapAttrMap& attrs )
00101       : QListViewItem( parent ), mAttrs( attrs )
00102     { }
00103 
00104     KPIM::LdapAttrMap mAttrs;
00105 
00106     virtual QString text( int col ) const
00107     {
00108       // Look up a suitable attribute for column col
00109       QString colName = listView()->columnText( col );
00110       return join( mAttrs[ adrbookattr2ldap()[ colName ] ], ", " );
00111     }
00112 };
00113 
00114 LDAPSearchDialog::LDAPSearchDialog( KABC::AddressBook *ab, KABCore *core,
00115                                     QWidget* parent, const char* name )
00116   : KDialogBase( Plain, i18n( "Search for Addresses in Directory" ), Help | User1 |
00117     User2 | User3 | Cancel, Default, parent, name, false, true ),
00118     mAddressBook( ab ), mCore( core )
00119 {
00120   setButtonCancel( KStdGuiItem::close() );
00121   QFrame *page = plainPage();
00122   QVBoxLayout *topLayout = new QVBoxLayout( page, marginHint(), spacingHint() );
00123 
00124   QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ),
00125                                        page );
00126   groupBox->setFrameShape( QGroupBox::Box );
00127   groupBox->setFrameShadow( QGroupBox::Sunken );
00128   groupBox->setColumnLayout( 0, Qt::Vertical );
00129   QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 2,
00130                                             5, spacingHint() );
00131   boxLayout->setColStretch( 1, 1 );
00132 
00133   QLabel *label = new QLabel( i18n( "Search for:" ), groupBox );
00134   boxLayout->addWidget( label, 0, 0 );
00135 
00136   mSearchEdit = new KLineEdit( groupBox );
00137   boxLayout->addWidget( mSearchEdit, 0, 1 );
00138   label->setBuddy( mSearchEdit );
00139 
00140   label = new QLabel( i18n( "in" ), groupBox );
00141   boxLayout->addWidget( label, 0, 2 );
00142 
00143   mFilterCombo = new KComboBox( groupBox );
00144   mFilterCombo->insertItem( i18n( "Name" ) );
00145   mFilterCombo->insertItem( i18n( "Email" ) );
00146   mFilterCombo->insertItem( i18n( "Home Number" ) );
00147   mFilterCombo->insertItem( i18n( "Work Number" ) );
00148   boxLayout->addWidget( mFilterCombo, 0, 3 );
00149 
00150   QSize buttonSize;
00151   mSearchButton = new QPushButton( i18n( "Stop" ), groupBox );
00152   buttonSize = mSearchButton->sizeHint();
00153   mSearchButton->setText( i18n( "Search" ) );
00154   if ( buttonSize.width() < mSearchButton->sizeHint().width() )
00155     buttonSize = mSearchButton->sizeHint();
00156   mSearchButton->setFixedWidth( buttonSize.width() );
00157 
00158   mSearchButton->setDefault( true );
00159   boxLayout->addWidget( mSearchButton, 0, 4 );
00160 
00161   mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox  );
00162   mRecursiveCheckbox->setChecked( true );
00163   boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 );
00164 
00165   mSearchType = new KComboBox( groupBox );
00166   mSearchType->insertItem( i18n( "Contains" ) );
00167   mSearchType->insertItem( i18n( "Starts With" ) );
00168   boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 );
00169   
00170   topLayout->addWidget( groupBox );
00171 
00172   mResultListView = new QListView( page );
00173   mResultListView->setSelectionMode( QListView::Multi );
00174   mResultListView->setAllColumnsShowFocus( true );
00175   mResultListView->setShowSortIndicator( true );
00176   topLayout->addWidget( mResultListView );
00177 
00178   resize( QSize( 600, 400).expandedTo( minimumSizeHint() ) );
00179 
00180   setButtonText( User1, i18n( "Unselect All" ) );
00181   setButtonText( User2, i18n( "Select All" ) );
00182   setButtonText( User3, i18n( "Add Selected" ) );
00183 
00184   mNumHosts = 0;
00185   mIsOK = false;
00186 
00187   connect( mRecursiveCheckbox, SIGNAL( toggled( bool ) ),
00188        this, SLOT( slotSetScope( bool ) ) );
00189   connect( mSearchButton, SIGNAL( clicked() ),
00190        this, SLOT( slotStartSearch() ) );
00191 
00192   setTabOrder(mSearchEdit, mFilterCombo);
00193   setTabOrder(mFilterCombo, mSearchButton);
00194   mSearchEdit->setFocus();
00195 
00196   restoreSettings();
00197 }
00198 
00199 LDAPSearchDialog::~LDAPSearchDialog()
00200 {
00201   saveSettings();
00202 }
00203 
00204 void LDAPSearchDialog::restoreSettings()
00205 {
00206   // Create one KPIM::LdapClient per selected server and configure it.
00207 
00208   // First clean the list to make sure it is empty at 
00209   // the beginning of the process
00210   mLdapClientList.setAutoDelete( true );
00211   mLdapClientList.clear();
00212 
00213   KConfig kabConfig( "kaddressbookrc" );
00214   kabConfig.setGroup( "LDAPSearch" );
00215   mSearchType->setCurrentItem( kabConfig.readNumEntry( "SearchType", 0 ) );
00216 
00217   // then read the config file and register all selected 
00218   // server in the list
00219   KConfig* config = KPIM::AddresseeLineEdit::config();
00220   KConfigGroupSaver saver( config, "LDAP" );
00221   mNumHosts = config->readUnsignedNumEntry( "NumSelectedHosts" ); 
00222   if ( !mNumHosts ) {
00223     KMessageBox::error( this, i18n( "You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) );
00224     mIsOK = false;
00225   } else {
00226     mIsOK = true;
00227     for ( int j = 0; j < mNumHosts; ++j ) {
00228       KPIM::LdapClient* ldapClient = new KPIM::LdapClient( 0, this, "ldapclient" );
00229     
00230       QString host = config->readEntry( QString( "SelectedHost%1" ).arg( j ), "" );
00231       if ( !host.isEmpty() )
00232         ldapClient->setHost( host );
00233 
00234       QString port = QString::number( config->readUnsignedNumEntry( QString( "SelectedPort%1" ).arg( j ) ) );
00235       if ( !port.isEmpty() )
00236         ldapClient->setPort( port );
00237 
00238       QString base = config->readEntry( QString( "SelectedBase%1" ).arg( j ), "" );
00239       if ( !base.isEmpty() )
00240         ldapClient->setBase( base );
00241 
00242       QString bindDN = config->readEntry( QString( "SelectedBind%1" ).arg( j ), "" );
00243       if ( !bindDN.isEmpty() )
00244         ldapClient->setBindDN( bindDN );
00245 
00246       QString pwdBindDN = config->readEntry( QString( "SelectedPwdBind%1" ).arg( j ), "" );
00247       if ( !pwdBindDN.isEmpty() )
00248         ldapClient->setPwdBindDN( pwdBindDN );
00249 
00250       QStringList attrs;
00251 
00252       for ( QMap<QString,QString>::Iterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it )
00253         attrs << *it;
00254         
00255       ldapClient->setAttrs( attrs );
00256 
00257       connect( ldapClient, SIGNAL( result( const KPIM::LdapObject& ) ),
00258            this, SLOT( slotAddResult( const KPIM::LdapObject& ) ) );
00259       connect( ldapClient, SIGNAL( done() ),
00260            this, SLOT( slotSearchDone() ) ); 
00261       connect( ldapClient, SIGNAL( error( const QString& ) ),
00262            this, SLOT( slotError( const QString& ) ) );
00263 
00264       mLdapClientList.append( ldapClient );     
00265     }
00266 
00268     while ( mResultListView->header()->count() > 0 ) {
00269       mResultListView->removeColumn(0);
00270     }
00271 
00272     mResultListView->addColumn( i18n( "Full Name" ) );
00273     mResultListView->addColumn( i18n( "Email" ) );
00274     mResultListView->addColumn( i18n( "Home Number" ) );
00275     mResultListView->addColumn( i18n( "Work Number" ) );
00276     mResultListView->addColumn( i18n( "Mobile Number" ) );
00277     mResultListView->addColumn( i18n( "Fax Number" ) );
00278     mResultListView->addColumn( i18n( "Company" ) );
00279     mResultListView->addColumn( i18n( "Organization" ) );
00280     mResultListView->addColumn( i18n( "Street" ) );
00281     mResultListView->addColumn( i18n( "State" ) );
00282     mResultListView->addColumn( i18n( "Country" ) );
00283     mResultListView->addColumn( i18n( "Zip Code" ) );
00284     mResultListView->addColumn( i18n( "Postal Address" ) );
00285     mResultListView->addColumn( i18n( "City" ) );
00286     mResultListView->addColumn( i18n( "Department" ) );
00287     mResultListView->addColumn( i18n( "Description" ) );
00288     mResultListView->addColumn( i18n( "User ID" ) );
00289     mResultListView->addColumn( i18n( "Title" ) );
00290 
00291     mResultListView->clear();
00292   }
00293 }
00294 
00295 void LDAPSearchDialog::saveSettings()
00296 {
00297   KConfig config( "kaddressbookrc" );
00298   config.setGroup( "LDAPSearch" );
00299   config.writeEntry( "SearchType", mSearchType->currentItem() );
00300   config.sync();
00301 }
00302 
00303 void LDAPSearchDialog::cancelQuery()
00304 {
00305   for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00306     client->cancelQuery();
00307   }
00308 }
00309 
00310 void LDAPSearchDialog::slotAddResult( const KPIM::LdapObject& obj )
00311 {
00312   new ContactListItem( mResultListView, obj.attrs );
00313 }
00314 
00315 void LDAPSearchDialog::slotSetScope( bool rec )
00316 {
00317   for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00318     if ( rec )
00319       client->setScope( "sub" );
00320     else
00321       client->setScope( "one" );  
00322   }
00323 }
00324 
00325 QString LDAPSearchDialog::makeFilter( const QString& query, const QString& attr,
00326                                       bool startsWith )
00327 {
00328   if( query.isEmpty() )
00329     // Return a filter that matches everything
00330     return QString( "|(cn=*)(sn=*)" );
00331 
00332   if ( attr == i18n( "Name" ) ) {
00333     QString result( (startsWith ? "|(cn=%1*)(sn=%2*)" : "|(cn=*%1*)(sn=*%2*)") );
00334 
00335     result = result.arg( query ).arg( query );
00336 
00337     return result;
00338   } else {
00339     QString result( (startsWith ? "%1=%2*" : "%1=*%2*") );
00340 
00341     if ( attr == i18n( "Email" ) ) {
00342       result = result.arg( "mail" ).arg( query );
00343     } else if ( attr == i18n( "Home Number" ) ) {
00344       result = result.arg( "homePhone" ).arg( query );
00345     } else if ( attr == i18n( "Work Number" ) ) {
00346       result = result.arg( "telephoneNumber" ).arg( query );
00347     } else {
00348       // Error?
00349       result = QString::null;
00350     }
00351 
00352     return result;
00353   }
00354 }
00355 
00356 void LDAPSearchDialog::slotStartSearch()
00357 {
00358   cancelQuery();
00359 
00360   QApplication::setOverrideCursor( Qt::waitCursor );
00361   mSearchButton->setText( i18n( "Stop" ) );
00362 
00363   disconnect( mSearchButton, SIGNAL( clicked() ),
00364               this, SLOT( slotStartSearch() ) );
00365   connect( mSearchButton, SIGNAL( clicked() ),
00366            this, SLOT( slotStopSearch() ) );
00367 
00368   bool startsWith = (mSearchType->currentItem() == 1);
00369 
00370   QString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith );
00371 
00372    // loop in the list and run the KPIM::LdapClients 
00373   mResultListView->clear();
00374   for( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00375     client->startQuery( filter );
00376   }
00377 
00378   saveSettings();
00379 }
00380 
00381 void LDAPSearchDialog::slotStopSearch()
00382 {
00383   cancelQuery();
00384   slotSearchDone();
00385 }
00386 
00387 void LDAPSearchDialog::slotSearchDone()
00388 {
00389   // If there are no more active clients, we are done.
00390   for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00391     if ( client->isActive() )
00392       return;
00393   }
00394 
00395   disconnect( mSearchButton, SIGNAL( clicked() ),
00396               this, SLOT( slotStopSearch() ) );
00397   connect( mSearchButton, SIGNAL( clicked() ),
00398            this, SLOT( slotStartSearch() ) );
00399 
00400   mSearchButton->setText( i18n( "Search" ) );
00401   QApplication::restoreOverrideCursor();
00402 }
00403 
00404 void LDAPSearchDialog::slotError( const QString& error )
00405 {
00406   QApplication::restoreOverrideCursor();
00407   KMessageBox::error( this, error );
00408 }
00409 
00410 void LDAPSearchDialog::closeEvent( QCloseEvent* e )
00411 {
00412   slotStopSearch();
00413   e->accept();
00414 }
00415 
00420 QString LDAPSearchDialog::selectedEMails() const
00421 {
00422   QStringList result;
00423   ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
00424   while ( cli ) {
00425     if ( cli->isSelected() ) {
00426       QString email = asUtf8( cli->mAttrs[ "mail" ].first() ).stripWhiteSpace();
00427       if ( !email.isEmpty() ) {
00428         QString name = asUtf8( cli->mAttrs[ "cn" ].first() ).stripWhiteSpace();
00429         if ( name.isEmpty() ) {
00430           result << email;
00431         } else {
00432           result << name + " <" + email + ">";
00433         }
00434       }
00435     }
00436     cli = static_cast<ContactListItem*>( cli->nextSibling() );
00437   }
00438 
00439   return result.join( ", " );
00440 }
00441 
00442 void LDAPSearchDialog::slotHelp()
00443 {
00444   kapp->invokeHelp( "ldap-queries" );
00445 }
00446 
00447 void LDAPSearchDialog::slotUser1()
00448 {
00449   mResultListView->selectAll( false );
00450 }
00451 
00452 void LDAPSearchDialog::slotUser2()
00453 {
00454   mResultListView->selectAll( true );
00455 }
00456 
00457 void LDAPSearchDialog::slotUser3()
00458 {
00459   
00460   KABC::Resource *resource = mCore->requestResource( this );
00461   if ( !resource ) return;
00462   KABLock::self( mAddressBook )->lock( resource );
00463 
00464   ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
00465   while ( cli ) {
00466     if ( cli->isSelected() ) {
00467       KABC::Addressee addr;
00468 
00469       // name
00470       addr.setNameFromString( asUtf8( cli->mAttrs["cn"].first() ) );
00471 
00472       // email
00473       KPIM::LdapAttrValue lst = cli->mAttrs["mail"];
00474       KPIM::LdapAttrValue::ConstIterator it = lst.begin();
00475       bool pref = true;
00476       if ( it != lst.end() ) {
00477         addr.insertEmail( asUtf8( *it ), pref );
00478         pref = false;
00479         ++it;
00480       }
00481 
00482       addr.setOrganization( asUtf8( cli->mAttrs[ "o" ].first() ) );
00483       if ( addr.organization().isEmpty() )
00484          addr.setOrganization( asUtf8( cli->mAttrs[ "Company" ].first() ) );
00485 
00486       addr.insertCustom("KADDRESSBOOK", "X-Department", asUtf8( cli->mAttrs[ "department" ].first() ) );
00487 
00488       // Address
00489       KABC::Address workAddr( KABC::Address::Work );
00490 
00491       workAddr.setStreet( asUtf8( cli->mAttrs[ "street" ].first()) );
00492       workAddr.setLocality( asUtf8( cli->mAttrs[ "l" ].first()) );
00493       workAddr.setRegion( asUtf8( cli->mAttrs[ "st" ].first()));
00494       workAddr.setPostalCode( asUtf8( cli->mAttrs[ "postalCode" ].first()) );
00495       workAddr.setCountry( asUtf8( cli->mAttrs[ "co" ].first()) );
00496 
00497       if ( !workAddr.isEmpty() )
00498         addr.insertAddress( workAddr );
00499 
00500       // phone
00501       KABC::PhoneNumber homeNr = asUtf8( cli->mAttrs[  "homePhone" ].first() );
00502       homeNr.setType( KABC::PhoneNumber::Home );
00503       addr.insertPhoneNumber( homeNr );
00504 
00505       KABC::PhoneNumber workNr = asUtf8( cli->mAttrs[  "telephoneNumber" ].first() );
00506       workNr.setType( KABC::PhoneNumber::Work );
00507       addr.insertPhoneNumber( workNr );
00508 
00509       KABC::PhoneNumber faxNr = asUtf8( cli->mAttrs[  "facsimileTelephoneNumber" ].first() );
00510       faxNr.setType( KABC::PhoneNumber::Fax );
00511       addr.insertPhoneNumber( faxNr );
00512 
00513       KABC::PhoneNumber cellNr = asUtf8( cli->mAttrs[  "mobile" ].first() );
00514       cellNr.setType( KABC::PhoneNumber::Cell );
00515       addr.insertPhoneNumber( cellNr );
00516 
00517       KABC::PhoneNumber pagerNr = asUtf8( cli->mAttrs[  "pager" ].first() );
00518       pagerNr.setType( KABC::PhoneNumber::Pager );
00519       addr.insertPhoneNumber( pagerNr );
00520 
00521       if ( mAddressBook ) {
00522         addr.setResource( resource );
00523         mAddressBook->insertAddressee( addr );
00524       }
00525     }
00526     cli = static_cast<ContactListItem*>( cli->nextSibling() );
00527   }
00528 
00529   KABLock::self( mAddressBook )->unlock( resource );
00530   emit addresseesAdded();
00531 }
00532 
00533 #include "ldapsearchdialog.moc"
KDE Logo
This file is part of the documentation for kaddressbook Library Version 3.3.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Mar 23 22:42:47 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003