mirror of
https://bitbucket.org/smil3y/kde-playground.git
synced 2025-02-23 18:32:51 +00:00
932 lines
30 KiB
C++
932 lines
30 KiB
C++
/*
|
|
* This file is part of libkldap.
|
|
*
|
|
* Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
|
*
|
|
* Author: Steffen Hansen <hansen@kde.org>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Library General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Library General Public License
|
|
* along with this library; see the file COPYING.LIB. If not, write to
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
* Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#include "ldapsearchdialog.h"
|
|
|
|
#include "ldapclient.h"
|
|
#include "ldapclientsearchconfig.h"
|
|
#include <QtCore/QPair>
|
|
#include <QApplication>
|
|
#include <QCheckBox>
|
|
#include <QCloseEvent>
|
|
#include <QFrame>
|
|
#include <QGridLayout>
|
|
#include <QGroupBox>
|
|
#include <QHeaderView>
|
|
#include <QLabel>
|
|
#include <QPushButton>
|
|
#include <QTableView>
|
|
#include <QVBoxLayout>
|
|
#include <QSortFilterProxyModel>
|
|
#include <QMenu>
|
|
#include <QClipboard>
|
|
|
|
#include <akonadi/collection.h>
|
|
#include <akonadi/itemcreatejob.h>
|
|
#include <kcombobox.h>
|
|
#include <kconfig.h>
|
|
#include <kconfiggroup.h>
|
|
#include <kcmultidialog.h>
|
|
#include <kdialogbuttonbox.h>
|
|
#include <kldap/ldapobject.h>
|
|
#include <kldap/ldapserver.h>
|
|
#include <klineedit.h>
|
|
#include <klocale.h>
|
|
#include <kmessagebox.h>
|
|
#include <KPushButton>
|
|
|
|
#include <KPIMUtils/ProgressIndicatorLabel>
|
|
|
|
using namespace KLDAP;
|
|
|
|
static QString asUtf8( const QByteArray &val )
|
|
{
|
|
if ( val.isEmpty() ) {
|
|
return QString();
|
|
}
|
|
|
|
const char *data = val.data();
|
|
|
|
//QString::fromUtf8() bug workaround
|
|
if ( data[ val.size() - 1 ] == '\0' ) {
|
|
return QString::fromUtf8( data, val.size() - 1 );
|
|
} else {
|
|
return QString::fromUtf8( data, val.size() );
|
|
}
|
|
}
|
|
|
|
static QString join( const KLDAP::LdapAttrValue &lst, const QString &sep )
|
|
{
|
|
QString res;
|
|
bool alredy = false;
|
|
KLDAP::LdapAttrValue::ConstIterator end(lst.constEnd());
|
|
for ( KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin(); it != end; ++it ) {
|
|
if ( alredy ) {
|
|
res += sep;
|
|
}
|
|
|
|
alredy = true;
|
|
res += asUtf8( *it );
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
static QMap<QString, QString>& adrbookattr2ldap()
|
|
{
|
|
static QMap<QString, QString> keys;
|
|
|
|
if ( keys.isEmpty() ) {
|
|
keys[ i18nc( "@item LDAP search key", "Title" ) ] = QLatin1String("title");
|
|
keys[ i18n( "Full Name" ) ] = QLatin1String("cn");
|
|
keys[ i18nc( "@item LDAP search key", "Email" ) ] = QLatin1String("mail");
|
|
keys[ i18n( "Home Number" ) ] = QLatin1String("homePhone");
|
|
keys[ i18n( "Work Number" ) ] = QLatin1String("telephoneNumber");
|
|
keys[ i18n( "Mobile Number" ) ] = QLatin1String("mobile");
|
|
keys[ i18n( "Fax Number" ) ] = QLatin1String("facsimileTelephoneNumber");
|
|
keys[ i18n( "Pager" ) ] = QLatin1String("pager");
|
|
keys[ i18n( "Street" ) ] = QLatin1String("street");
|
|
keys[ i18nc( "@item LDAP search key", "State" ) ] = QLatin1String("st");
|
|
keys[ i18n( "Country" ) ] = QLatin1String("co");
|
|
keys[ i18n( "City" ) ] = QLatin1String("l"); //krazy:exclude=doublequote_chars
|
|
keys[ i18n( "Organization" ) ] = QLatin1String("o"); //krazy:exclude=doublequote_chars
|
|
keys[ i18n( "Company" ) ] = QLatin1String("Company");
|
|
keys[ i18n( "Department" ) ] = QLatin1String("department");
|
|
keys[ i18n( "Zip Code" ) ] = QLatin1String("postalCode");
|
|
keys[ i18n( "Postal Address" ) ] = QLatin1String("postalAddress");
|
|
keys[ i18n( "Description" ) ] = QLatin1String("description");
|
|
keys[ i18n( "User ID" ) ] = QLatin1String("uid");
|
|
}
|
|
|
|
return keys;
|
|
}
|
|
|
|
static QString makeFilter( const QString &query, const QString &attr, bool startsWith )
|
|
{
|
|
/* The reasoning behind this filter is:
|
|
* If it's a person, or a distlist, show it, even if it doesn't have an email address.
|
|
* If it's not a person, or a distlist, only show it if it has an email attribute.
|
|
* This allows both resource accounts with an email address which are not a person and
|
|
* person entries without an email address to show up, while still not showing things
|
|
* like structural entries in the ldap tree. */
|
|
QString result( QLatin1String("&(|(objectclass=person)(objectclass=groupofnames)(mail=*))(") );
|
|
if ( query.isEmpty() ) {
|
|
// Return a filter that matches everything
|
|
return result + QLatin1String("|(cn=*)(sn=*)") + QLatin1Char(')');
|
|
}
|
|
|
|
if ( attr == i18nc( "Search attribute: Name of contact", "Name" ) ) {
|
|
result += startsWith ? QLatin1String("|(cn=%1*)(sn=%2*)") : QLatin1String("|(cn=*%1*)(sn=*%2*)");
|
|
result = result.arg( query ).arg( query );
|
|
} else {
|
|
result += startsWith ? QLatin1String("%1=%2*") : QLatin1String("%1=*%2*");
|
|
if ( attr == i18nc( "Search attribute: Email of the contact", "Email" ) ) {
|
|
result = result.arg( QLatin1String("mail") ).arg( query );
|
|
} else if ( attr == i18n( "Home Number" ) ) {
|
|
result = result.arg( QLatin1String("homePhone") ).arg( query );
|
|
} else if ( attr == i18n( "Work Number" ) ) {
|
|
result = result.arg( QLatin1String("telephoneNumber") ).arg( query );
|
|
} else {
|
|
// Error?
|
|
result.clear();
|
|
return result;
|
|
}
|
|
}
|
|
result += QLatin1Char(')');
|
|
return result;
|
|
}
|
|
|
|
static KABC::Addressee convertLdapAttributesToAddressee( const KLDAP::LdapAttrMap &attrs )
|
|
{
|
|
KABC::Addressee addr;
|
|
|
|
// name
|
|
if ( !attrs.value( QLatin1String("cn") ).isEmpty() ) {
|
|
addr.setNameFromString( asUtf8( attrs[QLatin1String("cn")].first() ) );
|
|
}
|
|
|
|
// email
|
|
KLDAP::LdapAttrValue lst = attrs[QLatin1String("mail")];
|
|
KLDAP::LdapAttrValue::ConstIterator it = lst.constBegin();
|
|
bool pref = true;
|
|
while ( it != lst.constEnd() ) {
|
|
addr.insertEmail( asUtf8( *it ), pref );
|
|
pref = false;
|
|
++it;
|
|
}
|
|
|
|
if ( !attrs.value( QLatin1String("o") ).isEmpty() ) {
|
|
addr.setOrganization( asUtf8( attrs[ QLatin1String("o") ].first() ) );
|
|
}
|
|
if ( addr.organization().isEmpty() && !attrs.value( QLatin1String("Company") ).isEmpty() ) {
|
|
addr.setOrganization( asUtf8( attrs[ QLatin1String("Company") ].first() ) );
|
|
}
|
|
|
|
// Address
|
|
KABC::Address workAddr( KABC::Address::Work );
|
|
|
|
if ( !attrs.value( QLatin1String("department") ).isEmpty() ) {
|
|
addr.setDepartment( asUtf8( attrs[ QLatin1String("department") ].first() ) );
|
|
}
|
|
|
|
if ( !workAddr.isEmpty() ) {
|
|
addr.insertAddress( workAddr );
|
|
}
|
|
|
|
// phone
|
|
if ( !attrs.value( QLatin1String("homePhone") ).isEmpty() ) {
|
|
KABC::PhoneNumber homeNr = asUtf8( attrs[ QLatin1String("homePhone") ].first() );
|
|
homeNr.setType( KABC::PhoneNumber::Home );
|
|
addr.insertPhoneNumber( homeNr );
|
|
}
|
|
|
|
if ( !attrs.value( QLatin1String("telephoneNumber") ).isEmpty() ) {
|
|
KABC::PhoneNumber workNr = asUtf8( attrs[ QLatin1String("telephoneNumber") ].first() );
|
|
workNr.setType( KABC::PhoneNumber::Work );
|
|
addr.insertPhoneNumber( workNr );
|
|
}
|
|
|
|
if ( !attrs.value( QLatin1String("facsimileTelephoneNumber") ).isEmpty() ) {
|
|
KABC::PhoneNumber faxNr = asUtf8( attrs[ QLatin1String("facsimileTelephoneNumber") ].first() );
|
|
faxNr.setType( KABC::PhoneNumber::Fax );
|
|
addr.insertPhoneNumber( faxNr );
|
|
}
|
|
|
|
if ( !attrs.value( QLatin1String("mobile") ).isEmpty() ) {
|
|
KABC::PhoneNumber cellNr = asUtf8( attrs[ QLatin1String("mobile") ].first() );
|
|
cellNr.setType( KABC::PhoneNumber::Cell );
|
|
addr.insertPhoneNumber( cellNr );
|
|
}
|
|
|
|
if ( !attrs.value( QLatin1String("pager") ).isEmpty() ) {
|
|
KABC::PhoneNumber pagerNr = asUtf8( attrs[ QLatin1String("pager") ].first() );
|
|
pagerNr.setType( KABC::PhoneNumber::Pager );
|
|
addr.insertPhoneNumber( pagerNr );
|
|
}
|
|
|
|
return addr;
|
|
}
|
|
|
|
class ContactListModel : public QAbstractTableModel
|
|
{
|
|
public:
|
|
enum Role {
|
|
ServerRole = Qt::UserRole + 1
|
|
};
|
|
|
|
ContactListModel( QObject *parent )
|
|
: QAbstractTableModel( parent )
|
|
{
|
|
}
|
|
|
|
void addContact( const KLDAP::LdapAttrMap &contact, const QString &server )
|
|
{
|
|
mContactList.append( contact );
|
|
mServerList.append( server );
|
|
reset();
|
|
}
|
|
|
|
QPair<KLDAP::LdapAttrMap, QString> contact( const QModelIndex &index ) const
|
|
{
|
|
if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
|
|
return qMakePair( KLDAP::LdapAttrMap(), QString() );
|
|
}
|
|
|
|
return qMakePair( mContactList.at( index.row() ), mServerList.at( index.row() ) );
|
|
}
|
|
|
|
QString email( const QModelIndex &index ) const
|
|
{
|
|
if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
|
|
return QString();
|
|
}
|
|
|
|
return asUtf8( mContactList.at( index.row() ).value( QLatin1String("mail") ).first() ).trimmed();
|
|
}
|
|
|
|
QString fullName( const QModelIndex &index ) const
|
|
{
|
|
if ( !index.isValid() || index.row() < 0 || index.row() >= mContactList.count() ) {
|
|
return QString();
|
|
}
|
|
|
|
return asUtf8( mContactList.at( index.row() ).value( QLatin1String("cn") ).first() ).trimmed();
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
mContactList.clear();
|
|
mServerList.clear();
|
|
reset();
|
|
}
|
|
|
|
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const
|
|
{
|
|
if ( !parent.isValid() ) {
|
|
return mContactList.count();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const
|
|
{
|
|
if ( !parent.isValid() ) {
|
|
return 18;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
virtual QVariant headerData( int section, Qt::Orientation orientation,
|
|
int role = Qt::DisplayRole ) const
|
|
{
|
|
if ( orientation == Qt::Vertical || role != Qt::DisplayRole || section < 0 || section > 17 ) {
|
|
return QVariant();
|
|
}
|
|
|
|
switch ( section ) {
|
|
case 0:
|
|
return i18n( "Full Name" );
|
|
break;
|
|
case 1:
|
|
return i18nc( "@title:column Column containing email addresses", "Email" );
|
|
break;
|
|
case 2:
|
|
return i18n( "Home Number" );
|
|
break;
|
|
case 3:
|
|
return i18n( "Work Number" );
|
|
break;
|
|
case 4:
|
|
return i18n( "Mobile Number" );
|
|
break;
|
|
case 5:
|
|
return i18n( "Fax Number" );
|
|
break;
|
|
case 6:
|
|
return i18n( "Company" );
|
|
break;
|
|
case 7:
|
|
return i18n( "Organization" );
|
|
break;
|
|
case 8:
|
|
return i18n( "Street" );
|
|
break;
|
|
case 9:
|
|
return i18nc( "@title:column Column containing the residential state of the address",
|
|
"State" );
|
|
break;
|
|
case 10:
|
|
return i18n( "Country" );
|
|
break;
|
|
case 11:
|
|
return i18n( "Zip Code" );
|
|
break;
|
|
case 12:
|
|
return i18n( "Postal Address" );
|
|
break;
|
|
case 13:
|
|
return i18n( "City" );
|
|
break;
|
|
case 14:
|
|
return i18n( "Department" );
|
|
break;
|
|
case 15:
|
|
return i18n( "Description" );
|
|
break;
|
|
case 16:
|
|
return i18n( "User ID" );
|
|
break;
|
|
case 17:
|
|
return i18nc( "@title:column Column containing title of the person", "Title" );
|
|
break;
|
|
default:
|
|
return QVariant();
|
|
break;
|
|
};
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const
|
|
{
|
|
if ( !index.isValid() ) {
|
|
return QVariant();
|
|
}
|
|
|
|
if ( index.row() < 0 || index.row() >= mContactList.count() ||
|
|
index.column() < 0 || index.column() > 17 ) {
|
|
return QVariant();
|
|
}
|
|
|
|
if ( role == ServerRole ) {
|
|
return mServerList.at( index.row() );
|
|
}
|
|
|
|
if ( (role != Qt::DisplayRole) && (role != Qt::ToolTipRole) ) {
|
|
return QVariant();
|
|
}
|
|
|
|
const KLDAP::LdapAttrMap map = mContactList.at( index.row() );
|
|
|
|
switch ( index.column() ) {
|
|
case 0:
|
|
return join( map.value( QLatin1String("cn") ), QLatin1String(", ") );
|
|
break;
|
|
case 1:
|
|
return join( map.value( QLatin1String("mail") ), QLatin1String(", ") );
|
|
break;
|
|
case 2:
|
|
return join( map.value( QLatin1String("homePhone") ), QLatin1String(", ") );
|
|
break;
|
|
case 3:
|
|
return join( map.value( QLatin1String("telephoneNumber") ), QLatin1String(", ") );
|
|
break;
|
|
case 4:
|
|
return join( map.value( QLatin1String("mobile") ), QLatin1String(", ") );
|
|
break;
|
|
case 5:
|
|
return join( map.value( QLatin1String("facsimileTelephoneNumber") ), QLatin1String(", ") );
|
|
break;
|
|
case 6:
|
|
return join( map.value( QLatin1String("Company") ), QLatin1String(", ") );
|
|
break;
|
|
case 7:
|
|
return join( map.value( QLatin1String("o") ), QLatin1String(", " ));
|
|
break;
|
|
case 8:
|
|
return join( map.value( QLatin1String("street") ), QLatin1String(", ") );
|
|
break;
|
|
case 9:
|
|
return join( map.value( QLatin1String("st") ), QLatin1String(", " ));
|
|
break;
|
|
case 10:
|
|
return join( map.value( QLatin1String("co") ), QLatin1String(", ") );
|
|
break;
|
|
case 11:
|
|
return join( map.value( QLatin1String("postalCode") ), QLatin1String(", ") );
|
|
break;
|
|
case 12:
|
|
return join( map.value( QLatin1String("postalAddress") ), QLatin1String(", ") );
|
|
break;
|
|
case 13:
|
|
return join( map.value( QLatin1String("l") ), QLatin1String(", ") );
|
|
break;
|
|
case 14:
|
|
return join( map.value( QLatin1String("department") ),QLatin1String( ", " ));
|
|
break;
|
|
case 15:
|
|
return join( map.value( QLatin1String("description") ), QLatin1String(", ") );
|
|
break;
|
|
case 16:
|
|
return join( map.value( QLatin1String("uid") ), QLatin1String(", ") );
|
|
break;
|
|
case 17:
|
|
return join( map.value( QLatin1String("title") ), QLatin1String(", ") );
|
|
break;
|
|
default:
|
|
return QVariant();
|
|
break;
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
private:
|
|
QList<KLDAP::LdapAttrMap> mContactList;
|
|
QStringList mServerList;
|
|
};
|
|
|
|
class LdapSearchDialog::Private
|
|
{
|
|
public:
|
|
Private( LdapSearchDialog *qq )
|
|
: q( qq ),
|
|
mNumHosts( 0 ),
|
|
mIsConfigured( false ),
|
|
mModel( 0 )
|
|
{
|
|
}
|
|
|
|
QList< QPair<KLDAP::LdapAttrMap, QString> > selectedItems()
|
|
{
|
|
QList< QPair<KLDAP::LdapAttrMap, QString> > contacts;
|
|
|
|
const QModelIndexList selected = mResultView->selectionModel()->selectedRows();
|
|
for ( int i = 0; i < selected.count(); ++i ) {
|
|
contacts.append( mModel->contact( sortproxy->mapToSource(selected.at( i )) ) );
|
|
}
|
|
|
|
return contacts;
|
|
}
|
|
|
|
|
|
void saveSettings();
|
|
void restoreSettings();
|
|
void cancelQuery();
|
|
|
|
void slotAddResult( const KLDAP::LdapClient&, const KLDAP::LdapObject& );
|
|
void slotSetScope( bool );
|
|
void slotStartSearch();
|
|
void slotStopSearch();
|
|
void slotSearchDone();
|
|
void slotError( const QString& );
|
|
void slotSelectAll();
|
|
void slotUnselectAll();
|
|
void slotSelectionChanged();
|
|
|
|
LdapSearchDialog *q;
|
|
KGuiItem startSearchGuiItem;
|
|
KGuiItem stopSearchGuiItem;
|
|
int mNumHosts;
|
|
QList<KLDAP::LdapClient*> mLdapClientList;
|
|
bool mIsConfigured;
|
|
KABC::Addressee::List mSelectedContacts;
|
|
|
|
KComboBox *mFilterCombo;
|
|
KComboBox *mSearchType;
|
|
KLineEdit *mSearchEdit;
|
|
|
|
QCheckBox *mRecursiveCheckbox;
|
|
QTableView *mResultView;
|
|
KPushButton *mSearchButton;
|
|
ContactListModel *mModel;
|
|
KPIMUtils::ProgressIndicatorLabel *progressIndication;
|
|
QSortFilterProxyModel *sortproxy;
|
|
KLineEdit *searchLine;
|
|
};
|
|
|
|
LdapSearchDialog::LdapSearchDialog( QWidget *parent )
|
|
: KDialog( parent ), d( new Private( this ) )
|
|
{
|
|
setCaption( i18n( "Import Contacts from LDAP" ) );
|
|
setButtons( /*Help |*/ User1 | User2 | Cancel );
|
|
setDefaultButton( User1 );
|
|
setModal( false );
|
|
showButtonSeparator( true );
|
|
setButtonGuiItem( KDialog::Cancel, KStandardGuiItem::close() );
|
|
QFrame *page = new QFrame( this );
|
|
setMainWidget( page );
|
|
QVBoxLayout *topLayout = new QVBoxLayout( page );
|
|
topLayout->setSpacing( spacingHint() );
|
|
topLayout->setMargin( marginHint() );
|
|
|
|
QGroupBox *groupBox = new QGroupBox( i18n( "Search for Addresses in Directory" ),
|
|
page );
|
|
QGridLayout *boxLayout = new QGridLayout();
|
|
groupBox->setLayout( boxLayout );
|
|
boxLayout->setSpacing( spacingHint() );
|
|
boxLayout->setColumnStretch( 1, 1 );
|
|
|
|
QLabel *label = new QLabel( i18n( "Search for:" ), groupBox );
|
|
boxLayout->addWidget( label, 0, 0 );
|
|
|
|
d->mSearchEdit = new KLineEdit( groupBox );
|
|
d->mSearchEdit->setClearButtonShown(true);
|
|
boxLayout->addWidget( d->mSearchEdit, 0, 1 );
|
|
label->setBuddy( d->mSearchEdit );
|
|
|
|
label = new QLabel( i18nc( "In LDAP attribute", "in" ), groupBox );
|
|
boxLayout->addWidget( label, 0, 2 );
|
|
|
|
d->mFilterCombo = new KComboBox( groupBox );
|
|
d->mFilterCombo->addItem( i18nc( "@item:inlistbox Name of the contact", "Name" ) );
|
|
d->mFilterCombo->addItem( i18nc( "@item:inlistbox email address of the contact", "Email" ) );
|
|
d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Home Number" ) );
|
|
d->mFilterCombo->addItem( i18nc( "@item:inlistbox", "Work Number" ) );
|
|
boxLayout->addWidget( d->mFilterCombo, 0, 3 );
|
|
d->startSearchGuiItem = KGuiItem( i18nc( "@action:button Start searching", "&Search" ), QLatin1String("edit-find") );
|
|
d->stopSearchGuiItem = KStandardGuiItem::stop();
|
|
|
|
QSize buttonSize;
|
|
d->mSearchButton = new KPushButton( groupBox );
|
|
d->mSearchButton->setGuiItem(d->startSearchGuiItem);
|
|
|
|
buttonSize = d->mSearchButton->sizeHint();
|
|
if ( buttonSize.width() < d->mSearchButton->sizeHint().width() ) {
|
|
buttonSize = d->mSearchButton->sizeHint();
|
|
}
|
|
d->mSearchButton->setFixedWidth( buttonSize.width() );
|
|
|
|
d->mSearchButton->setDefault( true );
|
|
boxLayout->addWidget( d->mSearchButton, 0, 4 );
|
|
|
|
d->mRecursiveCheckbox = new QCheckBox( i18n( "Recursive search" ), groupBox );
|
|
d->mRecursiveCheckbox->setChecked( true );
|
|
boxLayout->addWidget( d->mRecursiveCheckbox, 1, 0, 1, 5 );
|
|
|
|
d->mSearchType = new KComboBox( groupBox );
|
|
d->mSearchType->addItem( i18n( "Contains" ) );
|
|
d->mSearchType->addItem( i18n( "Starts With" ) );
|
|
boxLayout->addWidget( d->mSearchType, 1, 3, 1, 2 );
|
|
|
|
topLayout->addWidget( groupBox );
|
|
|
|
|
|
QHBoxLayout *quickSearchLineLayout = new QHBoxLayout;
|
|
quickSearchLineLayout->addStretch();
|
|
d->searchLine = new KLineEdit;
|
|
d->searchLine->setClearButtonShown(true);
|
|
d->searchLine->setClickMessage(i18n("Search in result"));
|
|
quickSearchLineLayout->addWidget(d->searchLine);
|
|
topLayout->addLayout( quickSearchLineLayout );
|
|
|
|
|
|
d->mResultView = new QTableView( page );
|
|
d->mResultView->setSelectionMode( QTableView::MultiSelection );
|
|
d->mResultView->setSelectionBehavior( QTableView::SelectRows );
|
|
d->mModel = new ContactListModel( d->mResultView );
|
|
|
|
d->sortproxy = new QSortFilterProxyModel( this );
|
|
d->sortproxy->setFilterKeyColumn(-1); //Search in all column
|
|
d->sortproxy->setSourceModel( d->mModel );
|
|
d->sortproxy->setFilterCaseSensitivity(Qt::CaseInsensitive);
|
|
connect(d->searchLine, SIGNAL(textChanged(QString)), d->sortproxy, SLOT(setFilterFixedString(QString)));
|
|
|
|
|
|
d->mResultView->setModel( d->sortproxy );
|
|
d->mResultView->verticalHeader()->hide();
|
|
d->mResultView->setSortingEnabled(true);
|
|
d->mResultView->horizontalHeader()->setSortIndicatorShown(true);
|
|
connect( d->mResultView, SIGNAL(clicked(QModelIndex)),
|
|
SLOT(slotSelectionChanged()) );
|
|
topLayout->addWidget( d->mResultView );
|
|
|
|
d->mResultView->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(d->mResultView, SIGNAL(customContextMenuRequested(QPoint)),
|
|
this, SLOT(slotCustomContextMenuRequested(QPoint)));
|
|
|
|
|
|
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
|
buttonLayout->setMargin(0);
|
|
topLayout->addLayout(buttonLayout);
|
|
|
|
d->progressIndication = new KPIMUtils::ProgressIndicatorLabel(i18n("Searching..."));
|
|
buttonLayout->addWidget(d->progressIndication);
|
|
|
|
KDialogButtonBox *buttons = new KDialogButtonBox( page, Qt::Horizontal );
|
|
buttons->addButton( i18n( "Select All" ),
|
|
QDialogButtonBox::ActionRole, this, SLOT(slotSelectAll()) );
|
|
buttons->addButton( i18n( "Unselect All" ),
|
|
QDialogButtonBox::ActionRole, this, SLOT(slotUnselectAll()) );
|
|
|
|
buttonLayout->addWidget( buttons );
|
|
|
|
|
|
|
|
setButtonText( User1, i18n( "Add Selected" ) );
|
|
setButtonText( User2, i18n( "Configure LDAP Servers..." ) );
|
|
|
|
connect( d->mRecursiveCheckbox, SIGNAL(toggled(bool)),
|
|
this, SLOT(slotSetScope(bool)) );
|
|
connect( d->mSearchButton, SIGNAL(clicked()),
|
|
this, SLOT(slotStartSearch()) );
|
|
|
|
setTabOrder( d->mSearchEdit, d->mFilterCombo );
|
|
setTabOrder( d->mFilterCombo, d->mSearchButton );
|
|
d->mSearchEdit->setFocus();
|
|
|
|
connect( this, SIGNAL(user1Clicked()), this, SLOT(slotUser1()) );
|
|
connect( this, SIGNAL(user2Clicked()), this, SLOT(slotUser2()) );
|
|
connect( this, SIGNAL(cancelClicked()), this, SLOT(slotCancelClicked()));
|
|
d->slotSelectionChanged();
|
|
d->restoreSettings();
|
|
}
|
|
|
|
LdapSearchDialog::~LdapSearchDialog()
|
|
{
|
|
d->saveSettings();
|
|
delete d;
|
|
}
|
|
|
|
void LdapSearchDialog::setSearchText( const QString &text )
|
|
{
|
|
d->mSearchEdit->setText( text );
|
|
}
|
|
|
|
KABC::Addressee::List LdapSearchDialog::selectedContacts() const
|
|
{
|
|
return d->mSelectedContacts;
|
|
}
|
|
|
|
void LdapSearchDialog::slotCustomContextMenuRequested(const QPoint &pos)
|
|
{
|
|
const QModelIndex index = d->mResultView->indexAt(pos);
|
|
if (index.isValid()) {
|
|
QMenu menu;
|
|
QAction *act = menu.addAction(i18n("Copy"));
|
|
if (menu.exec(QCursor::pos()) == act) {
|
|
QClipboard *cb = QApplication::clipboard();
|
|
cb->setText(index.data().toString(), QClipboard::Clipboard);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void LdapSearchDialog::Private::slotSelectionChanged()
|
|
{
|
|
q->enableButton( KDialog::User1, mResultView->selectionModel()->hasSelection() );
|
|
}
|
|
|
|
void LdapSearchDialog::Private::restoreSettings()
|
|
{
|
|
// Create one KLDAP::LdapClient per selected server and configure it.
|
|
|
|
// First clean the list to make sure it is empty at
|
|
// the beginning of the process
|
|
qDeleteAll( mLdapClientList ) ;
|
|
mLdapClientList.clear();
|
|
|
|
KConfig *config = KLDAP::LdapClientSearchConfig::config();
|
|
|
|
KConfigGroup searchGroup( config, "LDAPSearch" );
|
|
mSearchType->setCurrentIndex( searchGroup.readEntry( "SearchType", 0 ) );
|
|
|
|
// then read the config file and register all selected
|
|
// server in the list
|
|
KConfigGroup group( config, "LDAP" );
|
|
mNumHosts = group.readEntry( "NumSelectedHosts", 0 );
|
|
if ( !mNumHosts ) {
|
|
mIsConfigured = false;
|
|
} else {
|
|
mIsConfigured = true;
|
|
KLDAP::LdapClientSearchConfig *clientSearchConfig = new KLDAP::LdapClientSearchConfig;
|
|
for ( int j = 0; j < mNumHosts; ++j ) {
|
|
KLDAP::LdapServer ldapServer;
|
|
KLDAP::LdapClient *ldapClient = new KLDAP::LdapClient( 0, q );
|
|
clientSearchConfig->readConfig( ldapServer, group, j, true );
|
|
ldapClient->setServer( ldapServer );
|
|
QStringList attrs;
|
|
|
|
QMap<QString, QString>::ConstIterator end(adrbookattr2ldap().constEnd());
|
|
for ( QMap<QString, QString>::ConstIterator it = adrbookattr2ldap().constBegin();
|
|
it != end; ++it ) {
|
|
attrs << *it;
|
|
}
|
|
|
|
ldapClient->setAttributes( attrs );
|
|
|
|
q->connect( ldapClient, SIGNAL(result(KLDAP::LdapClient,KLDAP::LdapObject)),
|
|
q, SLOT(slotAddResult(KLDAP::LdapClient,KLDAP::LdapObject)) );
|
|
q->connect( ldapClient, SIGNAL(done()),
|
|
q, SLOT(slotSearchDone()) );
|
|
q->connect( ldapClient, SIGNAL(error(QString)),
|
|
q, SLOT(slotError(QString)) );
|
|
|
|
mLdapClientList.append( ldapClient );
|
|
}
|
|
delete clientSearchConfig;
|
|
|
|
mModel->clear();
|
|
}
|
|
KConfigGroup groupHeader( config, "Headers" );
|
|
mResultView->horizontalHeader()->restoreState(groupHeader.readEntry("HeaderState",QByteArray()));
|
|
|
|
KConfigGroup groupSize( config, "Size" );
|
|
const QSize dialogSize = groupSize.readEntry( "Size", QSize() );
|
|
if ( dialogSize.isValid() ) {
|
|
q->resize( dialogSize );
|
|
} else {
|
|
q->resize( QSize( 600, 400 ).expandedTo( q->minimumSizeHint() ) );
|
|
}
|
|
}
|
|
|
|
void LdapSearchDialog::Private::saveSettings()
|
|
{
|
|
KConfig *config = KLDAP::LdapClientSearchConfig::config();
|
|
KConfigGroup group( config, "LDAPSearch" );
|
|
group.writeEntry( "SearchType", mSearchType->currentIndex() );
|
|
|
|
KConfigGroup groupHeader( config, "Headers" );
|
|
groupHeader.writeEntry( "HeaderState", mResultView->horizontalHeader()->saveState());
|
|
groupHeader.sync();
|
|
|
|
KConfigGroup size( config, "Size" );
|
|
size.writeEntry( "Size", q->size());
|
|
size.sync();
|
|
|
|
group.sync();
|
|
}
|
|
|
|
void LdapSearchDialog::Private::cancelQuery()
|
|
{
|
|
Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
|
|
client->cancelQuery();
|
|
}
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotAddResult( const KLDAP::LdapClient &client,
|
|
const KLDAP::LdapObject &obj )
|
|
{
|
|
mModel->addContact( obj.attributes(), client.server().host() );
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotSetScope( bool rec )
|
|
{
|
|
Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
|
|
if ( rec ) {
|
|
client->setScope( QLatin1String("sub") );
|
|
} else {
|
|
client->setScope( QLatin1String("one") );
|
|
}
|
|
}
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotStartSearch()
|
|
{
|
|
cancelQuery();
|
|
|
|
if ( !mIsConfigured ) {
|
|
KMessageBox::error( q, i18n( "You must select an LDAP server before searching." ) );
|
|
q->slotUser2();
|
|
return;
|
|
}
|
|
|
|
#ifndef QT_NO_CURSOR
|
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
|
#endif
|
|
mSearchButton->setGuiItem(stopSearchGuiItem);
|
|
progressIndication->start();
|
|
|
|
q->disconnect( mSearchButton, SIGNAL(clicked()),
|
|
q, SLOT(slotStartSearch()) );
|
|
q->connect( mSearchButton, SIGNAL(clicked()),
|
|
q, SLOT(slotStopSearch()) );
|
|
|
|
const bool startsWith = (mSearchType->currentIndex() == 1);
|
|
|
|
const QString filter = makeFilter( mSearchEdit->text().trimmed(),
|
|
mFilterCombo->currentText(), startsWith );
|
|
|
|
// loop in the list and run the KLDAP::LdapClients
|
|
mModel->clear();
|
|
Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
|
|
client->startQuery( filter );
|
|
}
|
|
|
|
saveSettings();
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotStopSearch()
|
|
{
|
|
cancelQuery();
|
|
slotSearchDone();
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotSearchDone()
|
|
{
|
|
// If there are no more active clients, we are done.
|
|
Q_FOREACH( KLDAP::LdapClient *client, mLdapClientList ) {
|
|
if ( client->isActive() ) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
q->disconnect( mSearchButton, SIGNAL(clicked()),
|
|
q, SLOT(slotStopSearch()) );
|
|
q->connect( mSearchButton, SIGNAL(clicked()),
|
|
q, SLOT(slotStartSearch()) );
|
|
|
|
mSearchButton->setGuiItem(startSearchGuiItem);
|
|
progressIndication->stop();
|
|
#ifndef QT_NO_CURSOR
|
|
QApplication::restoreOverrideCursor();
|
|
#endif
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotError( const QString &error )
|
|
{
|
|
#ifndef QT_NO_CURSOR
|
|
QApplication::restoreOverrideCursor();
|
|
#endif
|
|
KMessageBox::error( q, error );
|
|
}
|
|
|
|
void LdapSearchDialog::closeEvent( QCloseEvent *e )
|
|
{
|
|
d->slotStopSearch();
|
|
e->accept();
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotUnselectAll()
|
|
{
|
|
mResultView->clearSelection();
|
|
slotSelectionChanged();
|
|
}
|
|
|
|
void LdapSearchDialog::Private::slotSelectAll()
|
|
{
|
|
mResultView->selectAll();
|
|
slotSelectionChanged();
|
|
}
|
|
|
|
void LdapSearchDialog::slotUser1()
|
|
{
|
|
// Import selected items
|
|
|
|
d->mSelectedContacts.clear();
|
|
|
|
const QList< QPair<KLDAP::LdapAttrMap, QString> >& items = d->selectedItems();
|
|
|
|
if ( !items.isEmpty() ) {
|
|
const QDateTime now = QDateTime::currentDateTime();
|
|
|
|
for ( int i = 0; i < items.count(); ++i ) {
|
|
KABC::Addressee contact = convertLdapAttributesToAddressee( items.at( i ).first );
|
|
|
|
// set a comment where the contact came from
|
|
contact.setNote( i18nc( "arguments are host name, datetime",
|
|
"Imported from LDAP directory %1 on %2",
|
|
items.at( i ).second, KGlobal::locale()->formatDateTime( now ) ) );
|
|
|
|
d->mSelectedContacts.append( contact );
|
|
}
|
|
}
|
|
|
|
d->slotStopSearch();
|
|
emit contactsAdded();
|
|
|
|
accept();
|
|
}
|
|
|
|
void LdapSearchDialog::slotUser2()
|
|
{
|
|
// Configure LDAP servers
|
|
|
|
KCMultiDialog dialog( this );
|
|
dialog.setCaption( i18n( "Configure the Address Book LDAP Settings" ) );
|
|
dialog.addModule( QLatin1String("kcmldap.desktop") );
|
|
|
|
if ( dialog.exec() ) { //krazy:exclude=crashy
|
|
d->restoreSettings();
|
|
}
|
|
}
|
|
|
|
void LdapSearchDialog::slotCancelClicked()
|
|
{
|
|
d->slotStopSearch();
|
|
reject();
|
|
}
|
|
|
|
#include "moc_ldapsearchdialog.cpp"
|