akonadi/contact
phoneeditwidget.cpp
00001 /* 00002 This file is part of Akonadi Contact. 00003 00004 Copyright (c) 2009 Tobias Koenig <tokoe@kde.org> 00005 00006 This library is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or (at your 00009 option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, but WITHOUT 00012 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 02110-1301, USA. 00020 */ 00021 00022 #include "phoneeditwidget.h" 00023 00024 #include "autoqpointer_p.h" 00025 00026 #include <QtCore/QSignalMapper> 00027 #include <QtCore/QString> 00028 #include <QtGui/QButtonGroup> 00029 #include <QtGui/QCheckBox> 00030 #include <QtGui/QGridLayout> 00031 #include <QtGui/QGroupBox> 00032 #include <QtGui/QHBoxLayout> 00033 #include <QtGui/QPushButton> 00034 #include <QtGui/QScrollArea> 00035 #include <QtGui/QScrollBar> 00036 #include <QtGui/QVBoxLayout> 00037 00038 #include <kabc/phonenumber.h> 00039 #include <kcombobox.h> 00040 #include <kdebug.h> 00041 #include <klineedit.h> 00042 #include <klocale.h> 00043 00044 PhoneTypeCombo::PhoneTypeCombo( QWidget *parent ) 00045 : KComboBox( parent ), 00046 mType( KABC::PhoneNumber::Home ), 00047 mLastSelected( 0 ) 00048 { 00049 for ( int i = 0; i < KABC::PhoneNumber::typeList().count(); ++i ) 00050 mTypeList.append( KABC::PhoneNumber::typeList().at( i ) ); 00051 00052 mTypeList.append( -1 ); // Others... 00053 00054 update(); 00055 00056 connect( this, SIGNAL( activated( int ) ), 00057 this, SLOT( selected( int ) ) ); 00058 } 00059 00060 PhoneTypeCombo::~PhoneTypeCombo() 00061 { 00062 } 00063 00064 void PhoneTypeCombo::setType( KABC::PhoneNumber::Type type ) 00065 { 00066 if ( !mTypeList.contains( type ) ) 00067 mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), type ); 00068 00069 mType = type; 00070 update(); 00071 } 00072 00073 KABC::PhoneNumber::Type PhoneTypeCombo::type() const 00074 { 00075 return mType; 00076 } 00077 00078 void PhoneTypeCombo::update() 00079 { 00080 clear(); 00081 00082 for ( int i = 0; i < mTypeList.count(); ++i ) { 00083 if ( mTypeList.at( i ) == -1 ) // "Other..." entry 00084 addItem( i18nc( "@item:inlistbox Category of contact info field", "Other..." ) ); 00085 else 00086 addItem( KABC::PhoneNumber::typeLabel( KABC::PhoneNumber::Type( mTypeList.at( i ) ) ) ); 00087 } 00088 00089 setCurrentIndex( mLastSelected = mTypeList.indexOf( mType ) ); 00090 } 00091 00092 void PhoneTypeCombo::selected( int pos ) 00093 { 00094 if ( mTypeList.at( pos ) == -1 ) 00095 otherSelected(); 00096 else { 00097 mType = KABC::PhoneNumber::Type( mTypeList.at( pos ) ); 00098 mLastSelected = pos; 00099 } 00100 } 00101 00102 void PhoneTypeCombo::otherSelected() 00103 { 00104 AutoQPointer<PhoneTypeDialog> dlg = new PhoneTypeDialog( mType, this ); 00105 if ( dlg->exec() ) { 00106 mType = dlg->type(); 00107 if ( !mTypeList.contains( mType ) ) 00108 mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), mType ); 00109 } else { 00110 setType( KABC::PhoneNumber::Type( mTypeList.at( mLastSelected ) ) ); 00111 } 00112 00113 update(); 00114 } 00115 00116 PhoneNumberWidget::PhoneNumberWidget( QWidget *parent ) 00117 : QWidget( parent ) 00118 { 00119 QHBoxLayout *layout = new QHBoxLayout( this ); 00120 layout->setSpacing( 11 ); 00121 layout->setMargin( 0 ); 00122 00123 mTypeCombo = new PhoneTypeCombo( this ); 00124 mNumberEdit = new KLineEdit( this ); 00125 00126 layout->addWidget( mTypeCombo ); 00127 layout->addWidget( mNumberEdit ); 00128 00129 connect( mTypeCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) ); 00130 connect( mNumberEdit, SIGNAL( textChanged( const QString& ) ), SIGNAL( modified() ) ); 00131 } 00132 00133 void PhoneNumberWidget::setNumber( const KABC::PhoneNumber &number ) 00134 { 00135 mNumber = number; 00136 00137 disconnect( mTypeCombo, SIGNAL( activated( int ) ), this, SIGNAL( modified() ) ); 00138 mTypeCombo->setType( number.type() ); 00139 connect( mTypeCombo, SIGNAL( activated( int ) ), SIGNAL( modified() ) ); 00140 00141 mNumberEdit->setText( number.number() ); 00142 } 00143 00144 KABC::PhoneNumber PhoneNumberWidget::number() const 00145 { 00146 KABC::PhoneNumber number( mNumber ); 00147 00148 number.setType( mTypeCombo->type() ); 00149 number.setNumber( mNumberEdit->text() ); 00150 00151 return number; 00152 } 00153 00154 void PhoneNumberWidget::setReadOnly( bool readOnly ) 00155 { 00156 mTypeCombo->setEnabled( !readOnly ); 00157 mNumberEdit->setReadOnly( readOnly ); 00158 } 00159 00160 PhoneNumberListWidget::PhoneNumberListWidget( QWidget *parent ) 00161 : QWidget( parent ), mReadOnly( false ) 00162 { 00163 mWidgetLayout = new QVBoxLayout( this ); 00164 00165 mMapper = new QSignalMapper( this ); 00166 connect( mMapper, SIGNAL( mapped( int ) ), SLOT( changed( int ) ) ); 00167 00168 setPhoneNumbers( KABC::PhoneNumber::List() ); 00169 } 00170 00171 PhoneNumberListWidget::~PhoneNumberListWidget() 00172 { 00173 } 00174 00175 void PhoneNumberListWidget::setReadOnly( bool readOnly ) 00176 { 00177 mReadOnly = readOnly; 00178 00179 foreach ( PhoneNumberWidget *const widget, mWidgets ) 00180 widget->setReadOnly( readOnly ); 00181 } 00182 00183 int PhoneNumberListWidget::phoneNumberCount() const 00184 { 00185 return mPhoneNumberList.count(); 00186 } 00187 00188 void PhoneNumberListWidget::setPhoneNumbers( const KABC::PhoneNumber::List &list ) 00189 { 00190 mPhoneNumberList = list; 00191 00192 KABC::PhoneNumber::TypeList types; 00193 types << KABC::PhoneNumber::Home; 00194 types << KABC::PhoneNumber::Work; 00195 types << KABC::PhoneNumber::Cell; 00196 00197 // add an empty entry per default 00198 if ( mPhoneNumberList.count() < 3 ) 00199 for ( int i = mPhoneNumberList.count(); i < 3; ++i ) 00200 mPhoneNumberList.append( KABC::PhoneNumber( QString(), types[ i ] ) ); 00201 00202 recreateNumberWidgets(); 00203 } 00204 00205 KABC::PhoneNumber::List PhoneNumberListWidget::phoneNumbers() const 00206 { 00207 KABC::PhoneNumber::List list; 00208 00209 KABC::PhoneNumber::List::ConstIterator it; 00210 for ( it = mPhoneNumberList.constBegin(); it != mPhoneNumberList.constEnd(); ++it ) 00211 if ( !(*it).number().isEmpty() ) 00212 list.append( *it ); 00213 00214 return list; 00215 } 00216 00217 void PhoneNumberListWidget::add() 00218 { 00219 mPhoneNumberList.append( KABC::PhoneNumber() ); 00220 00221 recreateNumberWidgets(); 00222 } 00223 00224 void PhoneNumberListWidget::remove() 00225 { 00226 mPhoneNumberList.removeLast(); 00227 00228 recreateNumberWidgets(); 00229 } 00230 00231 void PhoneNumberListWidget::recreateNumberWidgets() 00232 { 00233 foreach ( QWidget *const widget, mWidgets ) { 00234 mWidgetLayout->removeWidget( widget ); 00235 delete widget; 00236 } 00237 mWidgets.clear(); 00238 00239 KABC::PhoneNumber::List::ConstIterator it; 00240 int counter = 0; 00241 for ( it = mPhoneNumberList.constBegin(); it != mPhoneNumberList.constEnd(); ++it ) { 00242 PhoneNumberWidget *wdg = new PhoneNumberWidget( this ); 00243 wdg->setNumber( *it ); 00244 00245 mMapper->setMapping( wdg, counter ); 00246 connect( wdg, SIGNAL( modified() ), mMapper, SLOT( map() ) ); 00247 00248 mWidgetLayout->addWidget( wdg ); 00249 mWidgets.append( wdg ); 00250 wdg->show(); 00251 00252 ++counter; 00253 } 00254 00255 setReadOnly( mReadOnly ); 00256 } 00257 00258 void PhoneNumberListWidget::changed( int pos ) 00259 { 00260 mPhoneNumberList[ pos ] = mWidgets.at( pos )->number(); 00261 } 00262 00263 PhoneEditWidget::PhoneEditWidget( QWidget *parent ) 00264 : QWidget( parent ), mReadOnly( false ) 00265 { 00266 QGridLayout *layout = new QGridLayout( this ); 00267 layout->setSpacing( KDialog::spacingHint() ); 00268 00269 mListScrollArea = new QScrollArea( this ); 00270 mPhoneNumberListWidget = new PhoneNumberListWidget; 00271 mListScrollArea->setWidget( mPhoneNumberListWidget ); 00272 mListScrollArea->setWidgetResizable( true ); 00273 00274 // ugly but size policies seem to be messed up dialog (parent) wide 00275 const int scrollAreaMinHeight = mPhoneNumberListWidget->sizeHint().height() + 00276 mListScrollArea->horizontalScrollBar()->sizeHint().height(); 00277 mListScrollArea->setMinimumHeight( scrollAreaMinHeight ); 00278 layout->addWidget( mListScrollArea, 0, 0, 1, 2 ); 00279 00280 mAddButton = new QPushButton( i18n( "Add" ), this ); 00281 mAddButton->setMaximumSize( mAddButton->sizeHint() ); 00282 layout->addWidget( mAddButton, 1, 0, Qt::AlignRight ); 00283 00284 mRemoveButton = new QPushButton( i18n( "Remove" ), this ); 00285 mRemoveButton->setMaximumSize( mRemoveButton->sizeHint() ); 00286 layout->addWidget( mRemoveButton, 1, 1 ); 00287 00288 connect( mAddButton, SIGNAL( clicked() ), mPhoneNumberListWidget, SLOT( add() ) ); 00289 connect( mRemoveButton, SIGNAL( clicked() ), mPhoneNumberListWidget, SLOT( remove() ) ); 00290 connect( mAddButton, SIGNAL( clicked() ), SLOT( changed() ) ); 00291 connect( mRemoveButton, SIGNAL( clicked() ), SLOT( changed() ) ); 00292 } 00293 00294 PhoneEditWidget::~PhoneEditWidget() 00295 { 00296 } 00297 00298 void PhoneEditWidget::setReadOnly( bool readOnly ) 00299 { 00300 mReadOnly = readOnly; 00301 mAddButton->setEnabled( !readOnly ); 00302 mRemoveButton->setEnabled( !readOnly && mPhoneNumberListWidget->phoneNumberCount() > 3 ); 00303 00304 mPhoneNumberListWidget->setReadOnly( readOnly ); 00305 } 00306 00307 void PhoneEditWidget::changed() 00308 { 00309 mRemoveButton->setEnabled( !mReadOnly && mPhoneNumberListWidget->phoneNumberCount() > 3 ); 00310 } 00311 00312 void PhoneEditWidget::loadContact( const KABC::Addressee &contact ) 00313 { 00314 mPhoneNumberListWidget->setPhoneNumbers( contact.phoneNumbers() ); 00315 changed(); 00316 } 00317 00318 void PhoneEditWidget::storeContact( KABC::Addressee &contact ) const 00319 { 00320 const KABC::PhoneNumber::List oldNumbers = contact.phoneNumbers(); 00321 for ( int i = 0; i < oldNumbers.count(); ++i ) 00322 contact.removePhoneNumber( oldNumbers.at( i ) ); 00323 00324 const KABC::PhoneNumber::List newNumbers = mPhoneNumberListWidget->phoneNumbers(); 00325 for ( int i = 0; i < newNumbers.count(); ++i ) 00326 contact.insertPhoneNumber( newNumbers.at( i ) ); 00327 } 00328 00330 // PhoneTypeDialog 00331 PhoneTypeDialog::PhoneTypeDialog( KABC::PhoneNumber::Type type, QWidget *parent ) 00332 : KDialog( parent), 00333 mType( type ) 00334 { 00335 setCaption( i18n( "Edit Phone Number" ) ); 00336 setButtons( Ok | Cancel ); 00337 setDefaultButton( Ok ); 00338 showButtonSeparator( true ); 00339 00340 QWidget *page = new QWidget( this ); 00341 setMainWidget( page ); 00342 00343 QVBoxLayout *layout = new QVBoxLayout( page ); 00344 layout->setSpacing( spacingHint() ); 00345 layout->setMargin( 0 ); 00346 00347 mPreferredBox = new QCheckBox( i18n( "This is the preferred phone number" ), page ); 00348 layout->addWidget( mPreferredBox ); 00349 00350 QGroupBox *box = new QGroupBox( i18n( "Types" ), page ); 00351 layout->addWidget( box ); 00352 00353 QGridLayout *buttonLayout = new QGridLayout( box ); 00354 00355 // fill widgets 00356 mTypeList = KABC::PhoneNumber::typeList(); 00357 mTypeList.removeAll( KABC::PhoneNumber::Pref ); 00358 00359 KABC::PhoneNumber::TypeList::ConstIterator it; 00360 mGroup = new QButtonGroup( box ); 00361 mGroup->setExclusive( false ); 00362 int row, column, counter; 00363 row = column = counter = 0; 00364 for ( it = mTypeList.constBegin(); it != mTypeList.constEnd(); ++it, ++counter ) { 00365 QCheckBox *cb = new QCheckBox( KABC::PhoneNumber::typeLabel( *it ), box ); 00366 cb->setChecked( type & mTypeList[ counter ] ); 00367 buttonLayout->addWidget( cb, row, column ); 00368 mGroup->addButton( cb ); 00369 00370 column++; 00371 if ( column == 5 ) { 00372 column = 0; 00373 ++row; 00374 } 00375 } 00376 00377 mPreferredBox->setChecked( mType & KABC::PhoneNumber::Pref ); 00378 } 00379 00380 KABC::PhoneNumber::Type PhoneTypeDialog::type() const 00381 { 00382 KABC::PhoneNumber::Type type = 0; 00383 00384 for ( int i = 0; i < mGroup->buttons().count(); ++i ) { 00385 QCheckBox *box = dynamic_cast<QCheckBox*>( mGroup->buttons().at( i ) ) ; 00386 if ( box && box->isChecked() ) 00387 type |= mTypeList[ i ]; 00388 } 00389 00390 if ( mPreferredBox->isChecked() ) 00391 type = type | KABC::PhoneNumber::Pref; 00392 else 00393 type = type & ~KABC::PhoneNumber::Pref; 00394 00395 return type; 00396 } 00397 00398 #include "phoneeditwidget.moc"