diff options
Diffstat (limited to 'kaddressbook/customfieldswidget.cpp')
-rw-r--r-- | kaddressbook/customfieldswidget.cpp | 535 |
1 files changed, 535 insertions, 0 deletions
diff --git a/kaddressbook/customfieldswidget.cpp b/kaddressbook/customfieldswidget.cpp new file mode 100644 index 000000000..a2a6e7011 --- /dev/null +++ b/kaddressbook/customfieldswidget.cpp @@ -0,0 +1,535 @@ +/* + This file is part of KAddressbook. + Copyright (c) 2004 Tobias Koenig <tokoe@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qcheckbox.h> +#include <qdatetimeedit.h> +#include <qframe.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> +#include <qvalidator.h> +#include <qspinbox.h> + +#include <kaccelmanager.h> +#include <kcombobox.h> +#include <kinputdialog.h> +#include <klineedit.h> +#include <kmessagebox.h> + +#include "addresseeconfig.h" +#include "kabprefs.h" + +#include "customfieldswidget.h" + + +AddFieldDialog::AddFieldDialog( QWidget *parent, const char *name ) + : KDialogBase( Plain, i18n( "Add Field" ), Ok | Cancel, + Ok, parent, name, true, true ) +{ + QWidget *page = plainPage(); + + QGridLayout *layout = new QGridLayout( page, 3, 2, marginHint(), spacingHint() ); + + QLabel *label = new QLabel( i18n( "Title:" ), page ); + layout->addWidget( label, 0, 0 ); + + mTitle = new KLineEdit( page ); + mTitle->setValidator( new QRegExpValidator( QRegExp( "([a-zA-Z]|\\d|-)+" ), mTitle ) ); + label->setBuddy( mTitle ); + layout->addWidget( mTitle, 0, 1 ); + + label = new QLabel( i18n( "Type:" ), page ); + layout->addWidget( label, 1, 0 ); + + mType = new KComboBox( page ); + label->setBuddy( mType ); + layout->addWidget( mType, 1, 1 ); + + mGlobal = new QCheckBox( i18n( "Is available for all contacts" ), page ); + mGlobal->setChecked( true ); + layout->addMultiCellWidget( mGlobal, 2, 2, 0, 1 ); + + connect( mTitle, SIGNAL( textChanged( const QString& ) ), + this, SLOT( nameChanged( const QString& ) ) ); + + KAcceleratorManager::manage( this ); + + mTypeList.append( "text" ); + mTypeName.append( i18n( "Text" ) ); + mTypeList.append( "integer" ); + mTypeName.append( i18n( "Numeric Value" ) ); + mTypeList.append( "boolean" ); + mTypeName.append( i18n( "Boolean" ) ); + mTypeList.append( "date" ); + mTypeName.append( i18n( "Date" ) ); + mTypeList.append( "time" ); + mTypeName.append( i18n( "Time" ) ); + mTypeList.append( "datetime" ); + mTypeName.append( i18n( "Date & Time" ) ); + + for ( uint i = 0; i < mTypeName.count(); ++i ) + mType->insertItem( mTypeName[ i ] ); + + nameChanged( "" ); + + mTitle->setFocus(); +} + +QString AddFieldDialog::title() const +{ + return mTitle->text(); +} + +QString AddFieldDialog::identifier() const +{ + QString id = mTitle->text().lower(); + return id.replace( ",", "_" ).replace( " ", "_" ); +} + +QString AddFieldDialog::type() const +{ + return mTypeList[ mType->currentItem() ]; +} + +bool AddFieldDialog::isGlobal() const +{ + return mGlobal->isChecked(); +} + +void AddFieldDialog::nameChanged( const QString &name ) +{ + enableButton( Ok, !name.isEmpty() ); +} + +FieldWidget::FieldWidget( QWidget *parent, const char *name ) + : QWidget( parent, name ) +{ + QVBoxLayout *layout = new QVBoxLayout( this, KDialog::marginHint(), + KDialog::spacingHint() ); + + mGlobalLayout = new QVBoxLayout( layout, KDialog::spacingHint() ); + mGlobalLayout->setAlignment( Qt::AlignTop ); + + mSeparator = new QFrame( this ); + mSeparator->setFrameStyle( QFrame::HLine | QFrame::Sunken ); + mSeparator->hide(); + layout->addWidget( mSeparator ); + + mLocalLayout = new QVBoxLayout( layout, KDialog::spacingHint() ); + mLocalLayout->setAlignment( Qt::AlignTop ); +} + +void FieldWidget::addField( const QString &identifier, const QString &title, + const QString &type, bool isGlobal ) +{ + FieldRecord record; + + record.mIdentifier = identifier; + record.mTitle = title; + record.mLabel = new QLabel( title + ":", this ); + record.mGlobal = isGlobal; + if ( type == "integer" ) { + QSpinBox *wdg = new QSpinBox( 0, 1000, 1, this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( int ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "boolean" ) { + QCheckBox *wdg = new QCheckBox( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( toggled( bool ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "date" ) { + QDateEdit *wdg = new QDateEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QDate& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "time" ) { + QTimeEdit *wdg = new QTimeEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QTime& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "datetime" ) { + QDateTimeEdit *wdg = new QDateTimeEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( valueChanged( const QDateTime& ) ), + this, SIGNAL( changed() ) ); + } else if ( type == "text" ) { + QLineEdit *wdg = new QLineEdit( this ); + record.mWidget = wdg; + connect( wdg, SIGNAL( textChanged( const QString& ) ), + this, SIGNAL( changed() ) ); + } + + record.mLabel->show(); + record.mWidget->show(); + + if ( isGlobal ) { + record.mLayout = new QHBoxLayout( mGlobalLayout ); + record.mLayout->addWidget( record.mLabel ); + record.mLayout->addWidget( record.mWidget, Qt::AlignLeft ); + } else { + record.mLayout = new QHBoxLayout( mLocalLayout ); + record.mLayout->addWidget( record.mLabel ); + record.mLayout->addWidget( record.mWidget, Qt::AlignLeft ); + mSeparator->show(); + } + + mFieldList.append( record ); + + recalculateLayout(); +} + +void FieldWidget::removeField( const QString &identifier ) +{ + FieldRecordList::Iterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + if ( (*it).mIdentifier == identifier ) { + delete (*it).mLabel; + delete (*it).mWidget; + delete (*it).mLayout; + + mFieldList.remove( it ); + recalculateLayout(); + + bool hasLocal = false; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + hasLocal = hasLocal || !(*it).mGlobal; + + if ( !hasLocal ) + mSeparator->hide(); + + return; + } + } +} + +void FieldWidget::clearFields() +{ + FieldRecordList::ConstIterator fieldIt; + for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) { + if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget ); + wdg->setText( QString() ); + } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget ); + wdg->setValue( 0 ); + } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget ); + wdg->setChecked( true ); + } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget ); + wdg->setDate( QDate::currentDate() ); + } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget ); + wdg->setTime( QTime::currentTime() ); + } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget ); + wdg->setDateTime( QDateTime::currentDateTime() ); + } + } +} + +void FieldWidget::loadContact( KABC::Addressee *addr ) +{ + const QStringList customs = addr->customs(); + + clearFields(); + + QStringList::ConstIterator it; + for ( it = customs.begin(); it != customs.end(); ++it ) { + QString app, name, value; + splitField( *it, app, name, value ); + if ( app != "KADDRESSBOOK" ) + continue; + + FieldRecordList::ConstIterator fieldIt; + for ( fieldIt = mFieldList.begin(); fieldIt != mFieldList.end(); ++fieldIt ) { + if ( (*fieldIt).mIdentifier == name ) { + if ( (*fieldIt).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*fieldIt).mWidget ); + wdg->setText( value ); + } else if ( (*fieldIt).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*fieldIt).mWidget ); + wdg->setValue( value.toInt() ); + } else if ( (*fieldIt).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*fieldIt).mWidget ); + wdg->setChecked( value == "true" || value == "1" ); + } else if ( (*fieldIt).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*fieldIt).mWidget ); + wdg->setDate( QDate::fromString( value, Qt::ISODate ) ); + } else if ( (*fieldIt).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*fieldIt).mWidget ); + wdg->setTime( QTime::fromString( value, Qt::ISODate ) ); + } else if ( (*fieldIt).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*fieldIt).mWidget ); + wdg->setDateTime( QDateTime::fromString( value, Qt::ISODate ) ); + } + } + } + } +} + +void FieldWidget::storeContact( KABC::Addressee *addr ) +{ + FieldRecordList::ConstIterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + QString value; + if ( (*it).mWidget->isA( "QLineEdit" ) ) { + QLineEdit *wdg = static_cast<QLineEdit*>( (*it).mWidget ); + value = wdg->text(); + } else if ( (*it).mWidget->isA( "QSpinBox" ) ) { + QSpinBox *wdg = static_cast<QSpinBox*>( (*it).mWidget ); + value = QString::number( wdg->value() ); + } else if ( (*it).mWidget->isA( "QCheckBox" ) ) { + QCheckBox *wdg = static_cast<QCheckBox*>( (*it).mWidget ); + value = ( wdg->isChecked() ? "true" : "false" ); + } else if ( (*it).mWidget->isA( "QDateEdit" ) ) { + QDateEdit *wdg = static_cast<QDateEdit*>( (*it).mWidget ); + value = wdg->date().toString( Qt::ISODate ); + } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) { + QTimeEdit *wdg = static_cast<QTimeEdit*>( (*it).mWidget ); + value = wdg->time().toString( Qt::ISODate ); + } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) { + QDateTimeEdit *wdg = static_cast<QDateTimeEdit*>( (*it).mWidget ); + value = wdg->dateTime().toString( Qt::ISODate ); + } + + if ( value.isEmpty() ) + addr->removeCustom( "KADDRESSBOOK", (*it).mIdentifier ); + else + addr->insertCustom( "KADDRESSBOOK", (*it).mIdentifier, value ); + } +} + +void FieldWidget::removeLocalFields() +{ + FieldRecordList::Iterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) { + if ( !(*it).mGlobal ) { + delete (*it).mLabel; + delete (*it).mWidget; + delete (*it).mLayout; + + it = mFieldList.remove( it ); + it--; + recalculateLayout(); + } + } +} + +void FieldWidget::recalculateLayout() +{ + int maxWidth = 0; + + FieldRecordList::ConstIterator it; + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + maxWidth = QMAX( maxWidth, (*it).mLabel->minimumSizeHint().width() ); + + for ( it = mFieldList.begin(); it != mFieldList.end(); ++it ) + (*it).mLabel->setMinimumWidth( maxWidth ); +} + +CustomFieldsWidget::CustomFieldsWidget( KABC::AddressBook *ab, + QWidget *parent, const char *name ) + : KAB::ContactEditorWidget( ab, parent, name ) +{ + initGUI(); + + connect( mAddButton, SIGNAL( clicked() ), this, SLOT( addField() ) ); + connect( mRemoveButton, SIGNAL( clicked() ), this, SLOT( removeField() ) ); + + connect( mFieldWidget, SIGNAL( changed() ), this, SLOT( setModified() ) ); +} + +void CustomFieldsWidget::loadContact( KABC::Addressee *addr ) +{ + mAddressee = *addr; + + mFieldWidget->removeLocalFields(); + + AddresseeConfig addrConfig( mAddressee ); + QStringList fields = addrConfig.customFields(); + + if ( !fields.isEmpty() ) { + for ( uint i = 0; i < fields.count(); i += 3 ) { + mFieldWidget->addField( fields[ i ], fields[ i + 1 ], + fields[ i + 2 ] , false ); + mRemoveButton->setEnabled( true ); + } + } + + mFieldWidget->loadContact( addr ); +} + +void CustomFieldsWidget::storeContact( KABC::Addressee *addr ) +{ + mFieldWidget->storeContact( addr ); +} + +void CustomFieldsWidget::setReadOnly( bool readOnly ) +{ + mAddButton->setEnabled( !readOnly ); + mRemoveButton->setEnabled( !readOnly && !mFieldWidget->fields().isEmpty() ); +} + +void CustomFieldsWidget::addField() +{ + AddFieldDialog dlg( this ); + + if ( dlg.exec() ) { + FieldRecordList list = mFieldWidget->fields(); + + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + if ( (*it).mIdentifier == dlg.identifier() ) { + KMessageBox::sorry( this, i18n( "A field with the same name already exists, please choose another one." ) ); + return; + } + + mFieldWidget->addField( dlg.identifier(), dlg.title(), + dlg.type(), dlg.isGlobal() ); + + if ( dlg.isGlobal() ) { + KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) ); + } else { + AddresseeConfig addrConfig( mAddressee ); + addrConfig.setCustomFields( marshallFields( false ) ); + } + + mRemoveButton->setEnabled( true ); + } +} + +void CustomFieldsWidget::removeField() +{ + const FieldRecordList list = mFieldWidget->fields(); + + QStringList fields; + + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) + fields.append( (*it).mTitle ); + + bool ok; + QString title = KInputDialog::getItem( i18n( "Remove Field" ), + i18n( "Select the field you want to remove:" ), + fields, 0, false, &ok, this ); + + if ( ok ) { + for ( it = list.begin(); it != list.end(); ++it ) + if ( (*it).mTitle == title ) { + mFieldWidget->removeField( (*it).mIdentifier ); + + if ( list.count() == 1 ) + mRemoveButton->setEnabled( false ); + + if ( (*it).mGlobal ) { + KABPrefs::instance()->setGlobalCustomFields( marshallFields( true ) ); + } else { + AddresseeConfig addrConfig( mAddressee ); + addrConfig.setCustomFields( marshallFields( false ) ); + } + + return; + } + } +} + +void CustomFieldsWidget::initGUI() +{ + QGridLayout *layout = new QGridLayout( this, 2, 3, KDialog::marginHint(), + KDialog::spacingHint() ); + + mFieldWidget = new FieldWidget( this ); + layout->addMultiCellWidget( mFieldWidget, 0, 0, 0, 2 ); + + mAddButton = new QPushButton( i18n( "Add Field..." ), this ); + layout->addWidget( mAddButton, 1, 1, Qt::AlignRight ); + + mRemoveButton = new QPushButton( i18n( "Remove Field..." ), this ); + mRemoveButton->setEnabled( false ); + layout->addWidget( mRemoveButton, 1, 2, Qt::AlignRight ); + + // load global fields + QStringList globalFields = KABPrefs::instance()->globalCustomFields(); + + if ( globalFields.isEmpty() ) + return; + + for ( uint i = 0; i < globalFields.count(); i += 3 ) { + mFieldWidget->addField( globalFields[ i ], globalFields[ i + 1 ], + globalFields[ i + 2 ] , true ); + mRemoveButton->setEnabled( true ); + } +} + +QStringList CustomFieldsWidget::marshallFields( bool global ) const +{ + QStringList retval; + + const FieldRecordList list = mFieldWidget->fields(); + FieldRecordList::ConstIterator it; + for ( it = list.begin(); it != list.end(); ++it ) { + if ( (*it).mGlobal == global ) { + retval.append( (*it).mIdentifier ); + retval.append( (*it).mTitle ); + + QString type = "text"; + if ( (*it).mWidget->isA( "QSpinBox" ) ) { + type = "integer"; + } else if ( (*it).mWidget->isA( "QCheckBox" ) ) { + type = "boolean"; + } else if ( (*it).mWidget->isA( "QDateEdit" ) ) { + type = "date"; + } else if ( (*it).mWidget->isA( "QTimeEdit" ) ) { + type = "time"; + } else if ( (*it).mWidget->isA( "QDateTimeEdit" ) ) { + type = "datetime"; + } else if ( (*it).mWidget->isA( "QLineEdit" ) ) { + type = "text"; + } + + retval.append( type ); + } + } + + return retval; +} + + +void splitField( const QString &str, QString &app, QString &name, QString &value ) +{ + int colon = str.find( ':' ); + if ( colon != -1 ) { + QString tmp = str.left( colon ); + value = str.mid( colon + 1 ); + + int dash = tmp.find( '-' ); + if ( dash != -1 ) { + app = tmp.left( dash ); + name = tmp.mid( dash + 1 ); + } + } +} + +#include "customfieldswidget.moc" |