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