kaddressbook

ldapsearchdialog.cpp
1 /* ldapsearchdialogimpl.cpp - LDAP access
2  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
3  *
4  * Author: Steffen Hansen <hansen@kde.org>
5  *
6  * This file is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This file is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "config.h"
22 
23 #include <tqcheckbox.h>
24 #include <tqgroupbox.h>
25 #include <tqheader.h>
26 #include <tqlabel.h>
27 #include <tqlayout.h>
28 #include <tqlistview.h>
29 #include <tqmap.h>
30 #include <tqpushbutton.h>
31 
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>
40 
41 #include "kabcore.h"
42 #include "ldapsearchdialog.h"
43 #include "kablock.h"
44 
45 #ifdef TDEPIM_NEW_DISTRLISTS
46 #include "distributionlistpicker.h"
47 #endif
48 
49 static TQString asUtf8( const TQByteArray &val )
50 {
51  if ( val.isEmpty() )
52  return TQString();
53 
54  const char *data = val.data();
55 
56  //TQString::fromUtf8() bug workaround
57  if ( data[ val.size() - 1 ] == '\0' )
58  return TQString::fromUtf8( data, val.size() - 1 );
59  else
60  return TQString::fromUtf8( data, val.size() );
61 }
62 
63 static TQString join( const KPIM::LdapAttrValue& lst, const TQString& sep )
64 {
65  TQString res;
66  bool alredy = false;
67  for ( KPIM::LdapAttrValue::ConstIterator it = lst.begin(); it != lst.end(); ++it ) {
68  if ( alredy )
69  res += sep;
70  alredy = true;
71  res += asUtf8( *it );
72  }
73  return res;
74 }
75 
76 static TQMap<TQString, TQString>& adrbookattr2ldap()
77 {
78  static TQMap<TQString, TQString> keys;
79 
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";
100  }
101  return keys;
102 }
103 
104 class ContactListItem : public TQListViewItem
105 {
106  public:
107  ContactListItem( TQListView* parent, const KPIM::LdapAttrMap& attrs )
108  : TQListViewItem( parent ), mAttrs( attrs )
109  { }
110 
111  KPIM::LdapAttrMap mAttrs;
112 
113  virtual TQString text( int col ) const
114  {
115  // Look up a suitable attribute for column col
116  const TQString colName = listView()->columnText( col );
117  const TQString ldapAttrName = adrbookattr2ldap()[ colName ];
118  return join( mAttrs[ ldapAttrName ], ", " );
119  }
120 };
121 
122 class LDAPSearchDialog::Private
123 {
124  public:
125  static TQValueList<ContactListItem*> selectedItems( TQListView* );
126  TQMap<const ContactListItem*, TQString> itemToServer;
127 };
128 
129 TQValueList<ContactListItem*> LDAPSearchDialog::Private::selectedItems( TQListView* view )
130 {
131  TQValueList<ContactListItem*> selected;
132  ContactListItem* cli = static_cast<ContactListItem*>( view->firstChild() );
133  while ( cli ) {
134  if ( cli->isSelected() )
135  selected.append( cli );
136  cli = static_cast<ContactListItem*>( cli->nextSibling() );
137  }
138  return selected;
139 }
140 
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 )
146 {
147  setButtonCancel( KStdGuiItem::close() );
148  TQFrame *page = plainPage();
149  TQVBoxLayout *topLayout = new TQVBoxLayout( page, marginHint(), spacingHint() );
150 
151  TQGroupBox *groupBox = new TQGroupBox( i18n( "Search for Addresses in Directory" ),
152  page );
153  groupBox->setFrameShape( TQGroupBox::Box );
154  groupBox->setFrameShadow( TQGroupBox::Sunken );
155  groupBox->setColumnLayout( 0, TQt::Vertical );
156  TQGridLayout *boxLayout = new TQGridLayout( groupBox->layout(), 2,
157  5, spacingHint() );
158  boxLayout->setColStretch( 1, 1 );
159 
160  TQLabel *label = new TQLabel( i18n( "Search for:" ), groupBox );
161  boxLayout->addWidget( label, 0, 0 );
162 
163  mSearchEdit = new KLineEdit( groupBox );
164  boxLayout->addWidget( mSearchEdit, 0, 1 );
165  label->setBuddy( mSearchEdit );
166 
167  label = new TQLabel( i18n( "In LDAP attribute", "in" ), groupBox );
168  boxLayout->addWidget( label, 0, 2 );
169 
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 );
176 
177  TQSize buttonSize;
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() );
184 
185  mSearchButton->setDefault( true );
186  boxLayout->addWidget( mSearchButton, 0, 4 );
187 
188  mRecursiveCheckbox = new TQCheckBox( i18n( "Recursive search" ), groupBox );
189  mRecursiveCheckbox->setChecked( true );
190  boxLayout->addMultiCellWidget( mRecursiveCheckbox, 1, 1, 0, 4 );
191 
192  mSearchType = new KComboBox( groupBox );
193  mSearchType->insertItem( i18n( "Contains" ) );
194  mSearchType->insertItem( i18n( "Starts With" ) );
195  boxLayout->addMultiCellWidget( mSearchType, 1, 1, 3, 4 );
196 
197  topLayout->addWidget( groupBox );
198 
199  mResultListView = new TQListView( page );
200  mResultListView->setSelectionMode( TQListView::Multi );
201  mResultListView->setAllColumnsShowFocus( true );
202  mResultListView->setShowSortIndicator( true );
203  topLayout->addWidget( mResultListView );
204 
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() ) );
208 
209  topLayout->addWidget( buttons );
210 
211  resize( TQSize( 600, 400).expandedTo( minimumSizeHint() ) );
212 
213  setButtonText( User1, i18n( "Add Selected" ) );
214 
215  showButton( User2, false );
216 
217 #ifdef TDEPIM_NEW_DISTRLISTS
218  showButton( User2, true );
219  setButtonText( User2, i18n( "Add to Distribution List..." ) );
220 #endif
221 
222  mNumHosts = 0;
223  mIsOK = false;
224 
225  connect( mRecursiveCheckbox, TQ_SIGNAL( toggled( bool ) ),
226  this, TQ_SLOT( slotSetScope( bool ) ) );
227  connect( mSearchButton, TQ_SIGNAL( clicked() ),
228  this, TQ_SLOT( slotStartSearch() ) );
229 
230  setTabOrder(mSearchEdit, mFilterCombo);
231  setTabOrder(mFilterCombo, mSearchButton);
232  mSearchEdit->setFocus();
233 
234  restoreSettings();
235 }
236 
237 LDAPSearchDialog::~LDAPSearchDialog()
238 {
239  saveSettings();
240  delete d;
241 }
242 
243 void LDAPSearchDialog::restoreSettings()
244 {
245  // Create one KPIM::LdapClient per selected server and configure it.
246 
247  // First clean the list to make sure it is empty at
248  // the beginning of the process
249  mLdapClientList.setAutoDelete( true );
250  mLdapClientList.clear();
251 
252  TDEConfig kabConfig( "kaddressbookrc" );
253  kabConfig.setGroup( "LDAPSearch" );
254  mSearchType->setCurrentItem( kabConfig.readNumEntry( "SearchType", 0 ) );
255 
256  // then read the config file and register all selected
257  // server in the list
258  TDEConfig* config = KPIM::LdapSearch::config();
259  TDEConfigGroupSaver saver( config, "LDAP" );
260  mNumHosts = config->readUnsignedNumEntry( "NumSelectedHosts" );
261  if ( !mNumHosts ) {
262  KMessageBox::error( this, i18n( "You must select a LDAP server before searching.\nYou can do this from the menu Settings/Configure KAddressBook." ) );
263  mIsOK = false;
264  } else {
265  mIsOK = true;
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 );
271  TQStringList attrs;
272 
273  for ( TQMap<TQString,TQString>::ConstIterator it = adrbookattr2ldap().begin(); it != adrbookattr2ldap().end(); ++it )
274  attrs << *it;
275 
276  ldapClient->setAttrs( attrs );
277 
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& ) ) );
284 
285  mLdapClientList.append( ldapClient );
286  }
287 
289  while ( mResultListView->header()->count() > 0 ) {
290  mResultListView->removeColumn(0);
291  }
292 
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" ) );
311 
312  mResultListView->clear();
313  d->itemToServer.clear();
314  }
315 }
316 
317 void LDAPSearchDialog::saveSettings()
318 {
319  TDEConfig config( "kaddressbookrc" );
320  config.setGroup( "LDAPSearch" );
321  config.writeEntry( "SearchType", mSearchType->currentItem() );
322  config.sync();
323 }
324 
325 void LDAPSearchDialog::cancelQuery()
326 {
327  for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
328  client->cancelQuery();
329  }
330 }
331 
332 void LDAPSearchDialog::slotAddResult( const KPIM::LdapObject& obj )
333 {
334  ContactListItem* item = new ContactListItem( mResultListView, obj.attrs );
335  d->itemToServer[item] = obj.client->server().host();
336 }
337 
338 void LDAPSearchDialog::slotSetScope( bool rec )
339 {
340  for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
341  if ( rec )
342  client->setScope( "sub" );
343  else
344  client->setScope( "one" );
345  }
346 }
347 
348 TQString LDAPSearchDialog::makeFilter( const TQString& query, const TQString& attr,
349  bool startsWith )
350 {
351  /* The reasoning behind this filter is:
352  * If it's a person, or a distlist, show it, even if it doesn't have an email address.
353  * If it's not a person, or a distlist, only show it if it has an email attribute.
354  * This allows both resource accounts with an email address which are not a person and
355  * person entries without an email address to show up, while still not showing things
356  * like structural entries in the ldap tree. */
357  TQString result( "&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(" );
358  if( query.isEmpty() )
359  // Return a filter that matches everything
360  return result + "|(cn=*)(sn=*)" + ")";
361 
362  if ( attr == i18n( "Name" ) ) {
363  result += startsWith ? "|(cn=%1*)(sn=%2*)" : "|(cn=*%1*)(sn=*%2*)";
364  result = result.arg( query ).arg( query );
365  } else {
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 );
373  } else {
374  // Error?
375  result = TQString();
376  return result;
377  }
378  }
379  result += ")";
380  return result;
381 }
382 
383 void LDAPSearchDialog::slotStartSearch()
384 {
385  cancelQuery();
386 
387  TQApplication::setOverrideCursor( TQt::waitCursor );
388  mSearchButton->setText( i18n( "Stop" ) );
389 
390  disconnect( mSearchButton, TQ_SIGNAL( clicked() ),
391  this, TQ_SLOT( slotStartSearch() ) );
392  connect( mSearchButton, TQ_SIGNAL( clicked() ),
393  this, TQ_SLOT( slotStopSearch() ) );
394 
395  bool startsWith = (mSearchType->currentItem() == 1);
396 
397  TQString filter = makeFilter( mSearchEdit->text().stripWhiteSpace(), mFilterCombo->currentText(), startsWith );
398 
399  // loop in the list and run the KPIM::LdapClients
400  mResultListView->clear();
401  d->itemToServer.clear();
402  for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() )
403  client->startQuery( filter );
404 
405  saveSettings();
406 }
407 
408 void LDAPSearchDialog::slotStopSearch()
409 {
410  cancelQuery();
411  slotSearchDone();
412 }
413 
414 void LDAPSearchDialog::slotSearchDone()
415 {
416  // If there are no more active clients, we are done.
417  for ( KPIM::LdapClient* client = mLdapClientList.first(); client; client = mLdapClientList.next() ) {
418  if ( client->isActive() )
419  return;
420  }
421 
422  disconnect( mSearchButton, TQ_SIGNAL( clicked() ),
423  this, TQ_SLOT( slotStopSearch() ) );
424  connect( mSearchButton, TQ_SIGNAL( clicked() ),
425  this, TQ_SLOT( slotStartSearch() ) );
426 
427  mSearchButton->setText( i18n( "&Search" ) );
428  TQApplication::restoreOverrideCursor();
429 }
430 
431 void LDAPSearchDialog::slotError( const TQString& error )
432 {
433  TQApplication::restoreOverrideCursor();
434  KMessageBox::error( this, error );
435 }
436 
437 void LDAPSearchDialog::closeEvent( TQCloseEvent* e )
438 {
439  slotStopSearch();
440  e->accept();
441 }
442 
447 TQString LDAPSearchDialog::selectedEMails() const
448 {
449  TQStringList result;
450  ContactListItem* cli = static_cast<ContactListItem*>( mResultListView->firstChild() );
451  while ( cli ) {
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() ) {
457  result << email;
458  } else {
459  result << name + " <" + email + ">";
460  }
461  }
462  }
463  cli = static_cast<ContactListItem*>( cli->nextSibling() );
464  }
465 
466  return result.join( ", " );
467 }
468 
469 void LDAPSearchDialog::slotHelp()
470 {
471  kapp->invokeHelp( "ldap-queries" );
472 }
473 
474 void LDAPSearchDialog::slotUnselectAll()
475 {
476  mResultListView->selectAll( false );
477 }
478 
479 void LDAPSearchDialog::slotSelectAll()
480 {
481  mResultListView->selectAll( true );
482 }
483 
484 TDEABC::Addressee LDAPSearchDialog::convertLdapAttributesToAddressee( const KPIM::LdapAttrMap& attrs )
485 {
486  TDEABC::Addressee addr;
487 
488  // name
489  addr.setNameFromString( asUtf8( attrs["cn"].first() ) );
490 
491  // email
492  KPIM::LdapAttrValue lst = attrs["mail"];
493  KPIM::LdapAttrValue::ConstIterator it = lst.begin();
494  bool pref = true;
495  if ( it != lst.end() ) {
496  addr.insertEmail( asUtf8( *it ), pref );
497  pref = false;
498  ++it;
499  }
500 
501  addr.setOrganization( asUtf8( attrs[ "o" ].first() ) );
502  if ( addr.organization().isEmpty() )
503  addr.setOrganization( asUtf8( attrs[ "Company" ].first() ) );
504 
505 #if KDE_IS_VERSION(3,5,8)
506  addr.setDepartment( asUtf8( attrs[ "department" ].first() ) );
507 #else
508  addr.insertCustom( "KADDRESSBOOK", "X-Department", asUtf8( attrs[ "department" ].first() ) );
509 #endif
510 
511  // Address
512  TDEABC::Address workAddr( TDEABC::Address::Work );
513 
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()) );
519 
520  if ( !workAddr.isEmpty() )
521  addr.insertAddress( workAddr );
522 
523  // phone
524  TDEABC::PhoneNumber homeNr = asUtf8( attrs[ "homePhone" ].first() );
525  homeNr.setType( TDEABC::PhoneNumber::Home );
526  addr.insertPhoneNumber( homeNr );
527 
528  TDEABC::PhoneNumber workNr = asUtf8( attrs[ "telephoneNumber" ].first() );
529  workNr.setType( TDEABC::PhoneNumber::Work );
530  addr.insertPhoneNumber( workNr );
531 
532  TDEABC::PhoneNumber faxNr = asUtf8( attrs[ "facsimileTelephoneNumber" ].first() );
533  faxNr.setType( TDEABC::PhoneNumber::Fax );
534  addr.insertPhoneNumber( faxNr );
535 
536  TDEABC::PhoneNumber cellNr = asUtf8( attrs[ "mobile" ].first() );
537  cellNr.setType( TDEABC::PhoneNumber::Cell );
538  addr.insertPhoneNumber( cellNr );
539 
540  TDEABC::PhoneNumber pagerNr = asUtf8( attrs[ "pager" ].first() );
541  pagerNr.setType( TDEABC::PhoneNumber::Pager );
542  addr.insertPhoneNumber( pagerNr );
543  return addr;
544 }
545 
546 #ifdef TDEPIM_NEW_DISTRLISTS
547 KPIM::DistributionList LDAPSearchDialog::selectDistributionList()
548 {
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" ) );
552  picker->exec();
553  const KPIM::DistributionList list = KPIM::DistributionList::findByName( mCore->addressBook(), picker
554 ? picker->selectedDistributionList() : TQString() );
555  delete picker;
556  return list;
557 }
558 #endif
559 
560 TDEABC::Addressee::List LDAPSearchDialog::importContactsUnlessTheyExist( const TQValueList<ContactListItem*>& selectedItems,
561  TDEABC::Resource * const resource )
562 {
563  const TQDateTime now = TQDateTime::currentDateTime();
564  TQStringList importedAddrs;
565  TDEABC::Addressee::List localAddrs;
566 
567  KABLock::self( mCore->addressBook() )->lock( resource );
568 
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() );
573 
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();
582  }
583  else {
584  displayString = addr.formattedName();
585  }
586  importedAddrs.append( displayString );
587  localAddrs.append( addr );
588  } else {
589  localAddrs.append( existing.first() );
590  }
591  }
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() ),
596  importedAddrs );
597  emit addresseesAdded();
598  }
599  return localAddrs;
600 }
601 
602 void LDAPSearchDialog::slotUser2()
603 {
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" ) );
608  return;
609  }
610 
611  TDEABC::Resource *resource = mCore->requestResource( this );
612  if ( !resource ) return;
613 
614  KPIM::DistributionList dist = selectDistributionList();
615  if ( dist.isEmpty() )
616  return;
617 
618 
619  TDEABC::Addressee::List localAddrs = importContactsUnlessTheyExist( selectedItems, resource );
620 
621  if ( localAddrs.isEmpty() )
622  return;
623 
624  for ( TDEABC::Addressee::List::ConstIterator it = localAddrs.begin(); it != localAddrs.end(); ++it ) {
625  dist.insertEntry( *it, TQString() );
626  }
627  KABLock::self( mCore->addressBook() )->lock( resource );
628  mCore->addressBook()->insertAddressee( dist );
629  KABLock::self( mCore->addressBook() )->unlock( resource );
630  emit addresseesAdded();
631 #endif
632 }
633 
634 void LDAPSearchDialog::slotUser1()
635 {
636  TDEABC::Resource *resource = mCore->requestResource( this );
637  if ( !resource ) return;
638  const TQValueList<ContactListItem*> selectedItems = d->selectedItems( mResultListView );
639  if( selectedItems.isEmpty() )
640  return;
641  importContactsUnlessTheyExist( selectedItems, resource );
642 }
643 
644 #include "ldapsearchdialog.moc"