kaddressbook

kabcore.cpp

00001 /*
00002     This file is part of KAddressbook.
00003     Copyright (c) 2003 - 2004 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 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 // Needed for ugly hack, to be removed in 4.0
00025 #include <unistd.h> // for usleep
00026 #include <qeventloop.h>
00027 
00028 #include <qclipboard.h>
00029 #include <qdir.h>
00030 #include <qfile.h>
00031 #include <qlabel.h>
00032 #include <qlayout.h>
00033 #include <qptrlist.h>
00034 #include <qwidgetstack.h>
00035 #include <qregexp.h>
00036 #include <qvbox.h>
00037 #include <qtooltip.h>
00038 #include <qwhatsthis.h>
00039 
00040 #include <kabc/addresseelist.h>
00041 #include <kabc/errorhandler.h>
00042 #include <kabc/resource.h>
00043 #include <kabc/stdaddressbook.h>
00044 #include <kabc/vcardconverter.h>
00045 #include <kabc/resourcefile.h>
00046 #include <kaboutdata.h>
00047 #include <kaccelmanager.h>
00048 #include <kapplication.h>
00049 #include <dcopclient.h>
00050 #include <kactionclasses.h>
00051 #include <kcmdlineargs.h>
00052 #include <kcmultidialog.h>
00053 #include <kdebug.h>
00054 #include <kdeversion.h>
00055 #include <kimproxy.h>
00056 #include <klocale.h>
00057 #include <kmessagebox.h>
00058 #include <kprinter.h>
00059 #include <kprotocolinfo.h>
00060 #include <kpushbutton.h>
00061 #include <kresources/selectdialog.h>
00062 #include <kstandarddirs.h>
00063 #include <kstatusbar.h>
00064 #include <kstdguiitem.h>
00065 #include <kxmlguiclient.h>
00066 #include <ktoolbar.h>
00067 #include <libkdepim/addresseeview.h>
00068 #include <libkdepim/categoryeditdialog.h>
00069 #include <libkdepim/categoryselectdialog.h>
00070 #include <libkdepim/resourceabc.h>
00071 #include "distributionlisteditor.h"
00072 
00073 #include "addresseeutil.h"
00074 #include "addresseeeditordialog.h"
00075 #include "distributionlistentryview.h"
00076 #include "extensionmanager.h"
00077 #include "filterselectionwidget.h"
00078 #include "incsearchwidget.h"
00079 #include "jumpbuttonbar.h"
00080 #include "kablock.h"
00081 #include "kabprefs.h"
00082 #include "kabtools.h"
00083 #include "kaddressbookservice.h"
00084 #include "kaddressbookiface.h"
00085 #include "ldapsearchdialog.h"
00086 #include "locationmap.h"
00087 #include "printing/printingwizard.h"
00088 #include "searchmanager.h"
00089 #include "undocmds.h"
00090 #include "viewmanager.h"
00091 #include "xxportmanager.h"
00092 
00093 #include "kabcore.h"
00094 
00095 KABCore::KABCore( KXMLGUIClient *client, bool readWrite, QWidget *parent,
00096                   const QString &file, const char *name )
00097   : KAB::Core( client, parent, name ), mStatusBar( 0 ), mViewManager( 0 ),
00098     mExtensionManager( 0 ), mJumpButtonBar( 0 ), mCategorySelectDialog( 0 ),
00099     mCategoryEditDialog( 0 ), mLdapSearchDialog( 0 ), mReadWrite( readWrite ),
00100     mModified( false )
00101 {
00102   mWidget = new QWidget( parent, name );
00103 
00104   mIsPart = !parent->isA( "KAddressBookMain" );
00105 
00106   mAddressBookChangedTimer = new QTimer( this );
00107   connect( mAddressBookChangedTimer, SIGNAL( timeout() ),
00108            this, SLOT( addressBookChanged() ) );
00109 
00110   if ( file.isEmpty() ) {
00111     mAddressBook = KABC::StdAddressBook::self( true );
00112   } else {
00113     kdDebug(5720) << "KABCore(): document '" << file << "'" << endl;
00114     mAddressBook = new KABC::AddressBook;
00115     mAddressBook->addResource( new KABC::ResourceFile( file ) );
00116     if ( !mAddressBook->load() ) {
00117       KMessageBox::error( parent, i18n("Unable to load '%1'.").arg( file ) );
00118     }
00119   }
00120   mAddressBook->setErrorHandler( new KABC::GuiErrorHandler( mWidget ) );
00121 
00122 #if ! KDE_IS_VERSION(3,5,8)
00123   mAddressBook->addCustomField( i18n( "Department" ), KABC::Field::Organization,
00124                                 "X-Department", "KADDRESSBOOK" );
00125 #endif
00126   mAddressBook->addCustomField( i18n( "Profession" ), KABC::Field::Organization,
00127                                 "X-Profession", "KADDRESSBOOK" );
00128   mAddressBook->addCustomField( i18n( "Assistant's Name" ), KABC::Field::Organization,
00129                                 "X-AssistantsName", "KADDRESSBOOK" );
00130   mAddressBook->addCustomField( i18n( "Manager's Name" ), KABC::Field::Organization,
00131                                 "X-ManagersName", "KADDRESSBOOK" );
00132   mAddressBook->addCustomField( i18n( "Partner's Name" ), KABC::Field::Personal,
00133                                 "X-SpousesName", "KADDRESSBOOK" );
00134   mAddressBook->addCustomField( i18n( "Office" ), KABC::Field::Personal,
00135                                 "X-Office", "KADDRESSBOOK" );
00136   mAddressBook->addCustomField( i18n( "IM Address" ), KABC::Field::Personal,
00137                                 "X-IMAddress", "KADDRESSBOOK" );
00138   mAddressBook->addCustomField( i18n( "Anniversary" ), KABC::Field::Personal,
00139                                 "X-Anniversary", "KADDRESSBOOK" );
00140   mAddressBook->addCustomField( i18n( "Blog" ), KABC::Field::Personal,
00141                                 "BlogFeed", "KADDRESSBOOK" );
00142 
00143   mSearchManager = new KAB::SearchManager( mAddressBook, parent );
00144 
00145   connect( mSearchManager, SIGNAL( contactsUpdated() ),
00146            this, SLOT( slotContactsUpdated() ) );
00147 
00148   initGUI();
00149 
00150   connect( mAddressBook, SIGNAL( addressBookChanged( AddressBook* ) ),
00151            SLOT( delayedAddressBookChanged() ) );
00152   connect( mAddressBook, SIGNAL( loadingFinished( Resource* ) ),
00153            SLOT( delayedAddressBookChanged() ) );
00154 
00155   mIncSearchWidget->setFocus();
00156 
00157   connect( mViewManager, SIGNAL( selected( const QString& ) ),
00158            SLOT( setContactSelected( const QString& ) ) );
00159   connect( mViewManager, SIGNAL( executed( const QString& ) ),
00160            SLOT( editContact( const QString& ) ) );
00161   connect( mViewManager, SIGNAL( modified() ),
00162            SLOT( setModified() ) );
00163   connect( mViewManager, SIGNAL( urlDropped( const KURL& ) ),
00164            mXXPortManager, SLOT( importVCard( const KURL& ) ) );
00165   connect( mViewManager, SIGNAL( viewFieldsChanged() ),
00166            SLOT( updateIncSearchWidget() ) );
00167   connect( mExtensionManager, SIGNAL( modified( const KABC::Addressee::List& ) ),
00168            this, SLOT( extensionModified( const KABC::Addressee::List& ) ) );
00169   connect( mExtensionManager, SIGNAL( deleted( const QStringList& ) ),
00170            this, SLOT( extensionDeleted( const QStringList& ) ) );
00171 
00172   connect( mXXPortManager, SIGNAL( modified() ),
00173            SLOT( setModified() ) );
00174 
00175   connect( mDetailsViewer, SIGNAL( highlightedMessage( const QString& ) ),
00176            SLOT( detailsHighlighted( const QString& ) ) );
00177 
00178   connect( mIncSearchWidget, SIGNAL( scrollUp() ),
00179            mViewManager, SLOT( scrollUp() ) );
00180   connect( mIncSearchWidget, SIGNAL( scrollDown() ),
00181            mViewManager, SLOT( scrollDown() ) );
00182 
00183   mAddressBookService = new KAddressBookService( this );
00184 
00185   mCommandHistory = new KCommandHistory( actionCollection(), true );
00186   connect( mCommandHistory, SIGNAL( commandExecuted() ),
00187            mSearchManager, SLOT( reload() ) );
00188 
00189   mSearchManager->reload();
00190 
00191   setModified( false );
00192 
00193   KAcceleratorManager::manage( mWidget );
00194 
00195   mKIMProxy = ::KIMProxy::instance( kapp->dcopClient() );
00196 }
00197 
00198 KABCore::~KABCore()
00199 {
00200   mAddressBook->disconnect();
00201 
00202   mAddressBook = 0;
00203   KABC::StdAddressBook::close();
00204   mKIMProxy = 0;
00205 }
00206 
00207 void KABCore::restoreSettings()
00208 {
00209   bool state = KABPrefs::instance()->jumpButtonBarVisible();
00210   mActionJumpBar->setChecked( state );
00211   setJumpButtonBarVisible( state );
00212 
00213   state = KABPrefs::instance()->detailsPageVisible();
00214   mActionDetails->setChecked( state );
00215   setDetailsVisible( state );
00216 
00217   mViewManager->restoreSettings();
00218   mExtensionManager->restoreSettings();
00219 
00220   updateIncSearchWidget();
00221   mIncSearchWidget->setCurrentItem( KABPrefs::instance()->currentIncSearchField() );
00222 
00223   QValueList<int> splitterSize = KABPrefs::instance()->detailsSplitter();
00224   if ( splitterSize.count() == 0 ) {
00225     splitterSize.append( 360 );
00226     splitterSize.append( 260 );
00227   }
00228   mDetailsSplitter->setSizes( splitterSize );
00229 
00230   const QValueList<int> leftSplitterSizes = KABPrefs::instance()->leftSplitter();
00231   if ( !leftSplitterSizes.isEmpty() )
00232       mLeftSplitter->setSizes( leftSplitterSizes );
00233 }
00234 
00235 void KABCore::saveSettings()
00236 {
00237   KABPrefs::instance()->setJumpButtonBarVisible( mActionJumpBar->isChecked() );
00238   KABPrefs::instance()->setDetailsPageVisible( mActionDetails->isChecked() );
00239   KABPrefs::instance()->setDetailsSplitter( mDetailsSplitter->sizes() );
00240   KABPrefs::instance()->setLeftSplitter( mLeftSplitter->sizes() );
00241 
00242   mExtensionManager->saveSettings();
00243   mViewManager->saveSettings();
00244 
00245   KABPrefs::instance()->setCurrentIncSearchField( mIncSearchWidget->currentItem() );
00246 }
00247 
00248 KABC::AddressBook *KABCore::addressBook() const
00249 {
00250   return mAddressBook;
00251 }
00252 
00253 KConfig *KABCore::config() const
00254 {
00255   return KABPrefs::instance()->config();
00256 }
00257 
00258 KActionCollection *KABCore::actionCollection() const
00259 {
00260   return guiClient()->actionCollection();
00261 }
00262 
00263 KABC::Field *KABCore::currentSortField() const
00264 {
00265   return mViewManager->currentSortField();
00266 }
00267 
00268 QStringList KABCore::selectedUIDs() const
00269 {
00270   return mViewManager->selectedUids();
00271 }
00272 
00273 KABC::Resource *KABCore::requestResource( QWidget *parent )
00274 {
00275   QPtrList<KABC::Resource> kabcResources = addressBook()->resources();
00276 
00277   QPtrList<KRES::Resource> kresResources;
00278   QPtrListIterator<KABC::Resource> resIt( kabcResources );
00279   KABC::Resource *resource;
00280   while ( ( resource = resIt.current() ) != 0 ) {
00281     ++resIt;
00282     bool writable = false;
00283     if ( resource->inherits( "KPIM::ResourceABC" ) ) {
00284       KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( resource );
00285       const QStringList subresources = resAbc->subresources();
00286       for ( QStringList::ConstIterator it = subresources.begin(); it != subresources.end(); ++it ) {
00287         if ( resAbc->subresourceActive(*it) && resAbc->subresourceWritable(*it) ) {
00288           writable = true;
00289           break;
00290         }
00291       }
00292     } else {
00293       if ( !resource->readOnly() ) {
00294         writable = true;
00295       }
00296     }
00297 
00298     if ( writable ) {
00299       KRES::Resource *res = resource; // downcast
00300       kresResources.append( res );
00301     }
00302   }
00303 
00304   KRES::Resource *res = KRES::SelectDialog::getResource( kresResources, parent );
00305   return static_cast<KABC::Resource*>( res ); // upcast
00306 }
00307 
00308 QWidget *KABCore::widget() const
00309 {
00310   return mWidget;
00311 }
00312 
00313 KAboutData *KABCore::createAboutData()
00314 {
00315   KAboutData *about = new KAboutData( "kaddressbook", I18N_NOOP( "KAddressBook" ),
00316                                       "3.5.10", I18N_NOOP( "The KDE Address Book" ),
00317                                       KAboutData::License_GPL_V2,
00318                                       I18N_NOOP( "(c) 1997-2005, The KDE PIM Team" ) );
00319   about->addAuthor( "Tobias Koenig", I18N_NOOP( "Current maintainer" ), "tokoe@kde.org" );
00320   about->addAuthor( "Don Sanders", I18N_NOOP( "Original author" ) );
00321   about->addAuthor( "Cornelius Schumacher",
00322                     I18N_NOOP( "Co-maintainer, libkabc port, CSV import/export" ),
00323                     "schumacher@kde.org" );
00324   about->addAuthor( "Mike Pilone", I18N_NOOP( "GUI and framework redesign" ),
00325                     "mpilone@slac.com" );
00326   about->addAuthor( "Greg Stern", I18N_NOOP( "DCOP interface" ) );
00327   about->addAuthor( "Mark Westcott", I18N_NOOP( "Contact pinning" ) );
00328   about->addAuthor( "Mischel Boyer de la Giroday", I18N_NOOP( "LDAP Lookup" ),
00329                     "michel@klaralvdalens-datakonsult.se" );
00330   about->addAuthor( "Steffen Hansen", I18N_NOOP( "LDAP Lookup" ),
00331                     "hansen@kde.org" );
00332 
00333   return about;
00334 }
00335 
00336 void KABCore::setStatusBar( KStatusBar *statusBar )
00337 {
00338   mStatusBar = statusBar;
00339 }
00340 
00341 KStatusBar *KABCore::statusBar() const
00342 {
00343   return mStatusBar;
00344 }
00345 
00346 void KABCore::setContactSelected( const QString &uid )
00347 {
00348   KABC::Addressee addr = mAddressBook->findByUid( uid );
00349   if ( !mDetailsViewer->isHidden() )
00350     mDetailsViewer->setAddressee( addr );
00351 #ifdef KDEPIM_NEW_DISTRLISTS
00352   if ( !mSelectedDistributionList.isNull() && mDistListEntryView->isShown() ) {
00353       showDistributionListEntry( uid );
00354   }
00355 #endif
00356   mExtensionManager->setSelectionChanged();
00357 
00358   KABC::Addressee::List list = mViewManager->selectedAddressees();
00359   const bool someSelected = list.size() > 0;
00360   const bool singleSelected = list.size() == 1;
00361   bool writable = mReadWrite;
00362 
00363   if ( writable ) {
00364     //check if every single (sub)resource is writable
00365     //### We have a performance problem here - everytime *one* item is added or
00366     //    removed we re-check *all* items. If this turns out to be a bottleneck
00367     //    we need to keep some state and check new items only.
00368     KABC::Addressee::List::ConstIterator addrIt = list.constBegin();
00369     for ( ; addrIt != list.constEnd(); ++addrIt ) {
00370       KABC::Resource *res = ( *addrIt ).resource();
00371       if ( !res ) {
00372         kdDebug() << "KABCore::setContactSelected: this addressee has no resource!" << endl;
00373         writable = false;
00374         break;
00375       }
00376       if ( res->readOnly() ) {
00377         writable = false;
00378         break;
00379       }
00380       //HACK: manual polymorphism
00381       if ( res->inherits( "KPIM::ResourceABC" ) ) {
00382         KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( res );
00383 
00384         QString subresource = resAbc->uidToResourceMap()[ ( *addrIt ).uid() ];
00385         if ( !subresource.isEmpty() && !resAbc->subresourceWritable( subresource ) ) {
00386           writable = false;
00387           break;
00388         }
00389       }
00390     }
00391   }
00392 
00393   bool moreThanOneResource = mAddressBook->resources().count() > 1;
00394   if ( !moreThanOneResource && !mAddressBook->resources().isEmpty() ) {
00395       KABC::Resource *res = mAddressBook->resources().first();
00396       if ( res->inherits( "KPIM::ResourceABC" ) ) {
00397         KPIM::ResourceABC *resAbc = static_cast<KPIM::ResourceABC *>( res );
00398         const QStringList subresources = resAbc->subresources();
00399         int writeables = 0;
00400         for ( QStringList::ConstIterator it = subresources.begin(); it != subresources.end(); ++it ) {
00401             if ( resAbc->subresourceActive(*it) && resAbc->subresourceWritable(*it) ) {
00402                 writeables++;
00403             }
00404         }
00405         moreThanOneResource = ( writeables >= 2 );
00406       }
00407   }
00408 
00409   // update the actions
00410 
00411   mActionCopy->setEnabled( someSelected );
00412   mActionCut->setEnabled( someSelected && writable );
00413   mActionDelete->setEnabled( someSelected && writable );
00414   // the "edit" dialog doubles as the details dialog and it knows when the addressee is read-only
00415   // (### this does not make much sense from the user perspective!)
00416   mActionEditAddressee->setEnabled( singleSelected && !mExtensionManager->isQuickEditVisible());
00417   mActionCopyAddresseeTo->setEnabled( someSelected && moreThanOneResource );
00418   mActionMoveAddresseeTo->setEnabled( someSelected && moreThanOneResource && writable );
00419   mActionMail->setEnabled( someSelected );
00420   mActionMailVCard->setEnabled( someSelected );
00421   mActionChat->setEnabled( singleSelected && mKIMProxy && mKIMProxy->initialize() );
00422   mActionWhoAmI->setEnabled( singleSelected );
00423   mActionCategories->setEnabled( someSelected && writable );
00424   mActionMerge->setEnabled( ( list.size() == 2 ) && writable );
00425 
00426   if ( mReadWrite ) {
00427     QClipboard *cb = QApplication::clipboard();
00428 #if defined(KABC_VCARD_ENCODING_FIX)
00429     const QMimeSource *data = cb->data( QClipboard::Clipboard );
00430     list = AddresseeUtil::clipboardToAddressees( data->encodedData( "text/x-vcard" ) );
00431 #else
00432     list = AddresseeUtil::clipboardToAddressees( cb->text() );
00433 #endif
00434     mActionPaste->setEnabled( !list.isEmpty() );
00435   }
00436 #ifdef KDEPIM_NEW_DISTRLISTS
00437   mAddDistListButton->setEnabled( writable );
00438   mRemoveDistListButton->setEnabled( someSelected && writable );
00439 #endif
00440 }
00441 
00442 void KABCore::sendMail()
00443 {
00444   //FIXME: breaks with email addresses containing ","
00445   sendMail( mViewManager->selectedEmails().join( ", " ) );
00446 }
00447 
00448 void KABCore::sendMail( const QString& email )
00449 {
00450   kapp->invokeMailer( email, "" );
00451 }
00452 
00453 void KABCore::mailVCard()
00454 {
00455   QStringList uids = mViewManager->selectedUids();
00456   if ( !uids.isEmpty() )
00457     mailVCard( uids );
00458 }
00459 
00460 void KABCore::mailVCard( const QStringList &uids )
00461 {
00462   KABTools::mailVCards( uids, mAddressBook );
00463 }
00464 
00465 void KABCore::startChat()
00466 {
00467   QStringList uids = mViewManager->selectedUids();
00468   if ( !uids.isEmpty() )
00469     mKIMProxy->chatWithContact( uids.first() );
00470 }
00471 
00472 void KABCore::browse( const QString& url )
00473 {
00474   kapp->invokeBrowser( url );
00475 }
00476 
00477 void KABCore::selectAllContacts()
00478 {
00479   mViewManager->setSelected( QString::null, true );
00480 }
00481 
00482 void KABCore::deleteContacts()
00483 {
00484   QStringList uidList = mViewManager->selectedUids();
00485 
00486   deleteContacts( uidList );
00487 }
00488 
00489 void KABCore::deleteDistributionLists( const QStringList & names )
00490 {
00491   if ( names.isEmpty() )
00492       return;
00493   if ( KMessageBox::warningContinueCancelList( mWidget, i18n( "Do you really want to delete this distribution list?",
00494                                                  "Do you really want to delete these %n distribution lists?", names.count() ),
00495                                                  names, QString::null, KStdGuiItem::del() ) == KMessageBox::Cancel )
00496    return;
00497 
00498   QStringList uids;
00499   for ( QStringList::ConstIterator it = names.begin(); it != names.end(); ++it ) {
00500       uids.append( KPIM::DistributionList::findByName( mAddressBook, *it ).uid() );
00501   }
00502   DeleteCommand *command = new DeleteCommand( mAddressBook, uids );
00503   mCommandHistory->addCommand( command );
00504   setModified( true );
00505 }
00506 
00507 void KABCore::deleteContacts( const QStringList &uids )
00508 {
00509   if ( uids.count() > 0 ) {
00510     QStringList names;
00511     QStringList::ConstIterator it = uids.begin();
00512     const QStringList::ConstIterator endIt( uids.end() );
00513     while ( it != endIt ) {
00514       KABC::Addressee addr = mAddressBook->findByUid( *it );
00515       names.append( addr.realName().isEmpty() ? addr.preferredEmail() : addr.realName() );
00516       ++it;
00517     }
00518 
00519     if ( KMessageBox::warningContinueCancelList(
00520            mWidget,
00521            i18n( "<qt>"
00522                  "Do you really want to delete this contact from your addressbook?<br>"
00523                  "<b>Note:</b>The contact will be also removed from all distribution lists."
00524                  "</qt>",
00525                  "<qt>"
00526                  "Do you really want to delete these %n contacts from your addressbook?<br>"
00527                  "<b>Note:</b>The contacts will be also removed from all distribution lists."
00528                  "</qt>",
00529                  uids.count() ),
00530            names, QString::null, KStdGuiItem::del() ) == KMessageBox::Cancel ) {
00531       return;
00532     }
00533 
00534     DeleteCommand *command = new DeleteCommand( mAddressBook, uids );
00535     mCommandHistory->addCommand( command );
00536 
00537     // now if we deleted anything, refresh
00538     setContactSelected( QString::null );
00539     setModified( true );
00540   }
00541 }
00542 
00543 void KABCore::copyContacts()
00544 {
00545   KABC::Addressee::List addrList = mViewManager->selectedAddressees();
00546 
00547 #if defined(KABC_VCARD_ENCODING_FIX)
00548   QByteArray clipText = AddresseeUtil::addresseesToClipboard( addrList );
00549   QClipboard *cb = QApplication::clipboard();
00550   cb->setText( QString::fromUtf8( clipText.data() ) );
00551 #else
00552   QString clipText = AddresseeUtil::addresseesToClipboard( addrList );
00553   QClipboard *cb = QApplication::clipboard();
00554   cb->setText( clipText );
00555 #endif
00556 }
00557 
00558 void KABCore::cutContacts()
00559 {
00560   QStringList uidList = mViewManager->selectedUids();
00561 
00562   if ( uidList.size() > 0 ) {
00563     CutCommand *command = new CutCommand( mAddressBook, uidList );
00564     mCommandHistory->addCommand( command );
00565 
00566     setModified( true );
00567   }
00568 }
00569 
00570 void KABCore::pasteContacts()
00571 {
00572   QClipboard *cb = QApplication::clipboard();
00573 #if defined(KABC_VCARD_ENCODING_FIX)
00574   const QMimeSource *data = cb->data( QClipboard::Clipboard );
00575   KABC::Addressee::List list = AddresseeUtil::clipboardToAddressees( data->encodedData( "text/x-vcard" ) );
00576 #else
00577   KABC::Addressee::List list = AddresseeUtil::clipboardToAddressees( cb->text() );
00578 #endif
00579   pasteContacts( list );
00580 }
00581 
00582 void KABCore::pasteContacts( KABC::Addressee::List &list )
00583 {
00584   KABC::Resource *resource = requestResource( mWidget );
00585   if ( !resource )
00586     return;
00587 
00588   KABC::Addressee::List::Iterator it;
00589   const KABC::Addressee::List::Iterator endIt( list.end() );
00590   for ( it = list.begin(); it != endIt; ++it )
00591     (*it).setResource( resource );
00592 
00593   PasteCommand *command = new PasteCommand( this, list );
00594   mCommandHistory->addCommand( command );
00595 
00596   setModified( true );
00597 }
00598 
00599 void KABCore::mergeContacts()
00600 {
00601   KABC::Addressee::List list = mViewManager->selectedAddressees();
00602   if ( list.count() < 2 )
00603     return;
00604 
00605   KABC::Addressee addr = KABTools::mergeContacts( list );
00606 
00607   KABC::Addressee::List::Iterator it = list.begin();
00608   const KABC::Addressee::List::Iterator endIt( list.end() );
00609   KABC::Addressee origAddr = *it;
00610   QStringList uids;
00611   ++it;
00612   while ( it != endIt ) {
00613     uids.append( (*it).uid() );
00614     ++it;
00615   }
00616 
00617   DeleteCommand *command = new DeleteCommand( mAddressBook, uids );
00618   mCommandHistory->addCommand( command );
00619 
00620   EditCommand *editCommand = new EditCommand( mAddressBook, origAddr, addr );
00621   mCommandHistory->addCommand( editCommand );
00622 
00623   mSearchManager->reload();
00624 }
00625 
00626 void KABCore::setWhoAmI()
00627 {
00628   KABC::Addressee::List addrList = mViewManager->selectedAddressees();
00629 
00630   if ( addrList.count() > 1 ) {
00631     // can probably be removed because we now check the selection in setContactSelected().
00632     KMessageBox::sorry( mWidget, i18n( "Please select only one contact." ) );
00633     return;
00634   }
00635 
00636   QString text( i18n( "<qt>Do you really want to use <b>%1</b> as your new personal contact?</qt>" ) );
00637   if ( KMessageBox::questionYesNo( mWidget, text.arg( addrList[ 0 ].assembledName() ), QString::null, i18n("Use"), i18n("Do Not Use") ) == KMessageBox::Yes )
00638     static_cast<KABC::StdAddressBook*>( KABC::StdAddressBook::self( true ) )->setWhoAmI( addrList[ 0 ] );
00639 }
00640 
00641 void KABCore::incrementalTextSearch( const QString& text )
00642 {
00643   setContactSelected( QString::null );
00644   mSearchManager->search( text, mIncSearchWidget->currentFields() );
00645 }
00646 
00647 void KABCore::incrementalJumpButtonSearch( const QString& character )
00648 {
00649   mViewManager->setSelected( QString::null, false );
00650 
00651   KABC::AddresseeList list = mSearchManager->contacts();
00652   KABC::Field *field = mViewManager->currentSortField();
00653   if ( field ) {
00654     list.sortByField( field );
00655     KABC::AddresseeList::ConstIterator it;
00656     const KABC::AddresseeList::ConstIterator endIt( list.end() );
00657     for ( it = list.begin(); it != endIt; ++it ) {
00658       if ( field->value( *it ).startsWith( character, false ) ) {
00659         mViewManager->setSelected( (*it).uid(), true );
00660         return;
00661       }
00662     }
00663   }
00664 }
00665 
00666 void KABCore::setModified()
00667 {
00668   setModified( true );
00669 }
00670 
00671 void KABCore::setModified( bool modified )
00672 {
00673   mModified = modified;
00674   mActionSave->setEnabled( mModified );
00675 
00676   mSearchManager->reload();
00677 }
00678 
00679 bool KABCore::modified() const
00680 {
00681   return mModified;
00682 }
00683 
00684 void KABCore::contactModified( const KABC::Addressee &addr )
00685 {
00686   Command *command = 0;
00687 
00688   // check if it exists already
00689   KABC::Addressee origAddr = mAddressBook->findByUid( addr.uid() );
00690   if ( origAddr.isEmpty() ) {
00691     KABC::Addressee::List addressees;
00692     addressees.append( addr );
00693     command = new NewCommand( mAddressBook, addressees );
00694   } else {
00695     command = new EditCommand( mAddressBook, origAddr, addr );
00696   }
00697 
00698   mCommandHistory->addCommand( command );
00699 
00700   setContactSelected( addr.uid() );
00701   setModified( true );
00702 }
00703 
00704 void KABCore::newDistributionList()
00705 {
00706 #ifdef KDEPIM_NEW_DISTRLISTS
00707   KABC::Resource *resource = requestResource( mWidget );
00708   if ( !resource )
00709     return;
00710 
00711   QString name = i18n( "New Distribution List" );
00712   const KPIM::DistributionList distList = KPIM::DistributionList::findByName( addressBook(), name );
00713   if ( !distList.isEmpty() ) {
00714     bool foundUnused = false;
00715     int i = 1;
00716     while ( !foundUnused ) {
00717       name = i18n( "New Distribution List (%1)" ).arg( i++ );
00718       foundUnused = KPIM::DistributionList::findByName( addressBook(), name ).isEmpty();
00719     }
00720   }
00721   KPIM::DistributionList list;
00722   list.setUid( KApplication::randomString( 10 ) );
00723   list.setName( name );
00724   list.setResource( resource );
00725   editDistributionList( list );
00726 #endif
00727 }
00728 
00729 void KABCore::newContact()
00730 {
00731   AddresseeEditorDialog *dialog = 0;
00732 
00733   KABC::Resource* resource = requestResource( mWidget );
00734 
00735   if ( resource ) {
00736     KABC::Addressee addr;
00737     addr.setResource( resource );
00738 
00739     if ( !KABLock::self( mAddressBook )->lock( addr.resource() ) )
00740       return;
00741 
00742     dialog = createAddresseeEditorDialog( mWidget );
00743     dialog->setAddressee( addr );
00744   } else
00745     return;
00746 
00747   mEditorDict.insert( dialog->addressee().uid(), dialog );
00748 
00749   dialog->show();
00750 }
00751 
00752 void KABCore::addEmail( const QString &aStr )
00753 {
00754   QString fullName, email;
00755 
00756   KABC::Addressee::parseEmailAddress( aStr, fullName, email );
00757 
00758 #if KDE_IS_VERSION(3,4,89)
00759   // This ugly hack will be removed in 4.0
00760   // addressbook may not be reloaded yet, as done asynchronously sometimes, so wait
00761   while ( !mAddressBook->loadingHasFinished() ) {
00762     QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
00763     // use sleep here to reduce cpu usage
00764     usleep( 100 );
00765   }
00766 #endif
00767 
00768   // Try to lookup the addressee matching the email address
00769   bool found = false;
00770   QStringList emailList;
00771   KABC::AddressBook::Iterator it;
00772   const KABC::AddressBook::Iterator endIt( mAddressBook->end() );
00773   for ( it = mAddressBook->begin(); !found && (it != endIt); ++it ) {
00774     emailList = (*it).emails();
00775     if ( emailList.contains( email ) > 0 ) {
00776       found = true;
00777       (*it).setNameFromString( fullName );
00778       editContact( (*it).uid() );
00779     }
00780   }
00781 
00782   if ( !found ) {
00783     KABC::Addressee addr;
00784     addr.setNameFromString( fullName );
00785     addr.insertEmail( email, true );
00786 
00787     mAddressBook->insertAddressee( addr );
00788     mViewManager->refreshView( addr.uid() );
00789     editContact( addr.uid() );
00790   }
00791 }
00792 
00793 void KABCore::importVCard( const KURL &url )
00794 {
00795   mXXPortManager->importVCard( url );
00796 }
00797 
00798 void KABCore::importVCardFromData( const QString &vCard )
00799 {
00800   mXXPortManager->importVCardFromData( vCard );
00801 }
00802 
00803 void KABCore::editContact( const QString &uid )
00804 {
00805   if ( mExtensionManager->isQuickEditVisible() )
00806     return;
00807 
00808   // First, locate the contact entry
00809   QString localUID = uid;
00810   if ( localUID.isNull() ) {
00811     QStringList uidList = mViewManager->selectedUids();
00812     if ( uidList.count() > 0 )
00813       localUID = *( uidList.at( 0 ) );
00814   }
00815 #if KDE_IS_VERSION(3,4,89)
00816   // This ugly hack will be removed in 4.0
00817   // for calls with given uid, as done from commandline and DCOP
00818   // addressbook may not be reloaded yet, as done asynchronously, so wait
00819   else while ( !mAddressBook->loadingHasFinished() ) {
00820     QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
00821     // use sleep here to reduce cpu usage
00822     usleep( 100 );
00823   }
00824 #endif
00825 
00826   KABC::Addressee addr = mAddressBook->findByUid( localUID );
00827   if ( !addr.isEmpty() ) {
00828     AddresseeEditorDialog *dialog = mEditorDict.find( addr.uid() );
00829     if ( !dialog ) {
00830 
00831       if ( !addr.resource()->readOnly() )
00832         if ( !KABLock::self( mAddressBook )->lock( addr.resource() ) ) {
00833           return;
00834         }
00835 
00836       dialog = createAddresseeEditorDialog( mWidget );
00837 
00838       mEditorDict.insert( addr.uid(), dialog );
00839 
00840       dialog->setAddressee( addr );
00841     }
00842 
00843     dialog->raise();
00844     dialog->show();
00845   }
00846 }
00847 
00848 
00849 void KABCore::copySelectedContactToResource()
00850 {
00851     storeContactIn( QString(), true /*copy*/);
00852 }
00853 
00854 void KABCore::moveSelectedContactToResource()
00855 {
00856     storeContactIn( QString(), false /*copy*/);
00857 }
00858 
00859 void KABCore::storeContactIn( const QString &uid, bool copy /*false*/ )
00860 {
00861   // First, locate the contact entry
00862   QStringList uidList;
00863   if ( uid.isNull() ) {
00864     uidList = mViewManager->selectedUids();
00865   } else {
00866     uidList << uid;
00867   }
00868   KABC::Resource *resource = requestResource( mWidget );
00869   if ( !resource )
00870     return;
00871 
00872   if ( copy ) {
00873     CopyToCommand *command = new CopyToCommand( mAddressBook, uidList, resource );
00874     mCommandHistory->addCommand( command );
00875   }
00876   else {
00877     MoveToCommand *command = new MoveToCommand( this, uidList, resource );
00878     mCommandHistory->addCommand( command );
00879   }
00880 
00881   addressBookChanged();
00882   setModified( true );
00883 }
00884 
00885 void KABCore::save()
00886 {
00887   QPtrList<KABC::Resource> resources = mAddressBook->resources();
00888   QPtrListIterator<KABC::Resource> it( resources );
00889   while ( it.current() && !it.current()->readOnly() ) {
00890     KABC::Ticket *ticket = mAddressBook->requestSaveTicket( it.current() );
00891     if ( ticket ) {
00892       if ( !mAddressBook->save( ticket ) ) {
00893         KMessageBox::error( mWidget,
00894                             i18n( "<qt>Unable to save address book <b>%1</b>.</qt>" ).arg( it.current()->resourceName() ) );
00895         mAddressBook->releaseSaveTicket( ticket );
00896       } else {
00897         setModified( false );
00898       }
00899     } else {
00900       KMessageBox::error( mWidget,
00901                           i18n( "<qt>Unable to get access for saving the address book <b>%1</b>.</qt>" )
00902                           .arg( it.current()->resourceName() ) );
00903     }
00904 
00905     ++it;
00906   }
00907 }
00908 
00909 void KABCore::setJumpButtonBarVisible( bool visible )
00910 {
00911   if ( visible ) {
00912     if ( !mJumpButtonBar )
00913       createJumpButtonBar();
00914     mJumpButtonBar->show();
00915   } else
00916     if ( mJumpButtonBar )
00917       mJumpButtonBar->hide();
00918 }
00919 
00920 void KABCore::setDetailsVisible( bool visible )
00921 {
00922   if ( visible )
00923     mDetailsPage->show();
00924   else
00925     mDetailsPage->hide();
00926 }
00927 
00928 void KABCore::extensionModified( const KABC::Addressee::List &list )
00929 {
00930   if ( list.count() != 0 ) {
00931     KABC::Addressee::List::ConstIterator it;
00932     const KABC::Addressee::List::ConstIterator endIt( list.end() );
00933     for ( it = list.begin(); it != endIt; ++it ) {
00934       Command *command = 0;
00935 
00936       // check if it exists already
00937       KABC::Addressee origAddr = mAddressBook->findByUid( (*it).uid() );
00938       if ( origAddr.isEmpty() ) {
00939         KABC::Addressee::List addressees;
00940         addressees.append( *it );
00941         command = new NewCommand( mAddressBook, addressees );
00942       } else
00943         command = new EditCommand( mAddressBook, origAddr, *it );
00944 
00945       mCommandHistory->blockSignals( true );
00946       mCommandHistory->addCommand( command );
00947       mCommandHistory->blockSignals( false );
00948     }
00949 
00950     setModified(true);
00951   }
00952 }
00953 
00954 void KABCore::extensionDeleted( const QStringList &uidList )
00955 {
00956   DeleteCommand *command = new DeleteCommand( mAddressBook, uidList );
00957   mCommandHistory->addCommand( command );
00958 
00959   // now if we deleted anything, refresh
00960   setContactSelected( QString::null );
00961   setModified( true );
00962 }
00963 
00964 QString KABCore::getNameByPhone( const QString &phone )
00965 {
00966 #if KDE_IS_VERSION(3,4,89)
00967   // This ugly hack will be removed in 4.0
00968   // addressbook may not be reloaded yet, as done asynchronously, so wait
00969   while ( !mAddressBook->loadingHasFinished() ) {
00970     QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
00971     // use sleep here to reduce cpu usage
00972     usleep( 100 );
00973   }
00974 #endif
00975 
00976   QRegExp r( "[/*/-/ ]" );
00977   QString localPhone( phone );
00978 
00979   bool found = false;
00980   QString ownerName = "";
00981   KABC::PhoneNumber::List phoneList;
00982 
00983   KABC::AddressBook::ConstIterator iter;
00984   const KABC::AddressBook::ConstIterator endIter( mAddressBook->end() );
00985 
00986   for ( iter = mAddressBook->begin(); !found && ( iter != endIter ); ++iter ) {
00987     phoneList = (*iter).phoneNumbers();
00988     KABC::PhoneNumber::List::Iterator phoneIter( phoneList.begin() );
00989     const KABC::PhoneNumber::List::Iterator phoneEndIter( phoneList.end() );
00990     for ( ; !found && ( phoneIter != phoneEndIter ); ++phoneIter) {
00991       // Get rid of separator chars so just the numbers are compared.
00992       if ( (*phoneIter).number().replace( r, "" ) == localPhone.replace( r, "" ) ) {
00993         ownerName = (*iter).realName();
00994         found = true;
00995       }
00996     }
00997   }
00998 
00999   return ownerName;
01000 }
01001 
01002 void KABCore::openLDAPDialog()
01003 {
01004   if ( !KProtocolInfo::isKnownProtocol( KURL( "ldap://localhost" ) ) ) {
01005     KMessageBox::error( mWidget, i18n( "Your KDE installation is missing LDAP "
01006                                        "support, please ask your administrator or distributor for more information." ),
01007                         i18n( "No LDAP IO Slave Available" ) );
01008     return;
01009   }
01010 
01011   if ( !mLdapSearchDialog ) {
01012     mLdapSearchDialog = new LDAPSearchDialog( mAddressBook, this, mWidget );
01013     connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ),
01014             SLOT( addressBookChanged() ) );
01015     connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ),
01016             SLOT( setModified() ) );
01017   } else
01018     mLdapSearchDialog->restoreSettings();
01019 
01020   if ( mLdapSearchDialog->isOK() )
01021     mLdapSearchDialog->exec();
01022 }
01023 
01024 void KABCore::configure()
01025 {
01026   // Save the current config so we do not loose anything if the user accepts
01027   saveSettings();
01028 
01029   KCMultiDialog dlg( mWidget, "", true );
01030   connect( &dlg, SIGNAL( configCommitted() ),
01031            this, SLOT( configurationChanged() ) );
01032 
01033   dlg.addModule( "kabconfig.desktop" );
01034   dlg.addModule( "kabldapconfig.desktop" );
01035   dlg.addModule( "kabcustomfields.desktop" );
01036 
01037   dlg.exec();
01038 }
01039 
01040 void KABCore::print()
01041 {
01042   KPrinter printer;
01043   printer.setDocName( i18n( "Address Book" ) );
01044   printer.setDocFileName( "addressbook" );
01045 
01046   if ( !printer.setup( mWidget, i18n("Print Addresses") ) )
01047     return;
01048 
01049   KABPrinting::PrintingWizard wizard( &printer, mAddressBook,
01050                                       mViewManager->selectedUids(), mWidget );
01051 
01052   wizard.exec();
01053 }
01054 
01055 void KABCore::detailsHighlighted( const QString &msg )
01056 {
01057   if ( mStatusBar ) {
01058     if ( !mStatusBar->hasItem( 2 ) )
01059       mStatusBar->insertItem( msg, 2 );
01060     else
01061       mStatusBar->changeItem( msg, 2 );
01062   }
01063 }
01064 
01065 void KABCore::showContactsAddress( const QString &addrUid )
01066 {
01067   QStringList uidList = mViewManager->selectedUids();
01068   if ( uidList.isEmpty() )
01069     return;
01070 
01071   KABC::Addressee addr = mAddressBook->findByUid( uidList.first() );
01072   if ( addr.isEmpty() )
01073     return;
01074 
01075   const KABC::Address::List list = addr.addresses();
01076   KABC::Address::List::ConstIterator it;
01077   const KABC::Address::List::ConstIterator endIt( list.end() );
01078   for ( it = list.begin(); it != endIt; ++it )
01079     if ( (*it).id() == addrUid ) {
01080       LocationMap::instance()->showAddress( *it );
01081       break;
01082     }
01083 }
01084 
01085 void KABCore::configurationChanged()
01086 {
01087   mExtensionManager->reconfigure();
01088   mViewManager->refreshView();
01089 }
01090 
01091 bool KABCore::queryClose()
01092 {
01093   saveSettings();
01094   KABPrefs::instance()->writeConfig();
01095 
01096   QPtrList<KABC::Resource> resources = mAddressBook->resources();
01097   QPtrListIterator<KABC::Resource> it( resources );
01098   while ( it.current() ) {
01099     it.current()->close();
01100     ++it;
01101   }
01102 
01103   return true;
01104 }
01105 
01106 void KABCore::reinitXMLGUI()
01107 {
01108   mExtensionManager->createActions();
01109 }
01110 void KABCore::delayedAddressBookChanged()
01111 {
01112   mAddressBookChangedTimer->start( 1000 );
01113 }
01114 
01115 void KABCore::addressBookChanged()
01116 {
01117   const QStringList selectedUids = mViewManager->selectedUids();
01118 
01119   mAddressBookChangedTimer->stop();
01120 
01121   if ( mJumpButtonBar )
01122     mJumpButtonBar->updateButtons();
01123 
01124   mSearchManager->reload();
01125 
01126   mViewManager->setSelected( QString::null, false );
01127 
01128   QString uid = QString::null;
01129   if ( !selectedUids.isEmpty() ) {
01130     uid = selectedUids.first();
01131     mViewManager->setSelected( uid, true );
01132   }
01133 
01134   setContactSelected( uid );
01135 
01136   updateCategories();
01137 }
01138 
01139 AddresseeEditorDialog *KABCore::createAddresseeEditorDialog( QWidget *parent,
01140                                                              const char *name )
01141 {
01142   AddresseeEditorDialog *dialog = new AddresseeEditorDialog( this, parent,
01143                                                  name ? name : "editorDialog" );
01144   connect( dialog, SIGNAL( contactModified( const KABC::Addressee& ) ),
01145            SLOT( contactModified( const KABC::Addressee& ) ) );
01146   connect( dialog, SIGNAL( editorDestroyed( const QString& ) ),
01147            SLOT( slotEditorDestroyed( const QString& ) ) );
01148 
01149   return dialog;
01150 }
01151 
01152 void KABCore::activateDetailsWidget( QWidget *widget )
01153 {
01154   if ( mDetailsStack->visibleWidget() == widget )
01155     return;
01156   mDetailsStack->raiseWidget( widget );
01157 }
01158 
01159 void KABCore::deactivateDetailsWidget( QWidget *widget )
01160 {
01161   if ( mDetailsStack->visibleWidget() != widget )
01162     return;
01163   mDetailsStack->raiseWidget( mDetailsWidget );
01164 }
01165 
01166 void KABCore::slotEditorDestroyed( const QString &uid )
01167 {
01168   AddresseeEditorDialog *dialog = mEditorDict.take( uid );
01169 
01170   KABC::Addressee addr = dialog->addressee();
01171 
01172   if ( !addr.resource()->readOnly() ) {
01173     QApplication::setOverrideCursor( Qt::waitCursor );
01174     KABLock::self( mAddressBook )->unlock( addr.resource() );
01175     QApplication::restoreOverrideCursor();
01176   }
01177 }
01178 
01179 void KABCore::initGUI()
01180 {
01181   QVBoxLayout *topLayout = new QVBoxLayout( mWidget, 0, 0 );
01182   KToolBar* searchTB = new KToolBar( mWidget, "search toolbar");
01183   searchTB->boxLayout()->setSpacing( KDialog::spacingHint() );
01184   mIncSearchWidget = new IncSearchWidget( searchTB, "kde toolbar widget");
01185   searchTB->setStretchableWidget( mIncSearchWidget );
01186   connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ),
01187            SLOT( incrementalTextSearch( const QString& ) ) );
01188 
01189   mDetailsSplitter = new QSplitter( mWidget );
01190 
01191   mLeftSplitter = new QSplitter( mDetailsSplitter );
01192   mLeftSplitter->setOrientation( KABPrefs::instance()->contactListAboveExtensions() ? Qt::Vertical : Qt::Horizontal );
01193 
01194   topLayout->addWidget( searchTB );
01195   topLayout->addWidget( mDetailsSplitter );
01196 
01197   mDetailsStack = new QWidgetStack( mDetailsSplitter );
01198   mExtensionManager = new ExtensionManager( new QWidget( mLeftSplitter ), mDetailsStack, this, this );
01199   connect( mExtensionManager, SIGNAL( detailsWidgetDeactivated( QWidget* ) ),
01200            this, SLOT( deactivateDetailsWidget( QWidget* ) ) );
01201   connect( mExtensionManager, SIGNAL( detailsWidgetActivated( QWidget* ) ),
01202            this, SLOT( activateDetailsWidget( QWidget* ) ) );
01203 
01204   QWidget *viewWidget = new QWidget( mLeftSplitter );
01205   if ( KABPrefs::instance()->contactListAboveExtensions() )
01206     mLeftSplitter->moveToFirst( viewWidget );
01207   QVBoxLayout *viewLayout = new QVBoxLayout( viewWidget );
01208   viewLayout->setSpacing( KDialog::spacingHint() );
01209 
01210   mViewHeaderLabel = new QLabel( viewWidget );
01211 //  mViewHeaderLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
01212   mViewHeaderLabel->setText( i18n( "Contacts" ) );
01213   viewLayout->addWidget( mViewHeaderLabel );
01214   mViewManager = new ViewManager( this, viewWidget );
01215   viewLayout->addWidget( mViewManager, 1 );
01216 
01217 #ifdef KDEPIM_NEW_DISTRLISTS
01218   mDistListButtonWidget = new QWidget( viewWidget );
01219   QHBoxLayout *buttonLayout = new QHBoxLayout( mDistListButtonWidget );
01220   buttonLayout->setSpacing( KDialog::spacingHint() );
01221   buttonLayout->addStretch( 1 );
01222 
01223   mAddDistListButton = new KPushButton( mDistListButtonWidget );
01224   mAddDistListButton->setEnabled( false );
01225   mAddDistListButton->setText( i18n( "Add" ) );
01226   QToolTip::add( mAddDistListButton, i18n( "Add contacts to the distribution list" ) );
01227   QWhatsThis::add( mAddDistListButton,
01228                    i18n( "Click this button if you want to add more contacts to "
01229                          "the current distribution list. You will be shown a dialog that allows "
01230                          "to enter a list of existing contacts to this distribution list." ) );
01231   connect( mAddDistListButton, SIGNAL( clicked() ),
01232            this, SLOT( editSelectedDistributionList() ) );
01233   buttonLayout->addWidget( mAddDistListButton );
01234   mDistListButtonWidget->setShown( false );
01235   viewLayout->addWidget( mDistListButtonWidget );
01236 
01237   mRemoveDistListButton = new KPushButton( mDistListButtonWidget );
01238   mRemoveDistListButton->setEnabled( false );
01239   mRemoveDistListButton->setText( i18n( "Remove" ) );
01240   QToolTip::add( mRemoveDistListButton, i18n( "Remove contacts from the distribution list" ) );
01241   QWhatsThis::add( mRemoveDistListButton,
01242                    i18n( "Click this button if you want to remove the selected contacts from "
01243                          "the current distribution list." ) );
01244   connect( mRemoveDistListButton, SIGNAL( clicked() ),
01245            this, SLOT( removeSelectedContactsFromDistList() ) );
01246   buttonLayout->addWidget( mRemoveDistListButton );
01247 #endif
01248 
01249   mFilterSelectionWidget = new FilterSelectionWidget( searchTB , "kde toolbar widget" );
01250   mViewManager->setFilterSelectionWidget( mFilterSelectionWidget );
01251 
01252   connect( mFilterSelectionWidget, SIGNAL( filterActivated( int ) ),
01253            mViewManager, SLOT( setActiveFilter( int ) ) );
01254 
01255   mDetailsWidget = new QWidget( mDetailsSplitter );
01256   mDetailsLayout = new QHBoxLayout( mDetailsWidget );
01257 
01258   mDetailsPage = new QWidget( mDetailsWidget );
01259   mDetailsLayout->addWidget( mDetailsPage );
01260 
01261   QHBoxLayout *detailsPageLayout = new QHBoxLayout( mDetailsPage, 0, 0 );
01262   mDetailsViewer = new KPIM::AddresseeView( mDetailsPage );
01263   mDetailsViewer->setVScrollBarMode( QScrollView::Auto );
01264   detailsPageLayout->addWidget( mDetailsViewer );
01265 
01266   mDistListEntryView = new KAB::DistributionListEntryView( this, mWidget );
01267   connect( mDistListEntryView, SIGNAL( distributionListClicked( const QString& ) ),
01268            this, SLOT( sendMailToDistributionList( const QString& ) ) );
01269   mDetailsStack->addWidget( mDistListEntryView );
01270   mDetailsStack->addWidget( mDetailsWidget );
01271   mDetailsStack->raiseWidget( mDetailsWidget );
01272   mDetailsSplitter->moveToLast( mDetailsStack );
01273 
01274   connect( mDetailsViewer, SIGNAL( addressClicked( const QString&) ),
01275            this, SLOT( showContactsAddress( const QString& ) ) );
01276 
01277   topLayout->setStretchFactor( mDetailsSplitter, 1 );
01278 
01279   mXXPortManager = new XXPortManager( this, mWidget );
01280 
01281   initActions();
01282 }
01283 
01284 void KABCore::createJumpButtonBar()
01285 {
01286   mJumpButtonBar = new JumpButtonBar( this, mDetailsWidget );
01287   mDetailsLayout->addWidget( mJumpButtonBar );
01288   mDetailsLayout->setStretchFactor( mJumpButtonBar, 1 );
01289 
01290   connect( mJumpButtonBar, SIGNAL( jumpToLetter( const QString& ) ),
01291            SLOT( incrementalJumpButtonSearch( const QString& ) ) );
01292   connect( mViewManager, SIGNAL( sortFieldChanged() ),
01293            mJumpButtonBar, SLOT( updateButtons() ) );
01294 }
01295 
01296 void KABCore::initActions()
01297 {
01298   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
01299            SLOT( clipboardDataChanged() ) );
01300 
01301   KAction *action;
01302 
01303   // file menu
01304   mActionMail = new KAction( i18n( "&Send Email to Contact..." ), "mail_send", 0,
01305                              this, SLOT( sendMail() ), actionCollection(), "file_mail" );
01306   action = KStdAction::print( this, SLOT( print() ), actionCollection() );
01307   mActionMail->setWhatsThis( i18n( "Send a mail to all selected contacts." ) );
01308   action->setWhatsThis( i18n( "Print a special number of contacts." ) );
01309 
01310   mActionSave = KStdAction::save( this,
01311                              SLOT( save() ), actionCollection(), "file_sync" );
01312   mActionSave->setWhatsThis( i18n( "Save all changes of the address book to the storage backend." ) );
01313 
01314   action = new KAction( i18n( "&New Contact..." ), "identity", CTRL+Key_N, this,
01315                SLOT( newContact() ), actionCollection(), "file_new_contact" );
01316   action->setWhatsThis( i18n( "Create a new contact<p>You will be presented with a dialog where you can add all data about a person, including addresses and phone numbers." ) );
01317 
01318   action = new KAction( i18n( "&New Distribution List..." ), "kontact_contacts", 0, this,
01319                SLOT( newDistributionList() ), actionCollection(), "file_new_distributionlist" );
01320   action->setWhatsThis( i18n( "Create a new distribution list<p>You will be presented with a dialog where you can create a new distribution list." ) );
01321 
01322   mActionMailVCard = new KAction( i18n("Send &Contact..."), "mail_post_to", 0,
01323                                   this, SLOT( mailVCard() ),
01324                                   actionCollection(), "file_mail_vcard" );
01325   mActionMailVCard->setWhatsThis( i18n( "Send a mail with the selected contact as attachment." ) );
01326 
01327   mActionChat = new KAction( i18n("Chat &With..."), 0,
01328                                   this, SLOT( startChat() ),
01329                                   actionCollection(), "file_chat" );
01330   mActionChat->setWhatsThis( i18n( "Start a chat with the selected contact." ) );
01331 
01332   mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0,
01333                                       this, SLOT( editContact() ),
01334                                       actionCollection(), "file_properties" );
01335   mActionEditAddressee->setWhatsThis( i18n( "Edit a contact<p>You will be presented with a dialog where you can change all data about a person, including addresses and phone numbers." ) );
01336 
01337   mActionMerge = new KAction( i18n( "&Merge Contacts" ), "", 0,
01338                               this, SLOT( mergeContacts() ),
01339                               actionCollection(), "edit_merge" );
01340 
01341   // edit menu
01342   mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() );
01343   mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() );
01344   mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() );
01345   action = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() );
01346   mActionCopy->setWhatsThis( i18n( "Copy the currently selected contact(s) to system clipboard in vCard format." ) );
01347   mActionCut->setWhatsThis( i18n( "Cuts the currently selected contact(s) to system clipboard in vCard format." ) );
01348   mActionPaste->setWhatsThis( i18n( "Paste the previously cut or copied contacts from clipboard." ) );
01349   action->setWhatsThis( i18n( "Selects all visible contacts from current view." ) );
01350 //  mActionUndo->setWhatsThis( i18n( "Undoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01351 //  mActionRedo->setWhatsThis( i18n( "Redoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01352 
01353   mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete",
01354                                Key_Delete, this, SLOT( deleteContacts() ),
01355                                actionCollection(), "edit_delete" );
01356   mActionDelete->setWhatsThis( i18n( "Delete all selected contacts." ) );
01357 
01358 
01359   mActionCopyAddresseeTo = new KAction( i18n( "&Copy Contact To..." ), "", 0,
01360                                       this, SLOT( copySelectedContactToResource() ),
01361                                       actionCollection(), "copy_contact_to" );
01362   const QString copyMoveWhatsThis = i18n( "Store a contact in a different Addressbook<p>You will be presented with a dialog where you can select a new storage place for this contact." );
01363   mActionCopyAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01364 
01365   mActionMoveAddresseeTo = new KAction( i18n( "M&ove Contact To..." ), "", 0,
01366                                       this, SLOT( moveSelectedContactToResource() ),
01367                                       actionCollection(), "move_contact_to" );
01368   mActionMoveAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01369 
01370   // settings menu
01371   mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), "next", 0,
01372                                       actionCollection(), "options_show_jump_bar" );
01373   mActionJumpBar->setWhatsThis( i18n( "Toggle whether the jump button bar shall be visible." ) );
01374   mActionJumpBar->setCheckedState( i18n( "Hide Jump Bar") );
01375   connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) );
01376 
01377   mActionDetails = new KToggleAction( i18n( "Show Details" ), 0, 0,
01378                                       actionCollection(), "options_show_details" );
01379   mActionDetails->setWhatsThis( i18n( "Toggle whether the details page shall be visible." ) );
01380   mActionDetails->setCheckedState( i18n( "Hide Details") );
01381   connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) );
01382 
01383   if ( mIsPart )
01384     action = new KAction( i18n( "&Configure Address Book..." ), "configure", 0,
01385                           this, SLOT( configure() ), actionCollection(),
01386                           "kaddressbook_configure" );
01387   else
01388     action = KStdAction::preferences( this, SLOT( configure() ), actionCollection() );
01389 
01390   action->setWhatsThis( i18n( "You will be presented with a dialog, that offers you all possibilities to configure KAddressBook." ) );
01391 
01392   // misc
01393   action = new KAction( i18n( "&Lookup Addresses in LDAP Directory..." ), "find", 0,
01394                         this, SLOT( openLDAPDialog() ), actionCollection(), "ldap_lookup" );
01395   action->setWhatsThis( i18n( "Search for contacts on a LDAP server<p>You will be presented with a dialog, where you can search for contacts and select the ones you want to add to your local address book." ) );
01396 
01397   mActionWhoAmI = new KAction( i18n( "Set as Personal Contact Data" ), "personal", 0, this,
01398                                SLOT( setWhoAmI() ), actionCollection(),
01399                                "edit_set_personal" );
01400   mActionWhoAmI->setWhatsThis( i18n( "Set the personal contact<p>The data of this contact will be used in many other KDE applications, so you do not have to input your personal data several times." ) );
01401 
01402   mActionCategories = new KAction( i18n( "Select Categories..." ), 0, this,
01403                                    SLOT( setCategories() ), actionCollection(),
01404                                    "edit_set_categories" );
01405   mActionCategories->setWhatsThis( i18n( "Set the categories for all selected contacts." ) );
01406 
01407   KAction *clearLocation = new KAction( i18n( "Clear Search Bar" ),
01408                     QApplication::reverseLayout() ? "clear_left" : "locationbar_erase",
01409                     CTRL+Key_L, this, SLOT( slotClearSearchBar() ), actionCollection(), "clear_search" );
01410   clearLocation->setWhatsThis( i18n( "Clear Search Bar<p>"
01411                      "Clears the content of the quick search bar." ) );
01412 
01413   clipboardDataChanged();
01414 }
01415 
01416 void KABCore::clipboardDataChanged()
01417 {
01418   if ( mReadWrite )
01419     mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() );
01420 }
01421 
01422 void KABCore::updateIncSearchWidget()
01423 {
01424   mIncSearchWidget->setViewFields( mViewManager->viewFields() );
01425 }
01426 
01427 void KABCore::updateCategories()
01428 {
01429   QStringList categories( allCategories() );
01430   categories.sort();
01431 
01432   const QStringList customCategories( KABPrefs::instance()->customCategories() );
01433   QStringList::ConstIterator it;
01434   const QStringList::ConstIterator endIt( customCategories.end() );
01435   for ( it = customCategories.begin(); it != endIt; ++it ) {
01436     if ( categories.find( *it ) == categories.end() ) {
01437       categories.append( *it );
01438     }
01439   }
01440 
01441   KABPrefs::instance()->mCustomCategories = categories;
01442   KABPrefs::instance()->writeConfig();
01443 
01444   if ( mCategoryEditDialog )
01445     mCategoryEditDialog->reload();
01446 }
01447 
01448 QStringList KABCore::allCategories() const
01449 {
01450   QStringList categories, allCategories;
01451   QStringList::ConstIterator catIt;
01452 
01453   KABC::AddressBook::ConstIterator it;
01454   const KABC::AddressBook::ConstIterator endIt( mAddressBook->end() );
01455   for ( it = mAddressBook->begin(); it != endIt; ++it ) {
01456     categories = (*it).categories();
01457     const QStringList::ConstIterator catEndIt( categories.end() );
01458     for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01459       if ( !allCategories.contains( *catIt ) )
01460         allCategories.append( *catIt );
01461     }
01462   }
01463 
01464   return allCategories;
01465 }
01466 
01467 void KABCore::setCategories()
01468 {
01469   // Show the category dialog
01470   if ( mCategorySelectDialog == 0 ) {
01471     mCategorySelectDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), mWidget );
01472     connect( mCategorySelectDialog, SIGNAL( categoriesSelected( const QStringList& ) ),
01473              SLOT( categoriesSelected( const QStringList& ) ) );
01474     connect( mCategorySelectDialog, SIGNAL( editCategories() ), SLOT( editCategories() ) );
01475   }
01476 
01477   mCategorySelectDialog->show();
01478   mCategorySelectDialog->raise();
01479 }
01480 
01481 void KABCore::categoriesSelected( const QStringList &categories )
01482 {
01483   bool merge = false;
01484   QString msg = i18n( "Merge with existing categories?" );
01485   if ( KMessageBox::questionYesNo( mWidget, msg, QString::null, i18n( "Merge" ), i18n( "Do Not Merge" ) ) == KMessageBox::Yes )
01486     merge = true;
01487 
01488   QStringList uids = mViewManager->selectedUids();
01489   QStringList::ConstIterator it;
01490   const QStringList::ConstIterator endIt( uids.end() );
01491   for ( it = uids.begin(); it != endIt; ++it ) {
01492     KABC::Addressee addr = mAddressBook->findByUid( *it );
01493     if ( !addr.isEmpty() ) {
01494       if ( !merge )
01495         addr.setCategories( categories );
01496       else {
01497         QStringList addrCategories = addr.categories();
01498         QStringList::ConstIterator catIt;
01499         const QStringList::ConstIterator catEndIt( categories.end() );
01500         for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01501           if ( !addrCategories.contains( *catIt ) )
01502             addrCategories.append( *catIt );
01503         }
01504         addr.setCategories( addrCategories );
01505       }
01506 
01507       mAddressBook->insertAddressee( addr );
01508     }
01509   }
01510 
01511   if ( uids.count() > 0 )
01512     setModified( true );
01513 }
01514 
01515 void KABCore::editCategories()
01516 {
01517   if ( mCategoryEditDialog == 0 ) {
01518     mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), mWidget );
01519     connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ),
01520              mCategorySelectDialog, SLOT( updateCategoryConfig() ) );
01521   }
01522 
01523   mCategoryEditDialog->show();
01524   mCategoryEditDialog->raise();
01525 }
01526 
01527 void KABCore::slotClearSearchBar()
01528 {
01529   mIncSearchWidget->clear();
01530   mIncSearchWidget->setFocus();
01531 }
01532 
01533 void KABCore::slotContactsUpdated()
01534 {
01535   if ( mStatusBar ) {
01536     QString msg( i18n( "%n contact matches", "%n contacts matching", mSearchManager->contacts().count() ) );
01537     if ( !mStatusBar->hasItem( 1 ) )
01538       mStatusBar->insertItem( msg, 1 );
01539     else
01540       mStatusBar->changeItem( msg, 1 );
01541   }
01542 
01543   emit contactsUpdated();
01544 }
01545 
01546 bool KABCore::handleCommandLine( KAddressBookIface* iface )
01547 {
01548   KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
01549   QCString addrStr = args->getOption( "addr" );
01550   QCString uidStr = args->getOption( "uid" );
01551 
01552   QString addr, uid, vcard;
01553   if ( !addrStr.isEmpty() )
01554     addr = QString::fromLocal8Bit( addrStr );
01555   if ( !uidStr.isEmpty() )
01556     uid = QString::fromLocal8Bit( uidStr );
01557 
01558   bool doneSomething = false;
01559 
01560   // Can not see why anyone would pass both a uid and an email address, so I'll leave it that two contact editors will show if they do
01561   if ( !addr.isEmpty() ) {
01562     iface->addEmail( addr );
01563     doneSomething = true;
01564   }
01565 
01566   if ( !uid.isEmpty() ) {
01567     iface->showContactEditor( uid );
01568     doneSomething = true;
01569   }
01570 
01571   if ( args->isSet( "new-contact" ) ) {
01572     iface->newContact();
01573     doneSomething = true;
01574   }
01575 
01576   if ( args->count() >= 1 ) {
01577     for ( int i = 0; i < args->count(); ++i )
01578       iface->importVCard( args->url( i ).url() );
01579     doneSomething = true;
01580   }
01581   return doneSomething;
01582 }
01583 
01584 void KABCore::removeSelectedContactsFromDistList()
01585 {
01586 #ifdef KDEPIM_NEW_DISTRLISTS
01587 
01588   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01589   if ( dist.isEmpty() )
01590     return;
01591   const QStringList uids = selectedUIDs();
01592   if ( uids.isEmpty() )
01593       return;
01594 
01595   QStringList names;
01596   QStringList::ConstIterator it = uids.begin();
01597   const QStringList::ConstIterator endIt( uids.end() );
01598   while ( it != endIt ) {
01599     KABC::Addressee addr = mAddressBook->findByUid( *it );
01600     names.append( addr.realName().isEmpty() ? addr.preferredEmail() : addr.realName() );
01601     ++it;
01602   }
01603 
01604   if ( KMessageBox::warningContinueCancelList(
01605          mWidget,
01606          i18n( "<qt>"
01607                "Do you really want to remove this contact from the %1 distribution list?<br>"
01608                "<b>Note:</b>The contact will be not be removed from your addressbook nor from "
01609                "any other distribution list."
01610                "</qt>",
01611                "<qt>"
01612                "Do you really want to remove these %n contacts from the %1 distribution list?<br>"
01613                "<b>Note:</b>The contacts will be not be removed from your addressbook nor from "
01614                "any other distribution list."
01615                "</qt>",
01616                uids.count() ).arg( mSelectedDistributionList ),
01617          names, QString::null, KStdGuiItem::del() ) == KMessageBox::Cancel ) {
01618     return;
01619   }
01620 
01621   for ( QStringList::ConstIterator uidIt = uids.begin(); uidIt != uids.end(); ++uidIt ) {
01622     typedef KPIM::DistributionList::Entry::List EntryList;
01623     const EntryList entries = dist.entries( addressBook() );
01624     for ( EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) {
01625       if ( (*it).addressee.uid() == (*uidIt) ) {
01626         dist.removeEntry( (*it).addressee, (*it).email );
01627         break;
01628       }
01629     }
01630   }
01631   addressBook()->insertAddressee( dist );
01632   setModified();
01633 #endif
01634 }
01635 
01636 void KABCore::sendMailToDistributionList( const QString &name )
01637 {
01638 #ifdef KDEPIM_NEW_DISTRLISTS
01639   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), name );
01640   if ( dist.isEmpty() )
01641     return;
01642   typedef KPIM::DistributionList::Entry::List EntryList;
01643   QStringList mails;
01644   const EntryList entries = dist.entries( addressBook() );
01645   for ( EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it )
01646     mails += (*it).addressee.fullEmail( (*it).email );
01647   sendMail( mails.join( ", " ) );
01648 #endif
01649 }
01650 
01651 void KABCore::editSelectedDistributionList()
01652 {
01653 #ifdef KDEPIM_NEW_DISTRLISTS
01654   editDistributionList( KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ) );
01655 #endif
01656 }
01657 
01658 
01659 void KABCore::editDistributionList( const QString &name )
01660 {
01661 #ifdef KDEPIM_NEW_DISTRLISTS
01662   editDistributionList( KPIM::DistributionList::findByName( addressBook(), name ) );
01663 #endif
01664 }
01665 
01666 #ifdef KDEPIM_NEW_DISTRLISTS
01667 
01668 void KABCore::showDistributionListEntry( const QString& uid )
01669 {
01670   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01671   if ( !dist.isEmpty() ) {
01672     mDistListEntryView->clear();
01673     typedef KPIM::DistributionList::Entry::List EntryList;
01674     const EntryList entries = dist.entries( addressBook() );
01675     for (EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) {
01676       if ( (*it).addressee.uid() == uid ) {
01677         mDistListEntryView->setEntry( dist, *it );
01678         break;
01679       }
01680     }
01681   }
01682 }
01683 
01684 void KABCore::editDistributionList( const KPIM::DistributionList &dist )
01685 {
01686   if ( dist.isEmpty() )
01687     return;
01688   QGuardedPtr<KPIM::DistributionListEditor::EditorWidget> dlg = new KPIM::DistributionListEditor::EditorWidget( addressBook(), widget() );
01689   dlg->setDistributionList( dist );
01690   if ( dlg->exec() == QDialog::Accepted && dlg ) {
01691     const KPIM::DistributionList newDist = dlg->distributionList();
01692     if ( newDist != dist ) {
01693       setModified();
01694     }
01695   }
01696   delete dlg;
01697 }
01698 
01699 
01700 KPIM::DistributionList::List KABCore::distributionLists() const
01701 {
01702   return mSearchManager->distributionLists();
01703 }
01704 
01705 void KABCore::setSelectedDistributionList( const QString &name )
01706 {
01707   mSelectedDistributionList = name;
01708   mSearchManager->setSelectedDistributionList( name );
01709   mViewHeaderLabel->setText( name.isNull() ?
01710                              i18n( "Contacts" ) :
01711                              i18n( "Distribution List: %1" ).arg( name ) );
01712   mDistListButtonWidget->setShown( !mSelectedDistributionList.isNull() );
01713   if ( !name.isNull() ) {
01714     mDetailsStack->raiseWidget( mDistListEntryView );
01715     if ( selectedUIDs().isEmpty() ) {
01716       mViewManager->setFirstSelected( true );
01717     }
01718     const QStringList selectedUids = selectedUIDs();
01719     showDistributionListEntry( selectedUids.isEmpty() ? QString() : selectedUids.first() );
01720   } else {
01721     mDetailsStack->raiseWidget( mExtensionManager->activeDetailsWidget() ?
01722                                 mExtensionManager->activeDetailsWidget() : mDetailsWidget );
01723   }
01724 }
01725 
01726 QStringList KABCore::distributionListNames() const
01727 {
01728   return mSearchManager->distributionListNames();
01729 }
01730 #endif
01731 
01732 #include "kabcore.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys