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   if ( KABPrefs::instance()->contactListAboveExtensions() )
01117     mLeftSplitter->moveToFirst( viewWidget );
01118   QVBoxLayout *viewLayout = new QVBoxLayout( viewWidget );
01119   viewLayout->setSpacing( KDialog::spacingHint() );
01120 
01121   mViewHeaderLabel = new QLabel( viewWidget );
01122 //  mViewHeaderLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
01123   mViewHeaderLabel->setText( i18n( "Contacts" ) );
01124   viewLayout->addWidget( mViewHeaderLabel );
01125   mViewManager = new ViewManager( this, viewWidget );
01126   viewLayout->addWidget( mViewManager, 1 );
01127 
01128 #ifdef KDEPIM_NEW_DISTRLISTS
01129   mDistListButtonWidget = new QWidget( viewWidget );
01130   QHBoxLayout *buttonLayout = new QHBoxLayout( mDistListButtonWidget );
01131   buttonLayout->setSpacing( KDialog::spacingHint() );
01132   buttonLayout->addStretch( 1 );
01133 
01134   KPushButton *addDistListButton = new KPushButton( mDistListButtonWidget );
01135   addDistListButton->setText( i18n( "Add" ) );
01136   connect( addDistListButton, SIGNAL( clicked() ), 
01137            this, SLOT( editSelectedDistributionList() ) );
01138   buttonLayout->addWidget( addDistListButton );
01139   mDistListButtonWidget->setShown( false );
01140   viewLayout->addWidget( mDistListButtonWidget );
01141 
01142   KPushButton *removeDistListButton = new KPushButton( mDistListButtonWidget );
01143   removeDistListButton->setText( i18n( "Remove" ) );
01144   connect( removeDistListButton, SIGNAL( clicked() ), 
01145            this, SLOT( removeSelectedContactsFromDistList() ) );
01146   buttonLayout->addWidget( removeDistListButton );
01147 #endif
01148 
01149   mFilterSelectionWidget = new FilterSelectionWidget( searchTB , "kde toolbar widget" );
01150   mViewManager->setFilterSelectionWidget( mFilterSelectionWidget );
01151 
01152   connect( mFilterSelectionWidget, SIGNAL( filterActivated( int ) ),
01153            mViewManager, SLOT( setActiveFilter( int ) ) );
01154 
01155   mDetailsWidget = new QWidget( mDetailsSplitter );
01156   mDetailsLayout = new QHBoxLayout( mDetailsWidget );
01157 
01158   mDetailsPage = new QWidget( mDetailsWidget );
01159   mDetailsLayout->addWidget( mDetailsPage );
01160 
01161   QHBoxLayout *detailsPageLayout = new QHBoxLayout( mDetailsPage, 0, 0 );
01162   mDetailsViewer = new KPIM::AddresseeView( mDetailsPage );
01163   mDetailsViewer->setVScrollBarMode( QScrollView::Auto );
01164   detailsPageLayout->addWidget( mDetailsViewer );
01165 
01166   mDistListEntryView = new KAB::DistributionListEntryView( this, mWidget );
01167   connect( mDistListEntryView, SIGNAL( distributionListClicked( const QString& ) ),
01168            this, SLOT( sendMailToDistributionList( const QString& ) ) );
01169   mDetailsStack->addWidget( mDistListEntryView );
01170   mDetailsStack->addWidget( mDetailsWidget );
01171   mDetailsStack->raiseWidget( mDetailsWidget );
01172   mDetailsSplitter->moveToLast( mDetailsStack );
01173 
01174   connect( mDetailsViewer, SIGNAL( addressClicked( const QString&) ),
01175            this, SLOT( showContactsAddress( const QString& ) ) );
01176 
01177   topLayout->setStretchFactor( mDetailsSplitter, 1 );
01178 
01179   mXXPortManager = new XXPortManager( this, mWidget );
01180 
01181   initActions();
01182 }
01183 
01184 void KABCore::createJumpButtonBar()
01185 {
01186   mJumpButtonBar = new JumpButtonBar( this, mDetailsWidget );
01187   mDetailsLayout->addWidget( mJumpButtonBar );
01188   mDetailsLayout->setStretchFactor( mJumpButtonBar, 1 );
01189 
01190   connect( mJumpButtonBar, SIGNAL( jumpToLetter( const QString& ) ),
01191            SLOT( incrementalJumpButtonSearch( const QString& ) ) );
01192   connect( mViewManager, SIGNAL( sortFieldChanged() ),
01193            mJumpButtonBar, SLOT( updateButtons() ) );
01194 }
01195 
01196 void KABCore::initActions()
01197 {
01198   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
01199            SLOT( clipboardDataChanged() ) );
01200 
01201   KAction *action;
01202 
01203   // file menu
01204   mActionMail = new KAction( i18n( "&Send Email to Contact..." ), "mail_send", 0,
01205                              this, SLOT( sendMail() ), actionCollection(), "file_mail" );
01206   action = KStdAction::print( this, SLOT( print() ), actionCollection() );
01207   mActionMail->setWhatsThis( i18n( "Send a mail to all selected contacts." ) );
01208   action->setWhatsThis( i18n( "Print a special number of contacts." ) );
01209 
01210   mActionSave = KStdAction::save( this,
01211                              SLOT( save() ), actionCollection(), "file_sync" );
01212   mActionSave->setWhatsThis( i18n( "Save all changes of the address book to the storage backend." ) );
01213 
01214   action = new KAction( i18n( "&New Contact..." ), "identity", CTRL+Key_N, this,
01215                SLOT( newContact() ), actionCollection(), "file_new_contact" );
01216   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." ) );
01217 
01218   action = new KAction( i18n( "&New Distribution List..." ), "kontact_contacts", 0, this,
01219                SLOT( newDistributionList() ), actionCollection(), "file_new_distributionlist" );
01220   action->setWhatsThis( i18n( "Create a new distribution list<p>You will be presented with a dialog where you can create a new distribution list." ) );
01221 
01222   mActionMailVCard = new KAction( i18n("Send &Contact..."), "mail_post_to", 0,
01223                                   this, SLOT( mailVCard() ),
01224                                   actionCollection(), "file_mail_vcard" );
01225   mActionMailVCard->setWhatsThis( i18n( "Send a mail with the selected contact as attachment." ) );
01226 
01227   mActionChat = new KAction( i18n("Chat &With..."), 0,
01228                                   this, SLOT( startChat() ),
01229                                   actionCollection(), "file_chat" );
01230   mActionChat->setWhatsThis( i18n( "Start a chat with the selected contact." ) );
01231 
01232   mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0,
01233                                       this, SLOT( editContact() ),
01234                                       actionCollection(), "file_properties" );
01235   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." ) );
01236 
01237   mActionMerge = new KAction( i18n( "&Merge Contacts" ), "", 0,
01238                               this, SLOT( mergeContacts() ),
01239                               actionCollection(), "edit_merge" );
01240 
01241   // edit menu
01242   mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() );
01243   mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() );
01244   mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() );
01245   action = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() );
01246   mActionCopy->setWhatsThis( i18n( "Copy the currently selected contact(s) to system clipboard in vCard format." ) );
01247   mActionCut->setWhatsThis( i18n( "Cuts the currently selected contact(s) to system clipboard in vCard format." ) );
01248   mActionPaste->setWhatsThis( i18n( "Paste the previously cut or copied contacts from clipboard." ) );
01249   action->setWhatsThis( i18n( "Selects all visible contacts from current view." ) );
01250 //  mActionUndo->setWhatsThis( i18n( "Undoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01251 //  mActionRedo->setWhatsThis( i18n( "Redoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01252 
01253   mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete",
01254                                Key_Delete, this, SLOT( deleteContacts() ),
01255                                actionCollection(), "edit_delete" );
01256   mActionDelete->setWhatsThis( i18n( "Delete all selected contacts." ) );
01257 
01258 
01259   mActionCopyAddresseeTo = new KAction( i18n( "&Copy Contact To..." ), "", 0,
01260                                       this, SLOT( copySelectedContactToResource() ),
01261                                       actionCollection(), "copy_contact_to" );
01262   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." );
01263   mActionCopyAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01264 
01265   mActionMoveAddresseeTo = new KAction( i18n( "M&ove Contact To..." ), "", 0,
01266                                       this, SLOT( moveSelectedContactToResource() ),
01267                                       actionCollection(), "move_contact_to" );
01268   mActionMoveAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01269 
01270   // settings menu
01271   mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), "next", 0,
01272                                       actionCollection(), "options_show_jump_bar" );
01273   mActionJumpBar->setWhatsThis( i18n( "Toggle whether the jump button bar shall be visible." ) );
01274   mActionJumpBar->setCheckedState( i18n( "Hide Jump Bar") );
01275   connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) );
01276 
01277   mActionDetails = new KToggleAction( i18n( "Show Details" ), 0, 0,
01278                                       actionCollection(), "options_show_details" );
01279   mActionDetails->setWhatsThis( i18n( "Toggle whether the details page shall be visible." ) );
01280   mActionDetails->setCheckedState( i18n( "Hide Details") );
01281   connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) );
01282 
01283   if ( mIsPart )
01284     action = new KAction( i18n( "&Configure Address Book..." ), "configure", 0,
01285                           this, SLOT( configure() ), actionCollection(),
01286                           "kaddressbook_configure" );
01287   else
01288     action = KStdAction::preferences( this, SLOT( configure() ), actionCollection() );
01289 
01290   action->setWhatsThis( i18n( "You will be presented with a dialog, that offers you all possibilities to configure KAddressBook." ) );
01291 
01292   // misc
01293   action = new KAction( i18n( "&Lookup Addresses in LDAP Directory..." ), "find", 0,
01294                         this, SLOT( openLDAPDialog() ), actionCollection(), "ldap_lookup" );
01295   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." ) );
01296 
01297   mActionWhoAmI = new KAction( i18n( "Set as Personal Contact Data" ), "personal", 0, this,
01298                                SLOT( setWhoAmI() ), actionCollection(),
01299                                "edit_set_personal" );
01300   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." ) );
01301 
01302   mActionCategories = new KAction( i18n( "Select Categories..." ), 0, this,
01303                                    SLOT( setCategories() ), actionCollection(),
01304                                    "edit_set_categories" );
01305   mActionCategories->setWhatsThis( i18n( "Set the categories for all selected contacts." ) );
01306 
01307   KAction *clearLocation = new KAction( i18n( "Clear Search Bar" ),
01308                     QApplication::reverseLayout() ? "clear_left" : "locationbar_erase",
01309                     CTRL+Key_L, this, SLOT( slotClearSearchBar() ), actionCollection(), "clear_search" );
01310   clearLocation->setWhatsThis( i18n( "Clear Search Bar<p>"
01311                      "Clears the content of the quick search bar." ) );
01312 
01313   clipboardDataChanged();
01314 }
01315 
01316 void KABCore::clipboardDataChanged()
01317 {
01318   if ( mReadWrite )
01319     mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() );
01320 }
01321 
01322 void KABCore::updateIncSearchWidget()
01323 {
01324   mIncSearchWidget->setViewFields( mViewManager->viewFields() );
01325 }
01326 
01327 void KABCore::updateCategories()
01328 {
01329   QStringList categories( allCategories() );
01330   categories.sort();
01331 
01332   const QStringList customCategories( KABPrefs::instance()->customCategories() );
01333   QStringList::ConstIterator it;
01334   const QStringList::ConstIterator endIt( customCategories.end() );
01335   for ( it = customCategories.begin(); it != endIt; ++it ) {
01336     if ( categories.find( *it ) == categories.end() ) {
01337       categories.append( *it );
01338     }
01339   }
01340 
01341   KABPrefs::instance()->mCustomCategories = categories;
01342   KABPrefs::instance()->writeConfig();
01343 
01344   if ( mCategoryEditDialog )
01345     mCategoryEditDialog->reload();
01346 }
01347 
01348 QStringList KABCore::allCategories() const
01349 {
01350   QStringList categories, allCategories;
01351   QStringList::ConstIterator catIt;
01352 
01353   KABC::AddressBook::ConstIterator it;
01354   const KABC::AddressBook::ConstIterator endIt( mAddressBook->end() );
01355   for ( it = mAddressBook->begin(); it != endIt; ++it ) {
01356     categories = (*it).categories();
01357     const QStringList::ConstIterator catEndIt( categories.end() );
01358     for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01359       if ( !allCategories.contains( *catIt ) )
01360         allCategories.append( *catIt );
01361     }
01362   }
01363 
01364   return allCategories;
01365 }
01366 
01367 void KABCore::setCategories()
01368 {
01369   // Show the category dialog
01370   if ( mCategorySelectDialog == 0 ) {
01371     mCategorySelectDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), mWidget );
01372     connect( mCategorySelectDialog, SIGNAL( categoriesSelected( const QStringList& ) ),
01373              SLOT( categoriesSelected( const QStringList& ) ) );
01374     connect( mCategorySelectDialog, SIGNAL( editCategories() ), SLOT( editCategories() ) );
01375   }
01376 
01377   mCategorySelectDialog->show();
01378   mCategorySelectDialog->raise();
01379 }
01380 
01381 void KABCore::categoriesSelected( const QStringList &categories )
01382 {
01383   bool merge = false;
01384   QString msg = i18n( "Merge with existing categories?" );
01385   if ( KMessageBox::questionYesNo( mWidget, msg, QString::null, i18n( "Merge" ), i18n( "Do Not Merge" ) ) == KMessageBox::Yes )
01386     merge = true;
01387 
01388   QStringList uids = mViewManager->selectedUids();
01389   QStringList::ConstIterator it;
01390   const QStringList::ConstIterator endIt( uids.end() );
01391   for ( it = uids.begin(); it != endIt; ++it ) {
01392     KABC::Addressee addr = mAddressBook->findByUid( *it );
01393     if ( !addr.isEmpty() ) {
01394       if ( !merge )
01395         addr.setCategories( categories );
01396       else {
01397         QStringList addrCategories = addr.categories();
01398         QStringList::ConstIterator catIt;
01399         const QStringList::ConstIterator catEndIt( categories.end() );
01400         for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01401           if ( !addrCategories.contains( *catIt ) )
01402             addrCategories.append( *catIt );
01403         }
01404         addr.setCategories( addrCategories );
01405       }
01406 
01407       mAddressBook->insertAddressee( addr );
01408     }
01409   }
01410 
01411   if ( uids.count() > 0 )
01412     setModified( true );
01413 }
01414 
01415 void KABCore::editCategories()
01416 {
01417   if ( mCategoryEditDialog == 0 ) {
01418     mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), mWidget );
01419     connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ),
01420              mCategorySelectDialog, SLOT( updateCategoryConfig() ) );
01421   }
01422 
01423   mCategoryEditDialog->show();
01424   mCategoryEditDialog->raise();
01425 }
01426 
01427 void KABCore::slotClearSearchBar()
01428 {
01429   mIncSearchWidget->clear();
01430   mIncSearchWidget->setFocus();
01431 }
01432 
01433 void KABCore::slotContactsUpdated()
01434 {
01435   if ( mStatusBar ) {
01436     QString msg( i18n( "%n contact matches", "%n contacts matching", mSearchManager->contacts().count() ) );
01437     if ( !mStatusBar->hasItem( 1 ) )
01438       mStatusBar->insertItem( msg, 1 );
01439     else
01440       mStatusBar->changeItem( msg, 1 );
01441   }
01442 
01443   emit contactsUpdated();
01444 }
01445 
01446 bool KABCore::handleCommandLine( KAddressBookIface* iface )
01447 {
01448   KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
01449   QCString addrStr = args->getOption( "addr" );
01450   QCString uidStr = args->getOption( "uid" );
01451 
01452   QString addr, uid, vcard;
01453   if ( !addrStr.isEmpty() )
01454     addr = QString::fromLocal8Bit( addrStr );
01455   if ( !uidStr.isEmpty() )
01456     uid = QString::fromLocal8Bit( uidStr );
01457 
01458   bool doneSomething = false;
01459 
01460   // 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
01461   if ( !addr.isEmpty() ) {
01462     iface->addEmail( addr );
01463     doneSomething = true;
01464   }
01465 
01466   if ( !uid.isEmpty() ) {
01467     iface->showContactEditor( uid );
01468     doneSomething = true;
01469   }
01470 
01471   if ( args->isSet( "new-contact" ) ) {
01472     iface->newContact();
01473     doneSomething = true;
01474   }
01475 
01476   if ( args->count() >= 1 ) {
01477     for ( int i = 0; i < args->count(); ++i )
01478       iface->importVCard( args->url( i ).url() );
01479     doneSomething = true;
01480   }
01481   return doneSomething;
01482 }
01483 
01484 void KABCore::removeSelectedContactsFromDistList()
01485 {
01486 #ifdef KDEPIM_NEW_DISTRLISTS
01487 
01488   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01489   if ( dist.isEmpty() )
01490     return;
01491   const QStringList uids = selectedUIDs();
01492   if ( uids.isEmpty() )
01493       return;
01494   for ( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it ) {
01495       dist.removeEntry ( *it );
01496   }
01497   addressBook()->insertAddressee( dist );
01498   setModified();
01499 #endif
01500 }
01501 
01502 void KABCore::sendMailToDistributionList( const QString &name )
01503 {
01504 #ifdef KDEPIM_NEW_DISTRLISTS
01505   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), name );
01506   if ( dist.isEmpty() )
01507     return;
01508   typedef KPIM::DistributionList::Entry::List EntryList; 
01509   QStringList mails;
01510   const EntryList entries = dist.entries( addressBook() );
01511   for ( EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it )
01512     mails += (*it).addressee.fullEmail( (*it).email );
01513   sendMail( mails.join( ", " ) ); 
01514 #endif
01515 }
01516 
01517 void KABCore::editSelectedDistributionList()
01518 {
01519 #ifdef KDEPIM_NEW_DISTRLISTS
01520   editDistributionList( KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ) );
01521 #endif
01522 }
01523 
01524 
01525 void KABCore::editDistributionList( const QString &name )
01526 {
01527 #ifdef KDEPIM_NEW_DISTRLISTS
01528   editDistributionList( KPIM::DistributionList::findByName( addressBook(), name ) );
01529 #endif
01530 }
01531 
01532 #ifdef KDEPIM_NEW_DISTRLISTS
01533 
01534 void KABCore::showDistributionListEntry( const QString& uid )
01535 {
01536   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01537   if ( !dist.isEmpty() ) {
01538     mDistListEntryView->clear();
01539     typedef KPIM::DistributionList::Entry::List EntryList;   
01540     const EntryList entries = dist.entries( addressBook() ); 
01541     for (EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) {
01542       if ( (*it).addressee.uid() == uid ) {
01543         mDistListEntryView->setEntry( dist, *it );
01544         break;
01545       }
01546     }
01547   }
01548 }
01549 
01550 void KABCore::editDistributionList( const KPIM::DistributionList &dist )
01551 {
01552   if ( dist.isEmpty() )
01553     return;
01554   QGuardedPtr<KPIM::DistributionListEditor::EditorWidget> dlg = new KPIM::DistributionListEditor::EditorWidget( addressBook(), widget() );
01555   dlg->setDistributionList( dist );
01556   if ( dlg->exec() == QDialog::Accepted && dlg ) {
01557     const KPIM::DistributionList newDist = dlg->distributionList();
01558     if ( newDist != dist ) {
01559       addressBook()->insertAddressee( newDist );
01560       setModified();
01561     }
01562   }
01563   delete dlg;
01564 }
01565 
01566 
01567 KPIM::DistributionList::List KABCore::distributionLists() const
01568 {
01569   return mSearchManager->distributionLists();
01570 }
01571 
01572 void KABCore::setSelectedDistributionList( const QString &name )
01573 {
01574   mSelectedDistributionList = name;
01575   mSearchManager->setSelectedDistributionList( name );
01576   mViewHeaderLabel->setText( name.isNull() ? i18n( "Contacts" ) : i18n( "Distribution List: %1" ).arg( name ) );
01577   mDistListButtonWidget->setShown( !mSelectedDistributionList.isNull() );
01578   if ( !name.isNull() ) {
01579     mDetailsStack->raiseWidget( mDistListEntryView );
01580     const QStringList selectedUids = selectedUIDs();
01581     showDistributionListEntry( selectedUids.isEmpty() ? QString() : selectedUids.first() );
01582   }
01583   else
01584     mDetailsStack->raiseWidget( mExtensionManager->activeDetailsWidget() ? mExtensionManager->activeDetailsWidget() : mDetailsWidget );
01585 }
01586 
01587 QStringList KABCore::distributionListNames() const
01588 {
01589   return mSearchManager->distributionListNames();
01590 }
01591 #endif
01592 
01593 #include "kabcore.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys