akonadi/contact
addresseditwidget.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2009 Tobias Koenig <tokoe@kde.org> 00005 00006 This library is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or (at your 00009 option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, but WITHOUT 00012 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 02110-1301, USA. 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 ); // Others... 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 // insert at the end, but before the 'Others...' entry 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 ) // "Other..." entry 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(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 // as the preferred address is mutual exclusive, we have to 00324 // remove the flag from all other addresses 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 // set the preferred address as the visible one 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 // delete all previous addresses 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 // insert the new ones 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"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:02:51 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Tue May 8 2012 00:02:51 by doxygen 1.8.0 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.