00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "ldapsearchdialog.h"
00022 #include "ldapclient.h"
00023
00024 #include <qcheckbox.h>
00025 #include <qgroupbox.h>
00026 #include <qheader.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qlistview.h>
00030 #include <qpushbutton.h>
00031
00032 #include <kabc/addresslineedit.h>
00033 #include <kapplication.h>
00034 #include <kcombobox.h>
00035 #include <kconfig.h>
00036 #include <klineedit.h>
00037 #include <klocale.h>
00038 #include <kmessagebox.h>
00039
00040 using namespace KPIM;
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
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
00109 const QString colName = listView()->columnText( col );
00110 const QString ldapAttrName = adrbookattr2ldap()[ colName ];
00111 return join( mAttrs[ ldapAttrName ], ", " );
00112 }
00113 };
00114
00115 LDAPSearchDialog::LDAPSearchDialog( 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 {
00119 setButtonCancel( KStdGuiItem::close() );
00120 QFrame *page = plainPage();
00121 QVBoxLayout *topLayout = new QVBoxLayout( page, marginHint(), spacingHint() );
00122
00123 QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ),
00124 page );
00125 groupBox->setFrameShape( QGroupBox::Box );
00126 groupBox->setFrameShadow( QGroupBox::Sunken );
00127 groupBox->setColumnLayout( 0, Qt::Vertical );
00128 QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 2,
00129 5, spacingHint() );
00130 boxLayout->setColStretch( 1, 1 );
00131
00132 QLabel *label = new QLabel( i18n( "Search for:" ), groupBox );
00133 boxLayout->addWidget( label, 0, 0 );
00134
00135 mSearchEdit = new KLineEdit( groupBox );
00136 boxLayout->addWidget( mSearchEdit, 0, 1 );
00137 label->setBuddy( mSearchEdit );
00138
00139 label = new QLabel( i18n( "in" ), groupBox );
00140 boxLayout->addWidget( label, 0, 2 );
00141
00142 mFilterCombo = new KComboBox( groupBox );
00143 mFilterCombo->insertItem( i18n( "Name" ) );
00144 mFilterCombo->insertItem( i18n( "Email" ) );
00145 mFilterCombo->insertItem( i18n( "Home Number" ) );
00146 mFilterCombo->insertItem( i18n( "Work Number" ) );
00147 boxLayout->addWidget( mFilterCombo, 0, 3 );
00148
00149 QSize buttonSize;
00150 mSearchButton = new QPushButton( i18n( "Stop" ), groupBox );
00151 buttonSize = mSearchButton->sizeHint();
00152 mSearchButton->setText( i18n( "Search" ) );
00153 if ( buttonSize.width() < mSearchButton->sizeHint().width() )
00154 buttonSize = mSearchButton->sizeHint();
00155 mSearchButton->setFixedWidth( buttonSize.width() );
00156
00157 mSearchButton->setDefault( true );
00158 boxLayout->addWidget( mSearchButton, 0, 4 );
00159
00160 mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox );
00161 mRecursiveCheckbox->setChecked( true );
00162 boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 );
00163
00164 mSearchType = new KComboBox( groupBox );
00165 mSearchType->insertItem( i18n( "Contains" ) );
00166 mSearchType->insertItem( i18n( "Starts With" ) );
00167 boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 );
00168
00169 topLayout->addWidget( groupBox );
00170
00171 mResultListView = new QListView( page );
00172 mResultListView->setSelectionMode( QListView::Multi );
00173 mResultListView->setAllColumnsShowFocus( true );
00174 mResultListView->setShowSortIndicator( true );
00175 topLayout->addWidget( mResultListView );
00176
00177 resize( QSize( 600, 400).expandedTo( minimumSizeHint() ) );
00178
00179 setButtonText( User1, i18n( "Unselect All" ) );
00180 setButtonText( User2, i18n( "Select All" ) );
00181 setButtonText( User3, i18n( "Add Selected" ) );
00182
00183 mNumHosts = 0;
00184 mIsOK = false;
00185
00186 connect( mRecursiveCheckbox, SIGNAL( toggled( bool ) ),
00187 this, SLOT( slotSetScope( bool ) ) );
00188 connect( mSearchButton, SIGNAL( clicked() ),
00189 this, SLOT( slotStartSearch() ) );
00190
00191 setTabOrder(mSearchEdit, mFilterCombo);
00192 setTabOrder(mFilterCombo, mSearchButton);
00193 mSearchEdit->setFocus();
00194
00195 restoreSettings();
00196 }
00197
00198 LDAPSearchDialog::~LDAPSearchDialog()
00199 {
00200 saveSettings();
00201 }
00202
00203 void LDAPSearchDialog::restoreSettings()
00204 {
00205
00206
00207
00208
00209 mLdapClientList.setAutoDelete( true );
00210 mLdapClientList.clear();
00211
00212 KConfig kabConfig( "kaddressbookrc" );
00213 kabConfig.setGroup( "LDAPSearch" );
00214 mSearchType->setCurrentItem( kabConfig.readNumEntry( "SearchType", 0 ) );
00215
00216
00217
00218 KConfig* config = KABC::AddressLineEdit::config();
00219 KConfigGroupSaver saver( config, "LDAP" );
00220 mNumHosts = config->readUnsignedNumEntry( "NumSelectedHosts" );
00221 if ( !mNumHosts ) {
00222 KMessageBox::error( this, i18n( "You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) );
00223 mIsOK = false;
00224 } else {
00225 mIsOK = true;
00226 for ( int j = 0; j < mNumHosts; ++j ) {
00227 KPIM::LdapServer ldapServer;
00228
00229 QString host = config->readEntry( QString( "SelectedHost%1" ).arg( j ), "" );
00230 if ( !host.isEmpty() )
00231 ldapServer.setHost( host );
00232
00233 int port = config->readUnsignedNumEntry( QString( "SelectedPort%1" ).arg( j ) );
00234 if ( port )
00235 ldapServer.setPort( port );
00236
00237 QString base = config->readEntry( QString( "SelectedBase%1" ).arg( j ), "" );
00238 if ( !base.isEmpty() )
00239 ldapServer.setBaseDN( base );
00240
00241 QString bindDN = config->readEntry( QString( "SelectedBind%1" ).arg( j ), "" );
00242 if ( !bindDN.isEmpty() )
00243 ldapServer.setBindDN( bindDN );
00244
00245 QString pwdBindDN = config->readEntry( QString( "SelectedPwdBind%1" ).arg( j ), "" );
00246 if ( !pwdBindDN.isEmpty() )
00247 ldapServer.setPwdBindDN( pwdBindDN );
00248
00249 KPIM::LdapClient* ldapClient = new KPIM::LdapClient( 0, this, "ldapclient" );
00250 ldapClient->setServer( ldapServer );
00251
00252 QStringList attrs;
00253
00254 for ( QMap<QString,QString>::Iterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it )
00255 attrs << *it;
00256
00257 ldapClient->setAttrs( attrs );
00258
00259 connect( ldapClient, SIGNAL( result( const KPIM::LdapObject& ) ),
00260 this, SLOT( slotAddResult( const KPIM::LdapObject& ) ) );
00261 connect( ldapClient, SIGNAL( done() ),
00262 this, SLOT( slotSearchDone() ) );
00263 connect( ldapClient, SIGNAL( error( const QString& ) ),
00264 this, SLOT( slotError( const QString& ) ) );
00265
00266 mLdapClientList.append( ldapClient );
00267 }
00268
00270 while ( mResultListView->header()->count() > 0 ) {
00271 mResultListView->removeColumn(0);
00272 }
00273
00274 mResultListView->addColumn( i18n( "Full Name" ) );
00275 mResultListView->addColumn( i18n( "Email" ) );
00276 mResultListView->addColumn( i18n( "Home Number" ) );
00277 mResultListView->addColumn( i18n( "Work Number" ) );
00278 mResultListView->addColumn( i18n( "Mobile Number" ) );
00279 mResultListView->addColumn( i18n( "Fax Number" ) );
00280 mResultListView->addColumn( i18n( "Company" ) );
00281 mResultListView->addColumn( i18n( "Organization" ) );
00282 mResultListView->addColumn( i18n( "Street" ) );
00283 mResultListView->addColumn( i18n( "State" ) );
00284 mResultListView->addColumn( i18n( "Country" ) );
00285 mResultListView->addColumn( i18n( "Zip Code" ) );
00286 mResultListView->addColumn( i18n( "Postal Address" ) );
00287 mResultListView->addColumn( i18n( "City" ) );
00288 mResultListView->addColumn( i18n( "Department" ) );
00289 mResultListView->addColumn( i18n( "Description" ) );
00290 mResultListView->addColumn( i18n( "User ID" ) );
00291 mResultListView->addColumn( i18n( "Title" ) );
00292
00293 mResultListView->clear();
00294 }
00295 }
00296
00297 void LDAPSearchDialog::saveSettings()
00298 {
00299 KConfig config( "kaddressbookrc" );
00300 config.setGroup( "LDAPSearch" );
00301 config.writeEntry( "SearchType", mSearchType->currentItem() );
00302 config.sync();
00303 }
00304
00305 void LDAPSearchDialog::cancelQuery()
00306 {
00307 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00308 client->cancelQuery();
00309 }
00310 }
00311
00312 void LDAPSearchDialog::slotAddResult( const KPIM::LdapObject& obj )
00313 {
00314 new ContactListItem( mResultListView, obj.attrs );
00315 }
00316
00317 void LDAPSearchDialog::slotSetScope( bool rec )
00318 {
00319 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00320 if ( rec )
00321 client->setScope( "sub" );
00322 else
00323 client->setScope( "one" );
00324 }
00325 }
00326
00327 QString LDAPSearchDialog::makeFilter( const QString& query, const QString& attr,
00328 bool startsWith )
00329 {
00330
00331
00332
00333
00334
00335
00336 QString result( "&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(" );
00337 if( query.isEmpty() )
00338
00339 return result + "|(cn=*)(sn=*)" + ")";
00340
00341 if ( attr == i18n( "Name" ) ) {
00342 result += startsWith ? "|(cn=%1*)(sn=%2*)" : "|(cn=*%1*)(sn=*%2*)";
00343 result = result.arg( query ).arg( query );
00344 } else {
00345 result += (startsWith ? "%1=%2*" : "%1=*%2*");
00346 if ( attr == i18n( "Email" ) ) {
00347 result = result.arg( "mail" ).arg( query );
00348 } else if ( attr == i18n( "Home Number" ) ) {
00349 result = result.arg( "homePhone" ).arg( query );
00350 } else if ( attr == i18n( "Work Number" ) ) {
00351 result = result.arg( "telephoneNumber" ).arg( query );
00352 } else {
00353
00354 result = QString::null;
00355 return result;
00356 }
00357 }
00358 result += ")";
00359 return result;
00360 }
00361
00362 void LDAPSearchDialog::slotStartSearch()
00363 {
00364 cancelQuery();
00365
00366 QApplication::setOverrideCursor( Qt::waitCursor );
00367 mSearchButton->setText( i18n( "Stop" ) );
00368
00369 disconnect( mSearchButton, SIGNAL( clicked() ),
00370 this, SLOT( slotStartSearch() ) );
00371 connect( mSearchButton, SIGNAL( clicked() ),
00372 this, SLOT( slotStopSearch() ) );
00373
00374 bool startsWith = (mSearchType->currentItem() == 1);
00375
00376 QString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith );
00377
00378
00379 mResultListView->clear();
00380 for( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00381 client->startQuery( filter );
00382 }
00383
00384 saveSettings();
00385 }
00386
00387 void LDAPSearchDialog::slotStopSearch()
00388 {
00389 cancelQuery();
00390 slotSearchDone();
00391 }
00392
00393 void LDAPSearchDialog::slotSearchDone()
00394 {
00395
00396 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00397 if ( client->isActive() )
00398 return;
00399 }
00400
00401 disconnect( mSearchButton, SIGNAL( clicked() ),
00402 this, SLOT( slotStopSearch() ) );
00403 connect( mSearchButton, SIGNAL( clicked() ),
00404 this, SLOT( slotStartSearch() ) );
00405
00406 mSearchButton->setText( i18n( "Search" ) );
00407 QApplication::restoreOverrideCursor();
00408 }
00409
00410 void LDAPSearchDialog::slotError( const QString& error )
00411 {
00412 QApplication::restoreOverrideCursor();
00413 KMessageBox::error( this, error );
00414 }
00415
00416 void LDAPSearchDialog::closeEvent( QCloseEvent* e )
00417 {
00418 slotStopSearch();
00419 e->accept();
00420 }
00421
00426 QString LDAPSearchDialog::selectedEMails() const
00427 {
00428 QStringList result;
00429 ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
00430 while ( cli ) {
00431 if ( cli->isSelected() ) {
00432 QString email = asUtf8( cli->mAttrs[ "mail" ].first() ).stripWhiteSpace();
00433 if ( !email.isEmpty() ) {
00434 QString name = asUtf8( cli->mAttrs[ "cn" ].first() ).stripWhiteSpace();
00435 if ( name.isEmpty() ) {
00436 result << email;
00437 } else {
00438 result << name + " <" + email + ">";
00439 }
00440 }
00441 }
00442 cli = static_cast<ContactListItem*>( cli->nextSibling() );
00443 }
00444
00445 return result.join( ", " );
00446 }
00447
00448 void LDAPSearchDialog::slotHelp()
00449 {
00450 kapp->invokeHelp( "ldap-queries" );
00451 }
00452
00453 void LDAPSearchDialog::slotUser1()
00454 {
00455 mResultListView->selectAll( false );
00456 }
00457
00458 void LDAPSearchDialog::slotUser2()
00459 {
00460 mResultListView->selectAll( true );
00461 }
00462
00463 void LDAPSearchDialog::slotUser3()
00464 {
00465 emit addresseesAdded();
00466 }
00467
00468 #include "ldapsearchdialog.moc"