kmail

recipientseditor.cpp

00001 /*
00002     This file is part of KMail.
00003 
00004     Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
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 // ------------ RecipientsView ---------------------
00319 
00320 RecipientsView::RecipientsView( QWidget *parent )
00321   : QScrollView( parent ), mCurDelLine( 0 ), mModified( false ),
00322     mFirstColumnWidth( 0 ), mLineHeight( 0 )
00323 {
00324   setHScrollBarMode( AlwaysOff );
00325   setLineWidth( 0 );
00326 
00327   addLine();
00328   setResizePolicy( QScrollView::Manual );
00329   setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
00330 }
00331 
00332 RecipientLine *RecipientsView::activeLine()
00333 {
00334   return mLines.last();
00335 }
00336 
00337 RecipientLine *RecipientsView::emptyLine()
00338 {
00339   RecipientLine *line;
00340   for( line = mLines.first(); line; line = mLines.next() ) {
00341     if ( line->isEmpty() ) return line;
00342   }
00343 
00344   return 0;
00345 }
00346 
00347 RecipientLine *RecipientsView::addLine()
00348 {
00349   RecipientLine *line = new RecipientLine( viewport() );
00350   addChild( line, 0, mLines.count() * mLineHeight );
00351   line->show();
00352   connect( line, SIGNAL( returnPressed( RecipientLine * ) ),
00353     SLOT( slotReturnPressed( RecipientLine * ) ) );
00354   connect( line, SIGNAL( upPressed( RecipientLine * ) ),
00355     SLOT( slotUpPressed( RecipientLine * ) ) );
00356   connect( line, SIGNAL( downPressed( RecipientLine * ) ),
00357     SLOT( slotDownPressed( RecipientLine * ) ) );
00358   connect( line, SIGNAL( rightPressed() ), SIGNAL( focusRight() ) );
00359   connect( line, SIGNAL( deleteLine( RecipientLine * ) ),
00360     SLOT( slotDecideLineDeletion( RecipientLine * ) ) );
00361   connect( line, SIGNAL( countChanged() ), SLOT( calculateTotal() ) );
00362   connect( line, SIGNAL( typeModified( RecipientLine * ) ),
00363     SLOT( slotTypeModified( RecipientLine * ) ) );
00364 
00365   if ( mLines.last() ) {
00366     if ( mLines.count() == 1 ) {
00367       if ( GlobalSettings::self()->secondRecipientTypeDefault() ==
00368          GlobalSettings::EnumSecondRecipientTypeDefault::To ) {
00369         line->setRecipientType( Recipient::To );
00370       } else {
00371         if ( mLines.last()->recipientType() == Recipient::Bcc ) {
00372           line->setRecipientType( Recipient::To );
00373         } else {
00374           line->setRecipientType( Recipient::Cc );
00375         }
00376       }
00377     } else {
00378       line->setRecipientType( mLines.last()->recipientType() );
00379     }
00380     line->fixTabOrder( mLines.last()->tabOut() );
00381   }
00382 
00383   mLines.append( line );
00384   // If there is only one line, removing it makes no sense
00385   if ( mLines.count() == 1 ) {
00386     mLines.first()->setRemoveLineButtonEnabled( false );
00387   } else {
00388     mLines.first()->setRemoveLineButtonEnabled( true );
00389   }
00390 
00391   mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
00392 
00393   mLineHeight = line->minimumSizeHint().height();
00394 
00395   line->resize( viewport()->width(), mLineHeight );
00396 
00397   resizeView();
00398 
00399   calculateTotal();
00400 
00401   ensureVisible( 0, mLines.count() * mLineHeight );
00402 
00403   return line;
00404 }
00405 
00406 void RecipientsView::slotTypeModified( RecipientLine *line )
00407 {
00408   if ( mLines.count() == 2 ||
00409        ( mLines.count() == 3 && mLines.at( 2 )->isEmpty() ) ) {
00410     if ( mLines.at( 1 ) == line ) {
00411       if ( line->recipientType() == Recipient::To ) {
00412         GlobalSettings::self()->setSecondRecipientTypeDefault(
00413           GlobalSettings::EnumSecondRecipientTypeDefault::To );
00414       } else if ( line->recipientType() == Recipient::Cc ) {
00415         GlobalSettings::self()->setSecondRecipientTypeDefault(
00416           GlobalSettings::EnumSecondRecipientTypeDefault::Cc );
00417       }
00418     }
00419   }
00420 }
00421 
00422 void RecipientsView::calculateTotal()
00423 {
00424   int count = 0;
00425   int empty = 0;
00426 
00427   RecipientLine *line;
00428   for( line = mLines.first(); line; line = mLines.next() ) {
00429     if ( line->isEmpty() ) ++empty;
00430     else count += line->recipientsCount();
00431   }
00432 
00433   if ( empty == 0 ) addLine();
00434 
00435   emit totalChanged( count, mLines.count() );
00436 }
00437 
00438 void RecipientsView::slotReturnPressed( RecipientLine *line )
00439 {
00440   if ( !line->recipient().isEmpty() ) {
00441     RecipientLine *empty = emptyLine();
00442     if ( !empty ) empty = addLine();
00443     activateLine( empty );
00444   }
00445 }
00446 
00447 void RecipientsView::slotDownPressed( RecipientLine *line )
00448 {
00449   int pos = mLines.find( line );
00450   if ( pos >= (int)mLines.count() - 1 ) {
00451     emit focusDown();
00452   } else if ( pos >= 0 ) {
00453     activateLine( mLines.at( pos + 1 ) );
00454   }
00455 }
00456 
00457 void RecipientsView::slotUpPressed( RecipientLine *line )
00458 {
00459   int pos = mLines.find( line );
00460   if ( pos > 0 ) {
00461     activateLine( mLines.at( pos - 1 ) );
00462   } else {
00463     emit focusUp();
00464   }
00465 }
00466 
00467 void RecipientsView::slotDecideLineDeletion( RecipientLine *line )
00468 {
00469   if ( !line->isEmpty() )
00470     mModified = true;
00471   if ( mLines.count() == 1 ) {
00472     line->clear();
00473   } else {
00474     mCurDelLine = line;
00475     QTimer::singleShot( 0, this, SLOT( slotDeleteLine( ) ) );
00476   }
00477 }
00478 
00479 void RecipientsView::slotDeleteLine()
00480 {
00481   if ( !mCurDelLine )
00482     return;
00483 
00484   RecipientLine *line = mCurDelLine;
00485   int pos = mLines.find( line );
00486 
00487   int newPos;
00488   if ( pos == 0 ) newPos = pos + 1;
00489   else newPos = pos - 1;
00490 
00491   // if there is something left to activate, do so
00492   if ( mLines.at( newPos ) )
00493     mLines.at( newPos )->activate();
00494 
00495   mLines.remove( line );
00496   removeChild( line );
00497   delete line;
00498 
00499   bool atLeastOneToLine = false;
00500   unsigned int firstCC = 0;
00501   for( uint i = pos; i < mLines.count(); ++i ) {
00502     RecipientLine *line = mLines.at( i );
00503     moveChild( line, childX( line ), childY( line ) - mLineHeight );
00504     if ( line->recipientType() == Recipient::To )
00505       atLeastOneToLine = true;
00506     else if ( ( line->recipientType() == Recipient::Cc ) && ( i == 0 ) )
00507       firstCC = i;
00508   }
00509   // only one left, can't remove that one
00510   if ( mLines.count() == 1 )
00511     mLines.first()->setRemoveLineButtonEnabled( false );
00512 
00513   if ( !atLeastOneToLine )
00514     mLines.at( firstCC )->setRecipientType( Recipient::To );
00515 
00516   calculateTotal();
00517 
00518   resizeView();
00519 }
00520 
00521 void RecipientsView::resizeView()
00522 {
00523   resizeContents( width(), mLines.count() * mLineHeight );
00524 
00525   if ( mLines.count() < 6 ) {
00526     setFixedHeight( mLineHeight * mLines.count() );
00527   }
00528 }
00529 
00530 void RecipientsView::activateLine( RecipientLine *line )
00531 {
00532   line->activate();
00533   ensureVisible( 0, childY( line ) );
00534 }
00535 
00536 void RecipientsView::viewportResizeEvent ( QResizeEvent *ev )
00537 {
00538   for( uint i = 0; i < mLines.count(); ++i ) {
00539     mLines.at( i )->resize( ev->size().width(), mLineHeight );
00540   }
00541 }
00542 
00543 QSize RecipientsView::sizeHint() const
00544 {
00545   return QSize( 200, mLineHeight * mLines.count() );
00546 }
00547 
00548 QSize RecipientsView::minimumSizeHint() const
00549 {
00550   int height;
00551 
00552   uint numLines = 5;
00553 
00554   if ( mLines.count() < numLines ) height = mLineHeight * mLines.count();
00555   else height = mLineHeight * numLines;
00556 
00557   return QSize( 200, height );
00558 }
00559 
00560 Recipient::List RecipientsView::recipients() const
00561 {
00562   Recipient::List recipients;
00563 
00564   QPtrListIterator<RecipientLine> it( mLines );
00565   RecipientLine *line;
00566   while( ( line = it.current() ) ) {
00567     if ( !line->recipient().isEmpty() ) {
00568       recipients.append( line->recipient() );
00569     }
00570 
00571     ++it;
00572   }
00573 
00574   return recipients;
00575 }
00576 
00577 void RecipientsView::removeRecipient( const QString & recipient,
00578                                       Recipient::Type type )
00579 {
00580   // search a line which matches recipient and type
00581   QPtrListIterator<RecipientLine> it( mLines );
00582   RecipientLine *line;
00583   while( ( line = it.current() ) ) {
00584     if ( ( line->recipient().email() == recipient ) &&
00585          ( line->recipientType() == type ) ) {
00586       break;
00587     }
00588     ++it;
00589   }
00590   if ( line )
00591     line->clear();
00592 }
00593 
00594 bool RecipientsView::isModified()
00595 {
00596   if ( mModified )
00597     return true;
00598 
00599   QPtrListIterator<RecipientLine> it( mLines );
00600   RecipientLine *line;
00601   while( ( line = it.current() ) ) {
00602     if ( line->isModified() ) {
00603       return true;
00604     }
00605     ++it;
00606   }
00607 
00608   return false;
00609 }
00610 
00611 void RecipientsView::clearModified()
00612 {
00613   mModified = false;
00614 
00615   QPtrListIterator<RecipientLine> it( mLines );
00616   RecipientLine *line;
00617   while( ( line = it.current() ) ) {
00618     line->clearModified();
00619     ++it;
00620   }
00621 }
00622 
00623 void RecipientsView::setFocus()
00624 {
00625   if ( mLines.last()->isActive() ) setFocusBottom();
00626   else setFocusTop();
00627 }
00628 
00629 void RecipientsView::setFocusTop()
00630 {
00631   RecipientLine *line = mLines.first();
00632   if ( line ) line->activate();
00633   else kdWarning() << "No first" << endl;
00634 }
00635 
00636 void RecipientsView::setFocusBottom()
00637 {
00638   RecipientLine *line = mLines.last();
00639   if ( line ) line->activate();
00640   else  kdWarning() << "No last" << endl;
00641 }
00642 
00643 int RecipientsView::setFirstColumnWidth( int w )
00644 {
00645   mFirstColumnWidth = w;
00646 
00647   QPtrListIterator<RecipientLine> it( mLines );
00648   RecipientLine *line;
00649   while( ( line = it.current() ) ) {
00650     mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
00651     ++it;
00652   }
00653 
00654   resizeView();
00655   return mFirstColumnWidth;
00656 }
00657 
00658 RecipientsToolTip::RecipientsToolTip( RecipientsView *view, QWidget *parent )
00659   : QToolTip( parent ), mView( view )
00660 {
00661 }
00662 
00663 QString RecipientsToolTip::line( const Recipient &r )
00664 {
00665   QString txt = r.email();
00666 
00667   return "&nbsp;&nbsp;" + QStyleSheet::escape( txt ) + "<br/>";
00668 }
00669 
00670 void RecipientsToolTip::maybeTip( const QPoint & p )
00671 {
00672   QString text = "<qt>";
00673 
00674   QString to;
00675   QString cc;
00676   QString bcc;
00677 
00678   Recipient::List recipients = mView->recipients();
00679   Recipient::List::ConstIterator it;
00680   for( it = recipients.begin(); it != recipients.end(); ++it ) {
00681     switch( (*it).type() ) {
00682       case Recipient::To:
00683         to += line( *it );
00684         break;
00685       case Recipient::Cc:
00686         cc += line( *it );
00687         break;
00688       case Recipient::Bcc:
00689         bcc += line( *it );
00690         break;
00691       default:
00692         break;
00693     }
00694   }
00695 
00696   text += i18n("<b>To:</b><br/>") + to;
00697   if ( !cc.isEmpty() ) text += i18n("<b>CC:</b><br/>") + cc;
00698   if ( !bcc.isEmpty() ) text += i18n("<b>BCC:</b><br/>") + bcc;
00699 
00700   text.append( "</qt>" );
00701 
00702   QRect geometry( p + QPoint( 2, 2 ), QPoint( 400, 100 ) );
00703 
00704   tip( QRect( p.x() - 20, p.y() - 20, 40, 40 ), text, geometry );
00705 }
00706 
00707 
00708 SideWidget::SideWidget( RecipientsView *view, QWidget *parent )
00709   : QWidget( parent ), mView( view ), mRecipientPicker( 0 )
00710 {
00711   QBoxLayout *topLayout = new QVBoxLayout( this );
00712 
00713   topLayout->setSpacing( KDialog::spacingHint() );
00714   topLayout->addStretch( 1 );
00715 
00716   mTotalLabel = new QLabel( this );
00717   mTotalLabel->setAlignment( AlignCenter );
00718   topLayout->addWidget( mTotalLabel );
00719   mTotalLabel->hide();
00720 
00721   topLayout->addStretch( 1 );
00722 
00723   new RecipientsToolTip( view, mTotalLabel );
00724 
00725   mDistributionListButton = new QPushButton( i18n("Save List..."), this );
00726   topLayout->addWidget( mDistributionListButton );
00727   mDistributionListButton->hide();
00728   connect( mDistributionListButton, SIGNAL( clicked() ),
00729     SIGNAL( saveDistributionList() ) );
00730   QToolTip::add( mDistributionListButton,
00731     i18n("Save recipients as distribution list") );
00732 
00733   mSelectButton = new QPushButton( i18n("Se&lect..."), this );
00734   topLayout->addWidget( mSelectButton );
00735   connect( mSelectButton, SIGNAL( clicked() ), SLOT( pickRecipient() ) );
00736   QToolTip::add( mSelectButton, i18n("Select recipients from address book") );
00737 }
00738 
00739 SideWidget::~SideWidget()
00740 {
00741 }
00742 
00743 RecipientsPicker* SideWidget::picker() const
00744 {
00745   if ( !mRecipientPicker ) {
00746     // hacks to allow picker() to be const in the presence of lazy loading
00747     SideWidget *non_const_this = const_cast<SideWidget*>( this );
00748     mRecipientPicker = new RecipientsPicker( non_const_this );
00749     connect( mRecipientPicker, SIGNAL( pickedRecipient( const Recipient & ) ),
00750              non_const_this, SIGNAL( pickedRecipient( const Recipient & ) ) );
00751     mPickerPositioner = new KWindowPositioner( non_const_this, mRecipientPicker );
00752   }
00753   return mRecipientPicker;
00754 }
00755 
00756 void SideWidget::setFocus()
00757 {
00758   mSelectButton->setFocus();
00759 }
00760 
00761 void SideWidget::setTotal( int recipients, int lines )
00762 {
00763 #if 0
00764   kdDebug() << "SideWidget::setTotal() recipients: " << recipients <<
00765     "  lines: " << lines << endl;
00766 #endif
00767 
00768   QString labelText;
00769   if ( recipients == 0 ) labelText = i18n("No recipients");
00770   else labelText = i18n("1 recipient","%n recipients", recipients );
00771   mTotalLabel->setText( labelText );
00772 
00773   if ( lines > 3 ) mTotalLabel->show();
00774   else mTotalLabel->hide();
00775 
00776   if ( lines > 2 ) mDistributionListButton->show();
00777   else mDistributionListButton->hide();
00778 }
00779 
00780 void SideWidget::pickRecipient()
00781 {
00782 #if 0
00783   QString rec = KInputDialog::getText( "Pick Recipient",
00784     "Email address of recipient" );
00785   if ( !rec.isEmpty() ) emit pickedRecipient( rec );
00786 #else
00787   RecipientsPicker *p = picker();
00788   p->setDefaultType( mView->activeLine()->recipientType() );
00789   p->setRecipients( mView->recipients() );
00790   p->show();
00791   mPickerPositioner->reposition();
00792   p->raise();
00793 #endif
00794 }
00795 
00796 
00797 RecipientsEditor::RecipientsEditor( QWidget *parent )
00798   : QWidget( parent ), mModified( false )
00799 {
00800   QBoxLayout *topLayout = new QHBoxLayout( this );
00801   topLayout->setSpacing( KDialog::spacingHint() );
00802 
00803   mRecipientsView = new RecipientsView( this );
00804   topLayout->addWidget( mRecipientsView );
00805   connect( mRecipientsView, SIGNAL( focusUp() ), SIGNAL( focusUp() ) );
00806   connect( mRecipientsView, SIGNAL( focusDown() ), SIGNAL( focusDown() ) );
00807 
00808   mSideWidget = new SideWidget( mRecipientsView, this );
00809   topLayout->addWidget( mSideWidget );
00810   connect( mSideWidget, SIGNAL( pickedRecipient( const Recipient & ) ),
00811     SLOT( slotPickedRecipient( const Recipient & ) ) );
00812   connect( mSideWidget, SIGNAL( saveDistributionList() ),
00813     SLOT( saveDistributionList() ) );
00814 
00815   connect( mRecipientsView, SIGNAL( totalChanged( int, int ) ),
00816     mSideWidget, SLOT( setTotal( int, int ) ) );
00817   connect( mRecipientsView, SIGNAL( focusRight() ),
00818     mSideWidget, SLOT( setFocus() ) );
00819 }
00820 
00821 RecipientsEditor::~RecipientsEditor()
00822 {
00823 }
00824 
00825 RecipientsPicker* RecipientsEditor::picker() const
00826 {
00827   return mSideWidget->picker();
00828 }
00829 
00830 void RecipientsEditor::slotPickedRecipient( const Recipient &rec )
00831 {
00832   RecipientLine *line = mRecipientsView->activeLine();
00833   if ( !line->isEmpty() ) line = mRecipientsView->addLine();
00834 
00835   Recipient r = rec;
00836   if ( r.type() == Recipient::Undefined ) {
00837     r.setType( line->recipientType() );
00838   }
00839 
00840   line->setRecipient( r );
00841   mModified = true;
00842 }
00843 
00844 void RecipientsEditor::saveDistributionList()
00845 {
00846   DistributionListDialog *dlg = new DistributionListDialog( this );
00847   dlg->setRecipients( mRecipientsView->recipients() );
00848   dlg->show();
00849 }
00850 
00851 Recipient::List RecipientsEditor::recipients() const
00852 {
00853   return mRecipientsView->recipients();
00854 }
00855 
00856 void RecipientsEditor::setRecipientString( const QString &str,
00857   Recipient::Type type )
00858 {
00859   clear();
00860 
00861   int count = 1;
00862 
00863   QStringList r = KPIM::splitEmailAddrList( str );
00864   QStringList::ConstIterator it;
00865   for( it = r.begin(); it != r.end(); ++it ) {
00866     if ( count++ > GlobalSettings::self()->maximumRecipients() ) {
00867       KMessageBox::sorry( this,
00868         i18n("Truncating recipients list to %1 of %2 entries.")
00869         .arg( GlobalSettings::self()->maximumRecipients() )
00870         .arg( r.count() ) );
00871       break;
00872     }
00873     addRecipient( *it, type );
00874   }
00875 }
00876 
00877 QString RecipientsEditor::recipientString( Recipient::Type type )
00878 {
00879   QString str;
00880 
00881   Recipient::List recipients = mRecipientsView->recipients();
00882   Recipient::List::ConstIterator it;
00883   for( it = recipients.begin(); it != recipients.end(); ++it ) {
00884     if ( (*it).type() == type ) {
00885       if ( !str.isEmpty() ) str += ", ";
00886       str.append( (*it).email() );
00887     }
00888   }
00889 
00890   return str;
00891 }
00892 
00893 void RecipientsEditor::addRecipient( const QString & recipient,
00894                                      Recipient::Type type )
00895 {
00896   RecipientLine *line = mRecipientsView->emptyLine();
00897   if ( !line ) line = mRecipientsView->addLine();
00898   line->setRecipient( Recipient( recipient, type ) );
00899 }
00900 
00901 void RecipientsEditor::removeRecipient( const QString & recipient,
00902                                         Recipient::Type type )
00903 {
00904   mRecipientsView->removeRecipient( recipient, type );
00905 }
00906 
00907 bool RecipientsEditor::isModified()
00908 {
00909   return mModified || mRecipientsView->isModified();
00910 }
00911 
00912 void RecipientsEditor::clearModified()
00913 {
00914   mModified = false;
00915   mRecipientsView->clearModified();
00916 }
00917 
00918 void RecipientsEditor::clear()
00919 {
00920 }
00921 
00922 void RecipientsEditor::setFocus()
00923 {
00924   mRecipientsView->setFocus();
00925 }
00926 
00927 void RecipientsEditor::setFocusTop()
00928 {
00929   mRecipientsView->setFocusTop();
00930 }
00931 
00932 void RecipientsEditor::setFocusBottom()
00933 {
00934   mRecipientsView->setFocusBottom();
00935 }
00936 
00937 int RecipientsEditor::setFirstColumnWidth( int w )
00938 {
00939   return mRecipientsView->setFirstColumnWidth( w );
00940 }
00941 
00942 void RecipientsEditor::selectRecipients()
00943 {
00944   mSideWidget->pickRecipient();
00945 }
00946 
00947 #include "recipientseditor.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys