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