kaddressbook

kabcore.cpp

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