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