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   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   core()->addressBook()->removeAddressee( dist );
00359 
00360   emit deleted( dist.uid() );
00361 #else
00362   mManager->remove( mManager->list( mNameCombo->currentText() ) );
00363   mNameCombo->removeItem( mNameCombo->currentItem() );
00364 
00365   updateContactView();
00366 
00367   changed();
00368 #endif
00369 }
00370 
00371 void DistributionListWidget::addContact()
00372 {
00373 #ifdef KDEPIM_NEW_DISTRLISTS
00374   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00375     core()->addressBook(), mNameCombo->currentText() );
00376   if ( dist.isEmpty() ) { // not found
00377     kdDebug(5720) << k_funcinfo << mNameCombo->currentText() << " not found" << endl;
00378     return;
00379   }
00380 #else
00381   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00382   if ( !list )
00383     return;
00384   KABC::DistributionList& dist = *list;
00385 #endif
00386 
00387   const KABC::Addressee::List addrList = selectedContacts();
00388   KABC::Addressee::List::ConstIterator it;
00389   for ( it = addrList.begin(); it != addrList.end(); ++it )
00390     dist.insertEntry( *it );
00391 
00392 #ifdef KDEPIM_NEW_DISTRLISTS
00393   core()->addressBook()->insertAddressee( dist );
00394   changed( dist );
00395 #else
00396   updateContactView();
00397   changed();
00398 #endif
00399 }
00400 
00401 void DistributionListWidget::removeContact()
00402 {
00403 #ifdef KDEPIM_NEW_DISTRLISTS
00404   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00405     core()->addressBook(), mNameCombo->currentText() );
00406   if ( dist.isEmpty() ) // not found
00407     return;
00408 #else
00409   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00410   if ( !list )
00411     return;
00412   KABC::DistributionList& dist = *list;
00413 #endif
00414 
00415   ContactItem *contactItem =
00416                     static_cast<ContactItem *>( mContactView->selectedItem() );
00417   if ( !contactItem )
00418     return;
00419 
00420   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00421   delete contactItem;
00422 
00423 #ifdef KDEPIM_NEW_DISTRLISTS
00424   core()->addressBook()->insertAddressee( dist );
00425   changed( dist );
00426 #else
00427   changed();
00428 #endif
00429 }
00430 
00431 void DistributionListWidget::changeEmail()
00432 {
00433 #ifdef KDEPIM_NEW_DISTRLISTS
00434   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00435     core()->addressBook(), mNameCombo->currentText() );
00436   if ( dist.isEmpty() ) // not found
00437     return;
00438 #else
00439   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00440   if ( !list )
00441     return;
00442   KABC::DistributionList& dist = *list;
00443 #endif
00444 
00445   ContactItem *contactItem =
00446                     static_cast<ContactItem *>( mContactView->selectedItem() );
00447   if ( !contactItem )
00448     return;
00449 
00450   const QString email = EmailSelector::getEmail( contactItem->addressee().emails(),
00451                                                  contactItem->email(), this );
00452   dist.removeEntry( contactItem->addressee(), contactItem->email() );
00453   dist.insertEntry( contactItem->addressee(), email );
00454 
00455 #ifdef KDEPIM_NEW_DISTRLISTS
00456   core()->addressBook()->insertAddressee( dist );
00457   changed( dist );
00458 #else
00459   updateContactView();
00460   changed();
00461 #endif
00462 }
00463 
00464 void DistributionListWidget::updateContactView()
00465 {
00466   mContactView->clear();
00467 
00468   bool isListSelected = false;
00469 #ifdef KDEPIM_NEW_DISTRLISTS
00470   KPIM::DistributionList dist;
00471   if ( mNameCombo->count() != 0 )
00472     dist = KPIM::DistributionList::findByName(
00473       core()->addressBook(), mNameCombo->currentText() );
00474   isListSelected = !dist.isEmpty();
00475 #else
00476   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00477   isListSelected = list != 0;
00478 #endif
00479   if ( !isListSelected ) {
00480     mEditListButton->setEnabled( false );
00481     mRemoveListButton->setEnabled( false );
00482     mChangeEmailButton->setEnabled( false );
00483     mRemoveContactButton->setEnabled( false );
00484     mContactView->setEnabled( false );
00485     return;
00486   }
00487   mEditListButton->setEnabled( true );
00488   mRemoveListButton->setEnabled( true );
00489   mContactView->setEnabled( true );
00490 
00491   uint entryCount = 0;
00492 #ifdef KDEPIM_NEW_DISTRLISTS
00493   const KPIM::DistributionList::Entry::List entries = dist.entries( core()->addressBook() );
00494   KPIM::DistributionList::Entry::List::ConstIterator it;
00495 #else
00496   const KABC::DistributionList::Entry::List entries = list->entries();
00497   KABC::DistributionList::Entry::List::ConstIterator it;
00498 #endif
00499   for ( it = entries.begin(); it != entries.end(); ++it, ++entryCount )
00500     new ContactItem( mContactView, (*it).addressee, (*it).email );
00501 
00502   bool state = mContactView->selectedItem() != 0;
00503   mChangeEmailButton->setEnabled( state );
00504   mRemoveContactButton->setEnabled( state );
00505 
00506   mEntryCountLabel->setText( i18n( "Count: %n contact", "Count: %n contacts", entryCount ) );
00507 }
00508 
00509 void DistributionListWidget::updateNameCombo()
00510 {
00511   int pos = mNameCombo->currentItem();
00512   mNameCombo->clear();
00513 #ifdef KDEPIM_NEW_DISTRLISTS
00514   const QStringList names = core()->distributionListNames();
00515 #else
00516   mManager->load();
00517   const QStringList names = mManager->listNames();
00518 #endif
00519   mNameCombo->insertStringList( names );
00520   mNameCombo->setCurrentItem( QMIN( pos, (int)names.count() - 1 ) );
00521 
00522   updateContactView();
00523 }
00524 
00525 void DistributionListWidget::dropEvent( QDropEvent *e )
00526 {
00527   if ( mNameCombo->count() == 0 )
00528     return;
00529 
00530 #ifdef KDEPIM_NEW_DISTRLISTS
00531   KPIM::DistributionList dist = KPIM::DistributionList::findByName(
00532     core()->addressBook(), mNameCombo->currentText() );
00533   if ( dist.isEmpty() )
00534     return;
00535 #else
00536   KABC::DistributionList *list = mManager->list( mNameCombo->currentText() );
00537   if ( !list )
00538     return;
00539   KABC::DistributionList& dist = *list;
00540 #endif
00541 
00542   QString vcards;
00543   if ( KVCardDrag::decode( e, vcards ) ) {
00544     KABC::VCardConverter converter;
00545     const KABC::Addressee::List lst = converter.parseVCards( vcards );
00546     for ( KABC::Addressee::List::ConstIterator it = lst.begin(); it != lst.end(); ++it )
00547       dist.insertEntry( *it );
00548 
00549 #ifdef KDEPIM_NEW_DISTRLISTS
00550     core()->addressBook()->insertAddressee( dist );
00551     changed( dist );
00552 #else
00553     changed();
00554     updateContactView();
00555 #endif
00556   }
00557 }
00558 
00559 void DistributionListWidget::contactsSelectionChanged()
00560 {
00561   mAddContactButton->setEnabled( contactsSelected() && mNameCombo->count() > 0 );
00562 }
00563 
00564 QString DistributionListWidget::title() const
00565 {
00566   return i18n( "Distribution List Editor" );
00567 }
00568 
00569 QString DistributionListWidget::identifier() const
00570 {
00571   return "distribution_list_editor";
00572 }
00573 
00574 void DistributionListWidget::dropped( QDropEvent *e, QListViewItem* )
00575 {
00576   dropEvent( e );
00577 }
00578 
00579 #ifdef KDEPIM_NEW_DISTRLISTS
00580 void DistributionListWidget::changed( const KABC::Addressee& dist )
00581 {
00582   emit modified( KABC::Addressee::List() << dist );
00583 }
00584 #else
00585 void DistributionListWidget::changed()
00586 {
00587   save();
00588 }
00589 #endif
00590 
00591 DistributionListView::DistributionListView( QWidget *parent, const char* name )
00592   : KListView( parent, name )
00593 {
00594   setDragEnabled( true );
00595   setAcceptDrops( true );
00596   setAllColumnsShowFocus( true );
00597 }
00598 
00599 void DistributionListView::dragEnterEvent( QDragEnterEvent* e )
00600 {
00601   bool canDecode = QTextDrag::canDecode( e );
00602   e->accept( canDecode );
00603 }
00604 
00605 void DistributionListView::viewportDragMoveEvent( QDragMoveEvent *e )
00606 {
00607   bool canDecode = QTextDrag::canDecode( e );
00608   e->accept( canDecode );
00609 }
00610 
00611 void DistributionListView::viewportDropEvent( QDropEvent *e )
00612 {
00613   emit dropped( e, 0 );
00614 }
00615 
00616 void DistributionListView::dropEvent( QDropEvent *e )
00617 {
00618   emit dropped( e, 0 );
00619 }
00620 
00621 
00622 EmailSelector::EmailSelector( const QStringList &emails,
00623                               const QString &current, QWidget *parent )
00624   : KDialogBase( KDialogBase::Plain, i18n("Select Email Address"), Ok, Ok,
00625                parent )
00626 {
00627   QFrame *topFrame = plainPage();
00628   QBoxLayout *topLayout = new QVBoxLayout( topFrame );
00629 
00630   mButtonGroup = new QButtonGroup( 1, Horizontal, i18n("Email Addresses"),
00631                                    topFrame );
00632   mButtonGroup->setRadioButtonExclusive( true );
00633   topLayout->addWidget( mButtonGroup );
00634 
00635   QRadioButton *button = new QRadioButton( i18n("Preferred address"), mButtonGroup );
00636   button->setDown( true );
00637   mEmailMap.insert( mButtonGroup->id( button ), "" );
00638 
00639   QStringList::ConstIterator it;
00640   for ( it = emails.begin(); it != emails.end(); ++it ) {
00641     button = new QRadioButton( *it, mButtonGroup );
00642     mEmailMap.insert( mButtonGroup->id( button ), *it );
00643     if ( (*it) == current )
00644       button->setDown( true );
00645   }
00646 }
00647 
00648 QString EmailSelector::selected() const
00649 {
00650   QButton *button = mButtonGroup->selected();
00651   if ( button )
00652     return mEmailMap[ mButtonGroup->id( button ) ];
00653 
00654   return QString::null;
00655 }
00656 
00657 QString EmailSelector::getEmail( const QStringList &emails,
00658                                  const QString &current, QWidget *parent )
00659 {
00660   EmailSelector dlg( emails, current, parent );
00661   dlg.exec();
00662 
00663   return dlg.selected();
00664 }
00665 
00666 
00667 #include "distributionlistwidget.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys