00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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 <kbuttonbox.h>
00033 #include <kcombobox.h>
00034 #include <kconfig.h>
00035 #include <klineedit.h>
00036 #include <klocale.h>
00037 #include <kmessagebox.h>
00038
00039 #include "kabcore.h"
00040 #include "ldapsearchdialog.h"
00041 #include "kablock.h"
00042
00043 static QString asUtf8( const QByteArray &val )
00044 {
00045 if ( val.isEmpty() )
00046 return QString::null;
00047
00048 const char *data = val.data();
00049
00050
00051 if ( data[ val.size() - 1 ] == '\0' )
00052 return QString::fromUtf8( data, val.size() - 1 );
00053 else
00054 return QString::fromUtf8( data, val.size() );
00055 }
00056
00057 static QString join( const KPIM::LdapAttrValue& lst, const QString& sep )
00058 {
00059 QString res;
00060 bool alredy = false;
00061 for ( KPIM::LdapAttrValue::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
00062 if ( alredy )
00063 res += sep;
00064 alredy = true;
00065 res += asUtf8( *it );
00066 }
00067 return res;
00068 }
00069
00070 static QMap<QString, QString>& adrbookattr2ldap()
00071 {
00072 static QMap<QString, QString> keys;
00073
00074 if ( keys.isEmpty() ) {
00075 keys[ i18n( "Title" ) ] = "title";
00076 keys[ i18n( "Full Name" ) ] = "cn";
00077 keys[ i18n( "Email" ) ] = "mail";
00078 keys[ i18n( "Home Number" ) ] = "homePhone";
00079 keys[ i18n( "Work Number" ) ] = "telephoneNumber";
00080 keys[ i18n( "Mobile Number" ) ] = "mobile";
00081 keys[ i18n( "Fax Number" ) ] = "facsimileTelephoneNumber";
00082 keys[ i18n( "Pager" ) ] = "pager";
00083 keys[ i18n( "Street") ] = "street";
00084 keys[ i18n( "State" ) ] = "st";
00085 keys[ i18n( "Country" ) ] = "co";
00086 keys[ i18n( "City" ) ] = "l";
00087 keys[ i18n( "Organization" ) ] = "o";
00088 keys[ i18n( "Company" ) ] = "Company";
00089 keys[ i18n( "Department" ) ] = "department";
00090 keys[ i18n( "Zip Code" ) ] = "postalCode";
00091 keys[ i18n( "Postal Address" ) ] = "postalAddress";
00092 keys[ i18n( "Description" ) ] = "description";
00093 keys[ i18n( "User ID" ) ] = "uid";
00094 }
00095 return keys;
00096 }
00097
00098 class ContactListItem : public QListViewItem
00099 {
00100 public:
00101 ContactListItem( QListView* parent, const KPIM::LdapAttrMap& attrs )
00102 : QListViewItem( parent ), mAttrs( attrs )
00103 { }
00104
00105 KPIM::LdapAttrMap mAttrs;
00106
00107 virtual QString text( int col ) const
00108 {
00109
00110 const QString colName = listView()->columnText( col );
00111 const QString ldapAttrName = adrbookattr2ldap()[ colName ];
00112 return join( mAttrs[ ldapAttrName ], ", " );
00113 }
00114 };
00115
00116 LDAPSearchDialog::LDAPSearchDialog( KABC::AddressBook *ab, KABCore *core,
00117 QWidget* parent, const char* name )
00118 : KDialogBase( Plain, i18n( "Search for Addresses in Directory" ), Help | User1 |
00119 Cancel, Default, parent, name, false, true ),
00120 mAddressBook( ab ), mCore( core )
00121 {
00122 setButtonCancel( KStdGuiItem::close() );
00123 QFrame *page = plainPage();
00124 QVBoxLayout *topLayout = new QVBoxLayout( page, marginHint(), spacingHint() );
00125
00126 QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ),
00127 page );
00128 groupBox->setFrameShape( QGroupBox::Box );
00129 groupBox->setFrameShadow( QGroupBox::Sunken );
00130 groupBox->setColumnLayout( 0, Qt::Vertical );
00131 QGridLayout *boxLayout = new QGridLayout( groupBox->layout(), 2,
00132 5, spacingHint() );
00133 boxLayout->setColStretch( 1, 1 );
00134
00135 QLabel *label = new QLabel( i18n( "Search for:" ), groupBox );
00136 boxLayout->addWidget( label, 0, 0 );
00137
00138 mSearchEdit = new KLineEdit( groupBox );
00139 boxLayout->addWidget( mSearchEdit, 0, 1 );
00140 label->setBuddy( mSearchEdit );
00141
00142 label = new QLabel( i18n( "In LDAP attribute", "in" ), groupBox );
00143 boxLayout->addWidget( label, 0, 2 );
00144
00145 mFilterCombo = new KComboBox( groupBox );
00146 mFilterCombo->insertItem( i18n( "Name" ) );
00147 mFilterCombo->insertItem( i18n( "Email" ) );
00148 mFilterCombo->insertItem( i18n( "Home Number" ) );
00149 mFilterCombo->insertItem( i18n( "Work Number" ) );
00150 boxLayout->addWidget( mFilterCombo, 0, 3 );
00151
00152 QSize buttonSize;
00153 mSearchButton = new QPushButton( i18n( "Stop" ), groupBox );
00154 buttonSize = mSearchButton->sizeHint();
00155 mSearchButton->setText( i18n( "&Search" ) );
00156 if ( buttonSize.width() < mSearchButton->sizeHint().width() )
00157 buttonSize = mSearchButton->sizeHint();
00158 mSearchButton->setFixedWidth( buttonSize.width() );
00159
00160 mSearchButton->setDefault( true );
00161 boxLayout->addWidget( mSearchButton, 0, 4 );
00162
00163 mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox );
00164 mRecursiveCheckbox->setChecked( true );
00165 boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 );
00166
00167 mSearchType = new KComboBox( groupBox );
00168 mSearchType->insertItem( i18n( "Contains" ) );
00169 mSearchType->insertItem( i18n( "Starts With" ) );
00170 boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 );
00171
00172 topLayout->addWidget( groupBox );
00173
00174 mResultListView = new QListView( page );
00175 mResultListView->setSelectionMode( QListView::Multi );
00176 mResultListView->setAllColumnsShowFocus( true );
00177 mResultListView->setShowSortIndicator( true );
00178 topLayout->addWidget( mResultListView );
00179
00180 KButtonBox *buttons = new KButtonBox( page, Qt::Horizontal );
00181 buttons->addButton( i18n( "Select All" ), this, SLOT( slotSelectAll() ) );
00182 buttons->addButton( i18n( "Unselect All" ), this, SLOT( slotUnselectAll() ) );
00183
00184 topLayout->addWidget( buttons );
00185
00186 resize( QSize( 600, 400).expandedTo( minimumSizeHint() ) );
00187
00188 setButtonText( User1, i18n( "Add Selected" ) );
00189
00190 mNumHosts = 0;
00191 mIsOK = false;
00192
00193 connect( mRecursiveCheckbox, SIGNAL( toggled( bool ) ),
00194 this, SLOT( slotSetScope( bool ) ) );
00195 connect( mSearchButton, SIGNAL( clicked() ),
00196 this, SLOT( slotStartSearch() ) );
00197
00198 setTabOrder(mSearchEdit, mFilterCombo);
00199 setTabOrder(mFilterCombo, mSearchButton);
00200 mSearchEdit->setFocus();
00201
00202 restoreSettings();
00203 }
00204
00205 LDAPSearchDialog::~LDAPSearchDialog()
00206 {
00207 saveSettings();
00208 }
00209
00210 void LDAPSearchDialog::restoreSettings()
00211 {
00212
00213
00214
00215
00216 mLdapClientList.setAutoDelete( true );
00217 mLdapClientList.clear();
00218
00219 KConfig kabConfig( "kaddressbookrc" );
00220 kabConfig.setGroup( "LDAPSearch" );
00221 mSearchType->setCurrentItem( kabConfig.readNumEntry( "SearchType", 0 ) );
00222
00223
00224
00225 KConfig* config = KPIM::LdapSearch::config();
00226 KConfigGroupSaver saver( config, "LDAP" );
00227 mNumHosts = config->readUnsignedNumEntry( "NumSelectedHosts" );
00228 if ( !mNumHosts ) {
00229 KMessageBox::error( this, i18n( "You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) );
00230 mIsOK = false;
00231 } else {
00232 mIsOK = true;
00233 for ( int j = 0; j < mNumHosts; ++j ) {
00234 KPIM::LdapClient* ldapClient = new KPIM::LdapClient( 0, this, "ldapclient" );
00235 KPIM::LdapServer ldapServer;
00236 KPIM::LdapSearch::readConfig( ldapServer, config, j, true );
00237 ldapClient->setServer( ldapServer );
00238 QStringList attrs;
00239
00240 for ( QMap<QString,QString>::ConstIterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it )
00241 attrs << *it;
00242
00243 ldapClient->setAttrs( attrs );
00244
00245 connect( ldapClient, SIGNAL( result( const KPIM::LdapObject& ) ),
00246 this, SLOT( slotAddResult( const KPIM::LdapObject& ) ) );
00247 connect( ldapClient, SIGNAL( done() ),
00248 this, SLOT( slotSearchDone() ) );
00249 connect( ldapClient, SIGNAL( error( const QString& ) ),
00250 this, SLOT( slotError( const QString& ) ) );
00251
00252 mLdapClientList.append( ldapClient );
00253 }
00254
00256 while ( mResultListView->header()->count() > 0 ) {
00257 mResultListView->removeColumn(0);
00258 }
00259
00260 mResultListView->addColumn( i18n( "Full Name" ) );
00261 mResultListView->addColumn( i18n( "Email" ) );
00262 mResultListView->addColumn( i18n( "Home Number" ) );
00263 mResultListView->addColumn( i18n( "Work Number" ) );
00264 mResultListView->addColumn( i18n( "Mobile Number" ) );
00265 mResultListView->addColumn( i18n( "Fax Number" ) );
00266 mResultListView->addColumn( i18n( "Company" ) );
00267 mResultListView->addColumn( i18n( "Organization" ) );
00268 mResultListView->addColumn( i18n( "Street" ) );
00269 mResultListView->addColumn( i18n( "State" ) );
00270 mResultListView->addColumn( i18n( "Country" ) );
00271 mResultListView->addColumn( i18n( "Zip Code" ) );
00272 mResultListView->addColumn( i18n( "Postal Address" ) );
00273 mResultListView->addColumn( i18n( "City" ) );
00274 mResultListView->addColumn( i18n( "Department" ) );
00275 mResultListView->addColumn( i18n( "Description" ) );
00276 mResultListView->addColumn( i18n( "User ID" ) );
00277 mResultListView->addColumn( i18n( "Title" ) );
00278
00279 mResultListView->clear();
00280 }
00281 }
00282
00283 void LDAPSearchDialog::saveSettings()
00284 {
00285 KConfig config( "kaddressbookrc" );
00286 config.setGroup( "LDAPSearch" );
00287 config.writeEntry( "SearchType", mSearchType->currentItem() );
00288 config.sync();
00289 }
00290
00291 void LDAPSearchDialog::cancelQuery()
00292 {
00293 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00294 client->cancelQuery();
00295 }
00296 }
00297
00298 void LDAPSearchDialog::slotAddResult( const KPIM::LdapObject& obj )
00299 {
00300 new ContactListItem( mResultListView, obj.attrs );
00301 }
00302
00303 void LDAPSearchDialog::slotSetScope( bool rec )
00304 {
00305 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00306 if ( rec )
00307 client->setScope( "sub" );
00308 else
00309 client->setScope( "one" );
00310 }
00311 }
00312
00313 QString LDAPSearchDialog::makeFilter( const QString& query, const QString& attr,
00314 bool startsWith )
00315 {
00316
00317
00318
00319
00320
00321
00322 QString result( "&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(" );
00323 if( query.isEmpty() )
00324
00325 return result + "|(cn=*)(sn=*)" + ")";
00326
00327 if ( attr == i18n( "Name" ) ) {
00328 result += startsWith ? "|(cn=%1*)(sn=%2*)" : "|(cn=*%1*)(sn=*%2*)";
00329 result = result.arg( query ).arg( query );
00330 } else {
00331 result += (startsWith ? "%1=%2*" : "%1=*%2*");
00332 if ( attr == i18n( "Email" ) ) {
00333 result = result.arg( "mail" ).arg( query );
00334 } else if ( attr == i18n( "Home Number" ) ) {
00335 result = result.arg( "homePhone" ).arg( query );
00336 } else if ( attr == i18n( "Work Number" ) ) {
00337 result = result.arg( "telephoneNumber" ).arg( query );
00338 } else {
00339
00340 result = QString::null;
00341 return result;
00342 }
00343 }
00344 result += ")";
00345 return result;
00346 }
00347
00348 void LDAPSearchDialog::slotStartSearch()
00349 {
00350 cancelQuery();
00351
00352 QApplication::setOverrideCursor( Qt::waitCursor );
00353 mSearchButton->setText( i18n( "Stop" ) );
00354
00355 disconnect( mSearchButton, SIGNAL( clicked() ),
00356 this, SLOT( slotStartSearch() ) );
00357 connect( mSearchButton, SIGNAL( clicked() ),
00358 this, SLOT( slotStopSearch() ) );
00359
00360 bool startsWith = (mSearchType->currentItem() == 1);
00361
00362 QString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith );
00363
00364
00365 mResultListView->clear();
00366 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() )
00367 client->startQuery( filter );
00368
00369 saveSettings();
00370 }
00371
00372 void LDAPSearchDialog::slotStopSearch()
00373 {
00374 cancelQuery();
00375 slotSearchDone();
00376 }
00377
00378 void LDAPSearchDialog::slotSearchDone()
00379 {
00380
00381 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
00382 if ( client->isActive() )
00383 return;
00384 }
00385
00386 disconnect( mSearchButton, SIGNAL( clicked() ),
00387 this, SLOT( slotStopSearch() ) );
00388 connect( mSearchButton, SIGNAL( clicked() ),
00389 this, SLOT( slotStartSearch() ) );
00390
00391 mSearchButton->setText( i18n( "&Search" ) );
00392 QApplication::restoreOverrideCursor();
00393 }
00394
00395 void LDAPSearchDialog::slotError( const QString& error )
00396 {
00397 QApplication::restoreOverrideCursor();
00398 KMessageBox::error( this, error );
00399 }
00400
00401 void LDAPSearchDialog::closeEvent( QCloseEvent* e )
00402 {
00403 slotStopSearch();
00404 e->accept();
00405 }
00406
00411 QString LDAPSearchDialog::selectedEMails() const
00412 {
00413 QStringList result;
00414 ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
00415 while ( cli ) {
00416 if ( cli->isSelected() ) {
00417 QString email = asUtf8( cli->mAttrs[ "mail" ].first() ).stripWhiteSpace();
00418 if ( !email.isEmpty() ) {
00419 QString name = asUtf8( cli->mAttrs[ "cn" ].first() ).stripWhiteSpace();
00420 if ( name.isEmpty() ) {
00421 result << email;
00422 } else {
00423 result << name + " <" + email + ">";
00424 }
00425 }
00426 }
00427 cli = static_cast<ContactListItem*>( cli->nextSibling() );
00428 }
00429
00430 return result.join( ", " );
00431 }
00432
00433 void LDAPSearchDialog::slotHelp()
00434 {
00435 kapp->invokeHelp( "ldap-queries" );
00436 }
00437
00438 void LDAPSearchDialog::slotUnselectAll()
00439 {
00440 mResultListView->selectAll( false );
00441 }
00442
00443 void LDAPSearchDialog::slotSelectAll()
00444 {
00445 mResultListView->selectAll( true );
00446 }
00447
00448 void LDAPSearchDialog::slotUser1()
00449 {
00450
00451 KABC::Resource *resource = mCore->requestResource( this );
00452 if ( !resource ) return;
00453 KABLock::self( mAddressBook )->lock( resource );
00454
00455 ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
00456 while ( cli ) {
00457 if ( cli->isSelected() ) {
00458 KABC::Addressee addr;
00459
00460
00461 addr.setNameFromString( asUtf8( cli->mAttrs["cn"].first() ) );
00462
00463
00464 KPIM::LdapAttrValue lst = cli->mAttrs["mail"];
00465 KPIM::LdapAttrValue::ConstIterator it = lst.begin();
00466 bool pref = true;
00467 if ( it != lst.end() ) {
00468 addr.insertEmail( asUtf8( *it ), pref );
00469 pref = false;
00470 ++it;
00471 }
00472
00473 addr.setOrganization( asUtf8( cli->mAttrs[ "o" ].first() ) );
00474 if ( addr.organization().isEmpty() )
00475 addr.setOrganization( asUtf8( cli->mAttrs[ "Company" ].first() ) );
00476
00477 addr.insertCustom("KADDRESSBOOK", "X-Department", asUtf8( cli->mAttrs[ "department" ].first() ) );
00478
00479
00480 KABC::Address workAddr( KABC::Address::Work );
00481
00482 workAddr.setStreet( asUtf8( cli->mAttrs[ "street" ].first()) );
00483 workAddr.setLocality( asUtf8( cli->mAttrs[ "l" ].first()) );
00484 workAddr.setRegion( asUtf8( cli->mAttrs[ "st" ].first()));
00485 workAddr.setPostalCode( asUtf8( cli->mAttrs[ "postalCode" ].first()) );
00486 workAddr.setCountry( asUtf8( cli->mAttrs[ "co" ].first()) );
00487
00488 if ( !workAddr.isEmpty() )
00489 addr.insertAddress( workAddr );
00490
00491
00492 KABC::PhoneNumber homeNr = asUtf8( cli->mAttrs[ "homePhone" ].first() );
00493 homeNr.setType( KABC::PhoneNumber::Home );
00494 addr.insertPhoneNumber( homeNr );
00495
00496 KABC::PhoneNumber workNr = asUtf8( cli->mAttrs[ "telephoneNumber" ].first() );
00497 workNr.setType( KABC::PhoneNumber::Work );
00498 addr.insertPhoneNumber( workNr );
00499
00500 KABC::PhoneNumber faxNr = asUtf8( cli->mAttrs[ "facsimileTelephoneNumber" ].first() );
00501 faxNr.setType( KABC::PhoneNumber::Fax );
00502 addr.insertPhoneNumber( faxNr );
00503
00504 KABC::PhoneNumber cellNr = asUtf8( cli->mAttrs[ "mobile" ].first() );
00505 cellNr.setType( KABC::PhoneNumber::Cell );
00506 addr.insertPhoneNumber( cellNr );
00507
00508 KABC::PhoneNumber pagerNr = asUtf8( cli->mAttrs[ "pager" ].first() );
00509 pagerNr.setType( KABC::PhoneNumber::Pager );
00510 addr.insertPhoneNumber( pagerNr );
00511
00512 if ( mAddressBook ) {
00513 addr.setResource( resource );
00514 mAddressBook->insertAddressee( addr );
00515 }
00516 }
00517 cli = static_cast<ContactListItem*>( cli->nextSibling() );
00518 }
00519
00520 KABLock::self( mAddressBook )->unlock( resource );
00521 emit addresseesAdded();
00522 }
00523
00524 #include "ldapsearchdialog.moc"