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