kaddressbook

kabcore.cpp

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