libkdepim

addressesdialog.cpp

00001 /*  -*- mode: C++; c-file-style: "gnu" -*-
00002  *
00003  *  This file is part of libkdepim.
00004  *
00005  *  Copyright (c) 2003 Zack Rusin <zack@kde.org>
00006  *  Copyright (c) 2003 Aaron J. Seigo <aseigo@kde.org>
00007  *
00008  *  This library is free software; you can redistribute it and/or
00009  *  modify it under the terms of the GNU Library General Public
00010  *  License as published by the Free Software Foundation; either
00011  *  version 2 of the License, or (at your option) any later version.
00012  *
00013  *  This library is distributed in the hope that it will be useful,
00014  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  *  Library General Public License for more details.
00017  *
00018  *  You should have received a copy of the GNU Library General Public License
00019  *  along with this library; see the file COPYING.LIB.  If not, write to
00020  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021  *  Boston, MA 02110-1301, USA.
00022  *
00023  */
00024 
00025 #include "addressesdialog.h"
00026 #include "addresspicker.h"
00027 
00028 #include <config.h>
00029 
00030 #ifdef KDEPIM_NEW_DISTRLISTS
00031 #include "distributionlist.h"
00032 #include <kresources/selectdialog.h>
00033 #include <kabc/resource.h>
00034 #else
00035 #include <kabc/distributionlist.h>
00036 #endif
00037 
00038 #include <kabc/stdaddressbook.h>
00039 #include <kapplication.h>
00040 #include <kdebug.h>
00041 #include <kglobal.h>
00042 #include <kiconloader.h>
00043 #include <kinputdialog.h>
00044 #include <klineedit.h>
00045 #include <klocale.h>
00046 #include <kmessagebox.h>
00047 #include <kprocess.h>
00048 #include <kpushbutton.h>
00049 #include <krun.h>
00050 #include <kstandarddirs.h>
00051 
00052 #include <qdict.h>
00053 #include <qlayout.h>
00054 #include <qvbox.h>
00055 #include <qwidget.h>
00056 
00057 namespace KPIM {
00058 
00059 // private start :
00060 struct AddresseeViewItem::AddresseeViewItemPrivate {
00061   KABC::Addressee               address;
00062   AddresseeViewItem::Category   category;
00063   KABC::Addressee::List         addresses;
00064 };
00065 
00066 struct AddressesDialog::AddressesDialogPrivate {
00067   AddressesDialogPrivate() : ui(0), personal(0), recent(0), toItem(0), ccItem(0), bccItem(0)
00068   {}
00069 
00070   AddressPickerUI             *ui;
00071 
00072   AddresseeViewItem           *personal;
00073   AddresseeViewItem           *recent;
00074 
00075   AddresseeViewItem           *toItem;
00076   AddresseeViewItem           *ccItem;
00077   AddresseeViewItem           *bccItem;
00078 
00079   QDict<AddresseeViewItem>     groupDict;
00080 
00081   KABC::Addressee::List       recentAddresses;
00082 };
00083 // privates end
00084 
00085 AddresseeViewItem::AddresseeViewItem( AddresseeViewItem *parent, const KABC::Addressee& addr,
00086                                       int emailIndex )
00087   : QObject( 0 ), KListViewItem( parent, addr.realName(),
00088                                ( emailIndex == 0 ? addr.preferredEmail() : addr.emails()[ emailIndex ] ) )
00089 {
00090   d = new AddresseeViewItemPrivate;
00091   d->address = addr;
00092   d->category = Entry;
00093 
00094   if ( text( 0 ).stripWhiteSpace().isEmpty() )
00095     setText( 0, addr.preferredEmail() );
00096 
00097   if ( addr.photo().url().isEmpty() ) {
00098     if ( addr.photo().data().isNull() )
00099       setPixmap( 0, KGlobal::iconLoader()->loadIcon( "personal", KIcon::Small ) );
00100     else
00101       setPixmap( 0, addr.photo().data().smoothScale( 16, 16 ) );
00102   } else {
00103     setPixmap( 0, KGlobal::iconLoader()->loadIcon( addr.photo().url(), KIcon::Small ) );
00104   }
00105 }
00106 
00107 AddresseeViewItem::AddresseeViewItem( KListView *lv, const QString& name, Category cat )
00108   : QObject(0), KListViewItem( lv, name )
00109 {
00110   d = new AddresseeViewItemPrivate;
00111   d->category = cat;
00112 }
00113 
00114 AddresseeViewItem::AddresseeViewItem(  AddresseeViewItem *parent, const QString& name,
00115                                        const KABC::Addressee::List &lst )
00116   : QObject(0), KListViewItem( parent, name, i18n("<group>") )
00117 {
00118   d = new AddresseeViewItemPrivate;
00119   d->category = FilledGroup;
00120   d->addresses = lst;
00121 }
00122 
00123 AddresseeViewItem::AddresseeViewItem(  AddresseeViewItem *parent, const QString& name )
00124   : QObject(0), KListViewItem( parent, name, i18n("<group>") )
00125 {
00126   d = new AddresseeViewItemPrivate;
00127   d->category = DistList;
00128 
00129   setPixmap( 0, KGlobal::iconLoader()->loadIcon( "kdmconfig", KIcon::Small ) );
00130 }
00131 
00132 AddresseeViewItem::~AddresseeViewItem()
00133 {
00134   delete d;
00135   d = 0;
00136 }
00137 
00138 KABC::Addressee
00139 AddresseeViewItem::addressee() const
00140 {
00141   return d->address;
00142 }
00143 
00144 KABC::Addressee::List
00145 AddresseeViewItem::addresses() const
00146 {
00147   return d->addresses;
00148 }
00149 
00150 AddresseeViewItem::Category
00151 AddresseeViewItem::category() const
00152 {
00153   return d->category;
00154 }
00155 
00156 QString
00157 AddresseeViewItem::name() const
00158 {
00159   return text(0);
00160 }
00161 
00162 QString
00163 AddresseeViewItem::email() const
00164 {
00165   return text(1);
00166 }
00167 
00168 bool AddresseeViewItem::matches(const QString& txt) const
00169 {
00170     return d->address.realName().contains(txt, false) || d->address.preferredEmail().contains(txt, false);
00171 }
00172 
00173 void AddresseeViewItem::setSelected(bool selected)
00174 {
00175     if (selected == isSelected())
00176     {
00177         return;
00178     }
00179 
00180     emit addressSelected( this, selected );
00181     QListViewItem::setSelected(selected);
00182 }
00183 
00184 int
00185 AddresseeViewItem::compare( QListViewItem * i, int col, bool ascending ) const
00186 {
00187   if ( category() == Group || category() == Entry )
00188     return KListViewItem::compare( i , col, ascending );
00189 
00190   AddresseeViewItem *item = static_cast<AddresseeViewItem*>( i );
00191   int a = static_cast<int>( category() );
00192   int b = static_cast<int>( item->category() );
00193 
00194   if ( ascending )
00195     if ( a < b )
00196       return -1;
00197     else
00198       return 1;
00199   else
00200     if ( a < b )
00201       return 1;
00202     else
00203       return -1;
00204 }
00205 
00206 AddressesDialog::AddressesDialog( QWidget *widget, const char *name )
00207   : KDialogBase( widget, name, true, i18n("Address Selection"),
00208                  Ok|Cancel, Ok, true )
00209 {
00210   QVBox *page = makeVBoxMainWidget();
00211   d = new AddressesDialogPrivate;
00212   d->ui = new AddressPickerUI( page );
00213 
00214   KABC::StdAddressBook::self( true );
00215   updateAvailableAddressees();
00216   initConnections();
00217 
00218   d->ui->mAvailableView->setFocus();
00219 }
00220 
00221 AddressesDialog::~AddressesDialog()
00222 {
00223   delete d;
00224   d = 0;
00225 }
00226 
00227 AddresseeViewItem* AddressesDialog::selectedToItem()
00228 {
00229   if ( !d->toItem )
00230   {
00231     d->toItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("To"), AddresseeViewItem::To );
00232     connect(d->toItem, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00233             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00234   }
00235   return d->toItem;
00236 }
00237 
00238 AddresseeViewItem* AddressesDialog::selectedCcItem()
00239 {
00240   if ( !d->ccItem )
00241   {
00242     d->ccItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("CC"), AddresseeViewItem::CC );
00243     connect(d->ccItem, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00244             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00245   }
00246   return d->ccItem;
00247 }
00248 
00249 AddresseeViewItem* AddressesDialog::selectedBccItem()
00250 {
00251   if ( !d->bccItem )
00252   {
00253     d->bccItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("BCC"), AddresseeViewItem::BCC );
00254     connect(d->bccItem, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00255             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00256   }
00257   return d->bccItem;
00258 }
00259 
00260 void
00261 AddressesDialog::setSelectedTo( const QStringList& l )
00262 {
00263   QString name, email;
00264   for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
00265     KABC::Addressee addr;
00266     KABC::Addressee::parseEmailAddress( *it, name, email );
00267     addr.setNameFromString( name );
00268     addr.insertEmail( email );
00269     addAddresseeToSelected( addr, selectedToItem() );
00270   }
00271 }
00272 
00273 void
00274 AddressesDialog::setSelectedCC( const QStringList& l )
00275 {
00276   QString name, email;
00277   for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
00278     KABC::Addressee addr;
00279     KABC::Addressee::parseEmailAddress( *it, name, email );
00280     addr.setNameFromString( name );
00281     addr.insertEmail( email );
00282     addAddresseeToSelected( addr, selectedCcItem() );
00283   }
00284 }
00285 
00286 void
00287 AddressesDialog::setSelectedBCC( const QStringList& l )
00288 {
00289   QString name, email;
00290   for ( QStringList::ConstIterator it = l.begin(); it != l.end(); ++it ) {
00291     KABC::Addressee addr;
00292     KABC::Addressee::parseEmailAddress( *it, name, email );
00293     addr.setNameFromString( name );
00294     addr.insertEmail( email );
00295     addAddresseeToSelected( addr, selectedBccItem() );
00296   }
00297 }
00298 
00299 void
00300 AddressesDialog::setRecentAddresses( const KABC::Addressee::List& list )
00301 {
00302   d->recentAddresses = list;
00303 
00304   updateRecentAddresses();
00305 
00306   checkForSingleAvailableGroup();
00307 }
00308 
00309 void
00310 AddressesDialog::updateRecentAddresses()
00311 {
00312   static const QString &recentGroup = KGlobal::staticQString( i18n( "Recent Addresses" ) );
00313 
00314   if ( !d->recent ) {
00315     d->recent = new AddresseeViewItem( d->ui->mAvailableView, recentGroup );
00316     connect(d->recent, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00317             this, SLOT(availableAddressSelected(AddresseeViewItem*, bool)));
00318     d->recent->setVisible( false );
00319     d->groupDict.insert( recentGroup, d->recent );
00320   }
00321 
00322   KABC::Addressee::List::ConstIterator it;
00323   for ( it = d->recentAddresses.begin(); it != d->recentAddresses.end(); ++it )
00324     addAddresseeToAvailable( *it, d->recent );
00325 
00326   if ( d->recent->childCount() > 0 ) {
00327     d->recent->setVisible( true );
00328   }
00329 }
00330 
00331 void
00332 AddressesDialog::setShowCC( bool b )
00333 {
00334   d->ui->mCCButton->setShown( b );
00335 }
00336 
00337 void
00338 AddressesDialog::setShowBCC( bool b )
00339 {
00340   d->ui->mBCCButton->setShown( b );
00341 }
00342 
00343 QStringList
00344 AddressesDialog::to() const
00345 {
00346   QStringList emails = allDistributionLists( d->toItem );
00347   KABC::Addressee::List l = toAddresses();
00348   emails += entryToString( l );
00349 
00350   return emails;
00351 }
00352 
00353 QStringList
00354 AddressesDialog::cc() const
00355 {
00356   QStringList emails = allDistributionLists( d->ccItem );
00357   KABC::Addressee::List l = ccAddresses();
00358   emails += entryToString( l );
00359 
00360   return emails;
00361 }
00362 
00363 QStringList
00364 AddressesDialog::bcc() const
00365 {
00366   QStringList emails = allDistributionLists( d->bccItem );
00367 
00368   KABC::Addressee::List l = bccAddresses();
00369   emails += entryToString( l );
00370 
00371   return emails;
00372 }
00373 
00374 KABC::Addressee::List
00375 AddressesDialog::toAddresses()  const
00376 {
00377   return allAddressee( d->toItem );
00378 }
00379 KABC::Addressee::List
00380 AddressesDialog::allToAddressesNoDuplicates()  const
00381 {
00382   KABC::Addressee::List aList = allAddressee( d->toItem );
00383   const QStringList dList = toDistributionLists();
00384   KABC::AddressBook* abook = KABC::StdAddressBook::self( true );
00385 #ifdef KDEPIM_NEW_DISTRLISTS
00386   for ( QStringList::ConstIterator it = dList.begin(); it != dList.end(); ++it ) {
00387     const QValueList<KPIM::DistributionList::Entry> eList
00388       = KPIM::DistributionList::findByName(abook, *it).entries(abook);
00389     QValueList<KPIM::DistributionList::Entry>::ConstIterator eit;
00390     for( eit = eList.begin(); eit != eList.end(); ++eit ) {
00391       KABC::Addressee a = (*eit).addressee;
00392       if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
00393           aList.append( a ) ;
00394       }
00395     }
00396   }
00397 #else
00398   KABC::DistributionListManager manager( abook );
00399   manager.load();
00400   for ( QStringList::ConstIterator it = dList.begin(); it != dList.end(); ++it ) {
00401     const QValueList<KABC::DistributionList::Entry> eList = manager.list( *it )->entries();
00402     QValueList<KABC::DistributionList::Entry>::ConstIterator eit;
00403     for( eit = eList.begin(); eit != eList.end(); ++eit ) {
00404       KABC::Addressee a = (*eit).addressee;
00405       if ( !a.preferredEmail().isEmpty() && aList.find( a ) == aList.end() ) {
00406           aList.append( a ) ;
00407       }
00408     }
00409   }
00410 #endif
00411   return aList;
00412 }
00413 
00414 KABC::Addressee::List
00415 AddressesDialog::ccAddresses()  const
00416 {
00417   return allAddressee( d->ccItem );
00418 }
00419 
00420 KABC::Addressee::List
00421 AddressesDialog::bccAddresses()  const
00422 {
00423   return allAddressee( d->bccItem );
00424 }
00425 
00426 
00427 QStringList
00428 AddressesDialog::toDistributionLists() const
00429 {
00430   return allDistributionLists( d->toItem );
00431 }
00432 
00433 QStringList
00434 AddressesDialog::ccDistributionLists() const
00435 {
00436   return allDistributionLists( d->ccItem );
00437 }
00438 
00439 QStringList
00440 AddressesDialog::bccDistributionLists() const
00441 {
00442   return allDistributionLists( d->bccItem );
00443 }
00444 
00445 void
00446 AddressesDialog::updateAvailableAddressees()
00447 {
00448   d->ui->mAvailableView->clear();
00449   d->groupDict.clear();
00450 
00451   static const QString &personalGroup = KGlobal::staticQString( i18n( "Other Addresses" ) );
00452   d->ui->mAvailableView->setRootIsDecorated( true );
00453   d->personal = new AddresseeViewItem( d->ui->mAvailableView, personalGroup );
00454   //connect(d->personal, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00455   //        this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00456   d->personal->setVisible( false );
00457   d->groupDict.insert( personalGroup, d->personal );
00458 
00459   KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
00460   for( KABC::AddressBook::Iterator it = addressBook->begin();
00461        it != addressBook->end(); ++it ) {
00462     addAddresseeToAvailable( *it, d->personal );
00463   }
00464 
00465   d->recent = 0;
00466   updateRecentAddresses();
00467 
00468   addDistributionLists();
00469   if ( d->personal->childCount() > 0 ) {
00470     d->personal->setVisible( true );
00471   }
00472 
00473   checkForSingleAvailableGroup();
00474 }
00475 
00476 void AddressesDialog::checkForSingleAvailableGroup()
00477 {
00478   QListViewItem* item = d->ui->mAvailableView->firstChild();
00479   QListViewItem* firstGroup = 0;
00480   int found = 0;
00481   while (item)
00482   {
00483     if (item->isVisible())
00484     {
00485       if (!firstGroup && static_cast<AddresseeViewItem*>(item)->category() != AddresseeViewItem::Entry)
00486       {
00487         firstGroup = item;
00488       }
00489       ++found;
00490     }
00491     item = item->nextSibling();
00492   }
00493 
00494   if (found == 1 && firstGroup)
00495   {
00496     firstGroup->setOpen(true);
00497   }
00498 }
00499 
00500 void
00501 AddressesDialog::availableSelectionChanged()
00502 {
00503   bool selection = !selectedAvailableAddresses.isEmpty();
00504   d->ui->mToButton->setEnabled(selection);
00505   d->ui->mCCButton->setEnabled(selection);
00506   d->ui->mBCCButton->setEnabled(selection);
00507 }
00508 
00509 void
00510 AddressesDialog::selectedSelectionChanged()
00511 {
00512   bool selection = !selectedSelectedAddresses.isEmpty();
00513   d->ui->mRemoveButton->setEnabled(selection);
00514 }
00515 
00516 void
00517 AddressesDialog::availableAddressSelected( AddresseeViewItem* item, bool selected )
00518 {
00519   if (selected)
00520   {
00521     selectedAvailableAddresses.append(item);
00522   }
00523   else
00524   {
00525     selectedAvailableAddresses.remove(item);
00526   }
00527 }
00528 
00529 void
00530 AddressesDialog::selectedAddressSelected( AddresseeViewItem* item, bool selected )
00531 {
00532   // we have to avoid that a parent and a child is selected together
00533   // because in this case we get a double object deletion ( program crashes )
00534   // when removing the selected items from list
00535   AddresseeViewItem* parent = static_cast<AddresseeViewItem*>(((QListViewItem*)item)->parent());
00536   if ( parent  && selected )
00537     parent->setSelected( false );
00538   if (selected)
00539   {
00540     selectedSelectedAddresses.append(item);
00541   }
00542   else
00543   {
00544     selectedSelectedAddresses.remove(item);
00545   }
00546   if ( selected ) {
00547     AddresseeViewItem* child = static_cast<AddresseeViewItem*>(item->firstChild());
00548     while (child) {
00549       child->setSelected( false );
00550       child = static_cast<AddresseeViewItem*>(child->nextSibling());
00551     }
00552   }
00553 }
00554 
00555 void
00556 AddressesDialog::initConnections()
00557 {
00558   connect( d->ui->mFilterEdit, SIGNAL(textChanged(const QString &)),
00559            SLOT(filterChanged(const QString &)) );
00560   connect( d->ui->mToButton, SIGNAL(clicked()),
00561            SLOT(addSelectedTo()) );
00562   connect( d->ui->mCCButton, SIGNAL(clicked()),
00563            SLOT(addSelectedCC()) );
00564   connect( d->ui->mBCCButton, SIGNAL(clicked()),
00565            SLOT(addSelectedBCC())  );
00566   connect( d->ui->mSaveAs, SIGNAL(clicked()),
00567            SLOT(saveAs())  );
00568   connect( d->ui->mRemoveButton, SIGNAL(clicked()),
00569            SLOT(removeEntry()) );
00570   connect( d->ui->mAvailableView, SIGNAL(selectionChanged()),
00571            SLOT(availableSelectionChanged())  );
00572   connect( d->ui->mAvailableView, SIGNAL(doubleClicked(QListViewItem*)),
00573            SLOT(addSelectedTo()) );
00574   connect( d->ui->mSelectedView, SIGNAL(selectionChanged()),
00575            SLOT(selectedSelectionChanged()) );
00576   connect( d->ui->mSelectedView, SIGNAL(doubleClicked(QListViewItem*)),
00577            SLOT(removeEntry()) );
00578 
00579 #ifndef KDEPIM_NEW_DISTRLISTS
00580   connect( KABC::DistributionListWatcher::self(), SIGNAL( changed() ),
00581            this, SLOT( updateAvailableAddressees() ) );
00582 #endif
00583 
00584   connect( KABC::StdAddressBook::self( true ), SIGNAL( addressBookChanged(AddressBook*) ),
00585            this, SLOT( updateAvailableAddressees() ) );
00586 }
00587 
00588 void
00589 AddressesDialog::addAddresseeToAvailable( const KABC::Addressee& addr, AddresseeViewItem* defaultParent, bool useCategory )
00590 {
00591   if ( addr.preferredEmail().isEmpty() )
00592     return;
00593 
00594   if ( useCategory ) {
00595     QStringList categories = addr.categories();
00596 
00597     for ( QStringList::Iterator it = categories.begin(); it != categories.end(); ++it ) {
00598       if ( !d->groupDict[ *it ] ) {  //we don't have the category yet
00599         AddresseeViewItem* category = new AddresseeViewItem( d->ui->mAvailableView, *it );
00600         d->groupDict.insert( *it,  category );
00601       }
00602 
00603       for ( uint i = 0; i < addr.emails().count(); ++i ) {
00604         AddresseeViewItem* addressee = new AddresseeViewItem( d->groupDict[ *it ], addr, i );
00605         connect(addressee, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00606                 this, SLOT(availableAddressSelected(AddresseeViewItem*, bool)));
00607       }
00608     }
00609   }
00610 
00611   bool noCategory = false;
00612   if ( useCategory ) {
00613     if ( addr.categories().isEmpty() )
00614       noCategory = true;
00615   } else
00616     noCategory = true;
00617 
00618   if ( defaultParent && noCategory ) { // only non-categorized items here
00619     AddresseeViewItem* addressee = new AddresseeViewItem( defaultParent, addr );
00620     connect(addressee, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00621             this, SLOT(availableAddressSelected(AddresseeViewItem*, bool)));
00622   }
00623 }
00624 
00625 void
00626 AddressesDialog::addAddresseeToSelected( const KABC::Addressee& addr, AddresseeViewItem* defaultParent )
00627 {
00628   if ( addr.preferredEmail().isEmpty() )
00629     return;
00630 
00631   if ( defaultParent ) {
00632     AddresseeViewItem *myChild = static_cast<AddresseeViewItem*>( defaultParent->firstChild() );
00633     while( myChild ) {
00634       if ( myChild->addressee().preferredEmail() == addr.preferredEmail() )
00635         return;//already got it
00636       myChild = static_cast<AddresseeViewItem*>( myChild->nextSibling() );
00637     }
00638     AddresseeViewItem* addressee = new AddresseeViewItem( defaultParent, addr );
00639     connect(addressee, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00640             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00641     defaultParent->setOpen( true );
00642   }
00643 
00644   d->ui->mSaveAs->setEnabled(true);
00645 }
00646 
00647 void
00648 AddressesDialog::addAddresseesToSelected( AddresseeViewItem *parent,
00649                                           const QPtrList<AddresseeViewItem>& addresses )
00650 {
00651   Q_ASSERT( parent );
00652 
00653   QPtrListIterator<AddresseeViewItem> itr( addresses );
00654 
00655   if (itr.current())
00656   {
00657     d->ui->mSaveAs->setEnabled(true);
00658   }
00659 
00660   while ( itr.current() ) {
00661     AddresseeViewItem* address = itr.current();
00662     ++itr;
00663 
00664     if (selectedToAvailableMapping.find(address) != 0)
00665     {
00666       continue;
00667     }
00668 
00669     AddresseeViewItem* newItem = 0;
00670     if (address->category() == AddresseeViewItem::Entry)
00671     {
00672       newItem = new AddresseeViewItem( parent, address->addressee() );
00673     }
00674     else if (address->category() == AddresseeViewItem::DistList)
00675     {
00676       newItem = new AddresseeViewItem( parent, address->name() );
00677     }
00678     else
00679     {
00680       newItem = new AddresseeViewItem( parent, address->name(), allAddressee( address ) );
00681     }
00682 
00683     address->setSelected( false );
00684     address->setVisible( false );
00685     selectedToAvailableMapping.insert(address, newItem);
00686     selectedToAvailableMapping.insert(newItem, address);
00687     connect(newItem, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00688             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00689   }
00690 
00691   parent->setOpen( true );
00692 }
00693 
00694 QStringList
00695 AddressesDialog::entryToString( const KABC::Addressee::List& l ) const
00696 {
00697   QStringList entries;
00698 
00699   for( KABC::Addressee::List::ConstIterator it = l.begin(); it != l.end(); ++it ) {
00700     entries += (*it).fullEmail();
00701   }
00702   return entries;
00703 }
00704 
00705 void
00706 AddressesDialog::addSelectedTo()
00707 {
00708   if ( !d->toItem )
00709   {
00710     d->toItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("To"), AddresseeViewItem::To );
00711     connect(d->toItem, SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00712             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00713   }
00714 
00715   addAddresseesToSelected( d->toItem, selectedAvailableAddresses );
00716   selectedAvailableAddresses.clear();
00717 
00718   if ( d->toItem->childCount() > 0 )
00719     d->toItem->setVisible( true );
00720   else
00721   {
00722     delete d->toItem;
00723     d->toItem = 0;
00724   }
00725 }
00726 
00727 void
00728 AddressesDialog::addSelectedCC()
00729 {
00730   if ( !d->ccItem )
00731   {
00732     d->ccItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("CC"), AddresseeViewItem::CC );
00733     connect(d->ccItem , SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00734             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00735   }
00736 
00737   addAddresseesToSelected( d->ccItem, selectedAvailableAddresses );
00738   selectedAvailableAddresses.clear();
00739 
00740   if ( d->ccItem->childCount() > 0 )
00741     d->ccItem->setVisible( true );
00742   else
00743   {
00744     delete d->ccItem;
00745     d->ccItem = 0;
00746   }
00747 }
00748 
00749 void
00750 AddressesDialog::addSelectedBCC()
00751 {
00752   if ( !d->bccItem )
00753   {
00754     d->bccItem = new AddresseeViewItem( d->ui->mSelectedView, i18n("BCC"), AddresseeViewItem::BCC );
00755     connect(d->bccItem , SIGNAL(addressSelected(AddresseeViewItem*, bool)),
00756             this, SLOT(selectedAddressSelected(AddresseeViewItem*, bool)));
00757   }
00758 
00759   addAddresseesToSelected( d->bccItem, selectedAvailableAddresses );
00760   selectedAvailableAddresses.clear();
00761 
00762   if ( d->bccItem->childCount() > 0 )
00763     d->bccItem->setVisible( true );
00764   else
00765   {
00766     delete d->bccItem;
00767     d->bccItem = 0;
00768   }
00769 }
00770 
00771 void AddressesDialog::unmapSelectedAddress(AddresseeViewItem* item)
00772 {
00773   AddresseeViewItem* correspondingItem = selectedToAvailableMapping[item];
00774   if (correspondingItem)
00775   {
00776     correspondingItem->setVisible( true );
00777     selectedToAvailableMapping.remove( item );
00778     selectedToAvailableMapping.remove( correspondingItem );
00779   }
00780 
00781   AddresseeViewItem* child = static_cast<AddresseeViewItem*>(item->firstChild());
00782   while (child)
00783   {
00784     unmapSelectedAddress(child);
00785     child = static_cast<AddresseeViewItem*>(child->nextSibling());
00786   }
00787 }
00788 
00789 void
00790 AddressesDialog::removeEntry()
00791 {
00792   QPtrList<AddresseeViewItem> lst;
00793   bool resetTo  = false;
00794   bool resetCC  = false;
00795   bool resetBCC = false;
00796 
00797   lst.setAutoDelete( false );
00798   QPtrListIterator<AddresseeViewItem> it( selectedSelectedAddresses );
00799   while ( it.current() ) {
00800     AddresseeViewItem* item = it.current();
00801     ++it;
00802     if ( d->toItem == item )
00803       resetTo = true;
00804     else if ( d->ccItem == item )
00805       resetCC = true;
00806     else if( d->bccItem == item )
00807       resetBCC = true;
00808     // we may only append parent items
00809     unmapSelectedAddress(item);
00810     lst.append( item );
00811   }
00812   selectedSelectedAddresses.clear();
00813   lst.setAutoDelete( true );
00814   lst.clear();
00815   if ( resetTo )
00816     d->toItem  = 0;
00817   else if ( d->toItem && d->toItem->childCount() == 0 )
00818   {
00819     delete d->toItem;
00820     d->toItem = 0;
00821   }
00822   if ( resetCC )
00823     d->ccItem = 0;
00824   else if ( d->ccItem && d->ccItem->childCount() == 0 )
00825   {
00826     delete d->ccItem;
00827     d->ccItem = 0;
00828   }
00829   if ( resetBCC )
00830     d->bccItem  = 0;
00831   else if ( d->bccItem && d->bccItem->childCount() == 0 )
00832   {
00833     delete d->bccItem;
00834     d->bccItem = 0;
00835   }
00836   d->ui->mSaveAs->setEnabled(d->ui->mSelectedView->firstChild() != 0);
00837 }
00838 
00839 #ifdef KDEPIM_NEW_DISTRLISTS
00840 
00841 // copied from kabcore.cpp :(
00842 // KDE4: should be in libkabc I think
00843 static KABC::Resource *requestResource( KABC::AddressBook* abook, QWidget *parent )
00844 {
00845   QPtrList<KABC::Resource> kabcResources = abook->resources();
00846 
00847   QPtrList<KRES::Resource> kresResources;
00848   QPtrListIterator<KABC::Resource> resIt( kabcResources );
00849   KABC::Resource *resource;
00850   while ( ( resource = resIt.current() ) != 0 ) {
00851     ++resIt;
00852     if ( !resource->readOnly() ) {
00853       KRES::Resource *res = static_cast<KRES::Resource*>( resource );
00854       if ( res )
00855         kresResources.append( res );
00856     }
00857   }
00858 
00859   KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, parent );
00860   return static_cast<KABC::Resource*>( res );
00861 }
00862 #endif
00863 
00864 void
00865 AddressesDialog::saveAs()
00866 {
00867 #ifndef KDEPIM_NEW_DISTRLISTS
00868   KABC::DistributionListManager manager( KABC::StdAddressBook::self( true ) );
00869   manager.load();
00870 #endif
00871 
00872   if ( !d->ui->mSelectedView->firstChild() ) {
00873     KMessageBox::information( 0,
00874                               i18n("There are no addresses in your list. "
00875                                    "First add some addresses from your address book, "
00876                                    "then try again.") );
00877     return;
00878   }
00879 
00880   bool ok = false;
00881   QString name = KInputDialog::getText( i18n("New Distribution List"),
00882                                         i18n("Please enter name:"),
00883                                         QString::null, &ok,
00884                                         this );
00885   if ( !ok || name.isEmpty() )
00886     return;
00887 
00888   bool alreadyExists = false;
00889 #ifdef KDEPIM_NEW_DISTRLISTS
00890   KABC::AddressBook* abook = KABC::StdAddressBook::self( true );
00891   KPIM::DistributionList dlist = KPIM::DistributionList::findByName( abook, name );
00892   alreadyExists = !dlist.isEmpty();
00893 #else
00894   alreadyExists = manager.list( name );
00895 #endif
00896 
00897   if ( alreadyExists ) {
00898     KMessageBox::information( 0,
00899                               i18n( "<qt>Distribution list with the given name <b>%1</b> "
00900                                     "already exists. Please select a different name.</qt>" )
00901                               .arg( name ) );
00902     return;
00903   }
00904 
00905 #ifdef KDEPIM_NEW_DISTRLISTS
00906   KABC::Resource* resource = requestResource( abook, this );
00907   if ( !resource )
00908     return;
00909 
00910   dlist.setResource( resource );
00911   dlist.setName( name );
00912   KABC::Addressee::List addrl = allAddressee( d->ui->mSelectedView, false );
00913   for ( KABC::Addressee::List::iterator itr = addrl.begin();
00914         itr != addrl.end(); ++itr ) {
00915     dlist.insertEntry( *itr );
00916   }
00917   abook->insertAddressee( dlist );
00918 #else
00919   KABC::DistributionList *dlist = new KABC::DistributionList( &manager, name );
00920   KABC::Addressee::List addrl = allAddressee( d->ui->mSelectedView, false );
00921   for ( KABC::Addressee::List::iterator itr = addrl.begin();
00922         itr != addrl.end(); ++itr ) {
00923     dlist->insertEntry( *itr );
00924   }
00925 
00926   manager.save();
00927 #endif
00928 }
00929 
00930 void
00931 AddressesDialog::launchAddressBook()
00932 {
00933   kapp->startServiceByDesktopName( "kaddressbook", QString() );
00934 }
00935 
00936 void
00937 AddressesDialog::filterChanged( const QString& txt )
00938 {
00939   QListViewItemIterator it( d->ui->mAvailableView );
00940   bool showAll = false;
00941 
00942   if ( txt.isEmpty() )
00943     showAll = true;
00944 
00945   while ( it.current() ) {
00946     AddresseeViewItem* item = static_cast<AddresseeViewItem*>( it.current() );
00947     ++it;
00948     if ( showAll ) {
00949       item->setVisible( true );
00950       if ( item->category() == AddresseeViewItem::Group )
00951         item->setOpen( false );//close to not have too many entries
00952       continue;
00953     }
00954     if ( item->category() == AddresseeViewItem::Entry ) {
00955       bool matches = item->matches( txt ) ;
00956       item->setVisible( matches );
00957       if ( matches && static_cast<QListViewItem*>(item)->parent() ) {
00958           static_cast<QListViewItem*>(item)->parent()->setOpen( true );//open the parents with found entries
00959       }
00960     }
00961   }
00962 }
00963 
00964 KABC::Addressee::List
00965 AddressesDialog::allAddressee( KListView* view, bool onlySelected ) const
00966 {
00967   KABC::Addressee::List lst;
00968   QListViewItemIterator it( view );
00969   while ( it.current() ) {
00970     AddresseeViewItem* item = static_cast<AddresseeViewItem*>( it.current() );
00971     if ( !onlySelected || item->isSelected() ) {
00972       if ( item->category() != AddresseeViewItem::Entry  ) {
00973         AddresseeViewItem *myChild = static_cast<AddresseeViewItem*>( item->firstChild() );
00974         while( myChild ) {
00975           lst.append( myChild->addressee() );
00976           myChild = static_cast<AddresseeViewItem*>( myChild->nextSibling() );
00977         }
00978       } else {
00979         lst.append( item->addressee() );
00980       }
00981     }
00982     ++it;
00983   }
00984 
00985   return lst;
00986 }
00987 
00988 KABC::Addressee::List
00989 AddressesDialog::allAddressee( AddresseeViewItem* parent ) const
00990 {
00991   KABC::Addressee::List lst;
00992 
00993   if ( !parent ) return lst;
00994 
00995   if ( parent->category() == AddresseeViewItem::Entry )
00996   {
00997     lst.append( parent->addressee() );
00998     return lst;
00999   }
01000 
01001   AddresseeViewItem *myChild = static_cast<AddresseeViewItem*>( parent->firstChild() );
01002   while( myChild ) {
01003     if ( myChild->category() == AddresseeViewItem::FilledGroup )
01004       lst += myChild->addresses();
01005     else if ( !myChild->addressee().isEmpty() )
01006       lst.append( myChild->addressee() );
01007     myChild = static_cast<AddresseeViewItem*>( myChild->nextSibling() );
01008   }
01009 
01010   return lst;
01011 }
01012 
01013 QStringList
01014 AddressesDialog::allDistributionLists( AddresseeViewItem* parent ) const
01015 {
01016   QStringList lists;
01017 
01018   if ( !parent )
01019     return QStringList();
01020 
01021   AddresseeViewItem *item = static_cast<AddresseeViewItem*>( parent->firstChild() );
01022   while ( item ) {
01023     if ( item->category() == AddresseeViewItem::DistList && !item->name().isEmpty() )
01024       lists.append( item->name() );
01025 
01026     item = static_cast<AddresseeViewItem*>( item->nextSibling() );
01027   }
01028 
01029   return lists;
01030 }
01031 
01032 void
01033 AddressesDialog::addDistributionLists()
01034 {
01035   KABC::AddressBook* abook = KABC::StdAddressBook::self( true );
01036 
01037 #ifdef KDEPIM_NEW_DISTRLISTS
01038   const QValueList<KPIM::DistributionList> distLists =
01039     KPIM::DistributionList::allDistributionLists( abook );
01040 #else
01041   KABC::DistributionListManager manager( abook );
01042   manager.load();
01043 
01044   QStringList distLists = manager.listNames();
01045 #endif
01046 
01047   if ( distLists.isEmpty() )
01048     return;
01049 
01050   AddresseeViewItem *topItem = new AddresseeViewItem( d->ui->mAvailableView,
01051                                                       i18n( "Distribution Lists" ) );
01052 
01053 #ifdef KDEPIM_NEW_DISTRLISTS
01054   QValueList<KPIM::DistributionList>::ConstIterator listIt;
01055 #else
01056   QStringList::Iterator listIt;
01057 #endif
01058   for ( listIt = distLists.begin(); listIt != distLists.end(); ++listIt ) {
01059 #ifdef KDEPIM_NEW_DISTRLISTS
01060     KPIM::DistributionList dlist = *listIt;
01061     KPIM::DistributionList::Entry::List entries = dlist.entries(abook);
01062 #else
01063     KABC::DistributionList& dlist = *manager.list( *listIt );
01064     KABC::DistributionList::Entry::List entries = dlist.entries();
01065 #endif
01066 
01067     AddresseeViewItem *item = new AddresseeViewItem( topItem, dlist.name() );
01068     connect( item, SIGNAL( addressSelected( AddresseeViewItem*, bool ) ),
01069              this, SLOT( availableAddressSelected( AddresseeViewItem*, bool ) ) );
01070 
01071 #ifdef KDEPIM_NEW_DISTRLISTS
01072     KPIM::DistributionList::Entry::List::Iterator itemIt;
01073 #else
01074     KABC::DistributionList::Entry::List::Iterator itemIt;
01075 #endif
01076     for ( itemIt = entries.begin(); itemIt != entries.end(); ++itemIt )
01077       addAddresseeToAvailable( (*itemIt).addressee, item, false );
01078   }
01079 }
01080 
01081 } // namespace
01082 
01083 #include "addressesdialog.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys