kaddressbook

customfieldswidget.cpp

00001 /*
00002     This file is part of KAddressbook.
00003     Copyright (c) 2004 Tobias Koenig <tokoe@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
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   // load global fields
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"
KDE Home | KDE Accessibility Home | Description of Access Keys