You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdepim/libkdepim/addresseeselector.cpp

582 lines
16 KiB

/*
This file is part of libkdepim.
Copyright (c) 2004 Tobias Koenig <tokoe@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 <qheader.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qsignalmapper.h>
#include <qtoolbutton.h>
#include <kabc/stdaddressbook.h>
#include <kcombobox.h>
#include <kdialog.h>
#include <kglobal.h>
#include <kiconloader.h>
#include <klineedit.h>
#include <klistview.h>
#include <klocale.h>
#include "addresseeselector.h"
using namespace KPIM;
class AddresseeSelector::AddressBookManager
{
public:
QStringList titles() const;
void addResource( KABC::Resource* );
void addAddressBook( const QString &title, SelectionItem::List &list );
void clear();
bool contains( uint index, const SelectionItem& );
private:
struct AddressBookEntry {
QString title;
SelectionItem::List list;
};
QValueList<KABC::Resource*> mResources;
QValueList<AddressBookEntry> mAddressBooks;
};
QStringList AddresseeSelector::AddressBookManager::titles() const
{
QStringList titles;
// we've always an 'all' entry
titles.append( i18n( "All" ) );
QValueList<KABC::Resource*>::ConstIterator resIt;
for ( resIt = mResources.begin(); resIt != mResources.end(); ++resIt )
titles.append( (*resIt)->resourceName() );
QValueList<AddressBookEntry>::ConstIterator abIt;
for ( abIt = mAddressBooks.begin(); abIt != mAddressBooks.end(); ++abIt )
titles.append( (*abIt).title );
return titles;
}
void AddresseeSelector::AddressBookManager::addResource( KABC::Resource *resource )
{
if ( mResources.find( resource ) == mResources.end() )
mResources.append( resource );
}
void AddresseeSelector::AddressBookManager::addAddressBook( const QString &title,
SelectionItem::List &list )
{
AddressBookEntry entry;
entry.title = title;
entry.list = list;
// TODO: check for duplicates
mAddressBooks.append( entry );
}
void AddresseeSelector::AddressBookManager::clear()
{
mResources.clear();
mAddressBooks.clear();
}
bool AddresseeSelector::AddressBookManager::contains( uint index, const SelectionItem &item )
{
if ( index == 0 ) // the 'all' entry
return true;
if ( mResources.count() > 0 ) {
if ( index <= mResources.count() ) {
index--;
if ( item.addressee().resource() == mResources[ index ] )
return true;
else
return false;
}
}
index = index - mResources.count();
if ( mAddressBooks.count() > 0 ) {
if ( index <= mAddressBooks.count() ) {
index--;
AddressBookEntry entry = mAddressBooks[ index ];
SelectionItem::List::ConstIterator it;
for ( it = entry.list.begin(); it != entry.list.end(); ++it )
if ( (*it).addressee() == item.addressee() )
return true;
return false;
}
}
return false;
}
SelectionItem::SelectionItem( const KABC::Addressee &addressee, uint index )
: mAddressee( addressee ), mDistributionList( 0 ), mIndex( index )
{
mField.fill( false, 10 );
}
SelectionItem::SelectionItem( KABC::DistributionList *list, uint index )
: mDistributionList( list ), mIndex( index )
{
mField.fill( false, 10 );
}
SelectionItem::SelectionItem()
: mDistributionList( 0 ), mIndex( 0 )
{
mField.fill( false, 10 );
}
void SelectionItem::addToField( int index )
{
mField.setBit( index );
}
void SelectionItem::removeFromField( int index )
{
mField.clearBit( index );
}
bool SelectionItem::isInField( int index )
{
return mField.testBit( index );
}
KABC::Addressee SelectionItem::addressee() const
{
return mAddressee;
}
KABC::DistributionList* SelectionItem::distributionList() const
{
return mDistributionList;
}
uint SelectionItem::index() const
{
return mIndex;
}
class SelectionViewItem : public QListViewItem
{
public:
SelectionViewItem( QListView *parent, Selection *selection,
SelectionItem *item )
: QListViewItem( parent, "" ), mSelection( selection ), mItem( item )
{
if ( mItem->distributionList() == 0 )
mIcon = mSelection->itemIcon( mItem->addressee(), mItem->index() );
else
mIcon = mSelection->distributionListIcon( mItem->distributionList() );
}
QString text( int column ) const
{
if ( column == 0 ) {
if ( mItem->distributionList() == 0 )
return mSelection->itemText( mItem->addressee(), mItem->index() );
else
return mSelection->distributionListText( mItem->distributionList() );
} else
return QString::null;
}
const QPixmap* pixmap( int column ) const
{
if ( column == 0 ) {
return &mIcon;
} else
return 0;
}
SelectionItem* item() const { return mItem; }
private:
Selection *mSelection;
SelectionItem *mItem;
QPixmap mIcon;
};
AddresseeSelector::AddresseeSelector( Selection *selection, QWidget *parent, const char *name )
: QWidget( parent, name ), mSelection( selection ), mManager( 0 )
{
mMoveMapper = new QSignalMapper( this );
mRemoveMapper = new QSignalMapper( this );
mAddressBookManager = new AddressBookManager();
initGUI();
init();
mSelection->setSelector( this );
}
AddresseeSelector::~AddresseeSelector()
{
delete mManager;
mManager = 0;
delete mAddressBookManager;
mAddressBookManager = 0;
}
void AddresseeSelector::init()
{
connect( KABC::StdAddressBook::self( true ), SIGNAL( addressBookChanged( AddressBook* ) ),
this, SLOT( reloadAddressBook() ) );
connect( mAddresseeFilter, SIGNAL( textChanged( const QString& ) ),
this, SLOT( updateAddresseeView() ) );
connect( mAddressBookCombo, SIGNAL( activated( int ) ),
this, SLOT( updateAddresseeView() ) );
connect( mMoveMapper, SIGNAL( mapped( int ) ),
this, SLOT( move( int ) ) );
connect( mRemoveMapper, SIGNAL( mapped( int ) ),
this, SLOT( remove( int ) ) );
reloadAddressBook();
}
void AddresseeSelector::initGUI()
{
QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), KDialog::spacingHint() );
QGridLayout *topLayout = new QGridLayout( this, 2, 2, KDialog::marginHint() );
QLabel *label = new QLabel( i18n( "Address book:" ), this );
mAddressBookCombo = new KComboBox( false, this );
topLayout->addWidget( label, 0, 0 );
topLayout->addWidget( mAddressBookCombo, 0, 1 );
label = new QLabel( i18n( "Search:" ), this );
mAddresseeFilter = new KLineEdit( this );
topLayout->addWidget( label, 1, 0 );
topLayout->addWidget( mAddresseeFilter, 1, 1 );
topLayout->setColStretch( 1, 1 );
layout->addMultiCellLayout( topLayout, 0, 0, 0, 2 );
int row = 1;
QIconSet moveSet = KGlobal::iconLoader()->loadIconSet( "next", KIcon::Small );
QIconSet removeSet = KGlobal::iconLoader()->loadIconSet( "previous", KIcon::Small );
uint count = mSelection->fieldCount();
for ( uint i = 0; i < count; ++i, ++row ) {
KListView *listView = new KListView( this );
listView->addColumn( mSelection->fieldTitle( i ) );
listView->setFullWidth( true );
mSelectionViews.append( listView );
connect( listView, SIGNAL( doubleClicked( QListViewItem*, const QPoint&, int ) ),
mRemoveMapper, SLOT( map() ) );
mRemoveMapper->setMapping( listView, i );
QVBoxLayout *buttonLayout = new QVBoxLayout( this );
buttonLayout->setAlignment( Qt::AlignBottom );
layout->addLayout( buttonLayout, row, 1 );
// move button
QToolButton *moveButton = new QToolButton( this );
moveButton->setIconSet( moveSet );
moveButton->setFixedSize( 30, 30 );
connect( moveButton, SIGNAL( clicked() ),
mMoveMapper, SLOT( map() ) );
mMoveMapper->setMapping( moveButton, i );
// remove button
QToolButton *removeButton = new QToolButton( this );
removeButton->setIconSet( removeSet );
removeButton->setFixedSize( 30, 30 );
connect( removeButton, SIGNAL( clicked() ),
mRemoveMapper, SLOT( map() ) );
mRemoveMapper->setMapping( removeButton, i );
buttonLayout->addWidget( moveButton );
buttonLayout->addWidget( removeButton );
layout->addWidget( listView, row, 2 );
}
mAddresseeView = new KListView( this );
mAddresseeView->addColumn( "" );
mAddresseeView->header()->hide();
mAddresseeView->setFullWidth( true );
layout->addMultiCellWidget( mAddresseeView, 1, row, 0, 0 );
}
void AddresseeSelector::finish()
{
SelectionItem::List::Iterator it;
for ( uint field = 0; field < mSelection->fieldCount(); ++field ) {
for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) {
if ( (*it).isInField( field ) ) {
if ( (*it).distributionList() == 0 )
mSelection->addSelectedAddressees( field, (*it).addressee(), (*it).index() );
else
mSelection->addSelectedDistributionList( field, (*it).distributionList() );
}
}
}
}
void AddresseeSelector::updateAddresseeView()
{
mAddresseeView->clear();
int addressBookIndex = mAddressBookCombo->currentItem();
SelectionItem::List::Iterator it;
for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) {
if ( mAddressBookManager->contains( addressBookIndex, *it ) ) {
if ( (*it).distributionList() == 0 ) {
if ( mAddresseeFilter->text().isEmpty() ||
mSelection->itemMatches( (*it).addressee(), (*it).index(),
mAddresseeFilter->text() ) )
new SelectionViewItem( mAddresseeView, mSelection, &(*it) );
} else {
if ( mAddresseeFilter->text().isEmpty() ||
mSelection->distributionListMatches( (*it).distributionList(),
mAddresseeFilter->text() ) )
new SelectionViewItem( mAddresseeView, mSelection, &(*it) );
}
}
}
updateSelectionViews();
}
void AddresseeSelector::move( int index )
{
SelectionViewItem *item = dynamic_cast<SelectionViewItem*>( mAddresseeView->selectedItem() );
if ( item ) {
item->item()->addToField( index );
updateSelectionView( index );
}
}
void AddresseeSelector::remove( int index )
{
KListView *view = mSelectionViews[ index ];
SelectionViewItem *item = dynamic_cast<SelectionViewItem*>( view->selectedItem() );
if ( item ) {
item->item()->removeFromField( index );
updateSelectionView( index );
}
}
void AddresseeSelector::setItemSelected( uint fieldIndex, const KABC::Addressee &addr, uint itemIndex )
{
bool found = false;
SelectionItem::List::Iterator it;
for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) {
if ( (*it).addressee() == addr && (*it).index() == itemIndex ) {
(*it).addToField( fieldIndex );
found = true;
}
}
if ( !found ) {
SelectionItem item( addr, itemIndex );
item.addToField( fieldIndex );
mSelectionItems.append( item );
}
updateSelectionView( fieldIndex );
}
void AddresseeSelector::setItemSelected( uint fieldIndex, const KABC::Addressee &addr,
uint itemIndex, const QString &text )
{
bool found = false;
SelectionItem::List::Iterator it;
for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) {
if ( mSelection->itemEquals( (*it).addressee(), (*it).index(), text ) ) {
(*it).addToField( fieldIndex );
found = true;
}
}
if ( !found ) {
SelectionItem item( addr, itemIndex );
item.addToField( fieldIndex );
mSelectionItems.append( item );
}
updateSelectionView( fieldIndex );
}
void AddresseeSelector::updateSelectionView( int index )
{
KListView *view = mSelectionViews[ index ];
view->clear();
SelectionItem::List::Iterator it;
for ( it = mSelectionItems.begin(); it != mSelectionItems.end(); ++it ) {
if ( (*it).isInField( index ) )
new SelectionViewItem( view, mSelection, &(*it) );
}
}
void AddresseeSelector::updateSelectionViews()
{
for ( uint i = 0; i < mSelection->fieldCount(); ++i )
updateSelectionView( i );
}
void AddresseeSelector::reloadAddressBook()
{
// load contacts
KABC::Addressee::List list = KABC::StdAddressBook::self( true )->allAddressees();
KABC::Addressee::List::Iterator it;
SelectionItem::List selectedItems;
SelectionItem::List::Iterator itemIt;
for ( itemIt = mSelectionItems.begin(); itemIt != mSelectionItems.end(); ++itemIt ) {
bool isSelected = false;
for ( uint i = 0; i < mSelection->fieldCount(); ++i ) {
if ( (*itemIt).isInField( i ) ) {
isSelected = true;
break;
}
}
// we don't save distribution lists, since this leads to crashes
if ( isSelected && (*itemIt).distributionList() == 0 ) {
selectedItems.append( *itemIt );
}
}
mSelectionItems.clear();
mSelectionItems = selectedItems;
for ( it = list.begin(); it != list.end(); ++it ) {
uint itemCount = mSelection->itemCount( *it );
for ( uint index = 0; index < itemCount; ++index ) {
bool available = false;
for ( itemIt = mSelectionItems.begin(); itemIt != mSelectionItems.end(); ++itemIt ) {
if ( (*itemIt).addressee() == (*it) && (*itemIt).index() == index ) {
available = true;
break;
}
}
if ( !available ) {
SelectionItem item( *it, index );
mSelectionItems.append( item );
}
}
}
// load distribution lists
delete mManager;
mManager = new KABC::DistributionListManager( KABC::StdAddressBook::self( true ) );
mManager->load();
QStringList lists = mManager->listNames();
QStringList::Iterator listIt;
for ( listIt = lists.begin(); listIt != lists.end(); ++listIt ) {
KABC::DistributionList *list = mManager->list( *listIt );
SelectionItem item( list, 0 );
mSelectionItems.append( item );
}
mAddressBookManager->clear();
// update address book combo
mAddressBookCombo->clear();
QPtrList<KABC::Resource> resources = KABC::StdAddressBook::self( true )->resources();
QPtrListIterator<KABC::Resource> resIt( resources );
while ( resIt.current() ) {
if ( resIt.current()->isActive() )
mAddressBookManager->addResource( resIt );
++resIt;
}
for ( uint i = 0; i < mSelection->addressBookCount(); ++i ) {
SelectionItem::List itemList;
KABC::Addressee::List addrList = mSelection->addressBookContent( i );
for ( it = addrList.begin(); it != addrList.end(); ++it ) {
uint itemCount = mSelection->itemCount( *it );
for ( uint index = 0; index < itemCount; ++index ) {
SelectionItem item( *it, index );
mSelectionItems.append( item );
itemList.append( item );
}
}
mAddressBookManager->addAddressBook( mSelection->addressBookTitle( i ),
itemList );
}
mAddressBookCombo->insertStringList( mAddressBookManager->titles() );
updateAddresseeView();
}
AddresseeSelectorDialog::AddresseeSelectorDialog( Selection *selection,
QWidget *parent, const char *name )
: KDialogBase( Plain, "", Ok | Cancel, Ok, parent, name, true )
{
QFrame *frame = plainPage();
QVBoxLayout *layout = new QVBoxLayout( frame );
mSelector = new KPIM::AddresseeSelector( selection, frame );
layout->addWidget( mSelector );
resize( 500, 490 );
}
void AddresseeSelectorDialog::accept()
{
mSelector->finish();
QDialog::accept();
}
#include "addresseeselector.moc"