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