• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdepimlibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

akonadi/contact

  • akonadi
  • contact
  • editor
addresseditwidget.cpp
1 /*
2  This file is part of Akonadi Contact.
3 
4  Copyright (c) 2009 Tobias Koenig <tokoe@kde.org>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "addresseditwidget.h"
23 
24 #include "autoqpointer_p.h"
25 
26 #include <QtCore/QEvent>
27 #include <QtCore/QList>
28 #include <QApplication>
29 #include <QBoxLayout>
30 #include <QButtonGroup>
31 #include <QCheckBox>
32 #include <QFrame>
33 #include <QGridLayout>
34 #include <QGroupBox>
35 #include <QKeyEvent>
36 #include <QLabel>
37 #include <QPushButton>
38 
39 #include <kacceleratormanager.h>
40 #include <kcombobox.h>
41 #include <kdebug.h>
42 #include <khbox.h>
43 #include <kinputdialog.h>
44 #include <klineedit.h>
45 #include <klocale.h>
46 #include <kmessagebox.h>
47 #include <kseparator.h>
48 #include <ktextedit.h>
49 
50 #include <functional>
51 
52 struct LocaleAwareLessThan : std::binary_function<QString,QString,bool> {
53  bool operator()( const QString &s1, const QString &s2 ) const
54  {
55  return QString::localeAwareCompare( s1, s2 ) < 0 ;
56  }
57 };
58 
59 class TabPressEater : public QObject
60 {
61  public:
62  TabPressEater( QObject *parent )
63  : QObject( parent )
64  {
65  setObjectName( QLatin1String( "TabPressEater" ) );
66  }
67 
68  protected:
69  bool eventFilter( QObject*, QEvent *event )
70  {
71  if ( event->type() == QEvent::KeyPress ) {
72  QKeyEvent *keyEvent = (QKeyEvent*)event;
73  if ( keyEvent->key() == Qt::Key_Tab ) {
74  QApplication::sendEvent( parent(), event );
75  return true;
76  } else
77  return false;
78  } else {
79  return false;
80  }
81  }
82 };
83 
89 class AddressTypeDialog : public KDialog
90 {
91  public:
92  AddressTypeDialog( KABC::Address::Type type, QWidget *parent );
93  ~AddressTypeDialog();
94 
95  KABC::Address::Type type() const;
96 
97  private:
98  QButtonGroup *mGroup;
99 
100  KABC::Address::TypeList mTypeList;
101 };
102 
103 
104 AddressSelectionWidget::AddressSelectionWidget( QWidget *parent )
105  : KComboBox( parent )
106 {
107  connect( this, SIGNAL(activated(int)), SLOT(selected(int)) );
108 }
109 
110 AddressSelectionWidget::~AddressSelectionWidget()
111 {
112 }
113 
114 void AddressSelectionWidget::setAddresses( const KABC::Address::List &addresses )
115 {
116  mAddresses = addresses;
117  updateView();
118 }
119 
120 void AddressSelectionWidget::setCurrentAddress( const KABC::Address &address )
121 {
122  const int index = mAddresses.indexOf( address );
123  if ( index != -1 ) {
124  setCurrentIndex( index );
125  }
126 }
127 
128 KABC::Address AddressSelectionWidget::currentAddress() const
129 {
130  if ( currentIndex() != -1 && currentIndex() < mAddresses.count() ) {
131  return mAddresses.at( currentIndex() );
132  } else {
133  return KABC::Address();
134  }
135 }
136 
137 void AddressSelectionWidget::selected( int index )
138 {
139  Q_ASSERT( index != -1 && index < mAddresses.count() );
140  emit selectionChanged( mAddresses.at( index ) );
141 }
142 
143 void AddressSelectionWidget::updateView()
144 {
145  clear();
146  for ( int i = 0; i < mAddresses.count(); ++i ) {
147  addItem( KABC::Address::typeLabel( mAddresses.at( i ).type() ) );
148  }
149 }
150 
151 
152 
153 AddressTypeCombo::AddressTypeCombo( QWidget *parent )
154  : KComboBox( parent ),
155  mType( KABC::Address::Home ),
156  mLastSelected( 0 )
157 {
158  for ( int i = 0; i < KABC::Address::typeList().count(); ++i ) {
159  mTypeList.append( KABC::Address::typeList().at( i ) );
160  }
161  mTypeList.append( -1 ); // Others...
162 
163  update();
164 
165  connect( this, SIGNAL(activated(int)),
166  this, SLOT(selected(int)) );
167 }
168 
169 AddressTypeCombo::~AddressTypeCombo()
170 {
171 }
172 
173 void AddressTypeCombo::setType( KABC::Address::Type type )
174 {
175  if ( !mTypeList.contains( (int)type ) ) {
176  // insert at the end, but before the 'Others...' entry
177  mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), (int)type );
178  }
179 
180  mType = type;
181  update();
182 }
183 
184 KABC::Address::Type AddressTypeCombo::type() const
185 {
186  return mType;
187 }
188 
189 void AddressTypeCombo::update()
190 {
191  bool blocked = signalsBlocked();
192  blockSignals( true );
193 
194  clear();
195  for ( int i = 0; i < mTypeList.count(); ++i ) {
196  if ( mTypeList.at( i ) == -1 ) { // "Other..." entry
197  addItem( i18nc( "@item:inlistbox Category of contact info field", "Other..." ) );
198  } else {
199  addItem( KABC::Address::typeLabel( KABC::Address::Type( mTypeList.at( i ) ) ) );
200  }
201  }
202 
203  setCurrentIndex( mLastSelected = mTypeList.indexOf( mType ) );
204 
205  blockSignals( blocked );
206 }
207 
208 void AddressTypeCombo::selected( int pos )
209 {
210  if ( mTypeList.at( pos ) == -1 ) {
211  otherSelected();
212  } else {
213  mType = KABC::Address::Type( mTypeList.at( pos ) );
214  mLastSelected = pos;
215  }
216 }
217 
218 void AddressTypeCombo::otherSelected()
219 {
220  AutoQPointer<AddressTypeDialog> dlg = new AddressTypeDialog( mType, this );
221  if ( dlg->exec() ) {
222  mType = dlg->type();
223  if ( !mTypeList.contains( mType ) ) {
224  mTypeList.insert( mTypeList.at( mTypeList.count() - 1 ), mType );
225  }
226  } else {
227  setType( KABC::Address::Type( mTypeList.at( mLastSelected ) ) );
228  }
229 
230  update();
231 }
232 
233 
234 AddressEditWidget::AddressEditWidget( QWidget *parent )
235  : QWidget( parent ), mReadOnly( false )
236 {
237  QGridLayout *layout = new QGridLayout( this );
238  layout->setSpacing( KDialog::spacingHint() );
239  layout->setMargin( 0 );
240 
241  mAddressSelectionWidget = new AddressSelectionWidget( this );
242  connect( mAddressSelectionWidget, SIGNAL(selectionChanged(KABC::Address)),
243  SLOT(updateAddressView()) );
244  layout->addWidget( mAddressSelectionWidget, 0, 0, 1, 3 );
245 
246  mAddressView = new QLabel( this );
247  mAddressView->setFrameStyle( QFrame::Panel | QFrame::Sunken );
248  mAddressView->setMinimumHeight( 20 );
249  mAddressView->setAlignment( Qt::AlignTop );
250  mAddressView->setTextFormat( Qt::PlainText );
251  mAddressView->setTextInteractionFlags( Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse );
252  layout->addWidget( mAddressView, 1, 0, 1, 3 );
253 
254  mCreateButton = new QPushButton( i18nc( "street/postal", "New..." ), this );
255  connect( mCreateButton, SIGNAL(clicked()), this, SLOT(createAddress()) );
256  mEditButton = new QPushButton( i18nc( "street/postal", "Edit..." ), this );
257  connect( mEditButton, SIGNAL(clicked()), this, SLOT(editAddress()) );
258  mDeleteButton = new QPushButton( i18nc( "street/postal", "Delete" ), this );
259  connect( mDeleteButton, SIGNAL(clicked()), this, SLOT(deleteAddress()) );
260 
261  layout->addWidget( mCreateButton, 2, 0 );
262  layout->addWidget( mEditButton, 2, 1 );
263  layout->addWidget( mDeleteButton, 2, 2 );
264 
265  updateButtons();
266 }
267 
268 AddressEditWidget::~AddressEditWidget()
269 {
270 }
271 
272 void AddressEditWidget::setReadOnly( bool readOnly )
273 {
274  mReadOnly = readOnly;
275  updateButtons();
276 }
277 
278 void AddressEditWidget::updateName( const QString &name )
279 {
280  mName = name;
281  updateAddressView();
282 }
283 
284 void AddressEditWidget::createAddress()
285 {
286  AutoQPointer<AddressEditDialog> dialog = new AddressEditDialog( this );
287  if ( dialog->exec() ) {
288  const KABC::Address address = dialog->address();
289  fixPreferredAddress( address );
290  mAddressList.append( address );
291  mAddressSelectionWidget->setAddresses( mAddressList );
292  mAddressSelectionWidget->setCurrentAddress( address );
293 
294  updateAddressView();
295  updateButtons();
296  }
297 }
298 
299 void AddressEditWidget::editAddress()
300 {
301  AutoQPointer<AddressEditDialog> dialog = new AddressEditDialog( this );
302  dialog->setAddress( mAddressSelectionWidget->currentAddress() );
303  if ( dialog->exec() ) {
304  const KABC::Address address = dialog->address();
305  fixPreferredAddress( address );
306  mAddressList[ mAddressSelectionWidget->currentIndex() ] = address;
307  mAddressSelectionWidget->setAddresses( mAddressList );
308  mAddressSelectionWidget->setCurrentAddress( address );
309 
310  updateAddressView();
311  }
312 }
313 
314 void AddressEditWidget::deleteAddress()
315 {
316  const int result = KMessageBox::questionYesNo( this, i18n( "Do you really want to delete this address?" ) );
317 
318  if ( result != KMessageBox::Yes ) {
319  return;
320  }
321 
322  mAddressList.removeAt( mAddressSelectionWidget->currentIndex() );
323  mAddressSelectionWidget->setAddresses( mAddressList );
324  updateAddressView();
325  updateButtons();
326 }
327 
328 void AddressEditWidget::fixPreferredAddress( const KABC::Address &preferredAddress )
329 {
330  // as the preferred address is mutual exclusive, we have to
331  // remove the flag from all other addresses
332  if ( preferredAddress.type() & KABC::Address::Pref ) {
333  for ( int i = 0; i < mAddressList.count(); ++i ) {
334  KABC::Address &address = mAddressList[ i ];
335  address.setType( address.type() & ~KABC::Address::Pref );
336  }
337  }
338 }
339 
340 void AddressEditWidget::updateAddressView()
341 {
342  const KABC::Address address = mAddressSelectionWidget->currentAddress();
343 
344  if ( address.isEmpty() ) {
345  mAddressView->setText( QString() );
346  } else {
347  mAddressView->setText( address.formattedAddress( mName ) );
348  }
349 }
350 
351 void AddressEditWidget::updateButtons()
352 {
353  mCreateButton->setEnabled( !mReadOnly );
354  mEditButton->setEnabled( !mReadOnly && ( mAddressList.count() > 0 ) );
355  mDeleteButton->setEnabled( !mReadOnly && ( mAddressList.count() > 0 ) );
356 }
357 
358 void AddressEditWidget::loadContact( const KABC::Addressee &contact )
359 {
360  mName = contact.realName();
361  mAddressList = contact.addresses();
362 
363  mAddressSelectionWidget->setAddresses( mAddressList );
364 
365  // set the preferred address as the visible one
366  for ( int i = 0; i < mAddressList.count(); ++i ) {
367  if ( mAddressList.at( i ).type() & KABC::Address::Pref ) {
368  mAddressSelectionWidget->setCurrentAddress( mAddressList.at( i ) );
369  break;
370  }
371  }
372 
373  updateAddressView();
374  updateButtons();
375 }
376 
377 void AddressEditWidget::storeContact( KABC::Addressee &contact ) const
378 {
379  // delete all previous addresses
380  const KABC::Address::List oldAddresses = contact.addresses();
381  for ( int i = 0; i < oldAddresses.count(); ++i ) {
382  contact.removeAddress( oldAddresses.at( i ) );
383  }
384 
385  // insert the new ones
386  for ( int i = 0; i < mAddressList.count(); ++i ) {
387  const KABC::Address address( mAddressList.at( i ) );
388  if ( !address.isEmpty() ) {
389  contact.insertAddress( address );
390  }
391  }
392 }
393 
394 
395 AddressEditDialog::AddressEditDialog( QWidget *parent )
396  : KDialog(parent)
397 {
398  setCaption( i18nc( "street/postal", "Edit Address" ) );
399  setButtons( Ok | Cancel );
400  setDefaultButton( Ok );
401  showButtonSeparator( true );
402 
403  QWidget *page = new QWidget( this );
404  setMainWidget( page );
405 
406  QGridLayout *topLayout = new QGridLayout( page );
407  topLayout->setSpacing( spacingHint() );
408  topLayout->setMargin( 0 );
409 
410  mTypeCombo = new AddressTypeCombo( page );
411  topLayout->addWidget( mTypeCombo, 0, 0, 1, 2 );
412 
413  QLabel *label = new QLabel( i18nc( "<streetLabel>:", "%1:", KABC::Address::streetLabel() ), page );
414  label->setAlignment( Qt::AlignTop | Qt::AlignLeft );
415  topLayout->addWidget( label, 1, 0 );
416  mStreetTextEdit = new KTextEdit( page );
417  mStreetTextEdit->setAcceptRichText( false );
418  label->setBuddy( mStreetTextEdit );
419  topLayout->addWidget( mStreetTextEdit, 1, 1 );
420 
421  TabPressEater *eater = new TabPressEater( this );
422  mStreetTextEdit->installEventFilter( eater );
423 
424  label = new QLabel( i18nc( "<postOfficeBoxLabel>:", "%1:", KABC::Address::postOfficeBoxLabel() ), page );
425  topLayout->addWidget( label, 2 , 0 );
426  mPOBoxEdit = new KLineEdit( page );
427  label->setBuddy( mPOBoxEdit );
428  topLayout->addWidget( mPOBoxEdit, 2, 1 );
429 
430  label = new QLabel( i18nc( "<localityLabel>:", "%1:", KABC::Address::localityLabel() ), page );
431  topLayout->addWidget( label, 3, 0 );
432  mLocalityEdit = new KLineEdit( page );
433  label->setBuddy( mLocalityEdit );
434  topLayout->addWidget( mLocalityEdit, 3, 1 );
435 
436  label = new QLabel( i18nc( "<regionLabel>:", "%1:", KABC::Address::regionLabel() ), page );
437  topLayout->addWidget( label, 4, 0 );
438  mRegionEdit = new KLineEdit( page );
439  label->setBuddy( mRegionEdit );
440  topLayout->addWidget( mRegionEdit, 4, 1 );
441 
442  label = new QLabel( i18nc( "<postalCodeLabel>:", "%1:", KABC::Address::postalCodeLabel() ), page );
443  topLayout->addWidget( label, 5, 0 );
444  mPostalCodeEdit = new KLineEdit( page );
445  label->setBuddy( mPostalCodeEdit );
446  topLayout->addWidget( mPostalCodeEdit, 5, 1 );
447 
448  label = new QLabel( i18nc( "<countryLabel>:", "%1:", KABC::Address::countryLabel() ), page );
449  topLayout->addWidget( label, 6, 0 );
450  mCountryCombo = new KComboBox( page );
451  mCountryCombo->setEditable( true );
452  mCountryCombo->setDuplicatesEnabled( false );
453 
454  QPushButton *labelButton = new QPushButton( i18n( "Edit Label..." ), page );
455  topLayout->addWidget( labelButton, 7, 0, 1, 2 );
456  connect( labelButton, SIGNAL(clicked()), SLOT(editLabel()) );
457 
458  fillCountryCombo();
459  label->setBuddy( mCountryCombo );
460  topLayout->addWidget( mCountryCombo, 6, 1 );
461 
462  mPreferredCheckBox = new QCheckBox( i18nc( "street/postal", "This is the preferred address" ), page );
463  topLayout->addWidget( mPreferredCheckBox, 8, 0, 1, 2 );
464 
465  KSeparator *sep = new KSeparator( Qt::Horizontal, page );
466  topLayout->addWidget( sep, 9, 0, 1, 2 );
467 
468  KHBox *buttonBox = new KHBox( page );
469  buttonBox->setSpacing( spacingHint() );
470  topLayout->addWidget( buttonBox, 10, 0, 1, 2 );
471 
472  KAcceleratorManager::manage( this );
473 }
474 
475 AddressEditDialog::~AddressEditDialog()
476 {
477 }
478 
479 void AddressEditDialog::editLabel()
480 {
481  bool ok = false;
482  QString result = KInputDialog::getMultiLineText( KABC::Address::labelLabel(),
483  KABC::Address::labelLabel(),
484  mLabel, &ok, this );
485  if ( ok ) {
486  mLabel = result;
487  }
488 }
489 
490 void AddressEditDialog::setAddress( const KABC::Address &address )
491 {
492  mAddress = address;
493 
494  mTypeCombo->setType( mAddress.type() );
495  mStreetTextEdit->setPlainText( mAddress.street() );
496  mRegionEdit->setText( mAddress.region() );
497  mLocalityEdit->setText( mAddress.locality() );
498  mPostalCodeEdit->setText( mAddress.postalCode() );
499  mPOBoxEdit->setText( mAddress.postOfficeBox() );
500  mLabel = mAddress.label();
501  mPreferredCheckBox->setChecked( mAddress.type() & KABC::Address::Pref );
502 
503  if ( mAddress.isEmpty() ) {
504  mCountryCombo->setItemText( mCountryCombo->currentIndex(),
505  KGlobal::locale()->countryCodeToName( KGlobal::locale()->country() ) );
506  } else {
507  mCountryCombo->setItemText( mCountryCombo->currentIndex(), mAddress.country() );
508  }
509 
510  mStreetTextEdit->setFocus();
511 }
512 
513 KABC::Address AddressEditDialog::address() const
514 {
515  KABC::Address address( mAddress );
516 
517  address.setType( mTypeCombo->type() );
518  address.setLocality( mLocalityEdit->text() );
519  address.setRegion( mRegionEdit->text() );
520  address.setPostalCode( mPostalCodeEdit->text() );
521  address.setCountry( mCountryCombo->currentText() );
522  address.setPostOfficeBox( mPOBoxEdit->text() );
523  address.setStreet( mStreetTextEdit->toPlainText() );
524  address.setLabel( mLabel );
525 
526  if ( mPreferredCheckBox->isChecked() ) {
527  address.setType( address.type() | KABC::Address::Pref );
528  } else {
529  address.setType( address.type() & ~( KABC::Address::Pref ) );
530  }
531 
532  return address;
533 }
534 
535 void AddressEditDialog::fillCountryCombo()
536 {
537  QStringList countries;
538 
539  foreach ( const QString &cc, KGlobal::locale()->allCountriesList() ) {
540  countries.append( KGlobal::locale()->countryCodeToName( cc ) );
541  }
542 
543  qSort( countries.begin(), countries.end(), LocaleAwareLessThan() );
544 
545  mCountryCombo->addItems( countries );
546  mCountryCombo->setAutoCompletion( true );
547  mCountryCombo->completionObject()->setItems( countries );
548  mCountryCombo->completionObject()->setIgnoreCase( true );
549 
550  const QString currentCountry = KGlobal::locale()->countryCodeToName( KGlobal::locale()->country() );
551  mCountryCombo->setCurrentIndex( mCountryCombo->findText( currentCountry ) );
552 }
553 
554 
555 AddressTypeDialog::AddressTypeDialog( KABC::Address::Type type, QWidget *parent )
556  : KDialog( parent)
557 {
558  setCaption( i18nc( "street/postal", "Edit Address Type" ) );
559  setButtons( Ok | Cancel );
560  setDefaultButton( Ok );
561 
562  QWidget *page = new QWidget( this );
563  setMainWidget( page );
564  QVBoxLayout *layout = new QVBoxLayout( page );
565  layout->setSpacing( KDialog::spacingHint() );
566  layout->setMargin( 0 );
567 
568  QGroupBox *box = new QGroupBox( i18nc( "street/postal", "Address Types" ), page );
569  layout->addWidget( box );
570  mGroup = new QButtonGroup( box );
571  mGroup->setExclusive ( false );
572 
573  QGridLayout *buttonLayout = new QGridLayout( box );
574 
575  mTypeList = KABC::Address::typeList();
576  mTypeList.removeAll( KABC::Address::Pref );
577 
578  KABC::Address::TypeList::ConstIterator it;
579  int i = 0;
580  int row = 0;
581  for ( it = mTypeList.constBegin(); it != mTypeList.constEnd(); ++it, ++i ) {
582  QCheckBox *cb = new QCheckBox( KABC::Address::typeLabel( *it ), box );
583  cb->setChecked( type & mTypeList[ i ] );
584  buttonLayout->addWidget( cb, row, i%3 );
585 
586  if ( i % 3 == 2 ) {
587  ++row;
588  }
589  mGroup->addButton( cb );
590  }
591 }
592 
593 AddressTypeDialog::~AddressTypeDialog()
594 {
595 }
596 
597 KABC::Address::Type AddressTypeDialog::type() const
598 {
599  KABC::Address::Type type;
600  for ( int i = 0; i < mGroup->buttons().count(); ++i ) {
601  QCheckBox *box = dynamic_cast<QCheckBox*>( mGroup->buttons().at( i ) );
602  if ( box && box->isChecked() ) {
603  type |= mTypeList[ i ];
604  }
605  }
606 
607  return type;
608 }
609 
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Sat Jul 13 2013 01:28:41 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi/contact

Skip menu "akonadi/contact"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs-4.10.5 API Reference

Skip menu "kdepimlibs-4.10.5 API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal