00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "recipientspicker.h"
00023
00024 #include "globalsettings.h"
00025
00026 #include <libkdepim/recentaddresses.h>
00027
00028 #include <klistview.h>
00029 #include <klocale.h>
00030 #include <kabc/resource.h>
00031 #include <kiconloader.h>
00032 #include <kdialog.h>
00033 #include <kwin.h>
00034 #include <kabc/distributionlist.h>
00035 #include <kmessagebox.h>
00036
00037 #include <qlayout.h>
00038 #include <qcombobox.h>
00039 #include <qpushbutton.h>
00040 #include <qtoolbutton.h>
00041 #include <qlabel.h>
00042
00043 RecipientItem::RecipientItem()
00044 : mDistributionList( 0 )
00045 {
00046 }
00047
00048 void RecipientItem::setDistributionList( KABC::DistributionList *list )
00049 {
00050 mDistributionList = list;
00051
00052 mIcon = KGlobal::iconLoader()->loadIcon( "kdmconfig", KIcon::Small );
00053
00054 mKey = "D" + list->name();
00055 }
00056
00057 void RecipientItem::setAddressee( const KABC::Addressee &a,
00058 const QString &email )
00059 {
00060 mAddressee = a;
00061 mEmail = email;
00062
00063 QImage img = a.photo().data();
00064 if ( !img.isNull() )
00065 mIcon = img.smoothScale( 20, 20, QImage::ScaleMin );
00066 else
00067 mIcon = KGlobal::iconLoader()->loadIcon( "personal", KIcon::Small );
00068
00069 mKey = "A" + a.preferredEmail();
00070 }
00071
00072 QPixmap RecipientItem::icon() const
00073 {
00074 return mIcon;
00075 }
00076
00077 QString RecipientItem::name() const
00078 {
00079 if ( !mAddressee.isEmpty() ) return mAddressee.realName();
00080 else if ( mDistributionList ) return mDistributionList->name();
00081 else return QString::null;
00082 }
00083
00084 QString RecipientItem::email() const
00085 {
00086 if ( mAddressee.isEmpty() && mDistributionList ) {
00087 int count = mDistributionList->entries().count();
00088 return i18n( "1 email address", "%n email addresses", count );
00089 } else {
00090 return mEmail;
00091 }
00092 return QString::null;
00093 }
00094
00095 QString RecipientItem::recipient() const
00096 {
00097 QString r;
00098 if ( !mAddressee.isEmpty() ) r = mAddressee.fullEmail( mEmail );
00099 else if ( mDistributionList ) r = mDistributionList->name();
00100 return r;
00101 }
00102
00103 QString RecipientItem::toolTip() const
00104 {
00105 QString txt = "<qt>";
00106
00107 if ( !mAddressee.isEmpty() ) {
00108 if ( !mAddressee.realName().isEmpty() ) {
00109 txt += mAddressee.realName() + "<br/>";
00110 }
00111 txt += "<b>" + mEmail + "</b>";
00112 } else if ( mDistributionList ) {
00113 txt += "<b>" + i18n("Distribution List %1")
00114 .arg( mDistributionList->name() ) + "</b>";
00115 txt += "<ul>";
00116 KABC::DistributionList::Entry::List entries = mDistributionList->entries();
00117 KABC::DistributionList::Entry::List::ConstIterator it;
00118 for( it = entries.begin(); it != entries.end(); ++it ) {
00119 txt += "<li>";
00120 txt += (*it).addressee.realName() + " ";
00121 txt += "<em>";
00122 if ( (*it).email.isEmpty() ) txt += (*it).addressee.preferredEmail();
00123 else txt += (*it).email;
00124 txt += "</em>";
00125 txt += "<li/>";
00126 }
00127 txt += "</ul>";
00128 }
00129
00130 return txt;
00131 }
00132
00133 void RecipientItem::setRecipientType( const QString &type )
00134 {
00135 mType = type;
00136 }
00137
00138 QString RecipientItem::recipientType() const
00139 {
00140 return mType;
00141 }
00142
00143
00144 RecipientViewItem::RecipientViewItem( RecipientItem *item, KListView *listView )
00145 : KListViewItem( listView ), mRecipientItem( item )
00146 {
00147 setText( 0, item->recipientType() );
00148 setText( 1, item->name() );
00149 setText( 2, item->email() );
00150
00151 setPixmap( 1, item->icon() );
00152 }
00153
00154 RecipientItem *RecipientViewItem::recipientItem() const
00155 {
00156 return mRecipientItem;
00157 }
00158
00159
00160 RecipientsListToolTip::RecipientsListToolTip( QWidget *parent,
00161 KListView *listView )
00162 : QToolTip( parent )
00163 {
00164 mListView = listView;
00165 }
00166
00167 void RecipientsListToolTip::maybeTip( const QPoint & pos )
00168 {
00169 QRect r;
00170 QListViewItem *item = mListView->itemAt( pos );
00171 RecipientViewItem *i = static_cast<RecipientViewItem *>( item );
00172
00173 if( item ) {
00174 r = mListView->itemRect( item );
00175 QString tipText( i->recipientItem()->toolTip() );
00176 if ( !tipText.isEmpty() ) {
00177 tip( r, tipText );
00178 }
00179 }
00180 }
00181
00182
00183 RecipientsCollection::RecipientsCollection()
00184 {
00185 }
00186
00187 RecipientsCollection::~RecipientsCollection()
00188 {
00189 clear();
00190 }
00191
00192 void RecipientsCollection::setTitle( const QString &title )
00193 {
00194 mTitle = title;
00195 }
00196
00197 QString RecipientsCollection::title() const
00198 {
00199 return mTitle;
00200 }
00201
00202 void RecipientsCollection::addItem( RecipientItem *item )
00203 {
00204 mItems.append( item );
00205
00206 mKeyMap.insert( item->key(), item );
00207 }
00208
00209 RecipientItem::List RecipientsCollection::items() const
00210 {
00211 return mItems;
00212 }
00213
00214 bool RecipientsCollection::hasEquivalentItem( RecipientItem *item ) const
00215 {
00216 return mKeyMap.find( item->key() ) != mKeyMap.end();
00217 }
00218
00219 void RecipientsCollection::clear()
00220 {
00221 mKeyMap.clear();
00222 }
00223
00224 void RecipientsCollection::deleteAll()
00225 {
00226 QMap<QString, RecipientItem *>::ConstIterator it;
00227 for( it = mKeyMap.begin(); it != mKeyMap.end(); ++it ) {
00228 delete *it;
00229 }
00230 clear();
00231 }
00232
00233
00234 SearchLine::SearchLine( QWidget *parent, KListView *listView )
00235 : KListViewSearchLine( parent, listView )
00236 {
00237 }
00238
00239 void SearchLine::keyPressEvent( QKeyEvent *ev )
00240 {
00241 if ( ev->key() == Key_Down ) emit downPressed();
00242
00243 KListViewSearchLine::keyPressEvent( ev );
00244 }
00245
00246
00247 RecipientsPicker::RecipientsPicker( QWidget *parent )
00248 : QDialog( parent, "RecipientsPicker" ),
00249 mDistributionListManager( 0 )
00250 {
00251
00252
00253 setCaption( i18n("Select Recipient") );
00254
00255 QBoxLayout *topLayout = new QVBoxLayout( this );
00256 topLayout->setSpacing( KDialog::spacingHint() );
00257 topLayout->setMargin( KDialog::marginHint() );
00258
00259 QBoxLayout *resLayout = new QHBoxLayout( topLayout );
00260
00261 QLabel *label = new QLabel( i18n("Address book:"), this );
00262 resLayout->addWidget( label );
00263
00264 mCollectionCombo = new QComboBox( this );
00265 resLayout->addWidget( mCollectionCombo );
00266 resLayout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding));
00267
00268 connect( mCollectionCombo, SIGNAL( highlighted( int ) ),
00269 SLOT( updateList() ) );
00270 connect( mCollectionCombo, SIGNAL( activated( int ) ),
00271 SLOT( updateList() ) );
00272
00273 QBoxLayout *searchLayout = new QHBoxLayout( topLayout );
00274
00275 QToolButton *button = new QToolButton( this );
00276 button->setIconSet( KGlobal::iconLoader()->loadIconSet(
00277 KApplication::reverseLayout() ? "clear_left":"locationbar_erase", KIcon::Small, 0 ) );
00278 searchLayout->addWidget( button );
00279 connect( button, SIGNAL( clicked() ), SLOT( resetSearch() ) );
00280
00281 label = new QLabel( i18n("&Search:"), this );
00282 searchLayout->addWidget( label );
00283
00284 mRecipientList = new KListView( this );
00285 mRecipientList->setSelectionMode( QListView::Extended );
00286 mRecipientList->setAllColumnsShowFocus( true );
00287 mRecipientList->setFullWidth( true );
00288 topLayout->addWidget( mRecipientList );
00289 mRecipientList->addColumn( i18n("->") );
00290 mRecipientList->addColumn( i18n("Name") );
00291 mRecipientList->addColumn( i18n("Email") );
00292 connect( mRecipientList, SIGNAL( doubleClicked( QListViewItem *,
00293 const QPoint &, int ) ), SLOT( slotPicked() ) );
00294 connect( mRecipientList, SIGNAL( returnPressed( QListViewItem * ) ),
00295 SLOT( slotPicked() ) );
00296
00297 new RecipientsListToolTip( mRecipientList->viewport(), mRecipientList );
00298
00299 mSearchLine = new SearchLine( this, mRecipientList );
00300 searchLayout->addWidget( mSearchLine );
00301 label->setBuddy( label );
00302 connect( mSearchLine, SIGNAL( downPressed() ), SLOT( setFocusList() ) );
00303
00304 QBoxLayout *buttonLayout = new QHBoxLayout( topLayout );
00305
00306 buttonLayout->addStretch( 1 );
00307
00308 mToButton = new QPushButton( i18n("Add as To"), this );
00309 buttonLayout->addWidget( mToButton );
00310 connect( mToButton, SIGNAL( clicked() ), SLOT( slotToClicked() ) );
00311
00312 mCcButton = new QPushButton( i18n("Add as CC"), this );
00313 buttonLayout->addWidget( mCcButton );
00314 connect( mCcButton, SIGNAL( clicked() ), SLOT( slotCcClicked() ) );
00315
00316 mBccButton = new QPushButton( i18n("Add as BCC"), this );
00317 buttonLayout->addWidget( mBccButton );
00318 connect( mBccButton, SIGNAL( clicked() ), SLOT( slotBccClicked() ) );
00319
00320
00321
00322 QPushButton *closeButton = new QPushButton( i18n("&Cancel"), this );
00323 buttonLayout->addWidget( closeButton );
00324 connect( closeButton, SIGNAL( clicked() ), SLOT( close() ) );
00325
00326 {
00327 using namespace KABC;
00328 mAddressBook = KABC::StdAddressBook::self( true );
00329 connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook * ) ),
00330 this, SLOT( insertAddressBook( AddressBook * ) ) );
00331 }
00332
00333 initCollections();
00334
00335 mCollectionCombo->setCurrentItem( 0 );
00336
00337 updateList();
00338
00339 mSearchLine->setFocus();
00340
00341 readConfig();
00342
00343 setTabOrder( mCollectionCombo, mSearchLine );
00344 setTabOrder( mSearchLine, mRecipientList );
00345 setTabOrder( closeButton, mCollectionCombo );
00346 }
00347
00348 RecipientsPicker::~RecipientsPicker()
00349 {
00350 writeConfig();
00351
00352 delete mDistributionListManager;
00353
00354 mAllRecipients->deleteAll();
00355
00356 QMap<int,RecipientsCollection *>::ConstIterator it;
00357 for( it = mCollectionMap.begin(); it != mCollectionMap.end(); ++it ) {
00358 delete *it;
00359 }
00360 }
00361
00362 void RecipientsPicker::initCollections()
00363 {
00364 mAllRecipients = new RecipientsCollection;
00365 mAllRecipients->setTitle( i18n("All") );
00366 insertCollection( mAllRecipients );
00367
00368 insertAddressBook( mAddressBook );
00369
00370 insertAddressBook( mAddressBook );
00371
00372 insertDistributionLists();
00373
00374 insertRecentAddresses();
00375
00376 mSelectedRecipients = new RecipientsCollection;
00377 mSelectedRecipients->setTitle( i18n("Selected Recipients") );
00378 insertCollection( mSelectedRecipients );
00379 }
00380
00381 void RecipientsPicker::insertAddressBook( KABC::AddressBook *addressbook )
00382 {
00383 QMap<KABC::Resource *,RecipientsCollection *> collectionMap;
00384
00385 QPtrList<KABC::Resource> resources = addressbook->resources();
00386 KABC::Resource *res;
00387 for( res = resources.first(); res; res = resources.next() ) {
00388 RecipientsCollection *collection = new RecipientsCollection;
00389 collectionMap.insert( res, collection );
00390 collection->setTitle( res->resourceName() );
00391 }
00392
00393 QMap<QString,RecipientsCollection *> categoryMap;
00394
00395 KABC::AddressBook::Iterator it;
00396 for( it = addressbook->begin(); it != addressbook->end(); ++it ) {
00397 QStringList emails = (*it).emails();
00398 QStringList::ConstIterator it3;
00399 for( it3 = emails.begin(); it3 != emails.end(); ++it3 ) {
00400 RecipientItem *item = new RecipientItem;
00401 item->setAddressee( *it, *it3 );
00402 mAllRecipients->addItem( item );
00403
00404 QMap<KABC::Resource *,RecipientsCollection *>::ConstIterator collIt;
00405 collIt = collectionMap.find( it->resource() );
00406 if ( collIt != collectionMap.end() ) {
00407 (*collIt)->addItem( item );
00408 }
00409
00410 QStringList categories = (*it).categories();
00411 QStringList::ConstIterator catIt;
00412 for( catIt = categories.begin(); catIt != categories.end(); ++catIt ) {
00413 QMap<QString, RecipientsCollection *>::ConstIterator catMapIt;
00414 catMapIt = categoryMap.find( *catIt );
00415 RecipientsCollection *collection;
00416 if ( catMapIt == categoryMap.end() ) {
00417 collection = new RecipientsCollection;
00418 collection->setTitle( *catIt );
00419 categoryMap.insert( *catIt, collection );
00420 } else {
00421 collection = *catMapIt;
00422 }
00423 collection->addItem( item );
00424 }
00425 }
00426 }
00427
00428 QMap<KABC::Resource *,RecipientsCollection *>::ConstIterator it2;
00429 for( it2 = collectionMap.begin(); it2 != collectionMap.end(); ++it2 ) {
00430 insertCollection( *it2 );
00431 }
00432
00433 QMap<QString, RecipientsCollection *>::ConstIterator it3;
00434 for( it3 = categoryMap.begin(); it3 != categoryMap.end(); ++it3 ) {
00435 insertCollection( *it3 );
00436 }
00437
00438 updateList();
00439 }
00440
00441 void RecipientsPicker::insertDistributionLists()
00442 {
00443 RecipientsCollection *collection = new RecipientsCollection;
00444 collection->setTitle( i18n("Distribution Lists") );
00445
00446 delete mDistributionListManager;
00447 mDistributionListManager =
00448 new KABC::DistributionListManager( KABC::StdAddressBook::self( true ) );
00449
00450 mDistributionListManager->load();
00451
00452 QStringList lists = mDistributionListManager->listNames();
00453
00454 QStringList::Iterator listIt;
00455 for ( listIt = lists.begin(); listIt != lists.end(); ++listIt ) {
00456 KABC::DistributionList *list = mDistributionListManager->list( *listIt );
00457 RecipientItem *item = new RecipientItem;
00458 item->setDistributionList( list );
00459 mAllRecipients->addItem( item );
00460 collection->addItem( item );
00461 }
00462
00463 insertCollection( collection );
00464 }
00465
00466 void RecipientsPicker::insertRecentAddresses()
00467 {
00468 RecipientsCollection *collection = new RecipientsCollection;
00469 collection->setTitle( i18n("Recent Addresses") );
00470
00471 KConfig config( "kmailrc" );
00472 KABC::Addressee::List recents =
00473 KRecentAddress::RecentAddresses::self( &config )->kabcAddresses();
00474
00475 KABC::Addressee::List::ConstIterator it;
00476 for( it = recents.begin(); it != recents.end(); ++it ) {
00477 RecipientItem *item = new RecipientItem;
00478 item->setAddressee( *it, (*it).preferredEmail() );
00479 if ( !mAllRecipients->hasEquivalentItem( item ) ) {
00480 mAllRecipients->addItem( item );
00481 }
00482 collection->addItem( item );
00483 }
00484
00485 insertCollection( collection );
00486 }
00487
00488 void RecipientsPicker::insertCollection( RecipientsCollection *coll )
00489 {
00490 int index = mCollectionMap.count();
00491
00492 kdDebug() << "RecipientsPicker::insertCollection() " << coll->title()
00493 << " index: " << index << endl;
00494
00495 mCollectionCombo->insertItem( coll->title(), index );
00496 mCollectionMap.insert( index, coll );
00497 }
00498
00499 void RecipientsPicker::updateRecipient( const Recipient &recipient )
00500 {
00501 RecipientItem::List allRecipients = mAllRecipients->items();
00502 RecipientItem::List::ConstIterator itAll;
00503 for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
00504 if ( (*itAll)->recipient() == recipient.email() ) {
00505 (*itAll)->setRecipientType( recipient.typeLabel() );
00506 }
00507 }
00508 updateList();
00509 }
00510
00511 void RecipientsPicker::setRecipients( const Recipient::List &recipients )
00512 {
00513 RecipientItem::List allRecipients = mAllRecipients->items();
00514 RecipientItem::List::ConstIterator itAll;
00515 for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
00516 (*itAll)->setRecipientType( QString::null );
00517 }
00518
00519 mSelectedRecipients->clear();
00520
00521 Recipient::List::ConstIterator it;
00522 for( it = recipients.begin(); it != recipients.end(); ++it ) {
00523 RecipientItem *item = 0;
00524 for( itAll = allRecipients.begin(); itAll != allRecipients.end(); ++itAll ) {
00525 if ( (*itAll)->recipient() == (*it).email() ) {
00526 (*itAll)->setRecipientType( (*it).typeLabel() );
00527 item = *itAll;
00528 }
00529 }
00530 if ( !item ) {
00531 KABC::Addressee a;
00532 QString name;
00533 QString email;
00534 KABC::Addressee::parseEmailAddress( (*it).email(), name, email );
00535 a.setNameFromString( name );
00536 a.insertEmail( email );
00537
00538 item = new RecipientItem;
00539 item->setAddressee( a, a.preferredEmail() );
00540 item->setRecipientType( (*it).typeLabel() );
00541 mAllRecipients->addItem( item );
00542 }
00543 mSelectedRecipients->addItem( item );
00544 }
00545
00546 updateList();
00547 }
00548
00549 void RecipientsPicker::setDefaultButton( QPushButton *button )
00550 {
00551
00552 button->setDefault( true );
00553 }
00554
00555 void RecipientsPicker::setDefaultType( Recipient::Type type )
00556 {
00557 mDefaultType = type;
00558
00559 if ( type == Recipient::To ) {
00560 setDefaultButton( mToButton );
00561 } else if ( type == Recipient::Cc ) {
00562 setDefaultButton( mCcButton );
00563 } else if ( type == Recipient::Bcc ) {
00564 setDefaultButton( mBccButton );
00565 }
00566 }
00567
00568 void RecipientsPicker::updateList()
00569 {
00570 mRecipientList->clear();
00571
00572 RecipientsCollection *coll = mCollectionMap[ mCollectionCombo->currentItem() ];
00573
00574 RecipientItem::List items = coll->items();
00575 RecipientItem::List::ConstIterator it;
00576 for( it = items.begin(); it != items.end(); ++it ) {
00577 new RecipientViewItem( *it, mRecipientList );
00578 }
00579
00580 mSearchLine->updateSearch();
00581 }
00582
00583 void RecipientsPicker::slotToClicked()
00584 {
00585 pick( Recipient::To );
00586 }
00587
00588 void RecipientsPicker::slotCcClicked()
00589 {
00590 pick( Recipient::Cc );
00591 }
00592
00593 void RecipientsPicker::slotBccClicked()
00594 {
00595 pick( Recipient::Bcc );
00596 }
00597
00598 void RecipientsPicker::slotPicked( QListViewItem *viewItem )
00599 {
00600 RecipientViewItem *item = static_cast<RecipientViewItem *>( viewItem );
00601 if ( item ) {
00602 RecipientItem *i = item->recipientItem();
00603 emit pickedRecipient( Recipient( i->recipient(), Recipient::Undefined ) );
00604 }
00605 close();
00606 }
00607
00608 void RecipientsPicker::slotPicked()
00609 {
00610 pick( mDefaultType );
00611 }
00612
00613 void RecipientsPicker::pick( Recipient::Type type )
00614 {
00615 kdDebug() << "RecipientsPicker::pick " << int( type ) << endl;
00616
00617 int count = 0;
00618 QListViewItemIterator it( mRecipientList ,
00619 QListViewItemIterator::Visible | QListViewItemIterator::Selected );
00620 for ( ; it.current(); ++it )
00621 ++count;
00622
00623 if ( count > GlobalSettings::self()->maximumRecipients() ) {
00624 KMessageBox::sorry( this,
00625 i18n("You selected 1 recipient. The maximum supported number of "
00626 "recipients is %1. Please adapt the selection.",
00627 "You selected %n recipients. The maximum supported number of "
00628 "recipients is %1. Please adapt the selection.", count)
00629 .arg( GlobalSettings::self()->maximumRecipients() ) );
00630 return;
00631 }
00632
00633 it = QListViewItemIterator( mRecipientList ,
00634 QListViewItemIterator::Visible | QListViewItemIterator::Selected );
00635 for ( ; it.current(); ++it ) {
00636 RecipientViewItem *item = static_cast<RecipientViewItem *>( it.current() );
00637 if ( item ) {
00638 RecipientItem *i = item->recipientItem();
00639 Recipient r = i->recipient();
00640 r.setType( type );
00641 emit pickedRecipient( r );
00642 }
00643 }
00644 close();
00645 }
00646
00647 void RecipientsPicker::keyPressEvent( QKeyEvent *ev )
00648 {
00649 if ( ev->key() == Key_Escape ) close();
00650
00651 QWidget::keyPressEvent( ev );
00652 }
00653
00654 void RecipientsPicker::readConfig()
00655 {
00656 KConfig *cfg = KGlobal::config();
00657 cfg->setGroup( "RecipientsPicker" );
00658 QSize size = cfg->readSizeEntry( "Size" );
00659 if ( !size.isEmpty() ) {
00660 resize( size );
00661 }
00662 int currentCollection = cfg->readNumEntry( "CurrentCollection", -1 );
00663 if ( currentCollection >= 0 &&
00664 currentCollection < mCollectionCombo->count() ) {
00665 mCollectionCombo->setCurrentItem( currentCollection );
00666 }
00667 }
00668
00669 void RecipientsPicker::writeConfig()
00670 {
00671 KConfig *cfg = KGlobal::config();
00672 cfg->setGroup( "RecipientsPicker" );
00673 cfg->writeEntry( "Size", size() );
00674 cfg->writeEntry( "CurrentCollection", mCollectionCombo->currentItem() );
00675 }
00676
00677 void RecipientsPicker::setFocusList()
00678 {
00679 mRecipientList->setFocus();
00680 }
00681
00682 void RecipientsPicker::resetSearch()
00683 {
00684 mSearchLine->setText( QString::null );
00685 }
00686
00687 #include "recipientspicker.moc"