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