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 <tqcheckbox.h>
00025 #include <tqdatetimeedit.h>
00026 #include <tqframe.h>
00027 #include <tqlabel.h>
00028 #include <tqlayout.h>
00029 #include <tqpushbutton.h>
00030 #include <tqvalidator.h>
00031 #include <tqspinbox.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( TQWidget *parent, const char *name )
00046 : KDialogBase( Plain, i18n( "Add Field" ), Ok | Cancel,
00047 Ok, parent, name, true, true )
00048 {
00049 TQWidget *page = plainPage();
00050
00051 TQGridLayout *layout = new TQGridLayout( page, 3, 2, marginHint(), spacingHint() );
00052
00053 TQLabel *label = new TQLabel( i18n( "Title:" ), page );
00054 layout->addWidget( label, 0, 0 );
00055
00056 mTitle = new KLineEdit( page );
00057 mTitle->setValidator( new TQRegExpValidator( TQRegExp( "([a-zA-Z]|\\d|-)+" ), mTitle ) );
00058 label->setBuddy( mTitle );
00059 layout->addWidget( mTitle, 0, 1 );
00060
00061 label = new TQLabel( 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 TQCheckBox( i18n( "Is available for all contacts" ), page );
00069 mGlobal->setChecked( true );
00070 layout->addMultiCellWidget( mGlobal, 2, 2, 0, 1 );
00071
00072 connect( mTitle, TQT_SIGNAL( textChanged( const TQString& ) ),
00073 this, TQT_SLOT( nameChanged( const TQString& ) ) );
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 TQString AddFieldDialog::title() const
00099 {
00100 return mTitle->text();
00101 }
00102
00103 TQString AddFieldDialog::identifier() const
00104 {
00105 TQString id = mTitle->text().lower();
00106 return id.replace( ",", "_" ).replace( " ", "_" );
00107 }
00108
00109 TQString 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 TQString &name )
00120 {
00121 enableButton( Ok, !name.isEmpty() );
00122 }
00123
00124 FieldWidget::FieldWidget( TQWidget *parent, const char *name )
00125 : TQWidget( parent, name )
00126 {
00127 TQVBoxLayout *layout = new TQVBoxLayout( this, KDialog::marginHint(),
00128 KDialog::spacingHint() );
00129
00130 mGlobalLayout = new TQVBoxLayout( layout, KDialog::spacingHint() );
00131 mGlobalLayout->setAlignment( Qt::AlignTop );
00132
00133 mSeparator = new TQFrame( this );
00134 mSeparator->setFrameStyle( TQFrame::HLine | TQFrame::Sunken );
00135 mSeparator->hide();
00136 layout->addWidget( mSeparator );
00137
00138 mLocalLayout = new TQVBoxLayout( layout, KDialog::spacingHint() );
00139 mLocalLayout->setAlignment( Qt::AlignTop );
00140 }
00141
00142 void FieldWidget::addField( const TQString &identifier, const TQString &title,
00143 const TQString &type, bool isGlobal )
00144 {
00145 FieldRecord record;
00146
00147 record.mIdentifier = identifier;
00148 record.mTitle = title;
00149 record.mLabel = new TQLabel( title + ":", this );
00150 record.mGlobal = isGlobal;
00151 if ( type == "integer" ) {
00152 TQSpinBox *wdg = new TQSpinBox( 0, 1000, 1, this );
00153 record.mWidget = wdg;
00154 connect( wdg, TQT_SIGNAL( valueChanged( int ) ),
00155 this, TQT_SIGNAL( changed() ) );
00156 } else if ( type == "boolean" ) {
00157 TQCheckBox *wdg = new TQCheckBox( this );
00158 record.mWidget = wdg;
00159 connect( wdg, TQT_SIGNAL( toggled( bool ) ),
00160 this, TQT_SIGNAL( changed() ) );
00161 } else if ( type == "date" ) {
00162 QDateEdit *wdg = new QDateEdit( this );
00163 record.mWidget = wdg;
00164 connect( wdg, TQT_SIGNAL( valueChanged( const TQDate& ) ),
00165 this, TQT_SIGNAL( changed() ) );
00166 } else if ( type == "time" ) {
00167 QTimeEdit *wdg = new QTimeEdit( this );
00168 record.mWidget = wdg;
00169 connect( wdg, TQT_SIGNAL( valueChanged( const TQTime& ) ),
00170 this, TQT_SIGNAL( changed() ) );
00171 } else if ( type == "datetime" ) {
00172 QDateTimeEdit *wdg = new QDateTimeEdit( this );
00173 record.mWidget = wdg;
00174 connect( wdg, TQT_SIGNAL( valueChanged( const TQDateTime& ) ),
00175 this, TQT_SIGNAL( changed() ) );
00176 } else if ( type == "text" ) {
00177 TQLineEdit *wdg = new TQLineEdit( this );
00178 record.mWidget = wdg;
00179 connect( wdg, TQT_SIGNAL( textChanged( const TQString& ) ),
00180 this, TQT_SIGNAL( changed() ) );
00181 }
00182
00183 record.mLabel->show();
00184 record.mWidget->show();
00185
00186 if ( isGlobal ) {
00187 record.mLayout = new TQHBoxLayout( mGlobalLayout );
00188 record.mLayout->addWidget( record.mLabel );
00189 record.mLayout->addWidget( record.mWidget, Qt::AlignLeft );
00190 } else {
00191 record.mLayout = new TQHBoxLayout( 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 TQString &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( "TQLineEdit" ) ) {
00231 TQLineEdit *wdg = static_cast<TQLineEdit*>( (*fieldIt).mWidget );
00232 wdg->setText( TQString() );
00233 } else if ( (*fieldIt).mWidget->isA( "TQSpinBox" ) ) {
00234 TQSpinBox *wdg = static_cast<TQSpinBox*>( (*fieldIt).mWidget );
00235 wdg->setValue( 0 );
00236 } else if ( (*fieldIt).mWidget->isA( "TQCheckBox" ) ) {
00237 TQCheckBox *wdg = static_cast<TQCheckBox*>( (*fieldIt).mWidget );
00238 wdg->setChecked( true );
00239 } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) {
00240 QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget );
00241 wdg->setDate( TQDate::currentDate() );
00242 } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) {
00243 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget );
00244 wdg->setTime( TQTime::currentTime() );
00245 } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) {
00246 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget );
00247 wdg->setDateTime( TQDateTime::currentDateTime() );
00248 }
00249 }
00250 }
00251
00252 void FieldWidget::loadContact( KABC::Addressee *addr )
00253 {
00254 const TQStringList customs = addr->customs();
00255
00256 clearFields();
00257
00258 TQStringList::ConstIterator it;
00259 for ( it = customs.begin(); it != customs.end(); ++it ) {
00260 TQString 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( "TQLineEdit" ) ) {
00269 TQLineEdit *wdg = static_cast<TQLineEdit*>( (*fieldIt).mWidget );
00270 wdg->setText( value );
00271 } else if ( (*fieldIt).mWidget->isA( "TQSpinBox" ) ) {
00272 TQSpinBox *wdg = static_cast<TQSpinBox*>( (*fieldIt).mWidget );
00273 wdg->setValue( value.toInt() );
00274 } else if ( (*fieldIt).mWidget->isA( "TQCheckBox" ) ) {
00275 TQCheckBox *wdg = static_cast<TQCheckBox*>( (*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( TQDate::fromString( value, Qt::ISODate ) );
00280 } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) {
00281 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget );
00282 wdg->setTime( TQTime::fromString( value, Qt::ISODate ) );
00283 } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) {
00284 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget );
00285 wdg->setDateTime( TQDateTime::fromString( value, Qt::ISODate ) );
00286 }
00287 }
00288 }
00289 }
00290 }
00291
00292 void FieldWidget::setReadOnly( bool readOnly )
00293 {
00294 FieldRecordList::ConstIterator it;
00295 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00296 TQString value;
00297 if ( (*it).mWidget->isA( "TQLineEdit" ) ) {
00298 TQLineEdit *wdg = static_cast<TQLineEdit*>( (*it).mWidget );
00299 wdg->setReadOnly(readOnly);
00300 } else if ( (*it).mWidget->isA( "TQSpinBox" ) ) {
00301 TQSpinBox *wdg = static_cast<TQSpinBox*>( (*it).mWidget );
00302 wdg->setEnabled( !readOnly );
00303 } else if ( (*it).mWidget->isA( "TQCheckBox" ) ) {
00304 TQCheckBox *wdg = static_cast<TQCheckBox*>( (*it).mWidget );
00305 wdg->setEnabled( !readOnly );
00306 } else if ( (*it).mWidget->isA( "TQDateEdit" ) ) {
00307 TQDateEdit *wdg = static_cast<TQDateEdit*>( (*it).mWidget );
00308 wdg->setEnabled( !readOnly );
00309 } else if ( (*it).mWidget->isA( "TQTimeEdit" ) ) {
00310 TQTimeEdit *wdg = static_cast<TQTimeEdit*>( (*it).mWidget );
00311 wdg->setEnabled( !readOnly );
00312 } else if ( (*it).mWidget->isA( "TQDateTimeEdit" ) ) {
00313 TQDateTimeEdit *wdg = static_cast<TQDateTimeEdit*>( (*it).mWidget );
00314 wdg->setEnabled( !readOnly );
00315 }
00316 }
00317 }
00318
00319 void FieldWidget::storeContact( KABC::Addressee *addr )
00320 {
00321 FieldRecordList::ConstIterator it;
00322 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00323 TQString value;
00324 if ( (*it).mWidget->isA( "TQLineEdit" ) ) {
00325 TQLineEdit *wdg = static_cast<TQLineEdit*>( (*it).mWidget );
00326 value = wdg->text();
00327 } else if ( (*it).mWidget->isA( "TQSpinBox" ) ) {
00328 TQSpinBox *wdg = static_cast<TQSpinBox*>( (*it).mWidget );
00329 value = TQString::number( wdg->value() );
00330 } else if ( (*it).mWidget->isA( "TQCheckBox" ) ) {
00331 TQCheckBox *wdg = static_cast<TQCheckBox*>( (*it).mWidget );
00332 value = ( wdg->isChecked() ? "true" : "false" );
00333 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00334 QDateEdit *wdg = static_cast<QDateEdit*>( (*it).mWidget );
00335 value = wdg->date().toString( Qt::ISODate );
00336 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00337 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*it).mWidget );
00338 value = wdg->time().toString( Qt::ISODate );
00339 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00340 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*it).mWidget );
00341 value = wdg->dateTime().toString( Qt::ISODate );
00342 }
00343
00344 if ( value.isEmpty() )
00345 addr->removeCustom( "KADDRESSBOOK", (*it).mIdentifier );
00346 else
00347 addr->insertCustom( "KADDRESSBOOK", (*it).mIdentifier, value );
00348 }
00349 }
00350
00351 void FieldWidget::removeLocalFields()
00352 {
00353 FieldRecordList::Iterator it;
00354 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00355 if ( !(*it).mGlobal ) {
00356 delete (*it).mLabel;
00357 delete (*it).mWidget;
00358 delete (*it).mLayout;
00359
00360 it = mFieldList.remove( it );
00361 it--;
00362 recalculateLayout();
00363 }
00364 }
00365 }
00366
00367 void FieldWidget::recalculateLayout()
00368 {
00369 int maxWidth = 0;
00370
00371 FieldRecordList::ConstIterator it;
00372 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00373 maxWidth = QMAX( maxWidth, (*it).mLabel->minimumSizeHint().width() );
00374
00375 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00376 (*it).mLabel->setMinimumWidth( maxWidth );
00377 }
00378
00379 CustomFieldsWidget::CustomFieldsWidget( KABC::AddressBook *ab,
00380 TQWidget *parent, const char *name )
00381 : KAB::ContactEditorWidget( ab, parent, name )
00382 {
00383 initGUI();
00384
00385 connect( mAddButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( addField() ) );
00386 connect( mRemoveButton, TQT_SIGNAL( clicked() ), this, TQT_SLOT( removeField() ) );
00387
00388 connect( mFieldWidget, TQT_SIGNAL( changed() ), this, TQT_SLOT( setModified() ) );
00389 }
00390
00391 void CustomFieldsWidget::loadContact( KABC::Addressee *addr )
00392 {
00393 mAddressee = *addr;
00394
00395 mFieldWidget->removeLocalFields();
00396
00397 AddresseeConfig addrConfig( mAddressee );
00398 TQStringList fields = addrConfig.customFields();
00399
00400 if ( !fields.isEmpty() ) {
00401 for ( uint i = 0; i < fields.count(); i += 3 ) {
00402 mFieldWidget->addField( fields[ i ], fields[ i + 1 ],
00403 fields[ i + 2 ] , false );
00404 mRemoveButton->setEnabled( true );
00405 }
00406 }
00407
00408 mFieldWidget->loadContact( addr );
00409 }
00410
00411 void CustomFieldsWidget::storeContact( KABC::Addressee *addr )
00412 {
00413 mFieldWidget->storeContact( addr );
00414 }
00415
00416 void CustomFieldsWidget::setReadOnly( bool readOnly )
00417 {
00418 mAddButton->setEnabled( !readOnly );
00419 mRemoveButton->setEnabled( !readOnly && !mFieldWidget->fields().isEmpty() );
00420 mFieldWidget->setReadOnly( readOnly );
00421 }
00422
00423 void CustomFieldsWidget::addField()
00424 {
00425 AddFieldDialog dlg( this );
00426
00427 if ( dlg.exec() ) {
00428 FieldRecordList list = mFieldWidget->fields();
00429
00430 FieldRecordList::ConstIterator it;
00431 for ( it = list.begin(); it != list.end(); ++it )
00432 if ( (*it).mIdentifier == dlg.identifier() ) {
00433 KMessageBox::sorry( this, i18n( "A field with the same name already exists, please choose another one." ) );
00434 return;
00435 }
00436
00437 mFieldWidget->addField( dlg.identifier(), dlg.title(),
00438 dlg.type(), dlg.isGlobal() );
00439
00440 if ( dlg.isGlobal() ) {
00441 KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) );
00442 } else {
00443 AddresseeConfig addrConfig( mAddressee );
00444 addrConfig.setCustomFields( marshallFields( false ) );
00445 }
00446
00447 mRemoveButton->setEnabled( true );
00448 }
00449 }
00450
00451 void CustomFieldsWidget::removeField()
00452 {
00453 const FieldRecordList list = mFieldWidget->fields();
00454
00455 TQStringList fields;
00456
00457 FieldRecordList::ConstIterator it;
00458 for ( it = list.begin(); it != list.end(); ++it )
00459 fields.append( (*it).mTitle );
00460
00461 bool ok;
00462 TQString title = KInputDialog::getItem( i18n( "Remove Field" ),
00463 i18n( "Select the field you want to remove:" ),
00464 fields, 0, false, &ok, this );
00465
00466 if ( ok ) {
00467 for ( it = list.begin(); it != list.end(); ++it )
00468 if ( (*it).mTitle == title ) {
00469 mFieldWidget->removeField( (*it).mIdentifier );
00470
00471 if ( list.count() == 1 )
00472 mRemoveButton->setEnabled( false );
00473
00474 if ( (*it).mGlobal ) {
00475 KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) );
00476 } else {
00477 AddresseeConfig addrConfig( mAddressee );
00478 addrConfig.setCustomFields( marshallFields( false ) );
00479 }
00480
00481 return;
00482 }
00483 }
00484 }
00485
00486 void CustomFieldsWidget::initGUI()
00487 {
00488 TQGridLayout *layout = new TQGridLayout( this, 2, 3, KDialog::marginHint(),
00489 KDialog::spacingHint() );
00490
00491 mFieldWidget = new FieldWidget( this );
00492 layout->addMultiCellWidget( mFieldWidget, 0, 0, 0, 2 );
00493
00494 mAddButton = new TQPushButton( i18n( "Add Field..." ), this );
00495 layout->addWidget( mAddButton, 1, 1, Qt::AlignRight );
00496
00497 mRemoveButton = new TQPushButton( i18n( "Remove Field..." ), this );
00498 mRemoveButton->setEnabled( false );
00499 layout->addWidget( mRemoveButton, 1, 2, Qt::AlignRight );
00500
00501
00502 TQStringList globalFields = KABPrefs::instance()->globalCustomFields();
00503
00504 if ( globalFields.isEmpty() )
00505 return;
00506
00507 for ( uint i = 0; i < globalFields.count(); i += 3 ) {
00508 mFieldWidget->addField( globalFields[ i ], globalFields[ i + 1 ],
00509 globalFields[ i + 2 ] , true );
00510 mRemoveButton->setEnabled( true );
00511 }
00512 }
00513
00514 TQStringList CustomFieldsWidget::marshallFields( bool global ) const
00515 {
00516 TQStringList retval;
00517
00518 const FieldRecordList list = mFieldWidget->fields();
00519 FieldRecordList::ConstIterator it;
00520 for ( it = list.begin(); it != list.end(); ++it ) {
00521 if ( (*it).mGlobal == global ) {
00522 retval.append( (*it).mIdentifier );
00523 retval.append( (*it).mTitle );
00524
00525 TQString type = "text";
00526 if ( (*it).mWidget->isA( "TQSpinBox" ) ) {
00527 type = "integer";
00528 } else if ( (*it).mWidget->isA( "TQCheckBox" ) ) {
00529 type = "boolean";
00530 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00531 type = "date";
00532 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00533 type = "time";
00534 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00535 type = "datetime";
00536 } else if ( (*it).mWidget->isA( "TQLineEdit" ) ) {
00537 type = "text";
00538 }
00539
00540 retval.append( type );
00541 }
00542 }
00543
00544 return retval;
00545 }
00546
00547
00548 void splitField( const TQString &str, TQString &app, TQString &name, TQString &value )
00549 {
00550 int colon = str.find( ':' );
00551 if ( colon != -1 ) {
00552 TQString tmp = str.left( colon );
00553 value = str.mid( colon + 1 );
00554
00555 int dash = tmp.find( '-' );
00556 if ( dash != -1 ) {
00557 app = tmp.left( dash );
00558 name = tmp.mid( dash + 1 );
00559 }
00560 }
00561 }
00562
00563 #include "customfieldswidget.moc"