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