kaddressbook

kabcore.cpp

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