00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "recipientseditor.h"
00026
00027 #include "recipientspicker.h"
00028 #include "kwindowpositioner.h"
00029 #include "distributionlistdialog.h"
00030 #include "globalsettings.h"
00031
00032 #include <libemailfunctions/email.h>
00033
00034 #include <kapplication.h>
00035 #include <kdebug.h>
00036 #include <kinputdialog.h>
00037 #include <klocale.h>
00038 #include <kiconloader.h>
00039 #include <kmessagebox.h>
00040
00041 #include <qlayout.h>
00042 #include <qlabel.h>
00043 #include <qscrollview.h>
00044 #include <qcombobox.h>
00045 #include <qhbox.h>
00046 #include <qtimer.h>
00047 #include <qpushbutton.h>
00048 #include <qstylesheet.h>
00049
00050 Recipient::Recipient( const QString &email, Recipient::Type type )
00051 : mEmail( email ), mType( type )
00052 {
00053 }
00054
00055 void Recipient::setType( Type type )
00056 {
00057 mType = type;
00058 }
00059
00060 Recipient::Type Recipient::type() const
00061 {
00062 return mType;
00063 }
00064
00065 void Recipient::setEmail( const QString &email )
00066 {
00067 mEmail = email;
00068 }
00069
00070 QString Recipient::email() const
00071 {
00072 return mEmail;
00073 }
00074
00075 bool Recipient::isEmpty() const
00076 {
00077 return mEmail.isEmpty();
00078 }
00079
00080 int Recipient::typeToId( Recipient::Type type )
00081 {
00082 return static_cast<int>( type );
00083 }
00084
00085 Recipient::Type Recipient::idToType( int id )
00086 {
00087 return static_cast<Type>( id );
00088 }
00089
00090 QString Recipient::typeLabel() const
00091 {
00092 return typeLabel( mType );
00093 }
00094
00095 QString Recipient::typeLabel( Recipient::Type type )
00096 {
00097 switch( type ) {
00098 case To:
00099 return i18n("To");
00100 case Cc:
00101 return i18n("CC");
00102 case Bcc:
00103 return i18n("BCC");
00104 case Undefined:
00105 break;
00106 }
00107
00108 return i18n("<Undefined RecipientType>");
00109 }
00110
00111 QStringList Recipient::allTypeLabels()
00112 {
00113 QStringList types;
00114 types.append( typeLabel( To ) );
00115 types.append( typeLabel( Cc ) );
00116 types.append( typeLabel( Bcc ) );
00117 return types;
00118 }
00119
00120
00121 RecipientComboBox::RecipientComboBox( QWidget *parent )
00122 : QComboBox( parent )
00123 {
00124 }
00125
00126 void RecipientComboBox::keyPressEvent( QKeyEvent *ev )
00127 {
00128 if ( ev->key() == Key_Right ) emit rightPressed();
00129 else QComboBox::keyPressEvent( ev );
00130 }
00131
00132
00133 void RecipientLineEdit::keyPressEvent( QKeyEvent *ev )
00134 {
00135 if ( ev->key() == Key_Backspace && text().isEmpty() ) {
00136 ev->accept();
00137 emit deleteMe();
00138 } else if ( ev->key() == Key_Left && cursorPosition() == 0 ) {
00139 emit leftPressed();
00140 } else if ( ev->key() == Key_Right && cursorPosition() == (int)text().length() ) {
00141 emit rightPressed();
00142 } else {
00143 KMLineEdit::keyPressEvent( ev );
00144 }
00145 }
00146
00147 RecipientLine::RecipientLine( QWidget *parent )
00148 : QWidget( parent ), mRecipientsCount( 0 ), mModified( false )
00149 {
00150 QBoxLayout *topLayout = new QHBoxLayout( this );
00151 topLayout->setSpacing( KDialog::spacingHint() );
00152
00153 QStringList recipientTypes = Recipient::allTypeLabels();
00154
00155 mCombo = new RecipientComboBox( this );
00156 mCombo->insertStringList( recipientTypes );
00157 topLayout->addWidget( mCombo );
00158 QToolTip::add( mCombo, i18n("Select type of recipient") );
00159
00160 mEdit = new RecipientLineEdit( this );
00161 topLayout->addWidget( mEdit );
00162 connect( mEdit, SIGNAL( returnPressed() ), SLOT( slotReturnPressed() ) );
00163 connect( mEdit, SIGNAL( deleteMe() ), SLOT( slotPropagateDeletion() ) );
00164 connect( mEdit, SIGNAL( textChanged( const QString & ) ),
00165 SLOT( analyzeLine( const QString & ) ) );
00166 connect( mEdit, SIGNAL( focusUp() ), SLOT( slotFocusUp() ) );
00167 connect( mEdit, SIGNAL( focusDown() ), SLOT( slotFocusDown() ) );
00168 connect( mEdit, SIGNAL( rightPressed() ), SIGNAL( rightPressed() ) );
00169
00170 connect( mEdit, SIGNAL( leftPressed() ), mCombo, SLOT( setFocus() ) );
00171 connect( mCombo, SIGNAL( rightPressed() ), mEdit, SLOT( setFocus() ) );
00172
00173 connect( mCombo, SIGNAL( activated ( int ) ),
00174 this, SLOT( slotTypeModified() ) );
00175
00176 mRemoveButton = new QPushButton( this );
00177 mRemoveButton->setIconSet( KApplication::reverseLayout() ? SmallIconSet("locationbar_erase") : SmallIconSet( "clear_left" ) );
00178 topLayout->addWidget( mRemoveButton );
00179 connect( mRemoveButton, SIGNAL( clicked() ), SLOT( slotPropagateDeletion() ) );
00180 QToolTip::add( mRemoveButton, i18n("Remove recipient line") );
00181 }
00182
00183 void RecipientLine::slotFocusUp()
00184 {
00185 emit upPressed( this );
00186 }
00187
00188 void RecipientLine::slotFocusDown()
00189 {
00190 emit downPressed( this );
00191 }
00192
00193 void RecipientLine::slotTypeModified()
00194 {
00195 mModified = true;
00196
00197 emit typeModified( this );
00198 }
00199
00200 void RecipientLine::analyzeLine( const QString &text )
00201 {
00202 QStringList r = KPIM::splitEmailAddrList( text );
00203 if ( int( r.count() ) != mRecipientsCount ) {
00204 mRecipientsCount = r.count();
00205 emit countChanged();
00206 }
00207 }
00208
00209 int RecipientLine::recipientsCount()
00210 {
00211 return mRecipientsCount;
00212 }
00213
00214 void RecipientLine::setRecipient( const Recipient &rec )
00215 {
00216 mEdit->setText( rec.email() );
00217 mCombo->setCurrentItem( Recipient::typeToId( rec.type() ) );
00218 }
00219
00220 void RecipientLine::setRecipient( const QString &email )
00221 {
00222 setRecipient( Recipient( email ) );
00223 }
00224
00225 Recipient RecipientLine::recipient() const
00226 {
00227 return Recipient( mEdit->text(),
00228 Recipient::idToType( mCombo->currentItem() ) );
00229 }
00230
00231 void RecipientLine::setRecipientType( Recipient::Type type )
00232 {
00233 mCombo->setCurrentItem( Recipient::typeToId( type ) );
00234 }
00235
00236 Recipient::Type RecipientLine::recipientType() const
00237 {
00238 return Recipient::idToType( mCombo->currentItem() );
00239 }
00240
00241 void RecipientLine::activate()
00242 {
00243 mEdit->setFocus();
00244 }
00245
00246 bool RecipientLine::isActive()
00247 {
00248 return mEdit->hasFocus();
00249 }
00250
00251 bool RecipientLine::isEmpty()
00252 {
00253 return mEdit->text().isEmpty();
00254 }
00255
00256 bool RecipientLine::isModified()
00257 {
00258 return mModified || mEdit->isModified();
00259 }
00260
00261 void RecipientLine::clearModified()
00262 {
00263 mModified = false;
00264 mEdit->clearModified();
00265 }
00266
00267 void RecipientLine::slotReturnPressed()
00268 {
00269 emit returnPressed( this );
00270 }
00271
00272 void RecipientLine::slotPropagateDeletion()
00273 {
00274 emit deleteLine( this );
00275 }
00276
00277 void RecipientLine::keyPressEvent( QKeyEvent *ev )
00278 {
00279 if ( ev->key() == Key_Up ) {
00280 emit upPressed( this );
00281 } else if ( ev->key() == Key_Down ) {
00282 emit downPressed( this );
00283 }
00284 }
00285
00286 int RecipientLine::setComboWidth( int w )
00287 {
00288 w = QMAX( w, mCombo->sizeHint().width() );
00289 mCombo->setFixedWidth( w );
00290 mCombo->updateGeometry();
00291 parentWidget()->updateGeometry();
00292 return w;
00293 }
00294
00295 void RecipientLine::fixTabOrder( QWidget *previous )
00296 {
00297 setTabOrder( previous, mCombo );
00298 setTabOrder( mCombo, mEdit );
00299 setTabOrder( mEdit, mRemoveButton );
00300 }
00301
00302 QWidget *RecipientLine::tabOut() const
00303 {
00304 return mRemoveButton;
00305 }
00306
00307 void RecipientLine::clear()
00308 {
00309 mEdit->clear();
00310 }
00311
00312 void RecipientLine::setRemoveLineButtonEnabled( bool b )
00313 {
00314 mRemoveButton->setEnabled( b );
00315 }
00316
00317
00318
00319
00320 RecipientsView::RecipientsView( QWidget *parent )
00321 : QScrollView( parent ), mCurDelLine( 0 ),
00322 mLineHeight( 0 ), mFirstColumnWidth( 0 ),
00323 mModified( false )
00324 {
00325 mCompletionMode = KGlobalSettings::completionMode();
00326 setHScrollBarMode( AlwaysOff );
00327 setLineWidth( 0 );
00328
00329 addLine();
00330 setResizePolicy( QScrollView::Manual );
00331 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
00332 }
00333
00334 RecipientLine *RecipientsView::activeLine()
00335 {
00336 return mLines.last();
00337 }
00338
00339 RecipientLine *RecipientsView::emptyLine()
00340 {
00341 RecipientLine *line;
00342 for( line = mLines.first(); line; line = mLines.next() ) {
00343 if ( line->isEmpty() ) return line;
00344 }
00345
00346 return 0;
00347 }
00348
00349 RecipientLine *RecipientsView::addLine()
00350 {
00351 RecipientLine *line = new RecipientLine( viewport() );
00352 addChild( line, 0, mLines.count() * mLineHeight );
00353 line->mEdit->setCompletionMode( mCompletionMode );
00354 line->show();
00355 connect( line, SIGNAL( returnPressed( RecipientLine * ) ),
00356 SLOT( slotReturnPressed( RecipientLine * ) ) );
00357 connect( line, SIGNAL( upPressed( RecipientLine * ) ),
00358 SLOT( slotUpPressed( RecipientLine * ) ) );
00359 connect( line, SIGNAL( downPressed( RecipientLine * ) ),
00360 SLOT( slotDownPressed( RecipientLine * ) ) );
00361 connect( line, SIGNAL( rightPressed() ), SIGNAL( focusRight() ) );
00362 connect( line, SIGNAL( deleteLine( RecipientLine * ) ),
00363 SLOT( slotDecideLineDeletion( RecipientLine * ) ) );
00364 connect( line, SIGNAL( countChanged() ), SLOT( calculateTotal() ) );
00365 connect( line, SIGNAL( typeModified( RecipientLine * ) ),
00366 SLOT( slotTypeModified( RecipientLine * ) ) );
00367 connect( line->mEdit, SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ),
00368 SLOT( setCompletionMode( KGlobalSettings::Completion ) ) );
00369
00370 if ( mLines.last() ) {
00371 if ( mLines.count() == 1 ) {
00372 if ( GlobalSettings::self()->secondRecipientTypeDefault() ==
00373 GlobalSettings::EnumSecondRecipientTypeDefault::To ) {
00374 line->setRecipientType( Recipient::To );
00375 } else {
00376 if ( mLines.last()->recipientType() == Recipient::Bcc ) {
00377 line->setRecipientType( Recipient::To );
00378 } else {
00379 line->setRecipientType( Recipient::Cc );
00380 }
00381 }
00382 } else {
00383 line->setRecipientType( mLines.last()->recipientType() );
00384 }
00385 line->fixTabOrder( mLines.last()->tabOut() );
00386 }
00387
00388 mLines.append( line );
00389
00390 if ( mLines.count() == 1 ) {
00391 mLines.first()->setRemoveLineButtonEnabled( false );
00392 } else {
00393 mLines.first()->setRemoveLineButtonEnabled( true );
00394 }
00395
00396 mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
00397
00398 mLineHeight = line->minimumSizeHint().height();
00399
00400 line->resize( viewport()->width(), mLineHeight );
00401
00402 resizeView();
00403
00404 calculateTotal();
00405
00406 ensureVisible( 0, mLines.count() * mLineHeight );
00407
00408 return line;
00409 }
00410
00411 void RecipientsView::slotTypeModified( RecipientLine *line )
00412 {
00413 if ( mLines.count() == 2 ||
00414 ( mLines.count() == 3 && mLines.at( 2 )->isEmpty() ) ) {
00415 if ( mLines.at( 1 ) == line ) {
00416 if ( line->recipientType() == Recipient::To ) {
00417 GlobalSettings::self()->setSecondRecipientTypeDefault(
00418 GlobalSettings::EnumSecondRecipientTypeDefault::To );
00419 } else if ( line->recipientType() == Recipient::Cc ) {
00420 GlobalSettings::self()->setSecondRecipientTypeDefault(
00421 GlobalSettings::EnumSecondRecipientTypeDefault::Cc );
00422 }
00423 }
00424 }
00425 }
00426
00427 void RecipientsView::calculateTotal()
00428 {
00429 int count = 0;
00430 int empty = 0;
00431
00432 RecipientLine *line;
00433 for( line = mLines.first(); line; line = mLines.next() ) {
00434 if ( line->isEmpty() ) ++empty;
00435 else count += line->recipientsCount();
00436 }
00437
00438 if ( empty == 0 ) addLine();
00439
00440 emit totalChanged( count, mLines.count() );
00441 }
00442
00443 void RecipientsView::slotReturnPressed( RecipientLine *line )
00444 {
00445 if ( !line->recipient().isEmpty() ) {
00446 RecipientLine *empty = emptyLine();
00447 if ( !empty ) empty = addLine();
00448 activateLine( empty );
00449 }
00450 }
00451
00452 void RecipientsView::slotDownPressed( RecipientLine *line )
00453 {
00454 int pos = mLines.find( line );
00455 if ( pos >= (int)mLines.count() - 1 ) {
00456 emit focusDown();
00457 } else if ( pos >= 0 ) {
00458 activateLine( mLines.at( pos + 1 ) );
00459 }
00460 }
00461
00462 void RecipientsView::slotUpPressed( RecipientLine *line )
00463 {
00464 int pos = mLines.find( line );
00465 if ( pos > 0 ) {
00466 activateLine( mLines.at( pos - 1 ) );
00467 } else {
00468 emit focusUp();
00469 }
00470 }
00471
00472 void RecipientsView::slotDecideLineDeletion( RecipientLine *line )
00473 {
00474 if ( !line->isEmpty() )
00475 mModified = true;
00476 if ( mLines.count() == 1 ) {
00477 line->clear();
00478 } else {
00479 mCurDelLine = line;
00480 QTimer::singleShot( 0, this, SLOT( slotDeleteLine( ) ) );
00481 }
00482 }
00483
00484 void RecipientsView::slotDeleteLine()
00485 {
00486 if ( !mCurDelLine )
00487 return;
00488
00489 RecipientLine *line = mCurDelLine;
00490 int pos = mLines.find( line );
00491
00492 int newPos;
00493 if ( pos == 0 ) newPos = pos + 1;
00494 else newPos = pos - 1;
00495
00496
00497 if ( mLines.at( newPos ) )
00498 mLines.at( newPos )->activate();
00499
00500 mLines.remove( line );
00501 removeChild( line );
00502 delete line;
00503
00504 bool atLeastOneToLine = false;
00505 unsigned int firstCC = 0;
00506 for( uint i = pos; i < mLines.count(); ++i ) {
00507 RecipientLine *line = mLines.at( i );
00508 moveChild( line, childX( line ), childY( line ) - mLineHeight );
00509 if ( line->recipientType() == Recipient::To )
00510 atLeastOneToLine = true;
00511 else if ( ( line->recipientType() == Recipient::Cc ) && ( i == 0 ) )
00512 firstCC = i;
00513 }
00514
00515 if ( mLines.count() == 1 )
00516 mLines.first()->setRemoveLineButtonEnabled( false );
00517
00518 if ( !atLeastOneToLine )
00519 mLines.at( firstCC )->setRecipientType( Recipient::To );
00520
00521 calculateTotal();
00522
00523 resizeView();
00524 }
00525
00526 void RecipientsView::resizeView()
00527 {
00528 resizeContents( width(), mLines.count() * mLineHeight );
00529
00530 if ( mLines.count() < 6 ) {
00531 setFixedHeight( mLineHeight * mLines.count() );
00532 }
00533 }
00534
00535 void RecipientsView::activateLine( RecipientLine *line )
00536 {
00537 line->activate();
00538 ensureVisible( 0, childY( line ) );
00539 }
00540
00541 void RecipientsView::viewportResizeEvent ( QResizeEvent *ev )
00542 {
00543 for( uint i = 0; i < mLines.count(); ++i ) {
00544 mLines.at( i )->resize( ev->size().width(), mLineHeight );
00545 }
00546 }
00547
00548 QSize RecipientsView::sizeHint() const
00549 {
00550 return QSize( 200, mLineHeight * mLines.count() );
00551 }
00552
00553 QSize RecipientsView::minimumSizeHint() const
00554 {
00555 int height;
00556
00557 uint numLines = 5;
00558
00559 if ( mLines.count() < numLines ) height = mLineHeight * mLines.count();
00560 else height = mLineHeight * numLines;
00561
00562 return QSize( 200, height );
00563 }
00564
00565 Recipient::List RecipientsView::recipients() const
00566 {
00567 Recipient::List recipients;
00568
00569 QPtrListIterator<RecipientLine> it( mLines );
00570 RecipientLine *line;
00571 while( ( line = it.current() ) ) {
00572 if ( !line->recipient().isEmpty() ) {
00573 recipients.append( line->recipient() );
00574 }
00575
00576 ++it;
00577 }
00578
00579 return recipients;
00580 }
00581
00582 void RecipientsView::setCompletionMode ( KGlobalSettings::Completion mode )
00583 {
00584 if ( mCompletionMode == mode )
00585 return;
00586 mCompletionMode = mode;
00587
00588 QPtrListIterator<RecipientLine> it( mLines );
00589 RecipientLine *line;
00590 while( ( line = it.current() ) ) {
00591 line->mEdit->blockSignals( true );
00592 line->mEdit->setCompletionMode( mode );
00593 line->mEdit->blockSignals( false );
00594 ++it;
00595 }
00596 emit completionModeChanged( mode );
00597 }
00598
00599 void RecipientsView::removeRecipient( const QString & recipient,
00600 Recipient::Type type )
00601 {
00602
00603 QPtrListIterator<RecipientLine> it( mLines );
00604 RecipientLine *line;
00605 while( ( line = it.current() ) ) {
00606 if ( ( line->recipient().email() == recipient ) &&
00607 ( line->recipientType() == type ) ) {
00608 break;
00609 }
00610 ++it;
00611 }
00612 if ( line )
00613 line->slotPropagateDeletion();
00614 }
00615
00616 bool RecipientsView::isModified()
00617 {
00618 if ( mModified )
00619 return true;
00620
00621 QPtrListIterator<RecipientLine> it( mLines );
00622 RecipientLine *line;
00623 while( ( line = it.current() ) ) {
00624 if ( line->isModified() ) {
00625 return true;
00626 }
00627 ++it;
00628 }
00629
00630 return false;
00631 }
00632
00633 void RecipientsView::clearModified()
00634 {
00635 mModified = false;
00636
00637 QPtrListIterator<RecipientLine> it( mLines );
00638 RecipientLine *line;
00639 while( ( line = it.current() ) ) {
00640 line->clearModified();
00641 ++it;
00642 }
00643 }
00644
00645 void RecipientsView::setFocus()
00646 {
00647 if ( mLines.last()->isActive() ) setFocusBottom();
00648 else setFocusTop();
00649 }
00650
00651 void RecipientsView::setFocusTop()
00652 {
00653 RecipientLine *line = mLines.first();
00654 if ( line ) line->activate();
00655 else kdWarning() << "No first" << endl;
00656 }
00657
00658 void RecipientsView::setFocusBottom()
00659 {
00660 RecipientLine *line = mLines.last();
00661 if ( line ) line->activate();
00662 else kdWarning() << "No last" << endl;
00663 }
00664
00665 int RecipientsView::setFirstColumnWidth( int w )
00666 {
00667 mFirstColumnWidth = w;
00668
00669 QPtrListIterator<RecipientLine> it( mLines );
00670 RecipientLine *line;
00671 while( ( line = it.current() ) ) {
00672 mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
00673 ++it;
00674 }
00675
00676 resizeView();
00677 return mFirstColumnWidth;
00678 }
00679
00680 RecipientsToolTip::RecipientsToolTip( RecipientsView *view, QWidget *parent )
00681 : QToolTip( parent ), mView( view )
00682 {
00683 }
00684
00685 QString RecipientsToolTip::line( const Recipient &r )
00686 {
00687 QString txt = r.email();
00688
00689 return " " + QStyleSheet::escape( txt ) + "<br/>";
00690 }
00691
00692 void RecipientsToolTip::maybeTip( const QPoint & p )
00693 {
00694 QString text = "<qt>";
00695
00696 QString to;
00697 QString cc;
00698 QString bcc;
00699
00700 Recipient::List recipients = mView->recipients();
00701 Recipient::List::ConstIterator it;
00702 for( it = recipients.begin(); it != recipients.end(); ++it ) {
00703 switch( (*it).type() ) {
00704 case Recipient::To:
00705 to += line( *it );
00706 break;
00707 case Recipient::Cc:
00708 cc += line( *it );
00709 break;
00710 case Recipient::Bcc:
00711 bcc += line( *it );
00712 break;
00713 default:
00714 break;
00715 }
00716 }
00717
00718 text += i18n("<b>To:</b><br/>") + to;
00719 if ( !cc.isEmpty() ) text += i18n("<b>CC:</b><br/>") + cc;
00720 if ( !bcc.isEmpty() ) text += i18n("<b>BCC:</b><br/>") + bcc;
00721
00722 text.append( "</qt>" );
00723
00724 QRect geometry( p + QPoint( 2, 2 ), QPoint( 400, 100 ) );
00725
00726 tip( QRect( p.x() - 20, p.y() - 20, 40, 40 ), text, geometry );
00727 }
00728
00729
00730 SideWidget::SideWidget( RecipientsView *view, QWidget *parent )
00731 : QWidget( parent ), mView( view ), mRecipientPicker( 0 )
00732 {
00733 QBoxLayout *topLayout = new QVBoxLayout( this );
00734
00735 topLayout->setSpacing( KDialog::spacingHint() );
00736 topLayout->addStretch( 1 );
00737
00738 mTotalLabel = new QLabel( this );
00739 mTotalLabel->setAlignment( AlignCenter );
00740 topLayout->addWidget( mTotalLabel );
00741 mTotalLabel->hide();
00742
00743 topLayout->addStretch( 1 );
00744
00745 new RecipientsToolTip( view, mTotalLabel );
00746
00747 mDistributionListButton = new QPushButton( i18n("Save List..."), this );
00748 topLayout->addWidget( mDistributionListButton );
00749 mDistributionListButton->hide();
00750 connect( mDistributionListButton, SIGNAL( clicked() ),
00751 SIGNAL( saveDistributionList() ) );
00752 QToolTip::add( mDistributionListButton,
00753 i18n("Save recipients as distribution list") );
00754
00755 mSelectButton = new QPushButton( i18n("Se&lect..."), this );
00756 topLayout->addWidget( mSelectButton );
00757 connect( mSelectButton, SIGNAL( clicked() ), SLOT( pickRecipient() ) );
00758 QToolTip::add( mSelectButton, i18n("Select recipients from address book") );
00759 }
00760
00761 SideWidget::~SideWidget()
00762 {
00763 }
00764
00765 RecipientsPicker* SideWidget::picker() const
00766 {
00767 if ( !mRecipientPicker ) {
00768
00769 SideWidget *non_const_this = const_cast<SideWidget*>( this );
00770 mRecipientPicker = new RecipientsPicker( non_const_this );
00771 connect( mRecipientPicker, SIGNAL( pickedRecipient( const Recipient & ) ),
00772 non_const_this, SIGNAL( pickedRecipient( const Recipient & ) ) );
00773 mPickerPositioner = new KWindowPositioner( non_const_this, mRecipientPicker );
00774 }
00775 return mRecipientPicker;
00776 }
00777
00778 void SideWidget::setFocus()
00779 {
00780 mSelectButton->setFocus();
00781 }
00782
00783 void SideWidget::setTotal( int recipients, int lines )
00784 {
00785 #if 0
00786 kdDebug() << "SideWidget::setTotal() recipients: " << recipients <<
00787 " lines: " << lines << endl;
00788 #endif
00789
00790 QString labelText;
00791 if ( recipients == 0 ) labelText = i18n("No recipients");
00792 else labelText = i18n("1 recipient","%n recipients", recipients );
00793 mTotalLabel->setText( labelText );
00794
00795 if ( lines > 3 ) mTotalLabel->show();
00796 else mTotalLabel->hide();
00797
00798 if ( lines > 2 ) mDistributionListButton->show();
00799 else mDistributionListButton->hide();
00800 }
00801
00802 void SideWidget::pickRecipient()
00803 {
00804 #if 0
00805 QString rec = KInputDialog::getText( "Pick Recipient",
00806 "Email address of recipient" );
00807 if ( !rec.isEmpty() ) emit pickedRecipient( rec );
00808 #else
00809 RecipientsPicker *p = picker();
00810 p->setDefaultType( mView->activeLine()->recipientType() );
00811 p->setRecipients( mView->recipients() );
00812 p->show();
00813 mPickerPositioner->reposition();
00814 p->raise();
00815 #endif
00816 }
00817
00818
00819 RecipientsEditor::RecipientsEditor( QWidget *parent )
00820 : QWidget( parent ), mModified( false )
00821 {
00822 QBoxLayout *topLayout = new QHBoxLayout( this );
00823 topLayout->setSpacing( KDialog::spacingHint() );
00824
00825 mRecipientsView = new RecipientsView( this );
00826 topLayout->addWidget( mRecipientsView );
00827 connect( mRecipientsView, SIGNAL( focusUp() ), SIGNAL( focusUp() ) );
00828 connect( mRecipientsView, SIGNAL( focusDown() ), SIGNAL( focusDown() ) );
00829 connect( mRecipientsView, SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ),
00830 SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ) );
00831
00832 mSideWidget = new SideWidget( mRecipientsView, this );
00833 topLayout->addWidget( mSideWidget );
00834 connect( mSideWidget, SIGNAL( pickedRecipient( const Recipient & ) ),
00835 SLOT( slotPickedRecipient( const Recipient & ) ) );
00836 connect( mSideWidget, SIGNAL( saveDistributionList() ),
00837 SLOT( saveDistributionList() ) );
00838
00839 connect( mRecipientsView, SIGNAL( totalChanged( int, int ) ),
00840 mSideWidget, SLOT( setTotal( int, int ) ) );
00841 connect( mRecipientsView, SIGNAL( focusRight() ),
00842 mSideWidget, SLOT( setFocus() ) );
00843 }
00844
00845 RecipientsEditor::~RecipientsEditor()
00846 {
00847 }
00848
00849 RecipientsPicker* RecipientsEditor::picker() const
00850 {
00851 return mSideWidget->picker();
00852 }
00853
00854 void RecipientsEditor::slotPickedRecipient( const Recipient &rec )
00855 {
00856 RecipientLine *line = mRecipientsView->activeLine();
00857 if ( !line->isEmpty() ) line = mRecipientsView->addLine();
00858
00859 Recipient r = rec;
00860 if ( r.type() == Recipient::Undefined ) {
00861 r.setType( line->recipientType() );
00862 }
00863
00864 line->setRecipient( r );
00865 mModified = true;
00866 }
00867
00868 void RecipientsEditor::saveDistributionList()
00869 {
00870 DistributionListDialog *dlg = new DistributionListDialog( this );
00871 dlg->setRecipients( mRecipientsView->recipients() );
00872 dlg->show();
00873 }
00874
00875 Recipient::List RecipientsEditor::recipients() const
00876 {
00877 return mRecipientsView->recipients();
00878 }
00879
00880 void RecipientsEditor::setRecipientString( const QString &str,
00881 Recipient::Type type )
00882 {
00883 clear();
00884
00885 int count = 1;
00886
00887 QStringList r = KPIM::splitEmailAddrList( str );
00888 QStringList::ConstIterator it;
00889 for( it = r.begin(); it != r.end(); ++it ) {
00890 if ( count++ > GlobalSettings::self()->maximumRecipients() ) {
00891 KMessageBox::sorry( this,
00892 i18n("Truncating recipients list to %1 of %2 entries.")
00893 .arg( GlobalSettings::self()->maximumRecipients() )
00894 .arg( r.count() ) );
00895 break;
00896 }
00897 addRecipient( *it, type );
00898 }
00899 }
00900
00901 QString RecipientsEditor::recipientString( Recipient::Type type )
00902 {
00903 QString str;
00904
00905 Recipient::List recipients = mRecipientsView->recipients();
00906 Recipient::List::ConstIterator it;
00907 for( it = recipients.begin(); it != recipients.end(); ++it ) {
00908 if ( (*it).type() == type ) {
00909 if ( !str.isEmpty() ) str += ", ";
00910 str.append( (*it).email() );
00911 }
00912 }
00913
00914 return str;
00915 }
00916
00917 void RecipientsEditor::addRecipient( const QString & recipient,
00918 Recipient::Type type )
00919 {
00920 RecipientLine *line = mRecipientsView->emptyLine();
00921 if ( !line ) line = mRecipientsView->addLine();
00922 line->setRecipient( Recipient( recipient, type ) );
00923 }
00924
00925 void RecipientsEditor::removeRecipient( const QString & recipient,
00926 Recipient::Type type )
00927 {
00928 mRecipientsView->removeRecipient( recipient, type );
00929 }
00930
00931 bool RecipientsEditor::isModified()
00932 {
00933 return mModified || mRecipientsView->isModified();
00934 }
00935
00936 void RecipientsEditor::clearModified()
00937 {
00938 mModified = false;
00939 mRecipientsView->clearModified();
00940 }
00941
00942 void RecipientsEditor::clear()
00943 {
00944 }
00945
00946 void RecipientsEditor::setFocus()
00947 {
00948 mRecipientsView->setFocus();
00949 }
00950
00951 void RecipientsEditor::setFocusTop()
00952 {
00953 mRecipientsView->setFocusTop();
00954 }
00955
00956 void RecipientsEditor::setFocusBottom()
00957 {
00958 mRecipientsView->setFocusBottom();
00959 }
00960
00961 int RecipientsEditor::setFirstColumnWidth( int w )
00962 {
00963 return mRecipientsView->setFirstColumnWidth( w );
00964 }
00965
00966 void RecipientsEditor::selectRecipients()
00967 {
00968 mSideWidget->pickRecipient();
00969 }
00970
00971 void RecipientsEditor::setCompletionMode( KGlobalSettings::Completion mode )
00972 {
00973 mRecipientsView->setCompletionMode( mode );
00974 }
00975 #include "recipientseditor.moc"