kaddressbook

distributionlistwidget.cpp

00001 /*
00002     This file is part of KAddressBook.
00003     Copyright (c) 2002 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     As a special exception, permission is given to link this program
00019     with any edition of Qt, and distribute the resulting executable,
00020     without including the source code for Qt in the source distribution.
00021 */
00022 
00023 #include "distributionlistwidget.h"
00024 
00025 #include <qbuttongroup.h>
00026 #include <qcombobox.h>
00027 #include <qlabel.h>
00028 #include <qlayout.h>
00029 #include <qlistview.h>
00030 #include <qpushbutton.h>
00031 #include <qradiobutton.h>
00032 
00033 #include <kaccelmanager.h>
00034 #include <kconfig.h>
00035 #include <kdebug.h>
00036 #include <kglobal.h>
00037 #include <kinputdialog.h>
00038 #include <klocale.h>
00039 #include <kmessagebox.h>
00040 
00041 #include <kabc/addresseedialog.h>
00042 #ifdef KDEPIM_NEW_DISTRLISTS
00043 #include <libkdepim/distributionlist.h>
00044 typedef KPIM::DistributionList DistributionList;
00045 #else
00046 #include <kabc/distributionlist.h>
00047 typedef KABC::DistributionList DistributionList;
00048 #endif
00049 #include <kabc/stdaddressbook.h>
00050 #include <kabc/vcardconverter.h>
00051 #include <libkdepim/kvcarddrag.h>
00052 
00053 #include "core.h"
00054 
00055 class DistributionListFactory : public KAB::ExtensionFactory
00056 {
00057   public:
00058     KAB::ExtensionWidget *extension( KAB::Core *core, QWidget *parent, const char *name )
00059     {
00060       return new DistributionListWidget( core, parent, name );
00061     }
00062 
00063     QString identifier() const
00064     {
00065       return "distribution_list_editor";
00066     }
00067 };
00068 
00069 extern "C" {
00070   void *init_libkaddrbk_distributionlist()
00071   {
00072     return ( new DistributionListFactory );
00073   }
00074 }
00075 
00081 class DeletePressedCatcher : public QObject
00082 {
00083   public:
00084     DeletePressedCatcher( DistributionListWidget *parent )
00085       : QObject( parent, "DeletePressedCatcher" ), mWidget( parent )
00086     {
00087     }
00088 
00089   protected:
00090     bool eventFilter( QObject*, QEvent *event )
00091     {
00092       if ( event->type() == QEvent::AccelOverride ) {
00093         QKeyEvent *keyEvent = (QKeyEvent*)event;
00094         if ( keyEvent->key() == Qt::Key_Delete ) {
00095           keyEvent->accept();
00096           mWidget->removeContact();
00097           return true;
00098         } else
00099           return false;
00100       } else {
00101         return false;
00102       }
00103     }
00104 
00105   private:
00106     DistributionListWidget *mWidget;
00107 };
00108 
00109 class ContactItem : public QListViewItem
00110 {
00111   public:
00112     ContactItem( DistributionListView *parent, const KABC::Addressee &addressee,
00113                const QString &email = QString::null ) :
00114       QListViewItem( parent ),
00115       mAddressee( addressee ),
00116       mEmail( email )
00117     {
00118       setText( 0, addressee.realName() );
00119       if ( email.isEmpty() ) {
00120         setText( 1, addressee.preferredEmail() );
00121         setText( 2, i18n( "Yes" ) );
00122       } else {
00123         setText( 1, email );
00124         setText( 2, i18n( "No" ) );
00125       }
00126     }
00127 
00128     KABC::Addressee addressee() const
00129     {
00130       return mAddressee;
00131     }
00132 
00133     QString email() const
00134     {
00135       return mEmail;
00136     }
00137 
00138   protected:
00139     bool acceptDrop( const QMimeSource* )
00140     {
00141       return true;
00142     }
00143 
00144   private:
00145     KABC::Addressee mAddressee;
00146     QString mEmail;
00147 };
00148 
00149 DistributionListWidget::DistributionListWidget( KAB::Core *core, QWidget *parent,
00150                                                 const char *name )
00151   : KAB::ExtensionWidget( core, parent, name )
00152 #ifndef KDEPIM_NEW_DISTRLISTS
00153   , mManager( 0 )
00154 #endif
00155 {
00156   QGridLayout *topLayout = new QGridLayout( this, 3, 4, KDialog::marginHint(),
00157                                             KDialog::spacingHint() );
00158 
00159   mNameCombo = new QComboBox( this );
00160   topLayout->addWidget( mNameCombo, 0, 0 );
00161   connect( mNameCombo, SIGNAL( activated( int ) ), SLOT( updateContactView() ) );
00162 
00163   mCreateListButton = new QPushButton( i18n( "New List..." ), this );
00164   topLayout->addWidget( mCreateListButton, 0, 1 );
00165   connect( mCreateListButton, SIGNAL( clicked() ), SLOT( createList() ) );
00166 
00167   mEditListButton = new QPushButton( i18n( "Rename List..." ), this );
00168   topLayout->addWidget( mEditListButton, 0, 2 );
00169   connect( mEditListButton, SIGNAL( clicked() ), SLOT( editList() ) );
00170 
00171   mRemoveListButton = new QPushButton( i18n( "Remove List" ), this );
00172   topLayout->addWidget( mRemoveListButton, 0, 3 );
00173   connect( mRemoveListButton, SIGNAL( clicked() ), SLOT( removeList() ) );
00174 
00175   mContactView = new DistributionListView( this );
00176   mContactView->addColumn( i18n( "Name" ) );
00177   mContactView->addColumn( i18n( "Email" ) );
00178   mContactView->addColumn( i18n( "Use Preferred" ) );
00179   mContactView->setEnabled( false );
00180   mContactView->setAllColumnsShowFocus( true );
00181   mContactView->setFullWidth( true );
00182   topLayout->addMultiCellWidget( mContactView, 1, 1, 0, 3 );
00183   connect( mContactView, SIGNAL( selectionChanged() ),
00184            SLOT( selectionContactViewChanged() ) );
00185   connect( mContactView, SIGNAL( dropped( QDropEvent*, QListViewItem* ) ),
00186            SLOT( dropped( QDropEvent*, QListViewItem* ) ) );
00187 
00188   mAddContactButton = new QPushButton( i18n( "Add Contact" ), this );
00189   mAddContactButton->setEnabled( false );
00190   topLayout->addWidget( mAddContactButton, 2, 0 );
00191   connect( mAddContactButton, SIGNAL( clicked() ), SLOT( addContact() ) );
00192 
00193   mEntryCountLabel = new QLabel( this );
00194   topLayout->addWidget( mEntryCountLabel, 2, 1 );
00195 
00196   mChangeEmailButton = new QPushButton( i18n( "Change Email..." ), this );
00197   topLayout->addWidget( mChangeEmailButton, 2, 2 );
00198   connect( mChangeEmailButton, SIGNAL( clicked() ), SLOT( changeEmail() ) );
00199 
00200   mRemoveContactButton = new QPushButton( i18n( "Remove Contact" ), this );
00201   topLayout->addWidget( mRemoveContactButton, 2, 3 );
00202   connect( mRemoveContactButton, SIGNAL( clicked() ), SLOT( removeContact() ) );
00203 
00204 #ifdef KDEPIM_NEW_DISTRLISTS
00205   // When contacts are changed, update both distr list combo and contents of displayed distr list
00206   connect( core, SIGNAL( contactsUpdated() ),
00207            this, SLOT( updateNameCombo() ) );
00208 #else
00209   mManager = new KABC::DistributionListManager( core->addressBook() );
00210 
00211   connect( KABC::DistributionListWatcher::self(), SIGNAL( changed() ),
00212            this, SLOT( updateNameCombo() ) );
00213 #endif
00214 
00215   connect( core->addressBook(), SIGNAL( addressBookChanged( AddressBook* ) ),
00216            this, SLOT( updateNameCombo() ) );
00217 
00218   updateNameCombo();
00219 
00220   QObject *catcher = new DeletePressedCatcher( this );
00221   installEventFilter( catcher );
00222   mContactView->installEventFilter( catcher );
00223 
00224   mContactView->restoreLayout( KGlobal::config(), "DistributionListViewColumns" );
00225 
00226   KAcceleratorManager::manage( this );
00227 }
00228 
00229 DistributionListWidget::~DistributionListWidget()
00230 {
00231 #ifndef KDEPIM_NEW_DISTRLISTS
00232   delete mManager;
00233 #endif
00234 
00235   mContactView->saveLayout( KGlobal::config(), "DistributionListViewColumns" );
00236 }
00237 
00238 void DistributionListWidget::save()
00239 {
00240 #ifndef KDEPIM_NEW_DISTRLISTS
00241   mManager->save();
00242 #endif
00243 }
00244 
00245 void DistributionListWidget::selectionContactViewChanged()
00246 {
00247   ContactItem *contactItem =
00248                   static_cast<ContactItem *>( mContactView->selectedItem() );
00249   bool state = contactItem;
00250 
00251   mChangeEmailButton->setEnabled( state );
00252   mRemoveContactButton->setEnabled( state );
00253 }
00254 
00255 bool DistributionListWidget::alreadyExists( const QString& distrListName ) const
00256 {
00257 #ifdef KDEPIM_NEW_DISTRLISTS
00258   return core()->distributionListNames().contains( distrListName );
00259 #else
00260   return mManager->listNames().contains( distrListName );
00261 #endif
00262 }
00263 
00264 void DistributionListWidget::createList()
00265 {
00266   QString newName = KInputDialog::getText( i18n( "New Distribution List" ),
00267                                            i18n( "Please enter name:" ),
00268                                            QString::null, 0, this );
00269 
00270   if ( newName.isEmpty() ) return;
00271 
00272   if ( alreadyExists( newName ) ) {
00273     KMessageBox::sorry( this, i18n( "The name already exists" ) );
00274     return;
00275   }
00276 #ifdef KDEPIM_NEW_DISTRLISTS
00277   KABC::Resource* resource = core()->requestResource( this );
00278   if ( !resource )
00279     return;
00280 
00281   KPIM::DistributionList dist;
00282   dist.setResource( resource );
00283   dist.setName( newName );
00284   core()->addressBook()->insertAddressee( dist );
00285 
00286   // Creates undo-redo command, calls setModified, also triggers contactsUpdated,
00287   // which triggers updateNameCombo, so the new name appears
00288   changed( dist );
00289 
00290 #else
00291   new KABC::DistributionList( mManager, newName );
00292   changed();
00293 
00294   updateNameCombo();
00295 #endif
00296 
00297   // Select the new one in the list
00298   mNameCombo->setCurrentText( newName );
00299   // Display the contents of the list we just selected (well, it's empty)
00300   updateContactView();
00301 }
00302 
00303 void DistributionListWidget::editList()
00304 {
00305   const QString oldName = mNameCombo->currentText();
00306 
00307   const QString newName = KInputDialog::getText( i18n( "Rename Distribution List" ),
00308                                                  i18n( "Please enter name:" ),
00309                                                  oldName, 0, this );
00310 
00311   if ( newName.isEmpty() ) return;
00312 
00313   if ( alreadyExists( newName ) ) {
00314     KMessageBox::sorry( this, i18n( "The name already exists." ) );
00315     return;
00316   }
00317 #ifdef KDEPIM_NEW_DISTRLISTS
00318   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00319     core()->addressBook(), mNameCombo->currentText() );
00320   if ( dist.isEmpty() ) // not found [should be impossible]
00321     return;
00322 
00323   dist.setFormattedName( newName );
00324   core()->addressBook()->insertAddressee( dist );
00325 
00326   changed( dist );
00327 #else
00328   KABC::DistributionList *list = mManager->list( oldName );
00329   list->setName( newName );
00330   mManager->save();
00331   updateNameCombo();
00332 #endif
00333 
00334   // Select the new name in the list (updateNameCombo couldn't know we wanted that one)
00335   mNameCombo->setCurrentText( newName );
00336   // Display the contents of the list we just selected
00337   updateContactView();
00338 
00339 #ifndef KDEPIM_NEW_DISTRLISTS
00340   changed();
00341 #endif
00342 }
00343 
00344 void DistributionListWidget::removeList()
00345 {
00346   int result = KMessageBox::warningContinueCancel( this,
00347       i18n( "<qt>Delete distribution list <b>%1</b>?</qt>" ) .arg( mNameCombo->currentText() ),
00348       QString::null, KGuiItem( i18n("Delete"), "editdelete") );
00349 
00350   if ( result != KMessageBox::Continue )
00351     return;
00352 
00353 #ifdef KDEPIM_NEW_DISTRLISTS
00354   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00355     core()->addressBook(), mNameCombo->currentText() );
00356   if ( dist.isEmpty() ) // not found [should be impossible]
00357     return;
00358 
00359   core()->addressBook()->removeAddressee( dist );
00360 
00361   emit deleted( dist.uid() );
00362 #else
00363   mManager->remove( mManager->list( mNameCombo->currentText() ) );
00364   mNameCombo->removeItem( mNameCombo->currentItem() );
00365 
00366   updateContactView();
00367 
00368   changed();
00369 #endif
00370 }
00371 
00372 void DistributionListWidget::addContact()
00373 {
00374 #ifdef KDEPIM_NEW_DISTRLISTS
00375   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00376     core()->addressBook(), mNameCombo->currentText() );
00377   if ( dist.isEmpty() ) { // not found
00378     kdDebug(5720) << k_funcinfo << mNameCombo->currentText() << " not found" << endl;
00379     return;
00380   }
00381 #else
00382   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00383   if ( !list )
00384     return;
00385   KABC::DistributionList& dist = *list;
00386 #endif
00387 
00388   const KABC::Addressee::List addrList = selectedContacts();
00389   KABC::Addressee::List::ConstIterator it;
00390   for ( it = addrList.begin(); it != addrList.end(); ++it )
00391     dist.insertEntry( *it );
00392 
00393 #ifdef KDEPIM_NEW_DISTRLISTS
00394   core()->addressBook()->insertAddressee( dist );
00395   changed( dist );
00396 #else
00397   updateContactView();
00398   changed();
00399 #endif
00400 }
00401 
00402 void DistributionListWidget::removeContact()
00403 {
00404 #ifdef KDEPIM_NEW_DISTRLISTS
00405   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00406     core()->addressBook(), mNameCombo->currentText() );
00407   if ( dist.isEmpty() ) // not found
00408     return;
00409 #else
00410   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00411   if ( !list )
00412     return;
00413   KABC::DistributionList& dist = *list;
00414 #endif
00415 
00416   ContactItem *contactItem =
00417                     static_cast<ContactItem *>( mContactView->selectedItem() );
00418   if ( !contactItem )
00419     return;
00420 
00421   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00422   delete contactItem;
00423 
00424 #ifdef KDEPIM_NEW_DISTRLISTS
00425   core()->addressBook()->insertAddressee( dist );
00426   changed( dist );
00427 #else
00428   changed();
00429 #endif
00430 }
00431 
00432 void DistributionListWidget::changeEmail()
00433 {
00434 #ifdef KDEPIM_NEW_DISTRLISTS
00435   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00436     core()->addressBook(), mNameCombo->currentText() );
00437   if ( dist.isEmpty() ) // not found
00438     return;
00439 #else
00440   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00441   if ( !list )
00442     return;
00443   KABC::DistributionList& dist = *list;
00444 #endif
00445 
00446   ContactItem *contactItem =
00447                     static_cast<ContactItem *>( mContactView->selectedItem() );
00448   if ( !contactItem )
00449     return;
00450 
00451   const QString email = EmailSelector::getEmail( contactItem->addressee().emails(),
00452                                                  contactItem->email(), this );
00453   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00454   dist.insertEntry( contactItem->addressee(), email );
00455 
00456 #ifdef KDEPIM_NEW_DISTRLISTS
00457   core()->addressBook()->insertAddressee( dist );
00458   changed( dist );
00459 #else
00460   updateContactView();
00461   changed();
00462 #endif
00463 }
00464 
00465 void DistributionListWidget::updateContactView()
00466 {
00467   mContactView->clear();
00468 
00469   bool isListSelected = false;
00470 #ifdef KDEPIM_NEW_DISTRLISTS
00471   KPIM::DistributionList dist;
00472   if ( mNameCombo->count() != 0 )
00473     dist = KPIM::DistributionList::findByName(
00474       core()->addressBook(), mNameCombo->currentText() );
00475   isListSelected = !dist.isEmpty();
00476 #else
00477   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00478   isListSelected = list != 0;
00479 #endif
00480   if ( !isListSelected ) {
00481     mEditListButton->setEnabled( false );
00482     mRemoveListButton->setEnabled( false );
00483     mChangeEmailButton->setEnabled( false );
00484     mRemoveContactButton->setEnabled( false );
00485     mContactView->setEnabled( false );
00486     return;
00487   }
00488   mEditListButton->setEnabled( true );
00489   mRemoveListButton->setEnabled( true );
00490   mContactView->setEnabled( true );
00491 
00492   uint entryCount = 0;
00493 #ifdef KDEPIM_NEW_DISTRLISTS
00494   const KPIM::DistributionList::Entry::List entries = dist.entries( core()->addressBook() );
00495   KPIM::DistributionList::Entry::List::ConstIterator it;
00496 #else
00497   const KABC::DistributionList::Entry::List entries = list->entries();
00498   KABC::DistributionList::Entry::List::ConstIterator it;
00499 #endif
00500   for ( it = entries.begin(); it != entries.end(); ++it, ++entryCount )
00501     new ContactItem( mContactView, (*it).addressee, (*it).email );
00502 
00503   bool state = mContactView->selectedItem() != 0;
00504   mChangeEmailButton->setEnabled( state );
00505   mRemoveContactButton->setEnabled( state );
00506 
00507   mEntryCountLabel->setText( i18n( "Count: %n contact", "Count: %n contacts", entryCount ) );
00508 }
00509 
00510 void DistributionListWidget::updateNameCombo()
00511 {
00512   int pos = mNameCombo->currentItem();
00513   mNameCombo->clear();
00514 #ifdef KDEPIM_NEW_DISTRLISTS
00515   const QStringList names = core()->distributionListNames();
00516 #else
00517   mManager->load();
00518   const QStringList names = mManager->listNames();
00519 #endif
00520   mNameCombo->insertStringList( names );
00521   mNameCombo->setCurrentItem( QMIN( pos, (int)names.count() - 1 ) );
00522 
00523   updateContactView();
00524 }
00525 
00526 void DistributionListWidget::dropEvent( QDropEvent *e )
00527 {
00528   if ( mNameCombo->count() == 0 )
00529     return;
00530 
00531 #ifdef KDEPIM_NEW_DISTRLISTS
00532   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00533     core()->addressBook(), mNameCombo->currentText() );
00534   if ( dist.isEmpty() )
00535     return;
00536 #else
00537   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00538   if ( !list )
00539     return;
00540   KABC::DistributionList& dist = *list;
00541 #endif
00542 
00543   QString vcards;
00544   if ( KVCardDrag::decode( e, vcards ) ) {
00545     KABC::VCardConverter converter;
00546     const KABC::Addressee::List lst = converter.parseVCards( vcards );
00547     for ( KABC::Addressee::List::ConstIterator it = lst.begin(); it != lst.end(); ++it )
00548       dist.insertEntry( *it );
00549 
00550 #ifdef KDEPIM_NEW_DISTRLISTS
00551     core()->addressBook()->insertAddressee( dist );
00552     changed( dist );
00553 #else
00554     changed();
00555     updateContactView();
00556 #endif
00557   }
00558 }
00559 
00560 void DistributionListWidget::contactsSelectionChanged()
00561 {
00562   mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 );
00563 }
00564 
00565 QString DistributionListWidget::title() const
00566 {
00567   return i18n( "Distribution List Editor" );
00568 }
00569 
00570 QString DistributionListWidget::identifier() const
00571 {
00572   return "distribution_list_editor";
00573 }
00574 
00575 void DistributionListWidget::dropped( QDropEvent *e, QListViewItem* )
00576 {
00577   dropEvent( e );
00578 }
00579 
00580 #ifdef KDEPIM_NEW_DISTRLISTS
00581 void DistributionListWidget::changed( const KABC::Addressee& dist )
00582 {
00583   emit modified( KABC::Addressee::List() << dist );
00584 }
00585 #else
00586 void DistributionListWidget::changed()
00587 {
00588   save();
00589 }
00590 #endif
00591 
00592 DistributionListView::DistributionListView( QWidget *parent, const char* name )
00593   : KListView( parent, name )
00594 {
00595   setDragEnabled( true );
00596   setAcceptDrops( true );
00597   setAllColumnsShowFocus( true );
00598 }
00599 
00600 void DistributionListView::dragEnterEvent( QDragEnterEvent* e )
00601 {
00602   bool canDecode = QTextDrag::canDecode( e );
00603   e->accept( canDecode );
00604 }
00605 
00606 void DistributionListView::viewportDragMoveEvent( QDragMoveEvent *e )
00607 {
00608   bool canDecode = QTextDrag::canDecode( e );
00609   e->accept( canDecode );
00610 }
00611 
00612 void DistributionListView::viewportDropEvent( QDropEvent *e )
00613 {
00614   emit dropped( e, 0 );
00615 }
00616 
00617 void DistributionListView::dropEvent( QDropEvent *e )
00618 {
00619   emit dropped( e, 0 );
00620 }
00621 
00622 
00623 EmailSelector::EmailSelector( const QStringList &emails,
00624                               const QString &current, QWidget *parent )
00625   : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok,
00626                parent )
00627 {
00628   QFrame *topFrame = plainPage();
00629   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00630 
00631   mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"),
00632                                    topFrame );
00633   mButtonGroup->setRadioButtonExclusive( true );
00634   topLayout->addWidget( mButtonGroup );
00635 
00636   QRadioButton *button = new QRadioButton( i18n("Preferred address"), mButtonGroup );
00637   button->setDown( true );
00638   mEmailMap.insert( mButtonGroup->id( button ), "" );
00639 
00640   QStringList::ConstIterator it;
00641   for ( it = emails.begin(); it != emails.end(); ++it ) {
00642     button = new QRadioButton( *it, mButtonGroup );
00643     mEmailMap.insert( mButtonGroup->id( button ), *it );
00644     if ( (*it) == current )
00645       button->setDown( true );
00646   }
00647 }
00648 
00649 QString EmailSelector::selected() const
00650 {
00651   QButton *button = mButtonGroup->selected();
00652   if ( button )
00653     return mEmailMap[ mButtonGroup->id( button ) ];
00654 
00655   return QString::null;
00656 }
00657 
00658 QString EmailSelector::getEmail( const QStringList &emails,
00659                                  const QString &current, QWidget *parent )
00660 {
00661   EmailSelector dlg( emails, current, parent );
00662   dlg.exec();
00663 
00664   return dlg.selected();
00665 }
00666 
00667 
00668 #include "distributionlistwidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys