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

libkdepim

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

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