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   // Creates undo-redo command, calls setModified, also triggers contactsUpdated,
00285   // which triggers updateNameCombo, so the new name appears
00286   changed( dist );
00287   core()->addressBook()->insertAddressee( dist );
00288 
00289 #else
00290   new KABC::DistributionList( mManager, newName );
00291   changed();
00292 
00293   updateNameCombo();
00294 #endif
00295 
00296   // Select the new one in the list
00297   mNameCombo->setCurrentText( newName );
00298   // Display the contents of the list we just selected (well, it's empty)
00299   updateContactView();
00300 }
00301 
00302 void DistributionListWidget::editList()
00303 {
00304   const QString oldName = mNameCombo->currentText();
00305 
00306   const QString newName = KInputDialog::getText( i18n( "Rename Distribution List" ),
00307                                                  i18n( "Please enter name:" ),
00308                                                  oldName, 0, this );
00309 
00310   if ( newName.isEmpty() ) return;
00311 
00312   if ( alreadyExists( newName ) ) {
00313     KMessageBox::sorry( this, i18n( "The name already exists." ) );
00314     return;
00315   }
00316 #ifdef KDEPIM_NEW_DISTRLISTS
00317   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00318     core()->addressBook(), mNameCombo->currentText() );
00319   if ( dist.isEmpty() ) // not found [should be impossible]
00320     return;
00321 
00322   dist.setFormattedName( newName );
00323   core()->addressBook()->insertAddressee( dist );
00324 
00325   changed( dist );
00326 #else
00327   KABC::DistributionList *list = mManager->list( oldName );
00328   list->setName( newName );
00329   mManager->save();
00330   updateNameCombo();
00331 #endif
00332 
00333   // Select the new name in the list (updateNameCombo couldn't know we wanted that one)
00334   mNameCombo->setCurrentText( newName );
00335   // Display the contents of the list we just selected
00336   updateContactView();
00337 
00338 #ifndef KDEPIM_NEW_DISTRLISTS
00339   changed();
00340 #endif
00341 }
00342 
00343 void DistributionListWidget::removeList()
00344 {
00345   int result = KMessageBox::warningContinueCancel( this,
00346       i18n( "<qt>Delete distribution list <b>%1</b>?</qt>" ) .arg( mNameCombo->currentText() ),
00347       QString::null, KGuiItem( i18n("Delete"), "editdelete") );
00348 
00349   if ( result != KMessageBox::Continue )
00350     return;
00351 
00352 #ifdef KDEPIM_NEW_DISTRLISTS
00353   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00354     core()->addressBook(), mNameCombo->currentText() );
00355   if ( dist.isEmpty() ) // not found [should be impossible]
00356     return;
00357 
00358   emit deleted( dist.uid() );
00359   core()->addressBook()->removeAddressee( dist );
00360 #else
00361   mManager->remove( mManager->list( mNameCombo->currentText() ) );
00362   mNameCombo->removeItem( mNameCombo->currentItem() );
00363 
00364   updateContactView();
00365 
00366   changed();
00367 #endif
00368 }
00369 
00370 void DistributionListWidget::addContact()
00371 {
00372 #ifdef KDEPIM_NEW_DISTRLISTS
00373   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00374     core()->addressBook(), mNameCombo->currentText() );
00375   if ( dist.isEmpty() ) { // not found
00376     kdDebug(5720) << k_funcinfo << mNameCombo->currentText() << " not found" << endl;
00377     return;
00378   }
00379 #else
00380   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00381   if ( !list )
00382     return;
00383   KABC::DistributionList& dist = *list;
00384 #endif
00385 
00386   const KABC::Addressee::List addrList = selectedContacts();
00387   KABC::Addressee::List::ConstIterator it;
00388   for ( it = addrList.begin(); it != addrList.end(); ++it )
00389     dist.insertEntry( *it );
00390 
00391 #ifdef KDEPIM_NEW_DISTRLISTS
00392   core()->addressBook()->insertAddressee( dist );
00393   changed( dist );
00394 #else
00395   updateContactView();
00396   changed();
00397 #endif
00398 }
00399 
00400 void DistributionListWidget::removeContact()
00401 {
00402 #ifdef KDEPIM_NEW_DISTRLISTS
00403   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00404     core()->addressBook(), mNameCombo->currentText() );
00405   if ( dist.isEmpty() ) // not found
00406     return;
00407 #else
00408   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00409   if ( !list )
00410     return;
00411   KABC::DistributionList& dist = *list;
00412 #endif
00413 
00414   ContactItem *contactItem =
00415                     static_cast<ContactItem *>( mContactView->selectedItem() );
00416   if ( !contactItem )
00417     return;
00418 
00419   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00420   delete contactItem;
00421 
00422 #ifdef KDEPIM_NEW_DISTRLISTS
00423   core()->addressBook()->insertAddressee( dist );
00424   changed( dist );
00425 #else
00426   changed();
00427 #endif
00428 }
00429 
00430 void DistributionListWidget::changeEmail()
00431 {
00432 #ifdef KDEPIM_NEW_DISTRLISTS
00433   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00434     core()->addressBook(), mNameCombo->currentText() );
00435   if ( dist.isEmpty() ) // not found
00436     return;
00437 #else
00438   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00439   if ( !list )
00440     return;
00441   KABC::DistributionList& dist = *list;
00442 #endif
00443 
00444   ContactItem *contactItem =
00445                     static_cast<ContactItem *>( mContactView->selectedItem() );
00446   if ( !contactItem )
00447     return;
00448 
00449   const QString email = EmailSelector::getEmail( contactItem->addressee().emails(),
00450                                                  contactItem->email(), this );
00451   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00452   dist.insertEntry( contactItem->addressee(), email );
00453 
00454 #ifdef KDEPIM_NEW_DISTRLISTS
00455   core()->addressBook()->insertAddressee( dist );
00456   changed( dist );
00457 #else
00458   updateContactView();
00459   changed();
00460 #endif
00461 }
00462 
00463 void DistributionListWidget::updateContactView()
00464 {
00465   mContactView->clear();
00466 
00467   bool isListSelected = false;
00468 #ifdef KDEPIM_NEW_DISTRLISTS
00469   KPIM::DistributionList dist;
00470   if ( mNameCombo->count() != 0 )
00471     dist = KPIM::DistributionList::findByName(
00472       core()->addressBook(), mNameCombo->currentText() );
00473   isListSelected = !dist.isEmpty();
00474 #else
00475   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00476   isListSelected = list != 0;
00477 #endif
00478   if ( !isListSelected ) {
00479     mEditListButton->setEnabled( false );
00480     mRemoveListButton->setEnabled( false );
00481     mChangeEmailButton->setEnabled( false );
00482     mRemoveContactButton->setEnabled( false );
00483     mContactView->setEnabled( false );
00484     return;
00485   }
00486   mEditListButton->setEnabled( true );
00487   mRemoveListButton->setEnabled( true );
00488   mContactView->setEnabled( true );
00489 
00490   uint entryCount = 0;
00491 #ifdef KDEPIM_NEW_DISTRLISTS
00492   const KPIM::DistributionList::Entry::List entries = dist.entries( core()->addressBook() );
00493   KPIM::DistributionList::Entry::List::ConstIterator it;
00494 #else
00495   const KABC::DistributionList::Entry::List entries = list->entries();
00496   KABC::DistributionList::Entry::List::ConstIterator it;
00497 #endif
00498   for ( it = entries.begin(); it != entries.end(); ++it, ++entryCount )
00499     new ContactItem( mContactView, (*it).addressee, (*it).email );
00500 
00501   bool state = mContactView->selectedItem() != 0;
00502   mChangeEmailButton->setEnabled( state );
00503   mRemoveContactButton->setEnabled( state );
00504 
00505   mEntryCountLabel->setText( i18n( "Count: %n contact", "Count: %n contacts", entryCount ) );
00506 }
00507 
00508 void DistributionListWidget::updateNameCombo()
00509 {
00510   int pos = mNameCombo->currentItem();
00511   mNameCombo->clear();
00512 #ifdef KDEPIM_NEW_DISTRLISTS
00513   const QStringList names = core()->distributionListNames();
00514 #else
00515   mManager->load();
00516   const QStringList names = mManager->listNames();
00517 #endif
00518   mNameCombo->insertStringList( names );
00519   mNameCombo->setCurrentItem( QMIN( pos, (int)names.count() - 1 ) );
00520 
00521   updateContactView();
00522 }
00523 
00524 void DistributionListWidget::dropEvent( QDropEvent *e )
00525 {
00526   if ( mNameCombo->count() == 0 )
00527     return;
00528 
00529 #ifdef KDEPIM_NEW_DISTRLISTS
00530   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00531     core()->addressBook(), mNameCombo->currentText() );
00532   if ( dist.isEmpty() )
00533     return;
00534 #else
00535   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00536   if ( !list )
00537     return;
00538   KABC::DistributionList& dist = *list;
00539 #endif
00540 
00541   QString vcards;
00542   if ( KVCardDrag::decode( e, vcards ) ) {
00543     KABC::VCardConverter converter;
00544     const KABC::Addressee::List lst = converter.parseVCards( vcards );
00545     for ( KABC::Addressee::List::ConstIterator it = lst.begin(); it != lst.end(); ++it )
00546       dist.insertEntry( *it );
00547 
00548 #ifdef KDEPIM_NEW_DISTRLISTS
00549     core()->addressBook()->insertAddressee( dist );
00550     changed( dist );
00551 #else
00552     changed();
00553     updateContactView();
00554 #endif
00555   }
00556 }
00557 
00558 void DistributionListWidget::contactsSelectionChanged()
00559 {
00560   mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 );
00561 }
00562 
00563 QString DistributionListWidget::title() const
00564 {
00565   return i18n( "Distribution List Editor" );
00566 }
00567 
00568 QString DistributionListWidget::identifier() const
00569 {
00570   return "distribution_list_editor";
00571 }
00572 
00573 void DistributionListWidget::dropped( QDropEvent *e, QListViewItem* )
00574 {
00575   dropEvent( e );
00576 }
00577 
00578 #ifdef KDEPIM_NEW_DISTRLISTS
00579 void DistributionListWidget::changed( const KABC::Addressee& dist )
00580 {
00581   emit modified( KABC::Addressee::List() << dist );
00582 }
00583 #else
00584 void DistributionListWidget::changed()
00585 {
00586   save();
00587 }
00588 #endif
00589 
00590 DistributionListView::DistributionListView( QWidget *parent, const char* name )
00591   : KListView( parent, name )
00592 {
00593   setDragEnabled( true );
00594   setAcceptDrops( true );
00595   setAllColumnsShowFocus( true );
00596 }
00597 
00598 void DistributionListView::dragEnterEvent( QDragEnterEvent* e )
00599 {
00600   bool canDecode = QTextDrag::canDecode( e );
00601   e->accept( canDecode );
00602 }
00603 
00604 void DistributionListView::viewportDragMoveEvent( QDragMoveEvent *e )
00605 {
00606   bool canDecode = QTextDrag::canDecode( e );
00607   e->accept( canDecode );
00608 }
00609 
00610 void DistributionListView::viewportDropEvent( QDropEvent *e )
00611 {
00612   emit dropped( e, 0 );
00613 }
00614 
00615 void DistributionListView::dropEvent( QDropEvent *e )
00616 {
00617   emit dropped( e, 0 );
00618 }
00619 
00620 
00621 EmailSelector::EmailSelector( const QStringList &emails,
00622                               const QString &current, QWidget *parent )
00623   : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok,
00624                parent )
00625 {
00626   QFrame *topFrame = plainPage();
00627   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00628 
00629   mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"),
00630                                    topFrame );
00631   mButtonGroup->setRadioButtonExclusive( true );
00632   topLayout->addWidget( mButtonGroup );
00633 
00634   QRadioButton *button = new QRadioButton( i18n("Preferred address"), mButtonGroup );
00635   button->setDown( true );
00636   mEmailMap.insert( mButtonGroup->id( button ), "" );
00637 
00638   QStringList::ConstIterator it;
00639   for ( it = emails.begin(); it != emails.end(); ++it ) {
00640     button = new QRadioButton( *it, mButtonGroup );
00641     mEmailMap.insert( mButtonGroup->id( button ), *it );
00642     if ( (*it) == current )
00643       button->setDown( true );
00644   }
00645 }
00646 
00647 QString EmailSelector::selected() const
00648 {
00649   QButton *button = mButtonGroup->selected();
00650   if ( button )
00651     return mEmailMap[ mButtonGroup->id( button ) ];
00652 
00653   return QString::null;
00654 }
00655 
00656 QString EmailSelector::getEmail( const QStringList &emails,
00657                                  const QString &current, QWidget *parent )
00658 {
00659   EmailSelector dlg( emails, current, parent );
00660   dlg.exec();
00661 
00662   return dlg.selected();
00663 }
00664 
00665 
00666 #include "distributionlistwidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys