• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

libkdepim

  • sources
  • kde-4.12
  • kdepim
  • libkdepim
  • ldap
ldapsearchdialog.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of libkldap.
3  *
4  * Copyright (C) 2002 Klarälvdalens Datakonsult AB
5  *
6  * Author: Steffen Hansen <hansen@kde.org>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public License
19  * along with this library; see the file COPYING.LIB. If not, write to
20  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  * Boston, MA 02110-1301, USA.
22  */
23 
24 #include "ldapsearchdialog.h"
25 
26 #include "ldapclient.h"
27 #include "ldapclientsearchconfig.h"
28 #include <QtCore/QPair>
29 #include <QApplication>
30 #include <QCheckBox>
31 #include <QCloseEvent>
32 #include <QFrame>
33 #include <QGridLayout>
34 #include <QGroupBox>
35 #include <QHeaderView>
36 #include <QLabel>
37 #include <QPushButton>
38 #include <QTableView>
39 #include <QVBoxLayout>
40 #include <QSortFilterProxyModel>
41 #include <QMenu>
42 #include <QClipboard>
43 
44 #include <akonadi/collection.h>
45 #include <akonadi/itemcreatejob.h>
46 #include <kcombobox.h>
47 #include <kconfig.h>
48 #include <kconfiggroup.h>
49 #include <kcmultidialog.h>
50 #include <kdialogbuttonbox.h>
51 #include <kldap/ldapobject.h>
52 #include <kldap/ldapserver.h>
53 #include <klineedit.h>
54 #include <klocale.h>
55 #include <kmessagebox.h>
56 
57 #include <KPIMUtils/ProgressIndicatorLabel>
58 
59 using namespace KLDAP;
60 
61 static QString asUtf8( const QByteArray &val )
62 {
63  if ( val.isEmpty() ) {
64  return QString();
65  }
66 
67  const char *data = val.data();
68 
69  //QString::fromUtf8() bug workaround
70  if ( data[ val.size() - 1 ] == '\0' ) {
71  return QString::fromUtf8( data, val.size() - 1 );
72  } else {
73  return QString::fromUtf8( data, val.size() );
74  }
75 }
76 
77 static QString join( const KLDAP::LdapAttrValue &lst, const QString &sep )
78 {
79  QString res;
80  bool alredy = false;
81  KLDAP::LdapAttrValue::ConstIterator end(lst.constEnd());
82  for ( KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); it != end; ++it ) {
83  if ( alredy ) {
84  res += sep;
85  }
86 
87  alredy = true;
88  res += asUtf8( *it );
89  }
90 
91  return res;
92 }
93 
94 static QMap<QString, QString>& adrbookattr2ldap()
95 {
96  static QMap<QString, QString> keys;
97 
98  if ( keys.isEmpty() ) {
99  keys[ i18nc( "@item LDAP search key", "Title" ) ] = QLatin1String("title");
100  keys[ i18n( "Full Name" ) ] = QLatin1String("cn");
101  keys[ i18nc( "@item LDAP search key", "Email" ) ] = QLatin1String("mail");
102  keys[ i18n( "Home Number" ) ] = QLatin1String("homePhone");
103  keys[ i18n( "Work Number" ) ] = QLatin1String("telephoneNumber");
104  keys[ i18n( "Mobile Number" ) ] = QLatin1String("mobile");
105  keys[ i18n( "Fax Number" ) ] = QLatin1String("facsimileTelephoneNumber");
106  keys[ i18n( "Pager" ) ] = QLatin1String("pager");
107  keys[ i18n( "Street" ) ] = QLatin1String("street");
108  keys[ i18nc( "@item LDAP search key", "State" ) ] = QLatin1String("st");
109  keys[ i18n( "Country" ) ] = QLatin1String("co");
110  keys[ i18n( "City" ) ] = QLatin1String("l"); //krazy:exclude=doublequote_chars
111  keys[ i18n( "Organization" ) ] = QLatin1String("o"); //krazy:exclude=doublequote_chars
112  keys[ i18n( "Company" ) ] = QLatin1String("Company");
113  keys[ i18n( "Department" ) ] = QLatin1String("department");
114  keys[ i18n( "Zip Code" ) ] = QLatin1String("postalCode");
115  keys[ i18n( "Postal Address" ) ] = QLatin1String("postalAddress");
116  keys[ i18n( "Description" ) ] = QLatin1String("description");
117  keys[ i18n( "User ID" ) ] = QLatin1String("uid");
118  }
119 
120  return keys;
121 }
122 
123 static QString makeFilter( const QString &query, const QString &attr, bool startsWith )
124 {
125  /* The reasoning behind this filter is:
126  * If it's a person, or a distlist, show it, even if it doesn't have an email address.
127  * If it's not a person, or a distlist, only show it if it has an email attribute.
128  * This allows both resource accounts with an email address which are not a person and
129  * person entries without an email address to show up, while still not showing things
130  * like structural entries in the ldap tree. */
131  QString result( QLatin1String("&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(") );
132  if ( query.isEmpty() ) {
133  // Return a filter that matches everything
134  return result + QLatin1String("|(cn=*)(sn=*)") + QLatin1Char(')');
135  }
136 
137  if ( attr == i18nc( "Search attribute: Name of contact", "Name" ) ) {
138  result += startsWith ? QLatin1String("|(cn=%1*)(sn=%2*)") : QLatin1String("|(cn=*%1*)(sn=*%2*)");
139  result = result.arg( query ).arg( query );
140  } else {
141  result += startsWith ? QLatin1String("%1=%2*") : QLatin1String("%1=*%2*");
142  if ( attr == i18nc( "Search attribute: Email of the contact", "Email" ) ) {
143  result = result.arg( QLatin1String("mail") ).arg( query );
144  } else if ( attr == i18n( "Home Number" ) ) {
145  result = result.arg( QLatin1String("homePhone") ).arg( query );
146  } else if ( attr == i18n( "Work Number" ) ) {
147  result = result.arg( QLatin1String("telephoneNumber") ).arg( query );
148  } else {
149  // Error?
150  result.clear();
151  return result;
152  }
153  }
154  result += QLatin1Char(')');
155  return result;
156 }
157 
158 static KABC::Addressee convertLdapAttributesToAddressee( const KLDAP::LdapAttrMap &attrs )
159 {
160  KABC::Addressee addr;
161 
162  // name
163  if ( !attrs.value( QLatin1String("cn") ).isEmpty() ) {
164  addr.setNameFromString( asUtf8( attrs[QLatin1String("cn")].first() ) );
165  }
166 
167  // email
168  KLDAP::LdapAttrValue lst = attrs[QLatin1String("mail")];
169  KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin();
170  bool pref = true;
171  while ( it != lst.constEnd() ) {
172  addr.insertEmail( asUtf8( *it ), pref );
173  pref = false;
174  ++it;
175  }
176 
177  if ( !attrs.value( QLatin1String("o") ).isEmpty() ) {
178  addr.setOrganization( asUtf8( attrs[ QLatin1String("o") ].first() ) );
179  }
180  if ( addr.organization().isEmpty() && !attrs.value( QLatin1String("Company") ).isEmpty() ) {
181  addr.setOrganization( asUtf8( attrs[ QLatin1String("Company") ].first() ) );
182  }
183 
184  // Address
185  KABC::Address workAddr( KABC::Address::Work );
186 
187  if ( !attrs.value( QLatin1String("department") ).isEmpty() ) {
188  addr.setDepartment( asUtf8( attrs[ QLatin1String("department") ].first() ) );
189  }
190 
191  if ( !workAddr.isEmpty() ) {
192  addr.insertAddress( workAddr );
193  }
194 
195  // phone
196  if ( !attrs.value( QLatin1String("homePhone") ).isEmpty() ) {
197  KABC::PhoneNumber homeNr = asUtf8( attrs[ QLatin1String("homePhone") ].first() );
198  homeNr.setType( KABC::PhoneNumber::Home );
199  addr.insertPhoneNumber( homeNr );
200  }
201 
202  if ( !attrs.value( QLatin1String("telephoneNumber") ).isEmpty() ) {
203  KABC::PhoneNumber workNr = asUtf8( attrs[ QLatin1String("telephoneNumber") ].first() );
204  workNr.setType( KABC::PhoneNumber::Work );
205  addr.insertPhoneNumber( workNr );
206  }
207 
208  if ( !attrs.value( QLatin1String("facsimileTelephoneNumber") ).isEmpty() ) {
209  KABC::PhoneNumber faxNr = asUtf8( attrs[ QLatin1String("facsimileTelephoneNumber") ].first() );
210  faxNr.setType( KABC::PhoneNumber::Fax );
211  addr.insertPhoneNumber( faxNr );
212  }
213 
214  if ( !attrs.value( QLatin1String("mobile") ).isEmpty() ) {
215  KABC::PhoneNumber cellNr = asUtf8( attrs[ QLatin1String("mobile") ].first() );
216  cellNr.setType( KABC::PhoneNumber::Cell );
217  addr.insertPhoneNumber( cellNr );
218  }
219 
220  if ( !attrs.value( QLatin1String("pager") ).isEmpty() ) {
221  KABC::PhoneNumber pagerNr = asUtf8( attrs[ QLatin1String("pager") ].first() );
222  pagerNr.setType( KABC::PhoneNumber::Pager );
223  addr.insertPhoneNumber( pagerNr );
224  }
225 
226  return addr;
227 }
228 
229 class ContactListModel : public QAbstractTableModel
230 {
231  public:
232  enum Role {
233  ServerRole = Qt::UserRole + 1
234  };
235 
236  ContactListModel( QObject *parent )
237  : QAbstractTableModel( parent )
238  {
239  }
240 
241  void addContact( const KLDAP::LdapAttrMap &contact, const QString &server )
242  {
243  mContactList.append( contact );
244  mServerList.append( server );
245  reset();
246  }
247 
248  QPair<KLDAP::LdapAttrMap, QString> contact( const QModelIndex &index ) const
249  {
250  if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
251  return qMakePair( KLDAP::LdapAttrMap(), QString() );
252  }
253 
254  return qMakePair( mContactList.at( index.row() ), mServerList.at( index.row() ) );
255  }
256 
257  QString email( const QModelIndex &index ) const
258  {
259  if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
260  return QString();
261  }
262 
263  return asUtf8( mContactList.at( index.row() ).value( QLatin1String("mail") ).first() ).trimmed();
264  }
265 
266  QString fullName( const QModelIndex &index ) const
267  {
268  if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
269  return QString();
270  }
271 
272  return asUtf8( mContactList.at( index.row() ).value( QLatin1String("cn") ).first() ).trimmed();
273  }
274 
275  void clear()
276  {
277  mContactList.clear();
278  mServerList.clear();
279  reset();
280  }
281 
282  virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const
283  {
284  if ( !parent.isValid() ) {
285  return mContactList.count();
286  } else {
287  return 0;
288  }
289  }
290 
291  virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const
292  {
293  if ( !parent.isValid() ) {
294  return 18;
295  } else {
296  return 0;
297  }
298  }
299 
300  virtual QVariant headerData( int section, Qt::Orientation orientation,
301  int role = Qt::DisplayRole ) const
302  {
303  if ( orientation == Qt::Vertical || role != Qt::DisplayRole || section < 0 || section > 17 ) {
304  return QVariant();
305  }
306 
307  switch ( section ) {
308  case 0:
309  return i18n( "Full Name" );
310  break;
311  case 1:
312  return i18nc( "@title:column Column containing email addresses", "Email" );
313  break;
314  case 2:
315  return i18n( "Home Number" );
316  break;
317  case 3:
318  return i18n( "Work Number" );
319  break;
320  case 4:
321  return i18n( "Mobile Number" );
322  break;
323  case 5:
324  return i18n( "Fax Number" );
325  break;
326  case 6:
327  return i18n( "Company" );
328  break;
329  case 7:
330  return i18n( "Organization" );
331  break;
332  case 8:
333  return i18n( "Street" );
334  break;
335  case 9:
336  return i18nc( "@title:column Column containing the residential state of the address",
337  "State" );
338  break;
339  case 10:
340  return i18n( "Country" );
341  break;
342  case 11:
343  return i18n( "Zip Code" );
344  break;
345  case 12:
346  return i18n( "Postal Address" );
347  break;
348  case 13:
349  return i18n( "City" );
350  break;
351  case 14:
352  return i18n( "Department" );
353  break;
354  case 15:
355  return i18n( "Description" );
356  break;
357  case 16:
358  return i18n( "User ID" );
359  break;
360  case 17:
361  return i18nc( "@title:column Column containing title of the person", "Title" );
362  break;
363  default:
364  return QVariant();
365  break;
366  };
367 
368  return QVariant();
369  }
370 
371  virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const
372  {
373  if ( !index.isValid() ) {
374  return QVariant();
375  }
376 
377  if ( index.row() < 0 || index.row() >= mContactList.count() ||
378  index.column() < 0 || index.column() > 17 ) {
379  return QVariant();
380  }
381 
382  if ( role == ServerRole ) {
383  return mServerList.at( index.row() );
384  }
385 
386  if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) ) {
387  return QVariant();
388  }
389 
390  const KLDAP::LdapAttrMap map = mContactList.at( index.row() );
391 
392  switch ( index.column() ) {
393  case 0:
394  return join( map.value( QLatin1String("cn") ), QLatin1String(", ") );
395  break;
396  case 1:
397  return join( map.value( QLatin1String("mail") ), QLatin1String(", ") );
398  break;
399  case 2:
400  return join( map.value( QLatin1String("homePhone") ), QLatin1String(", ") );
401  break;
402  case 3:
403  return join( map.value( QLatin1String("telephoneNumber") ), QLatin1String(", ") );
404  break;
405  case 4:
406  return join( map.value( QLatin1String("mobile") ), QLatin1String(", ") );
407  break;
408  case 5:
409  return join( map.value( QLatin1String("facsimileTelephoneNumber") ), QLatin1String(", ") );
410  break;
411  case 6:
412  return join( map.value( QLatin1String("Company") ), QLatin1String(", ") );
413  break;
414  case 7:
415  return join( map.value( QLatin1String("o") ), QLatin1String(", " ));
416  break;
417  case 8:
418  return join( map.value( QLatin1String("street") ), QLatin1String(", ") );
419  break;
420  case 9:
421  return join( map.value( QLatin1String("st") ), QLatin1String(", " ));
422  break;
423  case 10:
424  return join( map.value( QLatin1String("co") ), QLatin1String(", ") );
425  break;
426  case 11:
427  return join( map.value( QLatin1String("postalCode") ), QLatin1String(", ") );
428  break;
429  case 12:
430  return join( map.value( QLatin1String("postalAddress") ), QLatin1String(", ") );
431  break;
432  case 13:
433  return join( map.value( QLatin1String("l") ), QLatin1String(", ") );
434  break;
435  case 14:
436  return join( map.value( QLatin1String("department") ),QLatin1String( ", " ));
437  break;
438  case 15:
439  return join( map.value( QLatin1String("description") ), QLatin1String(", ") );
440  break;
441  case 16:
442  return join( map.value( QLatin1String("uid") ), QLatin1String(", ") );
443  break;
444  case 17:
445  return join( map.value( QLatin1String("title") ), QLatin1String(", ") );
446  break;
447  default:
448  return QVariant();
449  break;
450  }
451 
452  return QVariant();
453  }
454 
455  private:
456  QList<KLDAP::LdapAttrMap> mContactList;
457  QStringList mServerList;
458 };
459 
460 class LdapSearchDialog::Private
461 {
462  public:
463  Private( LdapSearchDialog *qq )
464  : q( qq ),
465  mNumHosts( 0 ),
466  mIsConfigured( false ),
467  mModel( 0 )
468  {
469  }
470 
471  QList< QPair<KLDAP::LdapAttrMap, QString> > selectedItems()
472  {
473  QList< QPair<KLDAP::LdapAttrMap, QString> > contacts;
474 
475  const QModelIndexList selected = mResultView->selectionModel()->selectedRows();
476  for ( int i = 0; i < selected.count(); ++i ) {
477  contacts.append( mModel->contact( sortproxy->mapToSource(selected.at( i )) ) );
478  }
479 
480  return contacts;
481  }
482 
483 
484  void saveSettings();
485  void restoreSettings();
486  void cancelQuery();
487 
488  void slotAddResult( const KLDAP::LdapClient&, const KLDAP::LdapObject& );
489  void slotSetScope( bool );
490  void slotStartSearch();
491  void slotStopSearch();
492  void slotSearchDone();
493  void slotError( const QString& );
494  void slotSelectAll();
495  void slotUnselectAll();
496  void slotSelectionChanged();
497 
498  LdapSearchDialog *q;
499  int mNumHosts;
500  QList<KLDAP::LdapClient*> mLdapClientList;
501  bool mIsConfigured;
502  KABC::Addressee::List mSelectedContacts;
503 
504  KComboBox *mFilterCombo;
505  KComboBox *mSearchType;
506  KLineEdit *mSearchEdit;
507 
508  QCheckBox *mRecursiveCheckbox;
509  QTableView *mResultView;
510  QPushButton *mSearchButton;
511  ContactListModel *mModel;
512  KPIMUtils::ProgressIndicatorLabel *progressIndication;
513  QSortFilterProxyModel *sortproxy;
514 };
515 
516 LdapSearchDialog::LdapSearchDialog( QWidget *parent )
517  : KDialog( parent ), d( new Private( this ) )
518 {
519  setCaption( i18n( "Import Contacts from LDAP" ) );
520 #ifdef _WIN32_WCE
521  setButtons( /*Help |*/ User1 | Cancel );
522 #else
523  setButtons( /*Help |*/ User1 | User2 | Cancel );
524 #endif
525  setDefaultButton( User1 );
526  setModal( false );
527  showButtonSeparator( true );
528  setButtonGuiItem( KDialog::Cancel, KStandardGuiItem::close() );
529  QFrame *page = new QFrame( this );
530  setMainWidget( page );
531  QVBoxLayout *topLayout = new QVBoxLayout( page );
532  topLayout->setSpacing( spacingHint() );
533  topLayout->setMargin( marginHint() );
534 
535  QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ),
536  page );
537  QGridLayout *boxLayout = new QGridLayout();
538  groupBox->setLayout( boxLayout );
539  boxLayout->setSpacing( spacingHint() );
540  boxLayout->setColumnStretch( 1, 1 );
541 
542  QLabel *label = new QLabel( i18n( "Search for:" ), groupBox );
543  boxLayout->addWidget( label, 0, 0 );
544 
545  d->mSearchEdit = new KLineEdit( groupBox );
546  d->mSearchEdit->setClearButtonShown(true);
547  boxLayout->addWidget( d->mSearchEdit, 0, 1 );
548  label->setBuddy( d->mSearchEdit );
549 
550  label = new QLabel( i18nc( "In LDAP attribute", "in" ), groupBox );
551  boxLayout->addWidget( label, 0, 2 );
552 
553  d->mFilterCombo = new KComboBox( groupBox );
554  d->mFilterCombo->addItem( i18nc( "@item:inlistbox Name of the contact", "Name" ) );
555  d->mFilterCombo->addItem( i18nc( "@item:inlistbox email address of the contact", "Email" ) );
556  d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Home Number" ) );
557  d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Work Number" ) );
558  boxLayout->addWidget( d->mFilterCombo, 0, 3 );
559 
560  QSize buttonSize;
561  d->mSearchButton = new QPushButton( i18n( "Stop" ), groupBox );
562  buttonSize = d->mSearchButton->sizeHint();
563  d->mSearchButton->setText( i18nc( "@action:button Start searching", "&Search" ) );
564  if ( buttonSize.width() < d->mSearchButton->sizeHint().width() ) {
565  buttonSize = d->mSearchButton->sizeHint();
566  }
567  d->mSearchButton->setFixedWidth( buttonSize.width() );
568 
569  d->mSearchButton->setDefault( true );
570  boxLayout->addWidget( d->mSearchButton, 0, 4 );
571 
572  d->mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox );
573  d->mRecursiveCheckbox->setChecked( true );
574  boxLayout->addWidget( d->mRecursiveCheckbox, 1, 0, 1, 5 );
575 
576  d->mSearchType = new KComboBox( groupBox );
577  d->mSearchType->addItem( i18n( "Contains" ) );
578  d->mSearchType->addItem( i18n( "Starts With" ) );
579  boxLayout->addWidget( d->mSearchType, 1, 3, 1, 2 );
580 
581  topLayout->addWidget( groupBox );
582 
583  d->mResultView = new QTableView( page );
584  d->mResultView->setSelectionMode( QTableView::MultiSelection );
585  d->mResultView->setSelectionBehavior( QTableView::SelectRows );
586  d->mModel = new ContactListModel( d->mResultView );
587 
588  d->sortproxy = new QSortFilterProxyModel( this );
589  d->sortproxy->setSourceModel( d->mModel );
590 
591  d->mResultView->setModel( d->sortproxy );
592  d->mResultView->verticalHeader()->hide();
593  d->mResultView->setSortingEnabled(true);
594  d->mResultView->horizontalHeader()->setSortIndicatorShown(true);
595  connect( d->mResultView, SIGNAL(clicked(QModelIndex)),
596  SLOT(slotSelectionChanged()) );
597  topLayout->addWidget( d->mResultView );
598 
599  d->mResultView->setContextMenuPolicy(Qt::CustomContextMenu);
600  connect(d->mResultView, SIGNAL(customContextMenuRequested(QPoint)),
601  this, SLOT(slotCustomContextMenuRequested(QPoint)));
602 
603 
604  QHBoxLayout *buttonLayout = new QHBoxLayout;
605  buttonLayout->setMargin(0);
606  topLayout->addLayout(buttonLayout);
607 
608  d->progressIndication = new KPIMUtils::ProgressIndicatorLabel(i18n("Searching..."));
609  buttonLayout->addWidget(d->progressIndication);
610 
611  KDialogButtonBox *buttons = new KDialogButtonBox( page, Qt::Horizontal );
612  buttons->addButton( i18n( "Select All" ),
613  QDialogButtonBox::ActionRole, this, SLOT(slotSelectAll()) );
614  buttons->addButton( i18n( "Unselect All" ),
615  QDialogButtonBox::ActionRole, this, SLOT(slotUnselectAll()) );
616 
617  buttonLayout->addWidget( buttons );
618 
619 
620 
621  setButtonText( User1, i18n( "Add Selected" ) );
622 #ifndef _WIN32_WCE
623  setButtonText( User2, i18n( "Configure LDAP Servers..." ) );
624 #endif
625 
626  connect( d->mRecursiveCheckbox, SIGNAL(toggled(bool)),
627  this, SLOT(slotSetScope(bool)) );
628  connect( d->mSearchButton, SIGNAL(clicked()),
629  this, SLOT(slotStartSearch()) );
630 
631  setTabOrder( d->mSearchEdit, d->mFilterCombo );
632  setTabOrder( d->mFilterCombo, d->mSearchButton );
633  d->mSearchEdit->setFocus();
634 
635  connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) );
636 #ifndef _WIN32_WCE
637  connect( this, SIGNAL(user2Clicked()), this, SLOT(slotUser2()) );
638 #endif
639  d->slotSelectionChanged();
640  d->restoreSettings();
641 }
642 
643 LdapSearchDialog::~LdapSearchDialog()
644 {
645  d->saveSettings();
646  delete d;
647 }
648 
649 void LdapSearchDialog::setSearchText( const QString &text )
650 {
651  d->mSearchEdit->setText( text );
652 }
653 
654 KABC::Addressee::List LdapSearchDialog::selectedContacts() const
655 {
656  return d->mSelectedContacts;
657 }
658 
659 void LdapSearchDialog::slotCustomContextMenuRequested(const QPoint &pos)
660 {
661  const QModelIndex index = d->mResultView->indexAt(pos);
662  if (index.isValid()) {
663  QMenu menu;
664  QAction *act = menu.addAction(i18n("Copy"));
665  if (menu.exec(QCursor::pos()) == act) {
666  QClipboard *cb = QApplication::clipboard();
667  cb->setText(index.data().toString(), QClipboard::Clipboard);
668  }
669  }
670 }
671 
672 
673 void LdapSearchDialog::Private::slotSelectionChanged()
674 {
675  q->enableButton( KDialog::User1, mResultView->selectionModel()->hasSelection() );
676 }
677 
678 void LdapSearchDialog::Private::restoreSettings()
679 {
680  // Create one KLDAP::LdapClient per selected server and configure it.
681 
682  // First clean the list to make sure it is empty at
683  // the beginning of the process
684  qDeleteAll( mLdapClientList ) ;
685  mLdapClientList.clear();
686 
687  KConfig *config = KLDAP::LdapClientSearchConfig::config();
688 
689  KConfigGroup searchGroup( config, "LDAPSearch" );
690  mSearchType->setCurrentIndex( searchGroup.readEntry( "SearchType", 0 ) );
691 
692  // then read the config file and register all selected
693  // server in the list
694  KConfigGroup group( config, "LDAP" );
695  mNumHosts = group.readEntry( "NumSelectedHosts", 0 );
696  if ( !mNumHosts ) {
697  mIsConfigured = false;
698  } else {
699  mIsConfigured = true;
700  KLDAP::LdapClientSearchConfig *clientSearchConfig = new KLDAP::LdapClientSearchConfig;
701  for ( int j = 0; j < mNumHosts; ++j ) {
702  KLDAP::LdapServer ldapServer;
703  KLDAP::LdapClient *ldapClient = new KLDAP::LdapClient( 0, q );
704  clientSearchConfig->readConfig( ldapServer, group, j, true );
705  ldapClient->setServer( ldapServer );
706  QStringList attrs;
707 
708  QMap<QString, QString>::ConstIterator end(adrbookattr2ldap().constEnd());
709  for ( QMap<QString, QString>::ConstIterator it = adrbookattr2ldap().constBegin();
710  it != end; ++it ) {
711  attrs << *it;
712  }
713 
714  ldapClient->setAttributes( attrs );
715 
716  q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)),
717  q, SLOT(slotAddResult(KLDAP::LdapClient,KLDAP::LdapObject)) );
718  q->connect( ldapClient, SIGNAL(done()),
719  q, SLOT(slotSearchDone()) );
720  q->connect( ldapClient, SIGNAL(error(QString)),
721  q, SLOT(slotError(QString)) );
722 
723  mLdapClientList.append( ldapClient );
724  }
725  delete clientSearchConfig;
726 
727  mModel->clear();
728  }
729  KConfigGroup groupHeader( config, "Headers" );
730  mResultView->horizontalHeader()->restoreState(groupHeader.readEntry("HeaderState",QByteArray()));
731 
732  KConfigGroup groupSize( config, "Size" );
733  const QSize dialogSize = groupSize.readEntry( "Size", QSize() );
734  if ( dialogSize.isValid() ) {
735  q->resize( dialogSize );
736  } else {
737  q->resize( QSize( 600, 400 ).expandedTo( q->minimumSizeHint() ) );
738  }
739 }
740 
741 void LdapSearchDialog::Private::saveSettings()
742 {
743  KConfig *config = KLDAP::LdapClientSearchConfig::config();
744  KConfigGroup group( config, "LDAPSearch" );
745  group.writeEntry( "SearchType", mSearchType->currentIndex() );
746 
747  KConfigGroup groupHeader( config, "Headers" );
748  groupHeader.writeEntry( "HeaderState", mResultView->horizontalHeader()->saveState());
749  groupHeader.sync();
750 
751  KConfigGroup size( config, "Size" );
752  size.writeEntry( "Size", q->size());
753  size.sync();
754 
755  group.sync();
756 }
757 
758 void LdapSearchDialog::Private::cancelQuery()
759 {
760  Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
761  client->cancelQuery();
762  }
763 }
764 
765 void LdapSearchDialog::Private::slotAddResult( const KLDAP::LdapClient &client,
766  const KLDAP::LdapObject &obj )
767 {
768  mModel->addContact( obj.attributes(), client.server().host() );
769 }
770 
771 void LdapSearchDialog::Private::slotSetScope( bool rec )
772 {
773  Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
774  if ( rec ) {
775  client->setScope( QLatin1String("sub") );
776  } else {
777  client->setScope( QLatin1String("one") );
778  }
779  }
780 }
781 
782 void LdapSearchDialog::Private::slotStartSearch()
783 {
784  cancelQuery();
785 
786  if ( !mIsConfigured ) {
787  KMessageBox::error( q, i18n( "You must select an LDAP server before searching." ) );
788  q->slotUser2();
789  return;
790  }
791 
792 #ifndef QT_NO_CURSOR
793  QApplication::setOverrideCursor( Qt::WaitCursor );
794 #endif
795  mSearchButton->setText( i18n( "Stop" ) );
796  progressIndication->start();
797 
798  q->disconnect( mSearchButton, SIGNAL(clicked()),
799  q, SLOT(slotStartSearch()) );
800  q->connect( mSearchButton, SIGNAL(clicked()),
801  q, SLOT(slotStopSearch()) );
802 
803  const bool startsWith = (mSearchType->currentIndex() == 1);
804 
805  const QString filter = makeFilter( mSearchEdit->text().trimmed(),
806  mFilterCombo->currentText(), startsWith );
807 
808  // loop in the list and run the KLDAP::LdapClients
809  mModel->clear();
810  Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
811  client->startQuery( filter );
812  }
813 
814  saveSettings();
815 }
816 
817 void LdapSearchDialog::Private::slotStopSearch()
818 {
819  cancelQuery();
820  slotSearchDone();
821 }
822 
823 void LdapSearchDialog::Private::slotSearchDone()
824 {
825  // If there are no more active clients, we are done.
826  Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
827  if ( client->isActive() ) {
828  return;
829  }
830  }
831 
832  q->disconnect( mSearchButton, SIGNAL(clicked()),
833  q, SLOT(slotStopSearch()) );
834  q->connect( mSearchButton, SIGNAL(clicked()),
835  q, SLOT(slotStartSearch()) );
836 
837  mSearchButton->setText( i18nc( "@action:button Start searching", "&Search" ) );
838  progressIndication->stop();
839 #ifndef QT_NO_CURSOR
840  QApplication::restoreOverrideCursor();
841 #endif
842 }
843 
844 void LdapSearchDialog::Private::slotError( const QString &error )
845 {
846 #ifndef QT_NO_CURSOR
847  QApplication::restoreOverrideCursor();
848 #endif
849  KMessageBox::error( q, error );
850 }
851 
852 void LdapSearchDialog::closeEvent( QCloseEvent *e )
853 {
854  d->slotStopSearch();
855  e->accept();
856 }
857 
858 void LdapSearchDialog::Private::slotUnselectAll()
859 {
860  mResultView->clearSelection();
861  slotSelectionChanged();
862 }
863 
864 void LdapSearchDialog::Private::slotSelectAll()
865 {
866  mResultView->selectAll();
867  slotSelectionChanged();
868 }
869 
870 void LdapSearchDialog::slotUser1()
871 {
872  // Import selected items
873 
874  d->mSelectedContacts.clear();
875 
876  const QList< QPair<KLDAP::LdapAttrMap, QString> >& items = d->selectedItems();
877 
878  if ( !items.isEmpty() ) {
879  const QDateTime now = QDateTime::currentDateTime();
880 
881  for ( int i = 0; i < items.count(); ++i ) {
882  KABC::Addressee contact = convertLdapAttributesToAddressee( items.at( i ).first );
883 
884  // set a comment where the contact came from
885  contact.setNote( i18nc( "arguments are host name, datetime",
886  "Imported from LDAP directory %1 on %2",
887  items.at( i ).second, KGlobal::locale()->formatDateTime( now ) ) );
888 
889  d->mSelectedContacts.append( contact );
890  }
891  }
892 
893  emit contactsAdded();
894 
895  accept();
896 }
897 
898 void LdapSearchDialog::slotUser2()
899 {
900  // Configure LDAP servers
901 
902  KCMultiDialog dialog( this );
903  dialog.setCaption( i18n( "Configure the Address Book LDAP Settings" ) );
904  dialog.addModule( QLatin1String("kcmldap.desktop") );
905 
906  if ( dialog.exec() ) { //krazy:exclude=crashy
907  d->restoreSettings();
908  }
909 }
910 
911 #include "ldapsearchdialog.moc"
KLDAP::LdapSearchDialog::~LdapSearchDialog
~LdapSearchDialog()
Destroys the ldap search dialog.
Definition: ldapsearchdialog.cpp:643
KLDAP::LdapClient::server
const KLDAP::LdapServer server() const
Returns the ldap server information that are used by this client.
Definition: ldapclient.cpp:120
KLDAP::LdapSearchDialog::slotUser1
void slotUser1()
Definition: ldapsearchdialog.cpp:870
KLDAP::LdapSearchDialog::closeEvent
void closeEvent(QCloseEvent *)
Definition: ldapsearchdialog.cpp:852
KLDAP::LdapSearchDialog::slotCustomContextMenuRequested
void slotCustomContextMenuRequested(const QPoint &)
Definition: ldapsearchdialog.cpp:659
KLDAP::LdapSearchDialog::contactsAdded
void contactsAdded()
This signal is emitted whenever the user clicked the 'Add Selected' button.
QWidget
KDialog
QObject
ldapsearchdialog.h
KLDAP::LdapClient::isActive
bool isActive() const
Returns whether this client is currently running a search query.
Definition: ldapclient.cpp:105
KLDAP::LdapSearchDialog::LdapSearchDialog
LdapSearchDialog(QWidget *parent=0)
Creates a new ldap search dialog.
Definition: ldapsearchdialog.cpp:516
convertLdapAttributesToAddressee
static KABC::Addressee convertLdapAttributesToAddressee(const KLDAP::LdapAttrMap &attrs)
Definition: ldapsearchdialog.cpp:158
ldapclient.h
KLDAP::LdapClient::startQuery
void startQuery(const QString &filter)
Starts the query with the given filter.
Definition: ldapclient.cpp:141
join
static QString join(const KLDAP::LdapAttrValue &lst, const QString &sep)
Definition: ldapsearchdialog.cpp:77
ldapclientsearchconfig.h
KLDAP::LdapSearchDialog::setSearchText
void setSearchText(const QString &text)
Sets the text in the search line edit.
Definition: ldapsearchdialog.cpp:649
KLDAP::LdapClient::setAttributes
void setAttributes(const QStringList &attributes)
Sets the LDAP attributes that should be returned in the query result.
Definition: ldapclient.cpp:125
KLDAP::LdapSearchDialog
A dialog to search contacts in a LDAP directory.
Definition: ldapsearchdialog.h:48
QMenu
KLineEdit
QLabel
makeFilter
static QString makeFilter(const QString &query, const QString &attr, bool startsWith)
Definition: ldapsearchdialog.cpp:123
KComboBox
KLDAP::LdapSearchDialog::slotUser2
void slotUser2()
Definition: ldapsearchdialog.cpp:898
KLDAP::LdapClient::setServer
void setServer(const KLDAP::LdapServer &server)
Sets the LDAP server information that shall be used by this client.
Definition: ldapclient.cpp:110
KLDAP::LdapSearchDialog::selectedContacts
KABC::Addressee::List selectedContacts() const
Returns a list of contacts that have been selected in the LDAP search.
Definition: ldapsearchdialog.cpp:654
QFrame
KLDAP::LdapClient
An object that represents a configured LDAP server.
Definition: ldapclient.h:48
asUtf8
static QString asUtf8(const QByteArray &val)
Definition: ldapsearchdialog.cpp:61
KLDAP::LdapClient::setScope
void setScope(const QString scope)
Sets the scope of the LDAP query.
Definition: ldapclient.cpp:136
adrbookattr2ldap
static QMap< QString, QString > & adrbookattr2ldap()
Definition: ldapsearchdialog.cpp:94
QList
KLDAP::LdapClient::cancelQuery
void cancelQuery()
Cancels a running query.
Definition: ldapclient.cpp:173
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:58:03 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libkdepim

Skip menu "libkdepim"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal