00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qcheckbox.h>
00025 #include <qdatetimeedit.h>
00026 #include <qframe.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qpushbutton.h>
00030 #include <qvalidator.h>
00031 #include <qspinbox.h>
00032
00033 #include <kaccelmanager.h>
00034 #include <kcombobox.h>
00035 #include <kinputdialog.h>
00036 #include <klineedit.h>
00037 #include <kmessagebox.h>
00038
00039 #include "addresseeconfig.h"
00040 #include "kabprefs.h"
00041
00042 #include "customfieldswidget.h"
00043
00044
00045 AddFieldDialog::AddFieldDialog( QWidget *parent, const char *name )
00046 : KDialogBase( Plain, i18n( "Add Field" ), Ok | Cancel,
00047 Ok, parent, name, true, true )
00048 {
00049 QWidget *page = plainPage();
00050
00051 QGridLayout *layout = new QGridLayout( page, 3, 2, marginHint(), spacingHint() );
00052
00053 QLabel *label = new QLabel( i18n( "Title:" ), page );
00054 layout->addWidget( label, 0, 0 );
00055
00056 mTitle = new KLineEdit( page );
00057 mTitle->setValidator( new QRegExpValidator( QRegExp( "([a-zA-Z]|\\d|-)+" ), mTitle ) );
00058 label->setBuddy( mTitle );
00059 layout->addWidget( mTitle, 0, 1 );
00060
00061 label = new QLabel( i18n( "Type:" ), page );
00062 layout->addWidget( label, 1, 0 );
00063
00064 mType = new KComboBox( page );
00065 label->setBuddy( mType );
00066 layout->addWidget( mType, 1, 1 );
00067
00068 mGlobal = new QCheckBox( i18n( "Is available for all contacts" ), page );
00069 mGlobal->setChecked( true );
00070 layout->addMultiCellWidget( mGlobal, 2, 2, 0, 1 );
00071
00072 connect( mTitle, SIGNAL( textChanged( const QString& ) ),
00073 this, SLOT( nameChanged( const QString& ) ) );
00074
00075 KAcceleratorManager::manage( this );
00076
00077 mTypeList.append( "text" );
00078 mTypeName.append( i18n( "Text" ) );
00079 mTypeList.append( "integer" );
00080 mTypeName.append( i18n( "Numeric Value" ) );
00081 mTypeList.append( "boolean" );
00082 mTypeName.append( i18n( "Boolean" ) );
00083 mTypeList.append( "date" );
00084 mTypeName.append( i18n( "Date" ) );
00085 mTypeList.append( "time" );
00086 mTypeName.append( i18n( "Time" ) );
00087 mTypeList.append( "datetime" );
00088 mTypeName.append( i18n( "Date & Time" ) );
00089
00090 for ( uint i = 0; i < mTypeName.count(); ++i )
00091 mType->insertItem( mTypeName[ i ] );
00092
00093 nameChanged( "" );
00094
00095 mTitle->setFocus();
00096 }
00097
00098 QString AddFieldDialog::title() const
00099 {
00100 return mTitle->text();
00101 }
00102
00103 QString AddFieldDialog::identifier() const
00104 {
00105 QString id = mTitle->text().lower();
00106 return id.replace( ",", "_" ).replace( " ", "_" );
00107 }
00108
00109 QString AddFieldDialog::type() const
00110 {
00111 return mTypeList[ mType->currentItem() ];
00112 }
00113
00114 bool AddFieldDialog::isGlobal() const
00115 {
00116 return mGlobal->isChecked();
00117 }
00118
00119 void AddFieldDialog::nameChanged( const QString &name )
00120 {
00121 enableButton( Ok, !name.isEmpty() );
00122 }
00123
00124 FieldWidget::FieldWidget( QWidget *parent, const char *name )
00125 : QWidget( parent, name )
00126 {
00127 QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(),
00128 KDialog::spacingHint() );
00129
00130 mGlobalLayout = new QVBoxLayout( layout, KDialog::spacingHint() );
00131 mGlobalLayout->setAlignment( Qt::AlignTop );
00132
00133 mSeparator = new QFrame( this );
00134 mSeparator->setFrameStyle( QFrame::HLine | QFrame::Sunken );
00135 mSeparator->hide();
00136 layout->addWidget( mSeparator );
00137
00138 mLocalLayout = new QVBoxLayout( layout, KDialog::spacingHint() );
00139 mLocalLayout->setAlignment( Qt::AlignTop );
00140 }
00141
00142 void FieldWidget::addField( const QString &identifier, const QString &title,
00143 const QString &type, bool isGlobal )
00144 {
00145 FieldRecord record;
00146
00147 record.mIdentifier = identifier;
00148 record.mTitle = title;
00149 record.mLabel = new QLabel( title + ":", this );
00150 record.mGlobal = isGlobal;
00151 if ( type == "integer" ) {
00152 QSpinBox *wdg = new QSpinBox( 0, 1000, 1, this );
00153 record.mWidget = wdg;
00154 connect( wdg, SIGNAL( valueChanged( int ) ),
00155 this, SIGNAL( changed() ) );
00156 } else if ( type == "boolean" ) {
00157 QCheckBox *wdg = new QCheckBox( this );
00158 record.mWidget = wdg;
00159 connect( wdg, SIGNAL( toggled( bool ) ),
00160 this, SIGNAL( changed() ) );
00161 } else if ( type == "date" ) {
00162 QDateEdit *wdg = new QDateEdit( this );
00163 record.mWidget = wdg;
00164 connect( wdg, SIGNAL( valueChanged( const QDate& ) ),
00165 this, SIGNAL( changed() ) );
00166 } else if ( type == "time" ) {
00167 QTimeEdit *wdg = new QTimeEdit( this );
00168 record.mWidget = wdg;
00169 connect( wdg, SIGNAL( valueChanged( const QTime& ) ),
00170 this, SIGNAL( changed() ) );
00171 } else if ( type == "datetime" ) {
00172 QDateTimeEdit *wdg = new QDateTimeEdit( this );
00173 record.mWidget = wdg;
00174 connect( wdg, SIGNAL( valueChanged( const QDateTime& ) ),
00175 this, SIGNAL( changed() ) );
00176 } else if ( type == "text" ) {
00177 QLineEdit *wdg = new QLineEdit( this );
00178 record.mWidget = wdg;
00179 connect( wdg, SIGNAL( textChanged( const QString& ) ),
00180 this, SIGNAL( changed() ) );
00181 }
00182
00183 record.mLabel->show();
00184 record.mWidget->show();
00185
00186 if ( isGlobal ) {
00187 record.mLayout = new QHBoxLayout( mGlobalLayout );
00188 record.mLayout->addWidget( record.mLabel );
00189 record.mLayout->addWidget( record.mWidget, Qt::AlignLeft );
00190 } else {
00191 record.mLayout = new QHBoxLayout( mLocalLayout );
00192 record.mLayout->addWidget( record.mLabel );
00193 record.mLayout->addWidget( record.mWidget, Qt::AlignLeft );
00194 mSeparator->show();
00195 }
00196
00197 mFieldList.append( record );
00198
00199 recalculateLayout();
00200 }
00201
00202 void FieldWidget::removeField( const QString &identifier )
00203 {
00204 FieldRecordList::Iterator it;
00205 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00206 if ( (*it).mIdentifier == identifier ) {
00207 delete (*it).mLabel;
00208 delete (*it).mWidget;
00209 delete (*it).mLayout;
00210
00211 mFieldList.remove( it );
00212 recalculateLayout();
00213
00214 bool hasLocal = false;
00215 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00216 hasLocal = hasLocal || !(*it).mGlobal;
00217
00218 if ( !hasLocal )
00219 mSeparator->hide();
00220
00221 return;
00222 }
00223 }
00224 }
00225
00226 void FieldWidget::clearFields()
00227 {
00228 FieldRecordList::ConstIterator fieldIt;
00229 for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) {
00230 if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) {
00231 QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget );
00232 wdg->setText( QString() );
00233 } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) {
00234 QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget );
00235 wdg->setValue( 0 );
00236 } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) {
00237 QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget );
00238 wdg->setChecked( true );
00239 } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) {
00240 QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget );
00241 wdg->setDate( QDate::currentDate() );
00242 } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) {
00243 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget );
00244 wdg->setTime( QTime::currentTime() );
00245 } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) {
00246 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget );
00247 wdg->setDateTime( QDateTime::currentDateTime() );
00248 }
00249 }
00250 }
00251
00252 void FieldWidget::loadContact( KABC::Addressee *addr )
00253 {
00254 const QStringList customs = addr->customs();
00255
00256 clearFields();
00257
00258 QStringList::ConstIterator it;
00259 for ( it = customs.begin(); it != customs.end(); ++it ) {
00260 QString app, name, value;
00261 splitField( *it, app, name, value );
00262 if ( app != "KADDRESSBOOK" )
00263 continue;
00264
00265 FieldRecordList::ConstIterator fieldIt;
00266 for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) {
00267 if ( (*fieldIt).mIdentifier == name ) {
00268 if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) {
00269 QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget );
00270 wdg->setText( value );
00271 } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) {
00272 QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget );
00273 wdg->setValue( value.toInt() );
00274 } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) {
00275 QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget );
00276 wdg->setChecked( value == "true" || value == "1" );
00277 } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) {
00278 QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget );
00279 wdg->setDate( QDate::fromString( value, Qt::ISODate ) );
00280 } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) {
00281 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget );
00282 wdg->setTime( QTime::fromString( value, Qt::ISODate ) );
00283 } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) {
00284 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget );
00285 wdg->setDateTime( QDateTime::fromString( value, Qt::ISODate ) );
00286 }
00287 }
00288 }
00289 }
00290 }
00291
00292 void FieldWidget::storeContact( KABC::Addressee *addr )
00293 {
00294 FieldRecordList::ConstIterator it;
00295 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00296 QString value;
00297 if ( (*it).mWidget->isA( "QLineEdit" ) ) {
00298 QLineEdit *wdg = static_cast<QLineEdit*>( (*it).mWidget );
00299 value = wdg->text();
00300 } else if ( (*it).mWidget->isA( "QSpinBox" ) ) {
00301 QSpinBox *wdg = static_cast<QSpinBox*>( (*it).mWidget );
00302 value = QString::number( wdg->value() );
00303 } else if ( (*it).mWidget->isA( "QCheckBox" ) ) {
00304 QCheckBox *wdg = static_cast<QCheckBox*>( (*it).mWidget );
00305 value = ( wdg->isChecked() ? "true" : "false" );
00306 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00307 QDateEdit *wdg = static_cast<QDateEdit*>( (*it).mWidget );
00308 value = wdg->date().toString( Qt::ISODate );
00309 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00310 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*it).mWidget );
00311 value = wdg->time().toString( Qt::ISODate );
00312 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00313 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*it).mWidget );
00314 value = wdg->dateTime().toString( Qt::ISODate );
00315 }
00316
00317 if ( value.isEmpty() )
00318 addr->removeCustom( "KADDRESSBOOK", (*it).mIdentifier );
00319 else
00320 addr->insertCustom( "KADDRESSBOOK", (*it).mIdentifier, value );
00321 }
00322 }
00323
00324 void FieldWidget::removeLocalFields()
00325 {
00326 FieldRecordList::Iterator it;
00327 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00328 if ( !(*it).mGlobal ) {
00329 delete (*it).mLabel;
00330 delete (*it).mWidget;
00331 delete (*it).mLayout;
00332
00333 it = mFieldList.remove( it );
00334 it--;
00335 recalculateLayout();
00336 }
00337 }
00338 }
00339
00340 void FieldWidget::recalculateLayout()
00341 {
00342 int maxWidth = 0;
00343
00344 FieldRecordList::ConstIterator it;
00345 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00346 maxWidth = QMAX( maxWidth, (*it).mLabel->minimumSizeHint().width() );
00347
00348 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00349 (*it).mLabel->setMinimumWidth( maxWidth );
00350 }
00351
00352 CustomFieldsWidget::CustomFieldsWidget( KABC::AddressBook *ab,
00353 QWidget *parent, const char *name )
00354 : KAB::ContactEditorWidget( ab, parent, name )
00355 {
00356 initGUI();
00357
00358 connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addField() ) );
00359 connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( removeField() ) );
00360
00361 connect( mFieldWidget, SIGNAL( changed() ), this, SLOT( setModified() ) );
00362 }
00363
00364 void CustomFieldsWidget::loadContact( KABC::Addressee *addr )
00365 {
00366 mAddressee = *addr;
00367
00368 mFieldWidget->removeLocalFields();
00369
00370 AddresseeConfig addrConfig( mAddressee );
00371 QStringList fields = addrConfig.customFields();
00372
00373 if ( !fields.isEmpty() ) {
00374 for ( uint i = 0; i < fields.count(); i += 3 ) {
00375 mFieldWidget->addField( fields[ i ], fields[ i + 1 ],
00376 fields[ i + 2 ] , false );
00377 mRemoveButton->setEnabled( true );
00378 }
00379 }
00380
00381 mFieldWidget->loadContact( addr );
00382 }
00383
00384 void CustomFieldsWidget::storeContact( KABC::Addressee *addr )
00385 {
00386 mFieldWidget->storeContact( addr );
00387 }
00388
00389 void CustomFieldsWidget::setReadOnly( bool readOnly )
00390 {
00391 mAddButton->setEnabled( !readOnly );
00392 mRemoveButton->setEnabled( !readOnly && !mFieldWidget->fields().isEmpty() );
00393 }
00394
00395 void CustomFieldsWidget::addField()
00396 {
00397 AddFieldDialog dlg( this );
00398
00399 if ( dlg.exec() ) {
00400 FieldRecordList list = mFieldWidget->fields();
00401
00402 FieldRecordList::ConstIterator it;
00403 for ( it = list.begin(); it != list.end(); ++it )
00404 if ( (*it).mIdentifier == dlg.identifier() ) {
00405 KMessageBox::sorry( this, i18n( "A field with the same name already exists, please choose another one." ) );
00406 return;
00407 }
00408
00409 mFieldWidget->addField( dlg.identifier(), dlg.title(),
00410 dlg.type(), dlg.isGlobal() );
00411
00412 if ( dlg.isGlobal() ) {
00413 KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) );
00414 } else {
00415 AddresseeConfig addrConfig( mAddressee );
00416 addrConfig.setCustomFields( marshallFields( false ) );
00417 }
00418
00419 mRemoveButton->setEnabled( true );
00420 }
00421 }
00422
00423 void CustomFieldsWidget::removeField()
00424 {
00425 const FieldRecordList list = mFieldWidget->fields();
00426
00427 QStringList fields;
00428
00429 FieldRecordList::ConstIterator it;
00430 for ( it = list.begin(); it != list.end(); ++it )
00431 fields.append( (*it).mTitle );
00432
00433 bool ok;
00434 QString title = KInputDialog::getItem( i18n( "Remove Field" ),
00435 i18n( "Select the field you want to remove:" ),
00436 fields, 0, false, &ok, this );
00437
00438 if ( ok ) {
00439 for ( it = list.begin(); it != list.end(); ++it )
00440 if ( (*it).mTitle == title ) {
00441 mFieldWidget->removeField( (*it).mIdentifier );
00442
00443 if ( list.count() == 1 )
00444 mRemoveButton->setEnabled( false );
00445
00446 if ( (*it).mGlobal ) {
00447 KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) );
00448 } else {
00449 AddresseeConfig addrConfig( mAddressee );
00450 addrConfig.setCustomFields( marshallFields( false ) );
00451 }
00452
00453 return;
00454 }
00455 }
00456 }
00457
00458 void CustomFieldsWidget::initGUI()
00459 {
00460 QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(),
00461 KDialog::spacingHint() );
00462
00463 mFieldWidget = new FieldWidget( this );
00464 layout->addMultiCellWidget( mFieldWidget, 0, 0, 0, 2 );
00465
00466 mAddButton = new QPushButton( i18n( "Add Field..." ), this );
00467 layout->addWidget( mAddButton, 1, 1, Qt::AlignRight );
00468
00469 mRemoveButton = new QPushButton( i18n( "Remove Field..." ), this );
00470 mRemoveButton->setEnabled( false );
00471 layout->addWidget( mRemoveButton, 1, 2, Qt::AlignRight );
00472
00473
00474 QStringList globalFields = KABPrefs::instance()->globalCustomFields();
00475
00476 if ( globalFields.isEmpty() )
00477 return;
00478
00479 for ( uint i = 0; i < globalFields.count(); i += 3 ) {
00480 mFieldWidget->addField( globalFields[ i ], globalFields[ i + 1 ],
00481 globalFields[ i + 2 ] , true );
00482 mRemoveButton->setEnabled( true );
00483 }
00484 }
00485
00486 QStringList CustomFieldsWidget::marshallFields( bool global ) const
00487 {
00488 QStringList retval;
00489
00490 const FieldRecordList list = mFieldWidget->fields();
00491 FieldRecordList::ConstIterator it;
00492 for ( it = list.begin(); it != list.end(); ++it ) {
00493 if ( (*it).mGlobal == global ) {
00494 retval.append( (*it).mIdentifier );
00495 retval.append( (*it).mTitle );
00496
00497 QString type = "text";
00498 if ( (*it).mWidget->isA( "QSpinBox" ) ) {
00499 type = "integer";
00500 } else if ( (*it).mWidget->isA( "QCheckBox" ) ) {
00501 type = "boolean";
00502 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00503 type = "date";
00504 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00505 type = "time";
00506 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00507 type = "datetime";
00508 } else if ( (*it).mWidget->isA( "QLineEdit" ) ) {
00509 type = "text";
00510 }
00511
00512 retval.append( type );
00513 }
00514 }
00515
00516 return retval;
00517 }
00518
00519
00520 void splitField( const QString &str, QString &app, QString &name, QString &value )
00521 {
00522 int colon = str.find( ':' );
00523 if ( colon != -1 ) {
00524 QString tmp = str.left( colon );
00525 value = str.mid( colon + 1 );
00526
00527 int dash = tmp.find( '-' );
00528 if ( dash != -1 ) {
00529 app = tmp.left( dash );
00530 name = tmp.mid( dash + 1 );
00531 }
00532 }
00533 }
00534
00535 #include "customfieldswidget.moc"