krop's commit fixes my problem in a better way, reverting
[kdepim.git] / kmail / recipientseditor.cpp
blob30cfe807e5c1464e8f9b910933168f7066a2f506
1 /*
2 This file is part of KMail.
4 Copyright (c) 2004 Cornelius Schumacher <schumacher@kde.org>
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 As a special exception, permission is given to link this program
21 with any edition of Qt, and distribute the resulting executable,
22 without including the source code for Qt in the source distribution.
26 #include "recipientseditor.h"
28 #include "recipientspicker.h"
29 #include "kwindowpositioner.h"
30 #include "distributionlistdialog.h"
31 #include "globalsettings.h"
32 #include "autoqpointer.h"
34 #include <kpimutils/email.h>
36 #include <KDebug>
37 #include <KLocale>
38 #include <KCompletionBox>
39 #include <KMessageBox>
41 #include <QKeyEvent>
42 #include <QLayout>
43 #include <QLabel>
44 #include <QPushButton>
45 #include <QResizeEvent>
46 #include <QScrollBar>
47 #include <QTimer>
49 Recipient::Recipient( const QString &email, Recipient::Type type )
50 : mEmail( email ), mType( type )
54 void Recipient::setType( Type type )
56 mType = type;
59 Recipient::Type Recipient::type() const
61 return mType;
64 void Recipient::setEmail( const QString &email )
66 mEmail = email;
69 QString Recipient::email() const
71 return mEmail;
74 bool Recipient::isEmpty() const
76 return mEmail.isEmpty();
79 int Recipient::typeToId( Recipient::Type type )
81 return static_cast<int>( type );
84 Recipient::Type Recipient::idToType( int id )
86 return static_cast<Type>( id );
89 QString Recipient::typeLabel() const
91 return typeLabel( mType );
94 QString Recipient::typeLabel( Recipient::Type type )
96 switch( type ) {
97 case To:
98 return i18nc("@label:listbox Recipient of an email message.", "To");
99 case Cc:
100 return i18nc("@label:listbox Carbon Copy recipient of an email message.", "CC");
101 case Bcc:
102 return i18nc("@label:listbox Blind carbon copy recipient of an email message.", "BCC");
103 case Undefined:
104 break;
107 return i18nc("@label:listbox", "<placeholder>Undefined Recipient Type</placeholder>");
110 QStringList Recipient::allTypeLabels()
112 QStringList types;
113 types.append( typeLabel( To ) );
114 types.append( typeLabel( Cc ) );
115 types.append( typeLabel( Bcc ) );
116 return types;
120 RecipientComboBox::RecipientComboBox( QWidget *parent )
121 : KComboBox( parent )
125 void RecipientComboBox::keyPressEvent( QKeyEvent *ev )
127 if ( ev->key() == Qt::Key_Right ) emit rightPressed();
128 else KComboBox::keyPressEvent( ev );
132 void RecipientLineEdit::keyPressEvent( QKeyEvent *ev )
134 if ( ev->key() == Qt::Key_Backspace && text().isEmpty() ) {
135 ev->accept();
136 emit deleteMe();
137 } else if ( ev->key() == Qt::Key_Left && cursorPosition() == 0 &&
138 !ev->modifiers().testFlag( Qt::ShiftModifier ) ) { // Shift would be pressed during selection
139 emit leftPressed();
140 } else if ( ev->key() == Qt::Key_Right && cursorPosition() == (int)text().length() &&
141 !ev->modifiers().testFlag( Qt::ShiftModifier ) ) { // Shift would be pressed during selection
142 emit rightPressed();
143 } else {
144 KMLineEdit::keyPressEvent( ev );
148 RecipientLine::RecipientLine( QWidget *parent )
149 : QWidget( parent ), mRecipientsCount( 0 ), mModified( false )
151 setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
153 QBoxLayout *topLayout = new QHBoxLayout( this );
154 topLayout->setSpacing( KDialog::spacingHint() );
155 topLayout->setMargin( 0 );
157 QStringList recipientTypes = Recipient::allTypeLabels();
159 mCombo = new RecipientComboBox( this );
160 mCombo->addItems( recipientTypes );
161 topLayout->addWidget( mCombo );
162 mCombo->setToolTip( i18nc("@label:listbox","Select type of recipient") );
164 mEdit = new RecipientLineEdit( this );
165 mEdit->setClearButtonShown( true );
166 topLayout->addWidget( mEdit );
167 connect( mEdit, SIGNAL( returnPressed() ), SLOT( slotReturnPressed() ) );
168 connect( mEdit, SIGNAL( deleteMe() ), SLOT( slotPropagateDeletion() ) );
169 connect( mEdit, SIGNAL( textChanged( const QString & ) ),
170 SLOT( analyzeLine( const QString & ) ) );
171 connect( mEdit, SIGNAL( focusUp() ), SLOT( slotFocusUp() ) );
172 connect( mEdit, SIGNAL( focusDown() ), SLOT( slotFocusDown() ) );
173 connect( mEdit, SIGNAL( rightPressed() ), SIGNAL( rightPressed() ) );
175 connect( mEdit, SIGNAL( leftPressed() ), mCombo, SLOT( setFocus() ) );
176 connect( mEdit, SIGNAL( editingFinished() ), SLOT( slotEditingFinished() ) );
177 connect( mEdit, SIGNAL( clearButtonClicked() ), SLOT( slotPropagateDeletion() ) );
178 connect( mCombo, SIGNAL( rightPressed() ), mEdit, SLOT( setFocus() ) );
180 connect( mCombo, SIGNAL( activated ( int ) ),
181 this, SLOT( slotTypeModified() ) );
184 void RecipientLine::slotFocusUp()
186 emit upPressed( this );
189 void RecipientLine::slotFocusDown()
191 emit downPressed( this );
194 void RecipientLine::slotTypeModified()
196 mModified = true;
198 emit typeModified( this );
201 void RecipientLine::analyzeLine( const QString &text )
203 QStringList r = KPIMUtils::splitAddressList( text );
204 if ( int( r.count() ) != mRecipientsCount ) {
205 mRecipientsCount = r.count();
206 emit countChanged();
210 int RecipientLine::recipientsCount() const
212 return mRecipientsCount;
215 void RecipientLine::setRecipient( const Recipient &rec )
217 mEdit->setText( rec.email() );
218 mCombo->setCurrentIndex( Recipient::typeToId( rec.type() ) );
221 void RecipientLine::setRecipient( const QString &email )
223 setRecipient( Recipient( email ) );
226 Recipient RecipientLine::recipient() const
228 return Recipient( mEdit->text(),
229 Recipient::idToType( mCombo->currentIndex() ) );
232 void RecipientLine::setRecipientType( Recipient::Type type )
234 mCombo->setCurrentIndex( Recipient::typeToId( type ) );
237 Recipient::Type RecipientLine::recipientType() const
239 return Recipient::idToType( mCombo->currentIndex() );
242 void RecipientLine::activate()
244 mEdit->setFocus();
247 bool RecipientLine::isActive() const
249 return mEdit->hasFocus();
252 bool RecipientLine::isEmpty() const
254 return mEdit->text().isEmpty();
257 bool RecipientLine::isModified()
259 return mModified || mEdit->isModified();
262 void RecipientLine::clearModified()
264 mModified = false;
265 mEdit->setModified( false );
268 void RecipientLine::slotReturnPressed()
270 emit returnPressed( this );
273 void RecipientLine::slotPropagateDeletion()
275 emit deleteLine( this );
278 void RecipientLine::slotEditingFinished()
280 if ( mEdit->text().isEmpty() ) {
281 emit deleteLine( this );
285 void RecipientLine::keyPressEvent( QKeyEvent *ev )
287 if ( ev->key() == Qt::Key_Up ) {
288 emit upPressed( this );
289 } else if ( ev->key() == Qt::Key_Down ) {
290 emit downPressed( this );
294 int RecipientLine::setComboWidth( int w )
296 w = qMax( w, mCombo->sizeHint().width() );
297 mCombo->setFixedWidth( w );
298 mCombo->updateGeometry();
299 parentWidget()->updateGeometry();
300 return w;
303 void RecipientLine::fixTabOrder( QWidget *previous )
305 setTabOrder( previous, mCombo );
306 setTabOrder( mCombo, mEdit );
309 QWidget *RecipientLine::tabOut() const
311 return mEdit;
314 void RecipientLine::clear()
316 mEdit->clear();
319 void RecipientLine::setEditFont( const QFont& font )
321 mEdit->setFont( font );
324 // ------------ RecipientsView ---------------------
326 RecipientsView::RecipientsView( QWidget *parent )
327 : QScrollArea( parent ), mCurDelLine( 0 ),
328 mLineHeight( 0 ), mFirstColumnWidth( 0 ),
329 mModified( false )
331 mCompletionMode = KGlobalSettings::completionMode();
333 setWidgetResizable( true );
334 setFrameStyle( QFrame::NoFrame );
336 mEditFont = KGlobalSettings::generalFont();
337 mPage = new QWidget;
339 mPage->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
340 setWidget( mPage );
342 mTopLayout = new QVBoxLayout;
343 mTopLayout->setMargin( 0 );
344 mTopLayout->setSpacing( 0 );
345 mPage->setLayout( mTopLayout );
347 addLine();
350 RecipientLine *RecipientsView::activeLine() const
352 return mLines.last();
355 RecipientLine *RecipientsView::emptyLine() const
357 RecipientLine *line;
358 foreach( line, mLines ) {
359 if ( line->isEmpty() )
360 return line;
363 return 0;
366 RecipientLine *RecipientsView::addLine()
368 RecipientLine *line = new RecipientLine( widget() );
369 line->setEditFont( mEditFont );
370 //addChild( line, 0, mLines.count() * mLineHeight );
371 mTopLayout->addWidget( line );
372 line->mEdit->setCompletionMode( mCompletionMode );
373 line->show();
374 connect( line, SIGNAL( returnPressed( RecipientLine * ) ),
375 SLOT( slotReturnPressed( RecipientLine * ) ) );
376 connect( line, SIGNAL( upPressed( RecipientLine * ) ),
377 SLOT( slotUpPressed( RecipientLine * ) ) );
378 connect( line, SIGNAL( downPressed( RecipientLine * ) ),
379 SLOT( slotDownPressed( RecipientLine * ) ) );
380 connect( line, SIGNAL( rightPressed() ), SIGNAL( focusRight() ) );
381 connect( line, SIGNAL( deleteLine( RecipientLine * ) ),
382 SLOT( slotDecideLineDeletion( RecipientLine * ) ) );
383 connect( line, SIGNAL( countChanged() ), SLOT( calculateTotal() ) );
384 connect( line, SIGNAL( typeModified( RecipientLine * ) ),
385 SLOT( slotTypeModified( RecipientLine * ) ) );
386 connect( line->mEdit, SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ),
387 SLOT( setCompletionMode( KGlobalSettings::Completion ) ) );
388 connect( line->mEdit, SIGNAL( textChanged ( const QString & ) ),
389 SLOT( calculateTotal() ) );
391 if ( !mLines.isEmpty() ) {
392 if ( mLines.count() == 1 ) {
393 if ( GlobalSettings::self()->secondRecipientTypeDefault() ==
394 GlobalSettings::EnumSecondRecipientTypeDefault::To ) {
395 line->setRecipientType( Recipient::To );
396 } else {
397 if ( mLines.last()->recipientType() == Recipient::Bcc ) {
398 line->setRecipientType( Recipient::To );
399 } else {
400 line->setRecipientType( Recipient::Cc );
403 } else {
404 line->setRecipientType( mLines.last()->recipientType() );
406 line->fixTabOrder( mLines.last()->tabOut() );
409 mLines.append( line );
411 mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
413 mLineHeight = line->minimumSizeHint().height();
415 line->resize( viewport()->width(), mLineHeight );
417 resizeView();
419 calculateTotal();
421 ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 );
423 QTimer::singleShot( 0, this, SLOT(moveScrollBarToEnd()) );
425 return line;
428 void RecipientsView::moveScrollBarToEnd()
430 // scroll to bottom
431 verticalScrollBar()->triggerAction( QAbstractSlider::SliderToMaximum );
434 void RecipientsView::slotTypeModified( RecipientLine *line )
436 if ( mLines.count() == 2 ||
437 ( mLines.count() == 3 && mLines.at( 2 )->isEmpty() ) ) {
438 if ( mLines.at( 1 ) == line ) {
439 if ( line->recipientType() == Recipient::To ) {
440 GlobalSettings::self()->setSecondRecipientTypeDefault(
441 GlobalSettings::EnumSecondRecipientTypeDefault::To );
442 } else if ( line->recipientType() == Recipient::Cc ) {
443 GlobalSettings::self()->setSecondRecipientTypeDefault(
444 GlobalSettings::EnumSecondRecipientTypeDefault::Cc );
449 //Update the total tooltip
450 calculateTotal();
453 void RecipientsView::calculateTotal()
455 int count = 0;
456 int empty = 0;
458 RecipientLine *line;
459 foreach( line, mLines ) {
460 if ( line->isEmpty() ) ++empty;
461 else count += line->recipientsCount();
464 if ( empty == 0 ) addLine();
466 emit totalChanged( count, mLines.count() );
469 void RecipientsView::slotReturnPressed( RecipientLine *line )
471 if ( !line->recipient().isEmpty() ) {
472 RecipientLine *empty = emptyLine();
473 if ( !empty ) empty = addLine();
474 activateLine( empty );
478 void RecipientsView::slotDownPressed( RecipientLine *line )
480 int pos = mLines.indexOf( line );
481 if ( pos >= (int)mLines.count() - 1 ) {
482 emit focusDown();
483 } else if ( pos >= 0 ) {
484 activateLine( mLines.at( pos + 1 ) );
488 void RecipientsView::slotUpPressed( RecipientLine *line )
490 int pos = mLines.indexOf( line );
491 if ( pos > 0 ) {
492 activateLine( mLines.at( pos - 1 ) );
493 } else {
494 emit focusUp();
498 void RecipientsView::slotDecideLineDeletion( RecipientLine *line )
500 if ( !line->isEmpty() )
501 mModified = true;
502 if ( mLines.count() == 1 ) {
503 line->clear();
504 } else if ( mLines.indexOf( line ) != mLines.count() - 1 ) {
505 mCurDelLine = line;
506 QTimer::singleShot( 0, this, SLOT( slotDeleteLine( ) ) );
510 void RecipientsView::slotDeleteLine()
512 if ( !mCurDelLine )
513 return;
515 RecipientLine *line = mCurDelLine;
516 int pos = mLines.indexOf( line );
518 if ( mCurDelLine->isActive() ) {
519 int newPos;
520 if ( pos == 0 ) newPos = pos + 1;
521 else newPos = pos - 1;
523 // if there is something left to activate, do so
524 if ( mLines.at( newPos ) )
525 mLines.at( newPos )->activate();
528 mLines.removeAll( line );
529 line->setParent( 0 );
530 delete line;
532 bool atLeastOneToLine = false;
533 int firstCC = -1;
534 for( int i = pos; i < mLines.count(); ++i ) {
535 RecipientLine *line = mLines.at( i );
536 if ( line->recipientType() == Recipient::To )
537 atLeastOneToLine = true;
538 else if ( ( line->recipientType() == Recipient::Cc ) && ( firstCC < 0 ) )
539 firstCC = i;
542 if ( !atLeastOneToLine && ( firstCC >= 0 ) )
543 mLines.at( firstCC )->setRecipientType( Recipient::To );
545 calculateTotal();
547 resizeView();
550 void RecipientsView::resizeView()
552 if ( mLines.count() < 6 ) {
553 setMinimumHeight( mLineHeight * mLines.count() );
554 } else {
555 setMinimumHeight( mLineHeight * 5 );
556 setMaximumHeight( mLineHeight * mLines.count() );
559 parentWidget()->layout()->activate();
560 emit sizeHintChanged();
561 QTimer::singleShot( 0, this, SLOT(moveCompletionPopup()) );
564 void RecipientsView::activateLine( RecipientLine *line )
566 line->activate();
567 ensureWidgetVisible( line );
570 void RecipientsView::resizeEvent ( QResizeEvent *ev )
572 QScrollArea::resizeEvent(ev);
573 for( int i = 0; i < mLines.count(); ++i ) {
574 mLines.at( i )->resize( ev->size().width(), mLineHeight );
576 ensureVisible( 0, mLines.count() * mLineHeight, 0, 0 );
579 QSize RecipientsView::sizeHint() const
581 return QSize( 200, mLineHeight * mLines.count() );
584 QSize RecipientsView::minimumSizeHint() const
586 int height;
587 int numLines = 5;
588 if ( mLines.count() < numLines ) height = mLineHeight * mLines.count();
589 else height = mLineHeight * numLines;
590 return QSize( 200, height );
593 Recipient::List RecipientsView::recipients() const
595 Recipient::List recipients;
597 QListIterator<RecipientLine*> it( mLines );
598 RecipientLine *line;
599 while( it.hasNext()) {
600 line = it.next();
601 if ( !line->recipient().isEmpty() ) {
602 recipients.append( line->recipient() );
606 return recipients;
609 void RecipientsView::setCompletionMode ( KGlobalSettings::Completion mode )
611 if ( mCompletionMode == mode )
612 return;
613 mCompletionMode = mode;
615 QListIterator<RecipientLine*> it( mLines );
616 while( it.hasNext() ) {
617 RecipientLine *line = it.next();
618 line->mEdit->blockSignals( true );
619 line->mEdit->setCompletionMode( mode );
620 line->mEdit->blockSignals( false );
622 emit completionModeChanged( mode ); //report change to RecipientsEditor
625 void RecipientsView::removeRecipient( const QString & recipient,
626 Recipient::Type type )
628 // search a line which matches recipient and type
629 QListIterator<RecipientLine*> it( mLines );
630 RecipientLine *line = 0;
631 while (it.hasNext()) {
632 line = it.next();
633 if ( ( line->recipient().email() == recipient ) &&
634 ( line->recipientType() == type ) ) {
635 break;
638 if ( line )
639 line->slotPropagateDeletion();
642 bool RecipientsView::isModified()
644 if ( mModified )
645 return true;
647 QListIterator<RecipientLine*> it( mLines );
648 RecipientLine *line;
649 while( it.hasNext()) {
650 line = it.next();
651 if ( line->isModified() ) {
652 return true;
656 return false;
659 void RecipientsView::clearModified()
661 mModified = false;
663 QListIterator<RecipientLine*> it( mLines );
664 RecipientLine *line;
665 while( it.hasNext() ) {
666 line = it.next();
667 line->clearModified();
671 void RecipientsView::setFocus()
673 if ( !mLines.empty() && mLines.last()->isActive() )
674 setFocusBottom();
675 else
676 setFocusTop();
679 void RecipientsView::setFocusTop()
681 if ( !mLines.empty() ) {
682 RecipientLine *line = mLines.first();
683 if ( line ) line->activate();
684 else kWarning() <<"No first";
686 else kWarning() <<"No first";
689 void RecipientsView::setFocusBottom()
691 RecipientLine *line = mLines.last();
692 if ( line ) {
693 ensureWidgetVisible( line );
694 line->activate();
696 else kWarning() <<"No last";
699 int RecipientsView::setFirstColumnWidth( int w )
701 mFirstColumnWidth = w;
703 QListIterator<RecipientLine*> it( mLines );
704 RecipientLine *line;
705 while(it.hasNext()) {
706 line = it.next();
707 mFirstColumnWidth = line->setComboWidth( mFirstColumnWidth );
710 resizeView();
711 return mFirstColumnWidth;
714 void RecipientsView::setEditFont( const QFont& font )
716 mEditFont = font;
717 foreach ( RecipientLine *line, mLines ) {
718 line->setEditFont( mEditFont );
722 void RecipientsView::moveCompletionPopup()
724 foreach ( RecipientLine *const line, mLines ) {
725 if ( line->lineEdit()->completionBox( false ) ) {
726 if ( line->lineEdit()->completionBox()->isVisible() ) {
727 // ### trigger moving, is there a nicer way to do that?
728 line->lineEdit()->completionBox()->hide();
729 line->lineEdit()->completionBox()->show();
736 SideWidget::SideWidget( RecipientsView *view, QWidget *parent )
737 : QWidget( parent ), mView( view ), mRecipientPicker( 0 )
739 QBoxLayout *topLayout = new QVBoxLayout( this );
741 topLayout->setSpacing( KDialog::spacingHint() );
742 topLayout->setMargin( 0 );
743 topLayout->addStretch( 1 );
745 mTotalLabel = new QLabel( this );
746 mTotalLabel->setAlignment( Qt::AlignCenter );
747 topLayout->addWidget( mTotalLabel );
748 mTotalLabel->hide();
750 topLayout->addStretch( 1 );
752 mDistributionListButton = new QPushButton(
753 i18nc("@action:button","Save List..."), this );
754 topLayout->addWidget( mDistributionListButton );
755 mDistributionListButton->hide();
756 connect( mDistributionListButton, SIGNAL( clicked() ),
757 SIGNAL( saveDistributionList() ) );
758 mDistributionListButton->setToolTip(
759 i18nc( "@info:tooltip", "Save recipients as distribution list") );
761 mSelectButton = new QPushButton(
762 i18nc( "@action:button Open recipient selection dialog.", "Se&lect..."), this );
763 topLayout->addWidget( mSelectButton );
764 connect( mSelectButton, SIGNAL( clicked() ), SLOT( pickRecipient() ) );
765 mSelectButton->setToolTip( i18nc("@info:tooltip","Select recipients from address book") );
766 updateTotalToolTip();
769 SideWidget::~SideWidget()
773 RecipientsPicker* SideWidget::picker() const
775 if ( !mRecipientPicker ) {
776 // hacks to allow picker() to be const in the presence of lazy loading
777 SideWidget *non_const_this = const_cast<SideWidget*>( this );
778 mRecipientPicker = new RecipientsPicker( non_const_this );
779 connect( mRecipientPicker, SIGNAL( pickedRecipient( const Recipient & ) ),
780 non_const_this, SIGNAL( pickedRecipient( const Recipient & ) ) );
781 mPickerPositioner = new KWindowPositioner( mSelectButton, mRecipientPicker );
783 return mRecipientPicker;
786 void SideWidget::setFocus()
788 mSelectButton->setFocus();
791 void SideWidget::setTotal( int recipients, int lines )
793 QString labelText;
794 if ( recipients == 0 ) labelText = i18nc("@info:status No recipients selected"
795 , "No recipients");
796 else labelText = i18ncp("@info:status Number of recipients selected"
797 , "1 recipient","%1 recipients", recipients );
798 mTotalLabel->setText( labelText );
800 if ( lines > 3 ) mTotalLabel->show();
801 else mTotalLabel->hide();
803 if ( lines > 2 ) mDistributionListButton->show();
804 else mDistributionListButton->hide();
806 updateTotalToolTip();
809 void SideWidget::updateTotalToolTip()
811 QString text = "<qt>";
813 QString to;
814 QString cc;
815 QString bcc;
817 Recipient::List recipients = mView->recipients();
818 Recipient::List::ConstIterator it;
819 for( it = recipients.constBegin(); it != recipients.constEnd(); ++it ) {
820 QString emailLine = "&nbsp;&nbsp;" + Qt::escape( (*it).email() ) + "<br/>";
821 switch( (*it).type() ) {
822 case Recipient::To:
823 to += emailLine;
824 break;
825 case Recipient::Cc:
826 cc += emailLine;
827 break;
828 case Recipient::Bcc:
829 bcc += emailLine;
830 break;
831 default:
832 break;
836 text += i18nc("@info:tooltip %1 list of emails", "<interface>To:</interface><nl/>%1", to);
837 if ( !cc.isEmpty() ) {
838 text += i18nc("@info:tooltip %1 list of emails", "<interface>CC:</interface><nl/>%1", cc);
840 if ( !bcc.isEmpty() ) {
841 text += i18nc("@info:tooltip %1 list of emails", "<interface>BCC:</interface><nl/>%1", bcc);
844 text.append( "</qt>" );
845 mTotalLabel->setToolTip( text );
848 void SideWidget::pickRecipient()
850 RecipientsPicker *p = picker();
851 p->setDefaultType( mView->activeLine()->recipientType() );
852 p->setRecipients( mView->recipients() );
853 mPickerPositioner->reposition();
854 p->show();
858 RecipientsEditor::RecipientsEditor( QWidget *parent )
859 : QWidget( parent ), mModified( false )
861 QBoxLayout *topLayout = new QHBoxLayout();
862 topLayout->setSpacing( KDialog::spacingHint() );
863 topLayout->setMargin( 0 );
864 setLayout( topLayout );
866 mRecipientsView = new RecipientsView( this );
867 topLayout->addWidget( mRecipientsView );
868 connect( mRecipientsView, SIGNAL( focusUp() ), SIGNAL( focusUp() ) );
869 connect( mRecipientsView, SIGNAL( focusDown() ), SIGNAL( focusDown() ) );
870 connect( mRecipientsView, SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ),
871 SIGNAL( completionModeChanged( KGlobalSettings::Completion ) ) );
873 mSideWidget = new SideWidget( mRecipientsView, this );
874 topLayout->addWidget( mSideWidget );
875 connect( mSideWidget, SIGNAL( pickedRecipient( const Recipient & ) ),
876 SLOT( slotPickedRecipient( const Recipient & ) ) );
877 connect( mSideWidget, SIGNAL( saveDistributionList() ),
878 SLOT( saveDistributionList() ) );
880 connect( mRecipientsView, SIGNAL( totalChanged( int, int ) ),
881 mSideWidget, SLOT( setTotal( int, int ) ) );
882 connect( mRecipientsView, SIGNAL( focusRight() ),
883 mSideWidget, SLOT( setFocus() ) );
885 connect( mRecipientsView, SIGNAL(sizeHintChanged()),
886 SIGNAL(sizeHintChanged()) );
889 RecipientsEditor::~RecipientsEditor()
893 RecipientsPicker* RecipientsEditor::picker() const
895 return mSideWidget->picker();
898 void RecipientsEditor::slotPickedRecipient( const Recipient &rec )
900 RecipientLine *line = mRecipientsView->activeLine();
901 if ( !line->isEmpty() ) line = mRecipientsView->addLine();
903 Recipient r = rec;
904 if ( r.type() == Recipient::Undefined ) {
905 r.setType( line->recipientType() );
908 line->setRecipient( r );
909 mModified = true;
912 void RecipientsEditor::saveDistributionList()
914 AutoQPointer<DistributionListDialog> dlg( new DistributionListDialog( this ) );
915 dlg->setRecipients( mRecipientsView->recipients() );
916 dlg->exec();
919 Recipient::List RecipientsEditor::recipients() const
921 return mRecipientsView->recipients();
924 void RecipientsEditor::setRecipientString( const QString &str,
925 Recipient::Type type )
927 clear();
929 int count = 1;
931 QStringList r = KPIMUtils::splitAddressList( str );
932 QStringList::ConstIterator it;
933 for( it = r.constBegin(); it != r.constEnd(); ++it ) {
934 if ( count++ > GlobalSettings::self()->maximumRecipients() ) {
935 KMessageBox::sorry( this,
936 i18nc("@info:status", "Truncating recipients list to %1 of %2 entries.",
937 GlobalSettings::self()->maximumRecipients(),
938 r.count() ) );
939 break;
941 addRecipient( *it, type );
945 QString RecipientsEditor::recipientString( Recipient::Type type )
947 QString str;
949 Recipient::List recipients = mRecipientsView->recipients();
950 if ( !recipients.isEmpty() ) {
951 Recipient::List::ConstIterator it;
952 for( it = recipients.constBegin(); it != recipients.constEnd(); ++it ) {
953 if ( (*it).type() == type ) {
954 if ( !str.isEmpty() ) str += ", ";
955 str.append( (*it).email() );
959 return str;
962 void RecipientsEditor::addRecipient( const QString & recipient,
963 Recipient::Type type )
965 RecipientLine *line = mRecipientsView->emptyLine();
966 if ( !line ) line = mRecipientsView->addLine();
967 line->setRecipient( Recipient( recipient, type ) );
970 void RecipientsEditor::removeRecipient( const QString & recipient,
971 Recipient::Type type )
973 mRecipientsView->removeRecipient( recipient, type );
976 bool RecipientsEditor::isModified()
978 return mModified || mRecipientsView->isModified();
981 void RecipientsEditor::clearModified()
983 mModified = false;
984 mRecipientsView->clearModified();
987 void RecipientsEditor::clear()
991 void RecipientsEditor::setFocus()
993 mRecipientsView->setFocus();
996 void RecipientsEditor::setFocusTop()
998 mRecipientsView->setFocusTop();
1001 void RecipientsEditor::setFocusBottom()
1003 mRecipientsView->setFocusBottom();
1006 int RecipientsEditor::setFirstColumnWidth( int w )
1008 return mRecipientsView->setFirstColumnWidth( w );
1011 void RecipientsEditor::selectRecipients()
1013 mSideWidget->pickRecipient();
1016 void RecipientsEditor::setCompletionMode( KGlobalSettings::Completion mode )
1018 mRecipientsView->setCompletionMode( mode );
1021 void RecipientsEditor::setEditFont( const QFont& font )
1023 mRecipientsView->setEditFont( font );
1026 #include "recipientseditor.moc"