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::loadContact( KABC::Addressee *addr )
00225 {
00226 QStringList customs = addr->customs();
00227
00228 QStringList::Iterator it;
00229 for ( it = customs.begin(); it != customs.end(); ++it ) {
00230 QString app, name, value;
00231 splitField( *it, app, name, value );
00232 if ( app != "KADDRESSBOOK" )
00233 continue;
00234
00235 FieldRecordList::Iterator fieldIt;
00236 for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) {
00237 if ( (*fieldIt).mIdentifier == name ) {
00238 if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) {
00239 QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget );
00240 wdg->setText( value );
00241 } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) {
00242 QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget );
00243 wdg->setValue( value.toInt() );
00244 } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) {
00245 QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget );
00246 wdg->setChecked( value == "true" || value == "1" );
00247 } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) {
00248 QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget );
00249 wdg->setDate( QDate::fromString( value, Qt::ISODate ) );
00250 } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) {
00251 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget );
00252 wdg->setTime( QTime::fromString( value, Qt::ISODate ) );
00253 } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) {
00254 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget );
00255 wdg->setDateTime( QDateTime::fromString( value, Qt::ISODate ) );
00256 }
00257 }
00258 }
00259 }
00260 }
00261
00262 void FieldWidget::storeContact( KABC::Addressee *addr )
00263 {
00264 FieldRecordList::Iterator it;
00265 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00266 QString value;
00267 if ( (*it).mWidget->isA( "QLineEdit" ) ) {
00268 QLineEdit *wdg = static_cast<QLineEdit*>( (*it).mWidget );
00269 value = wdg->text();
00270 } else if ( (*it).mWidget->isA( "QSpinBox" ) ) {
00271 QSpinBox *wdg = static_cast<QSpinBox*>( (*it).mWidget );
00272 value = QString::number( wdg->value() );
00273 } else if ( (*it).mWidget->isA( "QCheckBox" ) ) {
00274 QCheckBox *wdg = static_cast<QCheckBox*>( (*it).mWidget );
00275 value = ( wdg->isChecked() ? "true" : "false" );
00276 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00277 QDateEdit *wdg = static_cast<QDateEdit*>( (*it).mWidget );
00278 value = wdg->date().toString( Qt::ISODate );
00279 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00280 QTimeEdit *wdg = static_cast<QTimeEdit*>( (*it).mWidget );
00281 value = wdg->time().toString( Qt::ISODate );
00282 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00283 QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*it).mWidget );
00284 value = wdg->dateTime().toString( Qt::ISODate );
00285 }
00286
00287 if ( value.isEmpty() )
00288 addr->removeCustom( "KADDRESSBOOK", (*it).mIdentifier );
00289 else
00290 addr->insertCustom( "KADDRESSBOOK", (*it).mIdentifier, value );
00291 }
00292 }
00293
00294 void FieldWidget::removeLocalFields()
00295 {
00296 FieldRecordList::Iterator it;
00297 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) {
00298 if ( !(*it).mGlobal ) {
00299 delete (*it).mLabel;
00300 delete (*it).mWidget;
00301 delete (*it).mLayout;
00302
00303 it = mFieldList.remove( it );
00304 it--;
00305 recalculateLayout();
00306 }
00307 }
00308 }
00309
00310 void FieldWidget::recalculateLayout()
00311 {
00312 int maxWidth = 0;
00313
00314 FieldRecordList::Iterator it;
00315 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00316 maxWidth = QMAX( maxWidth, (*it).mLabel->minimumSizeHint().width() );
00317
00318 for ( it = mFieldList.begin(); it != mFieldList.end(); ++it )
00319 (*it).mLabel->setMinimumWidth( maxWidth );
00320 }
00321
00322 CustomFieldsWidget::CustomFieldsWidget( KABC::AddressBook *ab,
00323 QWidget *parent, const char *name )
00324 : KAB::ContactEditorWidget( ab, parent, name )
00325 {
00326 initGUI();
00327
00328 connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addField() ) );
00329 connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( removeField() ) );
00330
00331 connect( mFieldWidget, SIGNAL( changed() ), this, SLOT( setModified() ) );
00332 }
00333
00334 void CustomFieldsWidget::loadContact( KABC::Addressee *addr )
00335 {
00336 mAddressee = *addr;
00337
00338 mFieldWidget->removeLocalFields();
00339
00340 AddresseeConfig addrConfig( mAddressee );
00341 QStringList fields = addrConfig.customFields();
00342
00343 if ( !fields.isEmpty() ) {
00344 for ( uint i = 0; i < fields.count(); i += 3 ) {
00345 mFieldWidget->addField( fields[ i ], fields[ i + 1 ],
00346 fields[ i + 2 ] , false );
00347 mRemoveButton->setEnabled( true );
00348 }
00349 }
00350
00351 mFieldWidget->loadContact( addr );
00352 }
00353
00354 void CustomFieldsWidget::storeContact( KABC::Addressee *addr )
00355 {
00356 mFieldWidget->storeContact( addr );
00357 }
00358
00359 void CustomFieldsWidget::setReadOnly( bool readOnly )
00360 {
00361 mAddButton->setEnabled( !readOnly );
00362 mRemoveButton->setEnabled( !readOnly && !mFieldWidget->fields().isEmpty() );
00363 }
00364
00365 void CustomFieldsWidget::addField()
00366 {
00367 AddFieldDialog dlg( this );
00368
00369 if ( dlg.exec() ) {
00370 FieldRecordList list = mFieldWidget->fields();
00371
00372 FieldRecordList::Iterator it;
00373 for ( it = list.begin(); it != list.end(); ++it )
00374 if ( (*it).mIdentifier == dlg.identifier() ) {
00375 KMessageBox::sorry( this, i18n( "A field with the same name already exists, please choose another one." ) );
00376 return;
00377 }
00378
00379 mFieldWidget->addField( dlg.identifier(), dlg.title(),
00380 dlg.type(), dlg.isGlobal() );
00381
00382 if ( dlg.isGlobal() ) {
00383 KABPrefs::instance()->mGlobalCustomFields = marshallFields( true );
00384 } else {
00385 AddresseeConfig addrConfig( mAddressee );
00386 addrConfig.setCustomFields( marshallFields( false ) );
00387 }
00388
00389 mRemoveButton->setEnabled( true );
00390 }
00391 }
00392
00393 void CustomFieldsWidget::removeField()
00394 {
00395 FieldRecordList list = mFieldWidget->fields();
00396
00397 QStringList fields;
00398
00399 FieldRecordList::Iterator it;
00400 for ( it = list.begin(); it != list.end(); ++it )
00401 fields.append( (*it).mTitle );
00402
00403 bool ok;
00404 QString title = KInputDialog::getItem( i18n( "Remove Field" ),
00405 i18n( "Select the field you want to remove:" ),
00406 fields, 0, false, &ok, this );
00407
00408 if ( ok ) {
00409 for ( it = list.begin(); it != list.end(); ++it )
00410 if ( (*it).mTitle == title ) {
00411 mFieldWidget->removeField( (*it).mIdentifier );
00412
00413 if ( list.count() == 1 )
00414 mRemoveButton->setEnabled( false );
00415
00416 if ( (*it).mGlobal ) {
00417 KABPrefs::instance()->mGlobalCustomFields = marshallFields( true );
00418 } else {
00419 AddresseeConfig addrConfig( mAddressee );
00420 addrConfig.setCustomFields( marshallFields( false ) );
00421 }
00422
00423 return;
00424 }
00425 }
00426 }
00427
00428 void CustomFieldsWidget::initGUI()
00429 {
00430 QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(),
00431 KDialog::spacingHint() );
00432
00433 mFieldWidget = new FieldWidget( this );
00434 layout->addMultiCellWidget( mFieldWidget, 0, 0, 0, 2 );
00435
00436 mAddButton = new QPushButton( i18n( "Add Field..." ), this );
00437 layout->addWidget( mAddButton, 1, 1, Qt::AlignRight );
00438
00439 mRemoveButton = new QPushButton( i18n( "Remove Field..." ), this );
00440 mRemoveButton->setEnabled( false );
00441 layout->addWidget( mRemoveButton, 1, 2, Qt::AlignRight );
00442
00443
00444 QStringList globalFields = KABPrefs::instance()->mGlobalCustomFields;
00445
00446 if ( globalFields.isEmpty() )
00447 return;
00448
00449 for ( uint i = 0; i < globalFields.count(); i += 3 ) {
00450 mFieldWidget->addField( globalFields[ i ], globalFields[ i + 1 ],
00451 globalFields[ i + 2 ] , true );
00452 mRemoveButton->setEnabled( true );
00453 }
00454 }
00455
00456 QStringList CustomFieldsWidget::marshallFields( bool global ) const
00457 {
00458 QStringList retval;
00459
00460 FieldRecordList list = mFieldWidget->fields();
00461 FieldRecordList::Iterator it;
00462 for ( it = list.begin(); it != list.end(); ++it ) {
00463 if ( (*it).mGlobal == global ) {
00464 retval.append( (*it).mIdentifier );
00465 retval.append( (*it).mTitle );
00466
00467 QString type = "text";
00468 if ( (*it).mWidget->isA( "QSpinBox" ) ) {
00469 type = "integer";
00470 } else if ( (*it).mWidget->isA( "QCheckBox" ) ) {
00471 type = "boolean";
00472 } else if ( (*it).mWidget->isA( "QDateEdit" ) ) {
00473 type = "date";
00474 } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) {
00475 type = "time";
00476 } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) {
00477 type = "datetime";
00478 } else if ( (*it).mWidget->isA( "QLineEdit" ) ) {
00479 type = "text";
00480 }
00481
00482 retval.append( type );
00483 }
00484 }
00485
00486 return retval;
00487 }
00488
00489
00490 void splitField( const QString &str, QString &app, QString &name, QString &value )
00491 {
00492 int colon = str.find( ':' );
00493 if ( colon != -1 ) {
00494 QString tmp = str.left( colon );
00495 value = str.mid( colon + 1 );
00496
00497 int dash = tmp.find( '-' );
00498 if ( dash != -1 ) {
00499 app = tmp.left( dash );
00500 name = tmp.mid( dash + 1 );
00501 }
00502 }
00503 }
00504
00505 #include "customfieldswidget.moc"