00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "addresseditwidget.h"
00023
00024 #include "autoqpointer_p.h"
00025
00026 #include <QtCore/QEvent>
00027 #include <QtCore/QList>
00028 #include <QtGui/QApplication>
00029 #include <QtGui/QBoxLayout>
00030 #include <QtGui/QButtonGroup>
00031 #include <QtGui/QCheckBox>
00032 #include <QtGui/QFrame>
00033 #include <QtGui/QGridLayout>
00034 #include <QtGui/QGroupBox>
00035 #include <QtGui/QKeyEvent>
00036 #include <QtGui/QLabel>
00037 #include <QtGui/QPushButton>
00038
00039 #include <kacceleratormanager.h>
00040 #include <kcombobox.h>
00041 #include <kdebug.h>
00042 #include <khbox.h>
00043 #include <kinputdialog.h>
00044 #include <klineedit.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047 #include <kseparator.h>
00048 #include <ktextedit.h>
00049
00050 class TabPressEater : public QObject
00051 {
00052 public:
00053 TabPressEater( QObject *parent )
00054 : QObject( parent )
00055 {
00056 setObjectName( QLatin1String( "TabPressEater" ) );
00057 }
00058
00059 protected:
00060 bool eventFilter( QObject*, QEvent *event )
00061 {
00062 if ( event->type() == QEvent::KeyPress ) {
00063 QKeyEvent *keyEvent = (QKeyEvent*)event;
00064 if ( keyEvent->key() == Qt::Key_Tab ) {
00065 QApplication::sendEvent( parent(), event );
00066 return true;
00067 } else
00068 return false;
00069 } else {
00070 return false;
00071 }
00072 }
00073 };
00074
00080 class AddressTypeDialog : public KDialog
00081 {
00082 public:
00083 AddressTypeDialog( KABC::Address::Type type, QWidget *parent );
00084 ~AddressTypeDialog();
00085
00086 KABC::Address::Type type() const;
00087
00088 private:
00089 QButtonGroup *mGroup;
00090
00091 KABC::Address::TypeList mTypeList;
00092 };
00093
00094
00095 AddressSelectionWidget::AddressSelectionWidget( QWidget *parent )
00096 : KComboBox( parent )
00097 {
00098 connect( this, SIGNAL( activated( int ) ), SLOT( selected( int ) ) );
00099 }
00100
00101 AddressSelectionWidget::~AddressSelectionWidget()
00102 {
00103 }
00104
00105 void AddressSelectionWidget::setAddresses( const KABC::Address::List &addresses )
00106 {
00107 mAddresses = addresses;
00108 updateView();
00109 }
00110
00111 void AddressSelectionWidget::setCurrentAddress( const KABC::Address &address )
00112 {
00113 const int index = mAddresses.indexOf( address );
00114 if ( index != -1 )
00115 setCurrentIndex( index );
00116 }
00117
00118 KABC::Address AddressSelectionWidget::currentAddress() const
00119 {
00120 if ( currentIndex() != -1 && currentIndex() < mAddresses.count() )
00121 return mAddresses.at( currentIndex() );
00122 else
00123 return KABC::Address();
00124 }
00125
00126 void AddressSelectionWidget::selected( int index )
00127 {
00128 Q_ASSERT( index != -1 && index < mAddresses.count() );
00129 emit selectionChanged( mAddresses.at( index ) );
00130 }
00131
00132 void AddressSelectionWidget::updateView()
00133 {
00134 clear();
00135 for ( int i = 0; i < mAddresses.count(); ++i )
00136 addItem( KABC::Address::typeLabel( mAddresses.at( i ).type() ) );
00137 }
00138
00139
00140
00141 AddressTypeCombo::AddressTypeCombo( QWidget *parent )
00142 : KComboBox( parent ),
00143 mType( KABC::Address::Home ),
00144 mLastSelected( 0 )
00145 {
00146 for ( int i = 0; i < KABC::Address::typeList().count(); ++i )
00147 mTypeList.append( KABC::Address::typeList().at( i ) );
00148 mTypeList.append( -1 );
00149
00150 update();
00151
00152 connect( this, SIGNAL( activated( int ) ),
00153 this, SLOT( selected( int ) ) );
00154 }
00155
00156 AddressTypeCombo::~AddressTypeCombo()
00157 {
00158 }
00159
00160 void AddressTypeCombo::setType( KABC::Address::Type type )
00161 {
00162 if ( !mTypeList.contains( (int)type ) ) {
00163
00164 mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), (int)type );
00165 }
00166
00167 mType = type;
00168 update();
00169 }
00170
00171 KABC::Address::Type AddressTypeCombo::type() const
00172 {
00173 return mType;
00174 }
00175
00176 void AddressTypeCombo::update()
00177 {
00178 bool blocked = signalsBlocked();
00179 blockSignals( true );
00180
00181 clear();
00182 for ( int i = 0; i < mTypeList.count(); ++i ) {
00183 if ( mTypeList.at( i ) == -1 )
00184 addItem( i18nc( "@item:inlistbox Category of contact info field", "Other..." ) );
00185 else
00186 addItem( KABC::Address::typeLabel( KABC::Address::Type( mTypeList.at( i ) ) ) );
00187 }
00188
00189 setCurrentIndex( mLastSelected = mTypeList.indexOf( mType ) );
00190
00191 blockSignals( blocked );
00192 }
00193
00194 void AddressTypeCombo::selected( int pos )
00195 {
00196 if ( mTypeList.at( pos ) == -1 )
00197 otherSelected();
00198 else {
00199 mType = KABC::Address::Type( mTypeList.at( pos ) );
00200 mLastSelected = pos;
00201 }
00202 }
00203
00204 void AddressTypeCombo::otherSelected()
00205 {
00206 AutoQPointer<AddressTypeDialog> dlg = new AddressTypeDialog( mType, this );
00207 if ( dlg->exec() ) {
00208 mType = dlg->type();
00209 if ( !mTypeList.contains( mType ) )
00210 mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), mType );
00211 } else {
00212 setType( KABC::Address::Type( mTypeList.at( mLastSelected ) ) );
00213 }
00214
00215 update();
00216 }
00217
00218
00219 AddressEditWidget::AddressEditWidget( QWidget *parent )
00220 : QWidget( parent ), mReadOnly( false )
00221 {
00222 QGridLayout *layout = new QGridLayout( this );
00223 layout->setSpacing( KDialog::spacingHint() );
00224 layout->setMargin( 0 );
00225
00226 mAddressSelectionWidget = new AddressSelectionWidget( this );
00227 connect( mAddressSelectionWidget, SIGNAL( selectionChanged( const KABC::Address& ) ),
00228 SLOT( updateAddressView() ) );
00229 layout->addWidget( mAddressSelectionWidget, 0, 0, 1, 3 );
00230
00231 mAddressView = new QLabel( this );
00232 mAddressView->setFrameStyle( QFrame::Panel | QFrame::Sunken );
00233 mAddressView->setMinimumHeight( 20 );
00234 mAddressView->setAlignment( Qt::AlignTop );
00235 mAddressView->setTextFormat( Qt::PlainText );
00236 mAddressView->setTextInteractionFlags( Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse );
00237 layout->addWidget( mAddressView, 1, 0, 1, 3 );
00238
00239 mCreateButton = new QPushButton( i18nc( "street/postal", "New..." ), this );
00240 connect( mCreateButton, SIGNAL( clicked() ), this, SLOT( createAddress() ) );
00241 mEditButton = new QPushButton( i18nc( "street/postal", "Edit..." ), this );
00242 connect( mEditButton, SIGNAL( clicked() ), this, SLOT( editAddress() ) );
00243 mDeleteButton = new QPushButton( i18nc( "street/postal", "Delete" ), this );
00244 connect( mDeleteButton, SIGNAL( clicked() ), this, SLOT( deleteAddress() ) );
00245
00246 layout->addWidget( mCreateButton, 2, 0 );
00247 layout->addWidget( mEditButton, 2, 1 );
00248 layout->addWidget( mDeleteButton, 2, 2 );
00249
00250 updateButtons();
00251 }
00252
00253 AddressEditWidget::~AddressEditWidget()
00254 {
00255 }
00256
00257 void AddressEditWidget::setReadOnly( bool readOnly )
00258 {
00259 mReadOnly = readOnly;
00260 updateButtons();
00261 }
00262
00263 void AddressEditWidget::updateName( const QString &name )
00264 {
00265 mName = name;
00266 updateAddressView();
00267 }
00268
00269 void AddressEditWidget::createAddress()
00270 {
00271 AutoQPointer<AddressEditDialog> dialog = new AddressEditDialog( this );
00272 if ( dialog->exec() ) {
00273 const KABC::Address address = dialog->address();
00274 fixPreferredAddress( address );
00275 mAddressList.append( address );
00276 mAddressSelectionWidget->setAddresses( mAddressList );
00277 mAddressSelectionWidget->setCurrentAddress( address );
00278
00279 updateAddressView();
00280 updateButtons();
00281 }
00282 }
00283
00284 void AddressEditWidget::editAddress()
00285 {
00286 AutoQPointer<AddressEditDialog> dialog = new AddressEditDialog( this );
00287 dialog->setAddress( mAddressSelectionWidget->currentAddress() );
00288 if ( dialog->exec() ) {
00289 const KABC::Address address = dialog->address();
00290 fixPreferredAddress( address );
00291 mAddressList[ mAddressSelectionWidget->currentIndex() ] = address;
00292 mAddressSelectionWidget->setAddresses( mAddressList );
00293 mAddressSelectionWidget->setCurrentAddress( address );
00294
00295 updateAddressView();
00296 }
00297 }
00298
00299 void AddressEditWidget::deleteAddress()
00300 {
00301 const int result = KMessageBox::questionYesNo( this, i18n( "Do you really want to delete this address?" ) );
00302
00303 if ( result != KMessageBox::Yes )
00304 return;
00305
00306 mAddressList.removeAt( mAddressSelectionWidget->currentIndex() );
00307 mAddressSelectionWidget->setAddresses( mAddressList );
00308 updateAddressView();
00309 updateButtons();
00310 }
00311
00312 void AddressEditWidget::fixPreferredAddress( const KABC::Address &preferredAddress )
00313 {
00314
00315
00316 if ( preferredAddress.type() & KABC::Address::Pref ) {
00317 for ( int i = 0; i < mAddressList.count(); ++i ) {
00318 KABC::Address &address = mAddressList[ i ];
00319 address.setType( address.type() & ~KABC::Address::Pref );
00320 }
00321 }
00322 }
00323
00324 void AddressEditWidget::updateAddressView()
00325 {
00326 const KABC::Address address = mAddressSelectionWidget->currentAddress();
00327
00328 if ( address.isEmpty() )
00329 mAddressView->setText( QString() );
00330 else
00331 mAddressView->setText( address.formattedAddress( mName ) );
00332 }
00333
00334 void AddressEditWidget::updateButtons()
00335 {
00336 mCreateButton->setEnabled( !mReadOnly );
00337 mEditButton->setEnabled( !mReadOnly && (mAddressList.count() > 0) );
00338 mDeleteButton->setEnabled( !mReadOnly && (mAddressList.count() > 0) );
00339 }
00340
00341 void AddressEditWidget::loadContact( const KABC::Addressee &contact )
00342 {
00343 mName = contact.realName();
00344 mAddressList = contact.addresses();
00345
00346 mAddressSelectionWidget->setAddresses( mAddressList );
00347
00348
00349 for ( int i = 0; i < mAddressList.count(); ++i ) {
00350 if ( mAddressList.at( i ).type() & KABC::Address::Pref ) {
00351 mAddressSelectionWidget->setCurrentAddress( mAddressList.at( i ) );
00352 break;
00353 }
00354 }
00355
00356 updateAddressView();
00357 updateButtons();
00358 }
00359
00360 void AddressEditWidget::storeContact( KABC::Addressee &contact ) const
00361 {
00362
00363 const KABC::Address::List oldAddresses = contact.addresses();
00364 for ( int i = 0; i < oldAddresses.count(); ++i )
00365 contact.removeAddress( oldAddresses.at( i ) );
00366
00367
00368 for ( int i = 0; i < mAddressList.count(); ++i ) {
00369 const KABC::Address address( mAddressList.at( i ) );
00370 if ( !address.isEmpty() )
00371 contact.insertAddress( address );
00372 }
00373 }
00374
00375
00376 AddressEditDialog::AddressEditDialog( QWidget *parent )
00377 : KDialog(parent)
00378 {
00379 setCaption( i18nc( "street/postal", "Edit Address" ) );
00380 setButtons( Ok | Cancel );
00381 setDefaultButton( Ok );
00382 showButtonSeparator( true );
00383
00384 QWidget *page = new QWidget( this );
00385 setMainWidget( page );
00386
00387 QGridLayout *topLayout = new QGridLayout( page );
00388 topLayout->setSpacing( spacingHint() );
00389 topLayout->setMargin( 0 );
00390
00391 mTypeCombo = new AddressTypeCombo( page );
00392 topLayout->addWidget( mTypeCombo, 0, 0, 1, 2 );
00393
00394 QLabel *label = new QLabel( i18nc( "<streetLabel>:", "%1:", KABC::Address::streetLabel() ), page );
00395 label->setAlignment( Qt::AlignTop | Qt::AlignLeft );
00396 topLayout->addWidget( label, 1, 0 );
00397 mStreetTextEdit = new KTextEdit( page );
00398 mStreetTextEdit->setAcceptRichText( false );
00399 label->setBuddy( mStreetTextEdit );
00400 topLayout->addWidget( mStreetTextEdit, 1, 1 );
00401
00402 TabPressEater *eater = new TabPressEater( this );
00403 mStreetTextEdit->installEventFilter( eater );
00404
00405 label = new QLabel( i18nc( "<postOfficeBoxLabel>:", "%1:", KABC::Address::postOfficeBoxLabel() ), page );
00406 topLayout->addWidget( label, 2 , 0 );
00407 mPOBoxEdit = new KLineEdit( page );
00408 label->setBuddy( mPOBoxEdit );
00409 topLayout->addWidget( mPOBoxEdit, 2, 1 );
00410
00411 label = new QLabel( i18nc( "<localityLabel>:", "%1:", KABC::Address::localityLabel() ), page );
00412 topLayout->addWidget( label, 3, 0 );
00413 mLocalityEdit = new KLineEdit( page );
00414 label->setBuddy( mLocalityEdit );
00415 topLayout->addWidget( mLocalityEdit, 3, 1 );
00416
00417 label = new QLabel( i18nc( "<regionLabel>:", "%1:", KABC::Address::regionLabel() ), page );
00418 topLayout->addWidget( label, 4, 0 );
00419 mRegionEdit = new KLineEdit( page );
00420 label->setBuddy( mRegionEdit );
00421 topLayout->addWidget( mRegionEdit, 4, 1 );
00422
00423 label = new QLabel( i18nc( "<postalCodeLabel>:", "%1:", KABC::Address::postalCodeLabel() ), page );
00424 topLayout->addWidget( label, 5, 0 );
00425 mPostalCodeEdit = new KLineEdit( page );
00426 label->setBuddy( mPostalCodeEdit );
00427 topLayout->addWidget( mPostalCodeEdit, 5, 1 );
00428
00429 label = new QLabel( i18nc( "<countryLabel>:", "%1:", KABC::Address::countryLabel() ), page );
00430 topLayout->addWidget( label, 6, 0 );
00431 mCountryCombo = new KComboBox( page );
00432 mCountryCombo->setEditable( true );
00433 mCountryCombo->setDuplicatesEnabled( false );
00434
00435 QPushButton *labelButton = new QPushButton( i18n( "Edit Label..." ), page );
00436 topLayout->addWidget( labelButton, 7, 0, 1, 2 );
00437 connect( labelButton, SIGNAL( clicked() ), SLOT( editLabel() ) );
00438
00439 fillCountryCombo();
00440 label->setBuddy( mCountryCombo );
00441 topLayout->addWidget( mCountryCombo, 6, 1 );
00442
00443 mPreferredCheckBox = new QCheckBox( i18nc( "street/postal", "This is the preferred address" ), page );
00444 topLayout->addWidget( mPreferredCheckBox, 8, 0, 1, 2 );
00445
00446 KSeparator *sep = new KSeparator( Qt::Horizontal, page );
00447 topLayout->addWidget( sep, 9, 0, 1, 2 );
00448
00449 KHBox *buttonBox = new KHBox( page );
00450 buttonBox->setSpacing( spacingHint() );
00451 topLayout->addWidget( buttonBox, 10, 0, 1, 2 );
00452
00453 KAcceleratorManager::manage( this );
00454 }
00455
00456 AddressEditDialog::~AddressEditDialog()
00457 {
00458 }
00459
00460 void AddressEditDialog::editLabel()
00461 {
00462 bool ok = false;
00463 QString result = KInputDialog::getMultiLineText( KABC::Address::labelLabel(),
00464 KABC::Address::labelLabel(),
00465 mLabel, &ok, this );
00466 if ( ok )
00467 mLabel = result;
00468 }
00469
00470 void AddressEditDialog::setAddress( const KABC::Address &address )
00471 {
00472 mAddress = address;
00473
00474 mTypeCombo->setType( mAddress.type() );
00475 mStreetTextEdit->setPlainText( mAddress.street() );
00476 mRegionEdit->setText( mAddress.region() );
00477 mLocalityEdit->setText( mAddress.locality() );
00478 mPostalCodeEdit->setText( mAddress.postalCode() );
00479 mPOBoxEdit->setText( mAddress.postOfficeBox() );
00480 mLabel = mAddress.label();
00481 mPreferredCheckBox->setChecked( mAddress.type() & KABC::Address::Pref );
00482
00483 if ( mAddress.isEmpty() )
00484 mCountryCombo->setItemText( mCountryCombo->currentIndex(),
00485 KGlobal::locale()->countryCodeToName( KGlobal::locale()->country() ) );
00486 else
00487 mCountryCombo->setItemText( mCountryCombo->currentIndex(), mAddress.country() );
00488
00489 mStreetTextEdit->setFocus();
00490 }
00491
00492 KABC::Address AddressEditDialog::address() const
00493 {
00494 KABC::Address address( mAddress );
00495
00496 address.setType( mTypeCombo->type() );
00497 address.setLocality( mLocalityEdit->text() );
00498 address.setRegion( mRegionEdit->text() );
00499 address.setPostalCode( mPostalCodeEdit->text() );
00500 address.setCountry( mCountryCombo->currentText() );
00501 address.setPostOfficeBox( mPOBoxEdit->text() );
00502 address.setStreet( mStreetTextEdit->toPlainText() );
00503 address.setLabel( mLabel );
00504
00505 if ( mPreferredCheckBox->isChecked() ) {
00506 address.setType( address.type() | KABC::Address::Pref );
00507 } else
00508 address.setType( address.type() & ~(KABC::Address::Pref) );
00509
00510 return address;
00511 }
00512
00513 void AddressEditDialog::fillCountryCombo()
00514 {
00515 QStringList countries;
00516
00517 foreach ( const QString &cc, KGlobal::locale()->allCountriesList() )
00518 countries.append( KGlobal::locale()->countryCodeToName( cc ) );
00519
00520 countries = sortLocaleAware( countries );
00521
00522 mCountryCombo->addItems( countries );
00523 mCountryCombo->setAutoCompletion( true );
00524 mCountryCombo->completionObject()->setItems( countries );
00525 mCountryCombo->completionObject()->setIgnoreCase( true );
00526
00527 const QString currentCountry = KGlobal::locale()->countryCodeToName( KGlobal::locale()->country() );
00528 mCountryCombo->setCurrentIndex( mCountryCombo->findText( currentCountry ) );
00529 }
00530
00531
00532 AddressTypeDialog::AddressTypeDialog( KABC::Address::Type type, QWidget *parent )
00533 : KDialog( parent)
00534 {
00535 setCaption( i18nc( "street/postal", "Edit Address Type" ) );
00536 setButtons( Ok | Cancel );
00537 setDefaultButton( Ok );
00538
00539 QWidget *page = new QWidget(this);
00540 setMainWidget( page );
00541 QVBoxLayout *layout = new QVBoxLayout( page );
00542 layout->setSpacing( KDialog::spacingHint() );
00543 layout->setMargin( 0 );
00544
00545 QGroupBox *box = new QGroupBox( i18nc( "street/postal", "Address Types" ), page );
00546 layout->addWidget( box );
00547 mGroup = new QButtonGroup( box );
00548 mGroup->setExclusive ( false );
00549
00550 QGridLayout *buttonLayout = new QGridLayout( box );
00551
00552 mTypeList = KABC::Address::typeList();
00553 mTypeList.removeAll( KABC::Address::Pref );
00554
00555 KABC::Address::TypeList::ConstIterator it;
00556 int i = 0;
00557 int row = 0;
00558 for ( it = mTypeList.constBegin(); it != mTypeList.constEnd(); ++it, ++i ) {
00559 QCheckBox *cb = new QCheckBox( KABC::Address::typeLabel( *it ), box );
00560 cb->setChecked( type & mTypeList[ i ] );
00561 buttonLayout->addWidget( cb, row, i%3 );
00562
00563 if( i%3 == 2 )
00564 ++row;
00565 mGroup->addButton( cb );
00566 }
00567 }
00568
00569 AddressTypeDialog::~AddressTypeDialog()
00570 {
00571 }
00572
00573 KABC::Address::Type AddressTypeDialog::type() const
00574 {
00575 KABC::Address::Type type;
00576 for ( int i = 0; i < mGroup->buttons().count(); ++i ) {
00577 QCheckBox *box = dynamic_cast<QCheckBox*>( mGroup->buttons().at( i ) );
00578 if ( box && box->isChecked() )
00579 type |= mTypeList[ i ];
00580 }
00581
00582 return type;
00583 }
00584
00589 class LocaleAwareString : public QString
00590 {
00591 public:
00592 LocaleAwareString() : QString()
00593 {}
00594
00595 LocaleAwareString( const QString &str ) : QString( str )
00596 {}
00597 };
00598
00599 static bool operator<( const LocaleAwareString &s1, const LocaleAwareString &s2 )
00600 {
00601 return ( QString::localeAwareCompare( s1, s2 ) < 0 );
00602 }
00603
00604 QStringList AddressEditDialog::sortLocaleAware( const QStringList &list )
00605 {
00606 QList<LocaleAwareString> sortedList;
00607
00608 QStringList::ConstIterator it;
00609 for ( it = list.constBegin(); it != list.constEnd(); ++it )
00610 sortedList.append( LocaleAwareString( *it ) );
00611
00612 qSort( sortedList.begin(), sortedList.end() );
00613
00614 QStringList retval;
00615 QList<LocaleAwareString>::ConstIterator retIt;
00616 for ( retIt = sortedList.constBegin(); retIt != sortedList.constEnd(); ++retIt )
00617 retval.append( *retIt );
00618
00619 return retval;
00620 }
00621
00622 #include "addresseditwidget.moc"