23 #include <tqcheckbox.h>
24 #include <tqgroupbox.h>
28 #include <tqlistview.h>
30 #include <tqpushbutton.h>
32 #include <addresseelineedit.h>
33 #include <tdeapplication.h>
34 #include <kbuttonbox.h>
35 #include <kcombobox.h>
36 #include <tdeconfig.h>
37 #include <klineedit.h>
38 #include <tdelocale.h>
39 #include <tdemessagebox.h>
42 #include "ldapsearchdialog.h"
45 #ifdef TDEPIM_NEW_DISTRLISTS
46 #include "distributionlistpicker.h"
49 static TQString asUtf8(
const TQByteArray &val )
54 const char *data = val.data();
57 if ( data[ val.size() - 1 ] ==
'\0' )
58 return TQString::fromUtf8( data, val.size() - 1 );
60 return TQString::fromUtf8( data, val.size() );
63 static TQString join(
const KPIM::LdapAttrValue& lst,
const TQString& sep )
67 for ( KPIM::LdapAttrValue::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
76 static TQMap<TQString, TQString>& adrbookattr2ldap()
78 static TQMap<TQString, TQString> keys;
80 if ( keys.isEmpty() ) {
81 keys[ i18n(
"Title" ) ] =
"title";
82 keys[ i18n(
"Full Name" ) ] =
"cn";
83 keys[ i18n(
"Email" ) ] =
"mail";
84 keys[ i18n(
"Home Number" ) ] =
"homePhone";
85 keys[ i18n(
"Work Number" ) ] =
"telephoneNumber";
86 keys[ i18n(
"Mobile Number" ) ] =
"mobile";
87 keys[ i18n(
"Fax Number" ) ] =
"facsimileTelephoneNumber";
88 keys[ i18n(
"Pager" ) ] =
"pager";
89 keys[ i18n(
"Street") ] =
"street";
90 keys[ i18n(
"State" ) ] =
"st";
91 keys[ i18n(
"Country" ) ] =
"co";
92 keys[ i18n(
"City" ) ] =
"l";
93 keys[ i18n(
"Organization" ) ] =
"o";
94 keys[ i18n(
"Company" ) ] =
"Company";
95 keys[ i18n(
"Department" ) ] =
"department";
96 keys[ i18n(
"Zip Code" ) ] =
"postalCode";
97 keys[ i18n(
"Postal Address" ) ] =
"postalAddress";
98 keys[ i18n(
"Description" ) ] =
"description";
99 keys[ i18n(
"User ID" ) ] =
"uid";
104 class ContactListItem :
public TQListViewItem
107 ContactListItem( TQListView* parent,
const KPIM::LdapAttrMap& attrs )
108 : TQListViewItem( parent ), mAttrs( attrs )
111 KPIM::LdapAttrMap mAttrs;
113 virtual TQString text(
int col )
const
116 const TQString colName = listView()->columnText( col );
117 const TQString ldapAttrName = adrbookattr2ldap()[ colName ];
118 return join( mAttrs[ ldapAttrName ],
", " );
122 class LDAPSearchDialog::Private
125 static TQValueList<ContactListItem*> selectedItems( TQListView* );
126 TQMap<const ContactListItem*, TQString> itemToServer;
129 TQValueList<ContactListItem*> LDAPSearchDialog::Private::selectedItems( TQListView* view )
131 TQValueList<ContactListItem*> selected;
132 ContactListItem* cli =
static_cast<ContactListItem*
>( view->firstChild() );
134 if ( cli->isSelected() )
135 selected.append( cli );
136 cli =
static_cast<ContactListItem*
>( cli->nextSibling() );
141 LDAPSearchDialog::LDAPSearchDialog( TDEABC::AddressBook *ab, KABCore *core,
142 TQWidget* parent,
const char* name )
143 : KDialogBase( Plain, i18n(
"Search for Addresses in Directory" ), Help | User1 | User2 |
144 Cancel, Default, parent, name, false, true ),
145 mAddressBook( ab ), mCore( core ), d( new Private )
147 setButtonCancel( KStdGuiItem::close() );
148 TQFrame *page = plainPage();
149 TQVBoxLayout *topLayout =
new TQVBoxLayout( page, marginHint(), spacingHint() );
151 TQGroupBox *groupBox =
new TQGroupBox( i18n(
"Search for Addresses in Directory" ),
153 groupBox->setFrameShape( TQGroupBox::Box );
154 groupBox->setFrameShadow( TQGroupBox::Sunken );
155 groupBox->setColumnLayout( 0, TQt::Vertical );
156 TQGridLayout *boxLayout =
new TQGridLayout( groupBox->layout(), 2,
158 boxLayout->setColStretch( 1, 1 );
160 TQLabel *label =
new TQLabel( i18n(
"Search for:" ), groupBox );
161 boxLayout->addWidget( label, 0, 0 );
163 mSearchEdit =
new KLineEdit( groupBox );
164 boxLayout->addWidget( mSearchEdit, 0, 1 );
165 label->setBuddy( mSearchEdit );
167 label =
new TQLabel( i18n(
"In LDAP attribute",
"in" ), groupBox );
168 boxLayout->addWidget( label, 0, 2 );
170 mFilterCombo =
new KComboBox( groupBox );
171 mFilterCombo->insertItem( i18n(
"Name" ) );
172 mFilterCombo->insertItem( i18n(
"Email" ) );
173 mFilterCombo->insertItem( i18n(
"Home Number" ) );
174 mFilterCombo->insertItem( i18n(
"Work Number" ) );
175 boxLayout->addWidget( mFilterCombo, 0, 3 );
178 mSearchButton =
new TQPushButton( i18n(
"Stop" ), groupBox );
179 buttonSize = mSearchButton->sizeHint();
180 mSearchButton->setText( i18n(
"&Search" ) );
181 if ( buttonSize.width() < mSearchButton->sizeHint().width() )
182 buttonSize = mSearchButton->sizeHint();
183 mSearchButton->setFixedWidth( buttonSize.width() );
185 mSearchButton->setDefault(
true );
186 boxLayout->addWidget( mSearchButton, 0, 4 );
188 mRecursiveCheckbox =
new TQCheckBox( i18n(
"Recursive search" ), groupBox );
189 mRecursiveCheckbox->setChecked(
true );
190 boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 );
192 mSearchType =
new KComboBox( groupBox );
193 mSearchType->insertItem( i18n(
"Contains" ) );
194 mSearchType->insertItem( i18n(
"Starts With" ) );
195 boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 );
197 topLayout->addWidget( groupBox );
199 mResultListView =
new TQListView( page );
200 mResultListView->setSelectionMode( TQListView::Multi );
201 mResultListView->setAllColumnsShowFocus(
true );
202 mResultListView->setShowSortIndicator(
true );
203 topLayout->addWidget( mResultListView );
205 KButtonBox *buttons =
new KButtonBox( page, TQt::Horizontal );
206 buttons->addButton( i18n(
"Select All" ),
this, TQ_SLOT( slotSelectAll() ) );
207 buttons->addButton( i18n(
"Unselect All" ),
this, TQ_SLOT( slotUnselectAll() ) );
209 topLayout->addWidget( buttons );
211 resize( TQSize( 600, 400).expandedTo( minimumSizeHint() ) );
213 setButtonText( User1, i18n(
"Add Selected" ) );
215 showButton( User2,
false );
217 #ifdef TDEPIM_NEW_DISTRLISTS
218 showButton( User2,
true );
219 setButtonText( User2, i18n(
"Add to Distribution List..." ) );
225 connect( mRecursiveCheckbox, TQ_SIGNAL( toggled(
bool ) ),
226 this, TQ_SLOT( slotSetScope(
bool ) ) );
227 connect( mSearchButton, TQ_SIGNAL( clicked() ),
228 this, TQ_SLOT( slotStartSearch() ) );
230 setTabOrder(mSearchEdit, mFilterCombo);
231 setTabOrder(mFilterCombo, mSearchButton);
232 mSearchEdit->setFocus();
237 LDAPSearchDialog::~LDAPSearchDialog()
243 void LDAPSearchDialog::restoreSettings()
249 mLdapClientList.setAutoDelete(
true );
250 mLdapClientList.clear();
252 TDEConfig kabConfig(
"kaddressbookrc" );
253 kabConfig.setGroup(
"LDAPSearch" );
254 mSearchType->setCurrentItem( kabConfig.readNumEntry(
"SearchType", 0 ) );
258 TDEConfig* config = KPIM::LdapSearch::config();
259 TDEConfigGroupSaver saver( config,
"LDAP" );
260 mNumHosts = config->readUnsignedNumEntry(
"NumSelectedHosts" );
262 KMessageBox::error(
this, i18n(
"You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) );
266 for (
int j = 0; j < mNumHosts; ++j ) {
267 KPIM::LdapClient* ldapClient =
new KPIM::LdapClient( 0,
this,
"ldapclient" );
268 KPIM::LdapServer ldapServer;
269 KPIM::LdapSearch::readConfig( ldapServer, config, j,
true );
270 ldapClient->setServer( ldapServer );
273 for ( TQMap<TQString,TQString>::ConstIterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it )
276 ldapClient->setAttrs( attrs );
278 connect( ldapClient, TQ_SIGNAL( result(
const KPIM::LdapObject& ) ),
279 this, TQ_SLOT( slotAddResult(
const KPIM::LdapObject& ) ) );
280 connect( ldapClient, TQ_SIGNAL( done() ),
281 this, TQ_SLOT( slotSearchDone() ) );
282 connect( ldapClient, TQ_SIGNAL( error(
const TQString& ) ),
283 this, TQ_SLOT( slotError(
const TQString& ) ) );
285 mLdapClientList.append( ldapClient );
289 while ( mResultListView->header()->count() > 0 ) {
290 mResultListView->removeColumn(0);
293 mResultListView->addColumn( i18n(
"Full Name" ) );
294 mResultListView->addColumn( i18n(
"Email" ) );
295 mResultListView->addColumn( i18n(
"Home Number" ) );
296 mResultListView->addColumn( i18n(
"Work Number" ) );
297 mResultListView->addColumn( i18n(
"Mobile Number" ) );
298 mResultListView->addColumn( i18n(
"Fax Number" ) );
299 mResultListView->addColumn( i18n(
"Company" ) );
300 mResultListView->addColumn( i18n(
"Organization" ) );
301 mResultListView->addColumn( i18n(
"Street" ) );
302 mResultListView->addColumn( i18n(
"State" ) );
303 mResultListView->addColumn( i18n(
"Country" ) );
304 mResultListView->addColumn( i18n(
"Zip Code" ) );
305 mResultListView->addColumn( i18n(
"Postal Address" ) );
306 mResultListView->addColumn( i18n(
"City" ) );
307 mResultListView->addColumn( i18n(
"Department" ) );
308 mResultListView->addColumn( i18n(
"Description" ) );
309 mResultListView->addColumn( i18n(
"User ID" ) );
310 mResultListView->addColumn( i18n(
"Title" ) );
312 mResultListView->clear();
313 d->itemToServer.clear();
317 void LDAPSearchDialog::saveSettings()
319 TDEConfig config(
"kaddressbookrc" );
320 config.setGroup(
"LDAPSearch" );
321 config.writeEntry(
"SearchType", mSearchType->currentItem() );
325 void LDAPSearchDialog::cancelQuery()
327 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
328 client->cancelQuery();
332 void LDAPSearchDialog::slotAddResult(
const KPIM::LdapObject& obj )
334 ContactListItem* item =
new ContactListItem( mResultListView, obj.attrs );
335 d->itemToServer[item] = obj.client->server().host();
338 void LDAPSearchDialog::slotSetScope(
bool rec )
340 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
342 client->setScope(
"sub" );
344 client->setScope(
"one" );
348 TQString LDAPSearchDialog::makeFilter(
const TQString& query,
const TQString& attr,
357 TQString result(
"&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(" );
358 if( query.isEmpty() )
360 return result +
"|(cn=*)(sn=*)" +
")";
362 if ( attr == i18n(
"Name" ) ) {
363 result += startsWith ?
"|(cn=%1*)(sn=%2*)" :
"|(cn=*%1*)(sn=*%2*)";
364 result = result.arg( query ).arg( query );
366 result += (startsWith ?
"%1=%2*" :
"%1=*%2*");
367 if ( attr == i18n(
"Email" ) ) {
368 result = result.arg(
"mail" ).arg( query );
369 }
else if ( attr == i18n(
"Home Number" ) ) {
370 result = result.arg(
"homePhone" ).arg( query );
371 }
else if ( attr == i18n(
"Work Number" ) ) {
372 result = result.arg(
"telephoneNumber" ).arg( query );
383 void LDAPSearchDialog::slotStartSearch()
387 TQApplication::setOverrideCursor( TQt::waitCursor );
388 mSearchButton->setText( i18n(
"Stop" ) );
390 disconnect( mSearchButton, TQ_SIGNAL( clicked() ),
391 this, TQ_SLOT( slotStartSearch() ) );
392 connect( mSearchButton, TQ_SIGNAL( clicked() ),
393 this, TQ_SLOT( slotStopSearch() ) );
395 bool startsWith = (mSearchType->currentItem() == 1);
397 TQString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith );
400 mResultListView->clear();
401 d->itemToServer.clear();
402 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() )
403 client->startQuery( filter );
408 void LDAPSearchDialog::slotStopSearch()
414 void LDAPSearchDialog::slotSearchDone()
417 for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
418 if ( client->isActive() )
422 disconnect( mSearchButton, TQ_SIGNAL( clicked() ),
423 this, TQ_SLOT( slotStopSearch() ) );
424 connect( mSearchButton, TQ_SIGNAL( clicked() ),
425 this, TQ_SLOT( slotStartSearch() ) );
427 mSearchButton->setText( i18n(
"&Search" ) );
428 TQApplication::restoreOverrideCursor();
431 void LDAPSearchDialog::slotError(
const TQString& error )
433 TQApplication::restoreOverrideCursor();
434 KMessageBox::error(
this, error );
437 void LDAPSearchDialog::closeEvent( TQCloseEvent* e )
447 TQString LDAPSearchDialog::selectedEMails()
const
450 ContactListItem* cli =
static_cast<ContactListItem*
>( mResultListView->firstChild() );
452 if ( cli->isSelected() ) {
453 TQString email = asUtf8( cli->mAttrs[
"mail" ].first() ).stripWhiteSpace();
454 if ( !email.isEmpty() ) {
455 TQString name = asUtf8( cli->mAttrs[
"cn" ].first() ).stripWhiteSpace();
456 if ( name.isEmpty() ) {
459 result << name +
" <" + email +
">";
463 cli =
static_cast<ContactListItem*
>( cli->nextSibling() );
466 return result.join(
", " );
469 void LDAPSearchDialog::slotHelp()
471 kapp->invokeHelp(
"ldap-queries" );
474 void LDAPSearchDialog::slotUnselectAll()
476 mResultListView->selectAll(
false );
479 void LDAPSearchDialog::slotSelectAll()
481 mResultListView->selectAll(
true );
484 TDEABC::Addressee LDAPSearchDialog::convertLdapAttributesToAddressee(
const KPIM::LdapAttrMap& attrs )
486 TDEABC::Addressee addr;
489 addr.setNameFromString( asUtf8( attrs[
"cn"].first() ) );
492 KPIM::LdapAttrValue lst = attrs[
"mail"];
493 KPIM::LdapAttrValue::ConstIterator it = lst.begin();
495 if ( it != lst.end() ) {
496 addr.insertEmail( asUtf8( *it ), pref );
501 addr.setOrganization( asUtf8( attrs[
"o" ].first() ) );
502 if ( addr.organization().isEmpty() )
503 addr.setOrganization( asUtf8( attrs[
"Company" ].first() ) );
505 #if KDE_IS_VERSION(3,5,8)
506 addr.setDepartment( asUtf8( attrs[
"department" ].first() ) );
508 addr.insertCustom(
"KADDRESSBOOK",
"X-Department", asUtf8( attrs[
"department" ].first() ) );
512 TDEABC::Address workAddr( TDEABC::Address::Work );
514 workAddr.setStreet( asUtf8( attrs[
"street" ].first()) );
515 workAddr.setLocality( asUtf8( attrs[
"l" ].first()) );
516 workAddr.setRegion( asUtf8( attrs[
"st" ].first()));
517 workAddr.setPostalCode( asUtf8( attrs[
"postalCode" ].first()) );
518 workAddr.setCountry( asUtf8( attrs[
"co" ].first()) );
520 if ( !workAddr.isEmpty() )
521 addr.insertAddress( workAddr );
524 TDEABC::PhoneNumber homeNr = asUtf8( attrs[
"homePhone" ].first() );
525 homeNr.setType( TDEABC::PhoneNumber::Home );
526 addr.insertPhoneNumber( homeNr );
528 TDEABC::PhoneNumber workNr = asUtf8( attrs[
"telephoneNumber" ].first() );
529 workNr.setType( TDEABC::PhoneNumber::Work );
530 addr.insertPhoneNumber( workNr );
532 TDEABC::PhoneNumber faxNr = asUtf8( attrs[
"facsimileTelephoneNumber" ].first() );
533 faxNr.setType( TDEABC::PhoneNumber::Fax );
534 addr.insertPhoneNumber( faxNr );
536 TDEABC::PhoneNumber cellNr = asUtf8( attrs[
"mobile" ].first() );
537 cellNr.setType( TDEABC::PhoneNumber::Cell );
538 addr.insertPhoneNumber( cellNr );
540 TDEABC::PhoneNumber pagerNr = asUtf8( attrs[
"pager" ].first() );
541 pagerNr.setType( TDEABC::PhoneNumber::Pager );
542 addr.insertPhoneNumber( pagerNr );
546 #ifdef TDEPIM_NEW_DISTRLISTS
547 KPIM::DistributionList LDAPSearchDialog::selectDistributionList()
549 TQGuardedPtr<KPIM::DistributionListPickerDialog> picker =
new KPIM::DistributionListPickerDialog( mCore->addressBook(),
this );
550 picker->setLabelText( i18n(
"Select a distribution list to add the selected contacts to." ) );
551 picker->setCaption( i18n(
"Select Distribution List" ) );
553 const KPIM::DistributionList list = KPIM::DistributionList::findByName( mCore->addressBook(), picker
554 ? picker->selectedDistributionList() : TQString() );
560 TDEABC::Addressee::List LDAPSearchDialog::importContactsUnlessTheyExist(
const TQValueList<ContactListItem*>& selectedItems,
561 TDEABC::Resource *
const resource )
563 const TQDateTime now = TQDateTime::currentDateTime();
564 TQStringList importedAddrs;
565 TDEABC::Addressee::List localAddrs;
567 KABLock::self( mCore->addressBook() )->lock( resource );
569 for ( TQValueList<ContactListItem*>::ConstIterator it = selectedItems.begin(); it != selectedItems.end(); ++it ) {
570 const ContactListItem *
const cli = *it;
571 TDEABC::Addressee addr = convertLdapAttributesToAddressee( cli->mAttrs );
572 const TDEABC::Addressee::List existing = mCore->addressBook()->findByEmail( addr.preferredEmail() );
574 if ( existing.isEmpty() ) {
575 addr.setUid( TDEApplication::randomString( 10 ) );
576 addr.setNote( i18n(
"arguments are host name, datetime",
"Imported from LDAP directory %1 on %2" ).arg( d->itemToServer[cli], TDEGlobal::locale()->formatDateTime( now ) ) );
577 addr.setResource( resource );
578 mCore->addressBook()->insertAddressee( addr );
579 TQString displayString;
580 if ( !addr.fullEmail().isEmpty() ) {
581 displayString = addr.fullEmail();
584 displayString = addr.formattedName();
586 importedAddrs.append( displayString );
587 localAddrs.append( addr );
589 localAddrs.append( existing.first() );
592 KABLock::self( mCore->addressBook() )->unlock( resource );
593 if ( !importedAddrs.isEmpty() ) {
594 KMessageBox::informationList(
this, i18n(
"The following contact was imported into your address book:",
595 "The following %n contacts were imported into your address book:", importedAddrs.count() ),
597 emit addresseesAdded();
602 void LDAPSearchDialog::slotUser2()
604 #ifdef TDEPIM_NEW_DISTRLISTS
605 const TQValueList<ContactListItem*> selectedItems = d->selectedItems( mResultListView );
606 if ( selectedItems.isEmpty() ) {
607 KMessageBox::information(
this, i18n(
"Please select the contacts you want to add to the distribution list." ), i18n(
"No Contacts Selected" ) );
611 TDEABC::Resource *resource = mCore->requestResource(
this );
612 if ( !resource )
return;
614 KPIM::DistributionList dist = selectDistributionList();
615 if ( dist.isEmpty() )
619 TDEABC::Addressee::List localAddrs = importContactsUnlessTheyExist( selectedItems, resource );
621 if ( localAddrs.isEmpty() )
624 for ( TDEABC::Addressee::List::ConstIterator it = localAddrs.begin(); it != localAddrs.end(); ++it ) {
625 dist.insertEntry( *it, TQString() );
627 KABLock::self( mCore->addressBook() )->lock( resource );
628 mCore->addressBook()->insertAddressee( dist );
629 KABLock::self( mCore->addressBook() )->unlock( resource );
630 emit addresseesAdded();
634 void LDAPSearchDialog::slotUser1()
636 TDEABC::Resource *resource = mCore->requestResource(
this );
637 if ( !resource )
return;
638 const TQValueList<ContactListItem*> selectedItems = d->selectedItems( mResultListView );
639 if( selectedItems.isEmpty() )
641 importContactsUnlessTheyExist( selectedItems, resource );
644 #include "ldapsearchdialog.moc"