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   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       if ( !copy ) {
00837           KABLock::self( mAddressBook )->lock( addr.resource() );
00838           addressBook()->removeAddressee( addr );
00839           KABLock::self( mAddressBook )->unlock( addr.resource() );
00840       }
00841     }
00842   }
00843   KABLock::self( mAddressBook )->unlock( resource );
00844 
00845   addressBookChanged();
00846   setModified( true );
00847 }
00848 
00849 void KABCore::save()
00850 {
00851   QPtrList<KABC::Resource> resources = mAddressBook->resources();
00852   QPtrListIterator<KABC::Resource> it( resources );
00853   while ( it.current() && !it.current()->readOnly() ) {
00854     KABC::Ticket *ticket = mAddressBook->requestSaveTicket( it.current() );
00855     if ( ticket ) {
00856       if ( !mAddressBook->save( ticket ) ) {
00857         KMessageBox::error( mWidget,
00858                             i18n( "<qt>Unable to save address book <b>%1</b>.</qt>" ).arg( it.current()->resourceName() ) );
00859         mAddressBook->releaseSaveTicket( ticket );
00860       } else {
00861         setModified( false );
00862       }
00863     } else {
00864       KMessageBox::error( mWidget,
00865                           i18n( "<qt>Unable to get access for saving the address book <b>%1</b>.</qt>" )
00866                           .arg( it.current()->resourceName() ) );
00867     }
00868 
00869     ++it;
00870   }
00871 }
00872 
00873 void KABCore::setJumpButtonBarVisible( bool visible )
00874 {
00875   if ( visible ) {
00876     if ( !mJumpButtonBar )
00877       createJumpButtonBar();
00878     mJumpButtonBar->show();
00879   } else
00880     if ( mJumpButtonBar )
00881       mJumpButtonBar->hide();
00882 }
00883 
00884 void KABCore::setDetailsVisible( bool visible )
00885 {
00886   if ( visible )
00887     mDetailsPage->show();
00888   else
00889     mDetailsPage->hide();
00890 }
00891 
00892 void KABCore::extensionModified( const KABC::Addressee::List &list )
00893 {
00894   if ( list.count() != 0 ) {
00895     KABC::Addressee::List::ConstIterator it;
00896     const KABC::Addressee::List::ConstIterator endIt( list.end() );
00897     for ( it = list.begin(); it != endIt; ++it ) {
00898       Command *command = 0;
00899 
00900       // check if it exists already
00901       KABC::Addressee origAddr = mAddressBook->findByUid( (*it).uid() );
00902       if ( origAddr.isEmpty() ) {
00903         KABC::Addressee::List addressees;
00904         addressees.append( *it );
00905         command = new NewCommand( mAddressBook, addressees );
00906       } else
00907         command = new EditCommand( mAddressBook, origAddr, *it );
00908 
00909       mCommandHistory->blockSignals( true );
00910       mCommandHistory->addCommand( command );
00911       mCommandHistory->blockSignals( false );
00912     }
00913 
00914     setModified(true);
00915   }
00916 }
00917 
00918 void KABCore::extensionDeleted( const QStringList &uidList )
00919 {
00920   DeleteCommand *command = new DeleteCommand( mAddressBook, uidList );
00921   mCommandHistory->addCommand( command );
00922 
00923   // now if we deleted anything, refresh
00924   setContactSelected( QString::null );
00925   setModified( true );
00926 }
00927 
00928 QString KABCore::getNameByPhone( const QString &phone )
00929 {
00930 #if KDE_IS_VERSION(3,4,89)
00931   // This ugly hack will be removed in 4.0
00932   // addressbook may not be reloaded yet, as done asynchronously, so wait
00933   while ( !mAddressBook->loadingHasFinished() ) {
00934     QApplication::eventLoop()->processEvents( QEventLoop::ExcludeUserInput );
00935     // use sleep here to reduce cpu usage
00936     usleep( 100 );
00937   }
00938 #endif
00939 
00940   QRegExp r( "[/*/-/ ]" );
00941   QString localPhone( phone );
00942 
00943   bool found = false;
00944   QString ownerName = "";
00945   KABC::PhoneNumber::List phoneList;
00946 
00947   KABC::AddressBook::ConstIterator iter;
00948   const KABC::AddressBook::ConstIterator endIter( mAddressBook->end() );
00949 
00950   for ( iter = mAddressBook->begin(); !found && ( iter != endIter ); ++iter ) {
00951     phoneList = (*iter).phoneNumbers();
00952     KABC::PhoneNumber::List::Iterator phoneIter( phoneList.begin() );
00953     const KABC::PhoneNumber::List::Iterator phoneEndIter( phoneList.end() );
00954     for ( ; !found && ( phoneIter != phoneEndIter ); ++phoneIter) {
00955       // Get rid of separator chars so just the numbers are compared.
00956       if ( (*phoneIter).number().replace( r, "" ) == localPhone.replace( r, "" ) ) {
00957         ownerName = (*iter).realName();
00958         found = true;
00959       }
00960     }
00961   }
00962 
00963   return ownerName;
00964 }
00965 
00966 void KABCore::openLDAPDialog()
00967 {
00968   if ( !KProtocolInfo::isKnownProtocol( KURL( "ldap://localhost" ) ) ) {
00969     KMessageBox::error( mWidget, i18n( "Your KDE installation is missing LDAP "
00970                                        "support, please ask your administrator or distributor for more information." ),
00971                         i18n( "No LDAP IO Slave Available" ) );
00972     return;
00973   }
00974 
00975   if ( !mLdapSearchDialog ) {
00976     mLdapSearchDialog = new LDAPSearchDialog( mAddressBook, this, mWidget );
00977     connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ),
00978             SLOT( addressBookChanged() ) );
00979     connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ),
00980             SLOT( setModified() ) );
00981   } else
00982     mLdapSearchDialog->restoreSettings();
00983 
00984   if ( mLdapSearchDialog->isOK() )
00985     mLdapSearchDialog->exec();
00986 }
00987 
00988 void KABCore::configure()
00989 {
00990   // Save the current config so we do not loose anything if the user accepts
00991   saveSettings();
00992 
00993   KCMultiDialog dlg( mWidget, "", true );
00994   connect( &dlg, SIGNAL( configCommitted() ),
00995            this, SLOT( configurationChanged() ) );
00996 
00997   dlg.addModule( "kabconfig.desktop" );
00998   dlg.addModule( "kabldapconfig.desktop" );
00999   dlg.addModule( "kabcustomfields.desktop" );
01000 
01001   dlg.exec();
01002 }
01003 
01004 void KABCore::print()
01005 {
01006   KPrinter printer;
01007   printer.setDocName( i18n( "Address Book" ) );
01008   printer.setDocFileName( "addressbook" );
01009 
01010   if ( !printer.setup( mWidget, i18n("Print Addresses") ) )
01011     return;
01012 
01013   KABPrinting::PrintingWizard wizard( &printer, mAddressBook,
01014                                       mViewManager->selectedUids(), mWidget );
01015 
01016   wizard.exec();
01017 }
01018 
01019 void KABCore::detailsHighlighted( const QString &msg )
01020 {
01021   if ( mStatusBar ) {
01022     if ( !mStatusBar->hasItem( 2 ) )
01023       mStatusBar->insertItem( msg, 2 );
01024     else
01025       mStatusBar->changeItem( msg, 2 );
01026   }
01027 }
01028 
01029 void KABCore::showContactsAddress( const QString &addrUid )
01030 {
01031   QStringList uidList = mViewManager->selectedUids();
01032   if ( uidList.isEmpty() )
01033     return;
01034 
01035   KABC::Addressee addr = mAddressBook->findByUid( uidList.first() );
01036   if ( addr.isEmpty() )
01037     return;
01038 
01039   const KABC::Address::List list = addr.addresses();
01040   KABC::Address::List::ConstIterator it;
01041   const KABC::Address::List::ConstIterator endIt( list.end() );
01042   for ( it = list.begin(); it != endIt; ++it )
01043     if ( (*it).id() == addrUid ) {
01044       LocationMap::instance()->showAddress( *it );
01045       break;
01046     }
01047 }
01048 
01049 void KABCore::configurationChanged()
01050 {
01051   mExtensionManager->reconfigure();
01052   mViewManager->refreshView();
01053 }
01054 
01055 bool KABCore::queryClose()
01056 {
01057   saveSettings();
01058   KABPrefs::instance()->writeConfig();
01059 
01060   QPtrList<KABC::Resource> resources = mAddressBook->resources();
01061   QPtrListIterator<KABC::Resource> it( resources );
01062   while ( it.current() ) {
01063     it.current()->close();
01064     ++it;
01065   }
01066 
01067   return true;
01068 }
01069 
01070 void KABCore::reinitXMLGUI()
01071 {
01072   mExtensionManager->createActions();
01073 }
01074 void KABCore::delayedAddressBookChanged()
01075 {
01076   mAddressBookChangedTimer->start( 1000 );
01077 }
01078 
01079 void KABCore::addressBookChanged()
01080 {
01081   const QStringList selectedUids = mViewManager->selectedUids();
01082 
01083   mAddressBookChangedTimer->stop();
01084 
01085   if ( mJumpButtonBar )
01086     mJumpButtonBar->updateButtons();
01087 
01088   mSearchManager->reload();
01089 
01090   mViewManager->setSelected( QString::null, false );
01091 
01092   QString uid = QString::null;
01093   if ( !selectedUids.isEmpty() ) {
01094     uid = selectedUids.first();
01095     mViewManager->setSelected( uid, true );
01096   }
01097 
01098   setContactSelected( uid );
01099 
01100   updateCategories();
01101 }
01102 
01103 AddresseeEditorDialog *KABCore::createAddresseeEditorDialog( QWidget *parent,
01104                                                              const char *name )
01105 {
01106   AddresseeEditorDialog *dialog = new AddresseeEditorDialog( this, parent,
01107                                                  name ? name : "editorDialog" );
01108   connect( dialog, SIGNAL( contactModified( const KABC::Addressee& ) ),
01109            SLOT( contactModified( const KABC::Addressee& ) ) );
01110   connect( dialog, SIGNAL( editorDestroyed( const QString& ) ),
01111            SLOT( slotEditorDestroyed( const QString& ) ) );
01112 
01113   return dialog;
01114 }
01115 
01116 void KABCore::activateDetailsWidget( QWidget *widget )
01117 {
01118   if ( mDetailsStack->visibleWidget() == widget )
01119     return;
01120   mDetailsStack->raiseWidget( widget );
01121 }
01122 
01123 void KABCore::deactivateDetailsWidget( QWidget *widget )
01124 {
01125   if ( mDetailsStack->visibleWidget() != widget )
01126     return;
01127   mDetailsStack->raiseWidget( mDetailsWidget );
01128 }
01129 
01130 void KABCore::slotEditorDestroyed( const QString &uid )
01131 {
01132   AddresseeEditorDialog *dialog = mEditorDict.take( uid );
01133 
01134   KABC::Addressee addr = dialog->addressee();
01135 
01136   if ( !addr.resource()->readOnly() ) {
01137     QApplication::setOverrideCursor( Qt::waitCursor );
01138     KABLock::self( mAddressBook )->unlock( addr.resource() );
01139     QApplication::restoreOverrideCursor();
01140   }
01141 }
01142 
01143 void KABCore::initGUI()
01144 {
01145   QVBoxLayout *topLayout = new QVBoxLayout( mWidget, 0, 0 );
01146   KToolBar* searchTB = new KToolBar( mWidget, "search toolbar");
01147   searchTB->boxLayout()->setSpacing( KDialog::spacingHint() );
01148   mIncSearchWidget = new IncSearchWidget( searchTB, "kde toolbar widget");
01149   searchTB->setStretchableWidget( mIncSearchWidget );
01150   connect( mIncSearchWidget, SIGNAL( doSearch( const QString& ) ),
01151            SLOT( incrementalTextSearch( const QString& ) ) );
01152 
01153   mDetailsSplitter = new QSplitter( mWidget );
01154 
01155   mLeftSplitter = new QSplitter( mDetailsSplitter );
01156   mLeftSplitter->setOrientation( KABPrefs::instance()->contactListAboveExtensions() ? Qt::Vertical : Qt::Horizontal );
01157 
01158   topLayout->addWidget( searchTB );
01159   topLayout->addWidget( mDetailsSplitter );
01160   
01161   mDetailsStack = new QWidgetStack( mDetailsSplitter );
01162   mExtensionManager = new ExtensionManager( new QWidget( mLeftSplitter ), mDetailsStack, this, this );
01163   connect( mExtensionManager, SIGNAL( detailsWidgetDeactivated( QWidget* ) ), 
01164            this, SLOT( deactivateDetailsWidget( QWidget* ) ) );
01165   connect( mExtensionManager, SIGNAL( detailsWidgetActivated( QWidget* ) ), 
01166            this, SLOT( activateDetailsWidget( QWidget* ) ) );
01167   
01168   QWidget *viewWidget = new QWidget( mLeftSplitter );
01169   if ( KABPrefs::instance()->contactListAboveExtensions() )
01170     mLeftSplitter->moveToFirst( viewWidget );
01171   QVBoxLayout *viewLayout = new QVBoxLayout( viewWidget );
01172   viewLayout->setSpacing( KDialog::spacingHint() );
01173 
01174   mViewHeaderLabel = new QLabel( viewWidget );
01175 //  mViewHeaderLabel->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
01176   mViewHeaderLabel->setText( i18n( "Contacts" ) );
01177   viewLayout->addWidget( mViewHeaderLabel );
01178   mViewManager = new ViewManager( this, viewWidget );
01179   viewLayout->addWidget( mViewManager, 1 );
01180 
01181 #ifdef KDEPIM_NEW_DISTRLISTS
01182   mDistListButtonWidget = new QWidget( viewWidget );
01183   QHBoxLayout *buttonLayout = new QHBoxLayout( mDistListButtonWidget );
01184   buttonLayout->setSpacing( KDialog::spacingHint() );
01185   buttonLayout->addStretch( 1 );
01186 
01187   KPushButton *addDistListButton = new KPushButton( mDistListButtonWidget );
01188   addDistListButton->setText( i18n( "Add" ) );
01189   connect( addDistListButton, SIGNAL( clicked() ), 
01190            this, SLOT( editSelectedDistributionList() ) );
01191   buttonLayout->addWidget( addDistListButton );
01192   mDistListButtonWidget->setShown( false );
01193   viewLayout->addWidget( mDistListButtonWidget );
01194 
01195   KPushButton *removeDistListButton = new KPushButton( mDistListButtonWidget );
01196   removeDistListButton->setText( i18n( "Remove" ) );
01197   connect( removeDistListButton, SIGNAL( clicked() ), 
01198            this, SLOT( removeSelectedContactsFromDistList() ) );
01199   buttonLayout->addWidget( removeDistListButton );
01200 #endif
01201 
01202   mFilterSelectionWidget = new FilterSelectionWidget( searchTB , "kde toolbar widget" );
01203   mViewManager->setFilterSelectionWidget( mFilterSelectionWidget );
01204 
01205   connect( mFilterSelectionWidget, SIGNAL( filterActivated( int ) ),
01206            mViewManager, SLOT( setActiveFilter( int ) ) );
01207 
01208   mDetailsWidget = new QWidget( mDetailsSplitter );
01209   mDetailsLayout = new QHBoxLayout( mDetailsWidget );
01210 
01211   mDetailsPage = new QWidget( mDetailsWidget );
01212   mDetailsLayout->addWidget( mDetailsPage );
01213 
01214   QHBoxLayout *detailsPageLayout = new QHBoxLayout( mDetailsPage, 0, 0 );
01215   mDetailsViewer = new KPIM::AddresseeView( mDetailsPage );
01216   mDetailsViewer->setVScrollBarMode( QScrollView::Auto );
01217   detailsPageLayout->addWidget( mDetailsViewer );
01218 
01219   mDistListEntryView = new KAB::DistributionListEntryView( this, mWidget );
01220   connect( mDistListEntryView, SIGNAL( distributionListClicked( const QString& ) ),
01221            this, SLOT( sendMailToDistributionList( const QString& ) ) );
01222   mDetailsStack->addWidget( mDistListEntryView );
01223   mDetailsStack->addWidget( mDetailsWidget );
01224   mDetailsStack->raiseWidget( mDetailsWidget );
01225   mDetailsSplitter->moveToLast( mDetailsStack );
01226 
01227   connect( mDetailsViewer, SIGNAL( addressClicked( const QString&) ),
01228            this, SLOT( showContactsAddress( const QString& ) ) );
01229 
01230   topLayout->setStretchFactor( mDetailsSplitter, 1 );
01231 
01232   mXXPortManager = new XXPortManager( this, mWidget );
01233 
01234   initActions();
01235 }
01236 
01237 void KABCore::createJumpButtonBar()
01238 {
01239   mJumpButtonBar = new JumpButtonBar( this, mDetailsWidget );
01240   mDetailsLayout->addWidget( mJumpButtonBar );
01241   mDetailsLayout->setStretchFactor( mJumpButtonBar, 1 );
01242 
01243   connect( mJumpButtonBar, SIGNAL( jumpToLetter( const QString& ) ),
01244            SLOT( incrementalJumpButtonSearch( const QString& ) ) );
01245   connect( mViewManager, SIGNAL( sortFieldChanged() ),
01246            mJumpButtonBar, SLOT( updateButtons() ) );
01247 }
01248 
01249 void KABCore::initActions()
01250 {
01251   connect( QApplication::clipboard(), SIGNAL( dataChanged() ),
01252            SLOT( clipboardDataChanged() ) );
01253 
01254   KAction *action;
01255 
01256   // file menu
01257   mActionMail = new KAction( i18n( "&Send Email to Contact..." ), "mail_send", 0,
01258                              this, SLOT( sendMail() ), actionCollection(), "file_mail" );
01259   action = KStdAction::print( this, SLOT( print() ), actionCollection() );
01260   mActionMail->setWhatsThis( i18n( "Send a mail to all selected contacts." ) );
01261   action->setWhatsThis( i18n( "Print a special number of contacts." ) );
01262 
01263   mActionSave = KStdAction::save( this,
01264                              SLOT( save() ), actionCollection(), "file_sync" );
01265   mActionSave->setWhatsThis( i18n( "Save all changes of the address book to the storage backend." ) );
01266 
01267   action = new KAction( i18n( "&New Contact..." ), "identity", CTRL+Key_N, this,
01268                SLOT( newContact() ), actionCollection(), "file_new_contact" );
01269   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." ) );
01270 
01271   action = new KAction( i18n( "&New Distribution List..." ), "kontact_contacts", 0, this,
01272                SLOT( newDistributionList() ), actionCollection(), "file_new_distributionlist" );
01273   action->setWhatsThis( i18n( "Create a new distribution list<p>You will be presented with a dialog where you can create a new distribution list." ) );
01274 
01275   mActionMailVCard = new KAction( i18n("Send &Contact..."), "mail_post_to", 0,
01276                                   this, SLOT( mailVCard() ),
01277                                   actionCollection(), "file_mail_vcard" );
01278   mActionMailVCard->setWhatsThis( i18n( "Send a mail with the selected contact as attachment." ) );
01279 
01280   mActionChat = new KAction( i18n("Chat &With..."), 0,
01281                                   this, SLOT( startChat() ),
01282                                   actionCollection(), "file_chat" );
01283   mActionChat->setWhatsThis( i18n( "Start a chat with the selected contact." ) );
01284 
01285   mActionEditAddressee = new KAction( i18n( "&Edit Contact..." ), "edit", 0,
01286                                       this, SLOT( editContact() ),
01287                                       actionCollection(), "file_properties" );
01288   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." ) );
01289 
01290   mActionMerge = new KAction( i18n( "&Merge Contacts" ), "", 0,
01291                               this, SLOT( mergeContacts() ),
01292                               actionCollection(), "edit_merge" );
01293 
01294   // edit menu
01295   mActionCopy = KStdAction::copy( this, SLOT( copyContacts() ), actionCollection() );
01296   mActionCut = KStdAction::cut( this, SLOT( cutContacts() ), actionCollection() );
01297   mActionPaste = KStdAction::paste( this, SLOT( pasteContacts() ), actionCollection() );
01298   action = KStdAction::selectAll( this, SLOT( selectAllContacts() ), actionCollection() );
01299   mActionCopy->setWhatsThis( i18n( "Copy the currently selected contact(s) to system clipboard in vCard format." ) );
01300   mActionCut->setWhatsThis( i18n( "Cuts the currently selected contact(s) to system clipboard in vCard format." ) );
01301   mActionPaste->setWhatsThis( i18n( "Paste the previously cut or copied contacts from clipboard." ) );
01302   action->setWhatsThis( i18n( "Selects all visible contacts from current view." ) );
01303 //  mActionUndo->setWhatsThis( i18n( "Undoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01304 //  mActionRedo->setWhatsThis( i18n( "Redoes the last <b>Cut</b>, <b>Copy</b> or <b>Paste</b>." ) );
01305 
01306   mActionDelete = new KAction( i18n( "&Delete Contact" ), "editdelete",
01307                                Key_Delete, this, SLOT( deleteContacts() ),
01308                                actionCollection(), "edit_delete" );
01309   mActionDelete->setWhatsThis( i18n( "Delete all selected contacts." ) );
01310 
01311 
01312   mActionCopyAddresseeTo = new KAction( i18n( "&Copy Contact To..." ), "", 0,
01313                                       this, SLOT( copySelectedContactToResource() ),
01314                                       actionCollection(), "copy_contact_to" );
01315   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." );
01316   mActionCopyAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01317 
01318   mActionMoveAddresseeTo = new KAction( i18n( "M&ove Contact To..." ), "", 0,
01319                                       this, SLOT( moveSelectedContactToResource() ),
01320                                       actionCollection(), "move_contact_to" );
01321   mActionMoveAddresseeTo->setWhatsThis( copyMoveWhatsThis );
01322 
01323   // settings menu
01324   mActionJumpBar = new KToggleAction( i18n( "Show Jump Bar" ), "next", 0,
01325                                       actionCollection(), "options_show_jump_bar" );
01326   mActionJumpBar->setWhatsThis( i18n( "Toggle whether the jump button bar shall be visible." ) );
01327   mActionJumpBar->setCheckedState( i18n( "Hide Jump Bar") );
01328   connect( mActionJumpBar, SIGNAL( toggled( bool ) ), SLOT( setJumpButtonBarVisible( bool ) ) );
01329 
01330   mActionDetails = new KToggleAction( i18n( "Show Details" ), 0, 0,
01331                                       actionCollection(), "options_show_details" );
01332   mActionDetails->setWhatsThis( i18n( "Toggle whether the details page shall be visible." ) );
01333   mActionDetails->setCheckedState( i18n( "Hide Details") );
01334   connect( mActionDetails, SIGNAL( toggled( bool ) ), SLOT( setDetailsVisible( bool ) ) );
01335 
01336   if ( mIsPart )
01337     action = new KAction( i18n( "&Configure Address Book..." ), "configure", 0,
01338                           this, SLOT( configure() ), actionCollection(),
01339                           "kaddressbook_configure" );
01340   else
01341     action = KStdAction::preferences( this, SLOT( configure() ), actionCollection() );
01342 
01343   action->setWhatsThis( i18n( "You will be presented with a dialog, that offers you all possibilities to configure KAddressBook." ) );
01344 
01345   // misc
01346   action = new KAction( i18n( "&Lookup Addresses in LDAP Directory..." ), "find", 0,
01347                         this, SLOT( openLDAPDialog() ), actionCollection(), "ldap_lookup" );
01348   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." ) );
01349 
01350   mActionWhoAmI = new KAction( i18n( "Set as Personal Contact Data" ), "personal", 0, this,
01351                                SLOT( setWhoAmI() ), actionCollection(),
01352                                "edit_set_personal" );
01353   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." ) );
01354 
01355   mActionCategories = new KAction( i18n( "Select Categories..." ), 0, this,
01356                                    SLOT( setCategories() ), actionCollection(),
01357                                    "edit_set_categories" );
01358   mActionCategories->setWhatsThis( i18n( "Set the categories for all selected contacts." ) );
01359 
01360   KAction *clearLocation = new KAction( i18n( "Clear Search Bar" ),
01361                     QApplication::reverseLayout() ? "clear_left" : "locationbar_erase",
01362                     CTRL+Key_L, this, SLOT( slotClearSearchBar() ), actionCollection(), "clear_search" );
01363   clearLocation->setWhatsThis( i18n( "Clear Search Bar<p>"
01364                      "Clears the content of the quick search bar." ) );
01365 
01366   clipboardDataChanged();
01367 }
01368 
01369 void KABCore::clipboardDataChanged()
01370 {
01371   if ( mReadWrite )
01372     mActionPaste->setEnabled( !QApplication::clipboard()->text().isEmpty() );
01373 }
01374 
01375 void KABCore::updateIncSearchWidget()
01376 {
01377   mIncSearchWidget->setViewFields( mViewManager->viewFields() );
01378 }
01379 
01380 void KABCore::updateCategories()
01381 {
01382   QStringList categories( allCategories() );
01383   categories.sort();
01384 
01385   const QStringList customCategories( KABPrefs::instance()->customCategories() );
01386   QStringList::ConstIterator it;
01387   const QStringList::ConstIterator endIt( customCategories.end() );
01388   for ( it = customCategories.begin(); it != endIt; ++it ) {
01389     if ( categories.find( *it ) == categories.end() ) {
01390       categories.append( *it );
01391     }
01392   }
01393 
01394   KABPrefs::instance()->mCustomCategories = categories;
01395   KABPrefs::instance()->writeConfig();
01396 
01397   if ( mCategoryEditDialog )
01398     mCategoryEditDialog->reload();
01399 }
01400 
01401 QStringList KABCore::allCategories() const
01402 {
01403   QStringList categories, allCategories;
01404   QStringList::ConstIterator catIt;
01405 
01406   KABC::AddressBook::ConstIterator it;
01407   const KABC::AddressBook::ConstIterator endIt( mAddressBook->end() );
01408   for ( it = mAddressBook->begin(); it != endIt; ++it ) {
01409     categories = (*it).categories();
01410     const QStringList::ConstIterator catEndIt( categories.end() );
01411     for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01412       if ( !allCategories.contains( *catIt ) )
01413         allCategories.append( *catIt );
01414     }
01415   }
01416 
01417   return allCategories;
01418 }
01419 
01420 void KABCore::setCategories()
01421 {
01422   // Show the category dialog
01423   if ( mCategorySelectDialog == 0 ) {
01424     mCategorySelectDialog = new KPIM::CategorySelectDialog( KABPrefs::instance(), mWidget );
01425     connect( mCategorySelectDialog, SIGNAL( categoriesSelected( const QStringList& ) ),
01426              SLOT( categoriesSelected( const QStringList& ) ) );
01427     connect( mCategorySelectDialog, SIGNAL( editCategories() ), SLOT( editCategories() ) );
01428   }
01429 
01430   mCategorySelectDialog->show();
01431   mCategorySelectDialog->raise();
01432 }
01433 
01434 void KABCore::categoriesSelected( const QStringList &categories )
01435 {
01436   bool merge = false;
01437   QString msg = i18n( "Merge with existing categories?" );
01438   if ( KMessageBox::questionYesNo( mWidget, msg, QString::null, i18n( "Merge" ), i18n( "Do Not Merge" ) ) == KMessageBox::Yes )
01439     merge = true;
01440 
01441   QStringList uids = mViewManager->selectedUids();
01442   QStringList::ConstIterator it;
01443   const QStringList::ConstIterator endIt( uids.end() );
01444   for ( it = uids.begin(); it != endIt; ++it ) {
01445     KABC::Addressee addr = mAddressBook->findByUid( *it );
01446     if ( !addr.isEmpty() ) {
01447       if ( !merge )
01448         addr.setCategories( categories );
01449       else {
01450         QStringList addrCategories = addr.categories();
01451         QStringList::ConstIterator catIt;
01452         const QStringList::ConstIterator catEndIt( categories.end() );
01453         for ( catIt = categories.begin(); catIt != catEndIt; ++catIt ) {
01454           if ( !addrCategories.contains( *catIt ) )
01455             addrCategories.append( *catIt );
01456         }
01457         addr.setCategories( addrCategories );
01458       }
01459 
01460       mAddressBook->insertAddressee( addr );
01461     }
01462   }
01463 
01464   if ( uids.count() > 0 )
01465     setModified( true );
01466 }
01467 
01468 void KABCore::editCategories()
01469 {
01470   if ( mCategoryEditDialog == 0 ) {
01471     mCategoryEditDialog = new KPIM::CategoryEditDialog( KABPrefs::instance(), mWidget );
01472     connect( mCategoryEditDialog, SIGNAL( categoryConfigChanged() ),
01473              mCategorySelectDialog, SLOT( updateCategoryConfig() ) );
01474   }
01475 
01476   mCategoryEditDialog->show();
01477   mCategoryEditDialog->raise();
01478 }
01479 
01480 void KABCore::slotClearSearchBar()
01481 {
01482   mIncSearchWidget->clear();
01483   mIncSearchWidget->setFocus();
01484 }
01485 
01486 void KABCore::slotContactsUpdated()
01487 {
01488   if ( mStatusBar ) {
01489     QString msg( i18n( "%n contact matches", "%n contacts matching", mSearchManager->contacts().count() ) );
01490     if ( !mStatusBar->hasItem( 1 ) )
01491       mStatusBar->insertItem( msg, 1 );
01492     else
01493       mStatusBar->changeItem( msg, 1 );
01494   }
01495 
01496   emit contactsUpdated();
01497 }
01498 
01499 bool KABCore::handleCommandLine( KAddressBookIface* iface )
01500 {
01501   KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
01502   QCString addrStr = args->getOption( "addr" );
01503   QCString uidStr = args->getOption( "uid" );
01504 
01505   QString addr, uid, vcard;
01506   if ( !addrStr.isEmpty() )
01507     addr = QString::fromLocal8Bit( addrStr );
01508   if ( !uidStr.isEmpty() )
01509     uid = QString::fromLocal8Bit( uidStr );
01510 
01511   bool doneSomething = false;
01512 
01513   // 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
01514   if ( !addr.isEmpty() ) {
01515     iface->addEmail( addr );
01516     doneSomething = true;
01517   }
01518 
01519   if ( !uid.isEmpty() ) {
01520     iface->showContactEditor( uid );
01521     doneSomething = true;
01522   }
01523 
01524   if ( args->isSet( "new-contact" ) ) {
01525     iface->newContact();
01526     doneSomething = true;
01527   }
01528 
01529   if ( args->count() >= 1 ) {
01530     for ( int i = 0; i < args->count(); ++i )
01531       iface->importVCard( args->url( i ).url() );
01532     doneSomething = true;
01533   }
01534   return doneSomething;
01535 }
01536 
01537 void KABCore::removeSelectedContactsFromDistList()
01538 {
01539 #ifdef KDEPIM_NEW_DISTRLISTS
01540 
01541   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01542   if ( dist.isEmpty() )
01543     return;
01544   const QStringList uids = selectedUIDs();
01545   if ( uids.isEmpty() )
01546       return;
01547   for ( QStringList::ConstIterator it = uids.begin(); it != uids.end(); ++it ) {
01548       dist.removeEntry ( *it );
01549   }
01550   addressBook()->insertAddressee( dist );
01551   setModified();
01552 #endif
01553 }
01554 
01555 void KABCore::sendMailToDistributionList( const QString &name )
01556 {
01557 #ifdef KDEPIM_NEW_DISTRLISTS
01558   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), name );
01559   if ( dist.isEmpty() )
01560     return;
01561   typedef KPIM::DistributionList::Entry::List EntryList; 
01562   QStringList mails;
01563   const EntryList entries = dist.entries( addressBook() );
01564   for ( EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it )
01565     mails += (*it).addressee.fullEmail( (*it).email );
01566   sendMail( mails.join( ", " ) ); 
01567 #endif
01568 }
01569 
01570 void KABCore::editSelectedDistributionList()
01571 {
01572 #ifdef KDEPIM_NEW_DISTRLISTS
01573   editDistributionList( KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList ) );
01574 #endif
01575 }
01576 
01577 
01578 void KABCore::editDistributionList( const QString &name )
01579 {
01580 #ifdef KDEPIM_NEW_DISTRLISTS
01581   editDistributionList( KPIM::DistributionList::findByName( addressBook(), name ) );
01582 #endif
01583 }
01584 
01585 #ifdef KDEPIM_NEW_DISTRLISTS
01586 
01587 void KABCore::showDistributionListEntry( const QString& uid )
01588 {
01589   KPIM::DistributionList dist = KPIM::DistributionList::findByName( addressBook(), mSelectedDistributionList );
01590   if ( !dist.isEmpty() ) {
01591     mDistListEntryView->clear();
01592     typedef KPIM::DistributionList::Entry::List EntryList;   
01593     const EntryList entries = dist.entries( addressBook() ); 
01594     for (EntryList::ConstIterator it = entries.begin(); it != entries.end(); ++it ) {
01595       if ( (*it).addressee.uid() == uid ) {
01596         mDistListEntryView->setEntry( dist, *it );
01597         break;
01598       }
01599     }
01600   }
01601 }
01602 
01603 void KABCore::editDistributionList( const KPIM::DistributionList &dist )
01604 {
01605   if ( dist.isEmpty() )
01606     return;
01607   QGuardedPtr<KPIM::DistributionListEditor::EditorWidget> dlg = new KPIM::DistributionListEditor::EditorWidget( addressBook(), widget() );
01608   dlg->setDistributionList( dist );
01609   if ( dlg->exec() == QDialog::Accepted && dlg ) {
01610     const KPIM::DistributionList newDist = dlg->distributionList();
01611     if ( newDist != dist ) {
01612       addressBook()->insertAddressee( newDist );
01613       setModified();
01614     }
01615   }
01616   delete dlg;
01617 }
01618 
01619 
01620 KPIM::DistributionList::List KABCore::distributionLists() const
01621 {
01622   return mSearchManager->distributionLists();
01623 }
01624 
01625 void KABCore::setSelectedDistributionList( const QString &name )
01626 {
01627   mSelectedDistributionList = name;
01628   mSearchManager->setSelectedDistributionList( name );
01629   mViewHeaderLabel->setText( name.isNull() ? i18n( "Contacts" ) : i18n( "Distribution List: %1" ).arg( name ) );
01630   mDistListButtonWidget->setShown( !mSelectedDistributionList.isNull() );
01631   if ( !name.isNull() ) {
01632     mDetailsStack->raiseWidget( mDistListEntryView );
01633     const QStringList selectedUids = selectedUIDs();
01634     showDistributionListEntry( selectedUids.isEmpty() ? QString() : selectedUids.first() );
01635   }
01636   else
01637     mDetailsStack->raiseWidget( mExtensionManager->activeDetailsWidget() ? mExtensionManager->activeDetailsWidget() : mDetailsWidget );
01638 }
01639 
01640 QStringList KABCore::distributionListNames() const
01641 {
01642   return mSearchManager->distributionListNames();
01643 }
01644 #endif
01645 
01646 #include "kabcore.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys