kaddressbook Library API Documentation

kaddressbook.cpp

00001 /*
00002  * kaddressbook.cpp
00003  *
00004  * Copyright (C) 1999 Don Sanders <dsanders@kde.org>
00005  */
00006 #include "kaddressbook.h"
00007 #include <kabc/vcardconverter.h>
00008 
00009 #include <qkeycode.h>
00010 #include <qregexp.h>
00011 #include <qlayout.h>
00012 
00013 #include <klocale.h>
00014 #include <kglobal.h>
00015 #include <kconfig.h>
00016 #include <kdebug.h>
00017 #include <kfiledialog.h>
00018 #include <kmessagebox.h>
00019 #include <kstatusbar.h>
00020 #include <kstandarddirs.h>
00021 #include <kprocess.h>
00022 #include <kapplication.h>
00023 #include <kprotocolinfo.h>
00024 #include <kprinter.h>
00025 #include <kabc/stdaddressbook.h>
00026 #include <kabc/distributionlistdialog.h>
00027 #include <kabc/distributionlist.h>
00028 #include <kabc/field.h>
00029 #include <kabc/resourceselectdialog.h>
00030 
00031 #include "undo.h"
00032 #include "undocmds.h"
00033 #include "addresseeeditordialog.h"
00034 #include "filtereditdialog.h"
00035 #include "importdialog.h"
00036 #include "prefsdialog.h"
00037 #include "ldapsearchdialogimpl.h"
00038 #include "viewmanager.h"
00039 #include "printing/printingwizard.h"
00040 #include "filter.h"
00041 #include "incsearchwidget.h"
00042 
00043 KAddressBook::KAddressBook( QWidget *parent, const char *name )
00044   : QWidget( parent, name )
00045 {
00046   QBoxLayout *topLayout = new QVBoxLayout( this );
00047 
00048   mDocument = KABC::StdAddressBook::self();
00049   KABC::StdAddressBook::setAutomaticSave( false );
00050 
00051   connect( mDocument, SIGNAL( addressBookChanged( AddressBook * ) ),
00052            SLOT( slotAddressBookChanged() ) );
00053 
00054   mDocument->addCustomField( i18n("Department"), KABC::Field::Organization,
00055                              "X-Department", "KADDRESSBOOK" );
00056   mDocument->addCustomField( i18n("Profession"), KABC::Field::Organization,
00057                              "X-Profession", "KADDRESSBOOK" );
00058   mDocument->addCustomField( i18n("Assistant's Name"),
00059                              KABC::Field::Organization,
00060                              "X-AssistantsName", "KADDRESSBOOK" );
00061   mDocument->addCustomField( i18n("Manager's Name"),
00062                              KABC::Field::Organization,
00063                              "X-ManagersName", "KADDRESSBOOK" );
00064   mDocument->addCustomField( i18n("Spouse's Name"),
00065                              KABC::Field::Personal,
00066                              "X-SpousesName", "KADDRESSBOOK" );
00067   mDocument->addCustomField( i18n("Office"),
00068                              KABC::Field::Personal,
00069                              "X-Office", "KADDRESSBOOK" );
00070   mDocument->addCustomField( i18n("IM Address"),
00071                              KABC::Field::Personal,
00072                              "X-IMAddress", "KADDRESSBOOK" );
00073   mDocument->addCustomField( i18n("Anniversary"),
00074                              KABC::Field::Personal,
00075                              "X-Anniversary", "KADDRESSBOOK" );
00076 
00077   // Create the GUI
00078   mViewManager = new ViewManager(mDocument, kapp->config(),
00079                                  this, "mViewManager");
00080   topLayout->addWidget(mViewManager);
00081   connect(mViewManager, SIGNAL(selected(const QString &)),
00082           SLOT(addresseeSelected(const QString &)));
00083   connect(mViewManager, SIGNAL(executed(const QString &)),
00084           SLOT(addresseeExecuted(const QString &)));
00085   connect(mViewManager, SIGNAL(modified()),
00086           SLOT(viewModified()));
00087   connect(mViewManager, SIGNAL(importVCard(const QString &, bool)),
00088           SLOT(importVCard(const QString &, bool)));
00089 
00090   mPrefsDialog = 0;
00091   mLdapSearchDialog = 0;
00092 }
00093 
00094 
00095 void KAddressBook::newContact()
00096 {/* OLD DCOP CALL  -- still works, but should be newAddressee */
00097   newAddressee();
00098 }
00099 
00100 void KAddressBook::addEmail( QString aStr )
00101 {
00102 
00103   QString fullName, email;
00104 
00105   KABC::Addressee::parseEmailAddress(aStr, fullName, email);
00106 
00107   // Try to lookup the addressee matching the email address
00108   bool found = false;
00109   QStringList emailList;
00110   KABC::AddressBook::Iterator iter;
00111   for (iter = mDocument->begin(); !found && (iter != mDocument->end());
00112        ++iter)
00113   {
00114     emailList = (*iter).emails();
00115     if (emailList.contains(email) > 0)
00116     {
00117       // This changes the name event if the user cancels the edit. I am
00118       // not sure that is the behaviour that we want, but it was how
00119       // the original implementation worked.
00120       found = true;
00121       (*iter).setNameFromString(fullName);
00122       editAddressee((*iter).uid());
00123     }
00124   }
00125 
00126   if (!found)
00127   {
00128     // create a new entry and edit it
00129     KABC::Addressee a;
00130     a.setNameFromString(fullName);
00131     a.insertEmail(email, true);
00132 
00133     mDocument->insertAddressee(a);
00134     mViewManager->refresh( a.uid() );
00135     editAddressee(a.uid());
00136   }
00137 }
00138 
00139 ASYNC KAddressBook::showContactEditor ( QString uid )
00140 { /* OLD DCOP CALL   -- still works, but should be editAddressee */
00141   editAddressee(uid);
00142 }
00143 
00144 void KAddressBook::editAddressee(QString uid)
00145 {
00146   if ( mViewManager->isQuickEditVisible() ) {
00147     return;
00148   }
00149 
00150   // First, locate the contact entry
00151   if (uid == QString::null)
00152   {
00153     QStringList uidList = mViewManager->selectedUids();
00154     if (uidList.count() > 0)
00155       uid = *(uidList.at(0));
00156   }
00157 
00158   KABC::Addressee a = mDocument->findByUid(uid);
00159   if (!a.isEmpty())
00160   {
00161     AddresseeEditorDialog *dialog = mEditorDict.find( a.uid() );
00162     if ( !dialog ) {
00163       dialog = createAddresseeEditorDialog( this );
00164 
00165       mEditorDict.insert( a.uid(), dialog );
00166 
00167       dialog->setAddressee(a);
00168     }
00169 
00170     dialog->raise();
00171     dialog->show();
00172   }
00173 }
00174 
00175 void KAddressBook::newAddressee()
00176 {
00177   AddresseeEditorDialog *dialog = 0;
00178 
00179   KABC::Resource *resource = KABC::ResourceSelectDialog::getResource( mDocument,
00180                                                                       this );
00181   if ( resource ) {
00182     KABC::Addressee addr;
00183     addr.setResource( resource );
00184     dialog = createAddresseeEditorDialog( this );
00185     dialog->setAddressee( addr );
00186   } else {
00187     return;
00188   }
00189 
00190   mEditorDict.insert( dialog->addressee().uid(), dialog );
00191 
00192   dialog->show();
00193 }
00194 
00195 AddresseeEditorDialog *KAddressBook::createAddresseeEditorDialog( QWidget *parent,
00196                                                                   const char *name )
00197 {
00198   AddresseeEditorDialog *dialog = new AddresseeEditorDialog( parent,
00199                                                              name ? name : "editorDialog" );
00200   connect(dialog, SIGNAL(addresseeModified(const KABC::Addressee &)),
00201           SLOT(addresseeModified(const KABC::Addressee &)));
00202   connect(dialog, SIGNAL( editorDestroyed( const QString & ) ),
00203           SLOT( slotEditorDestroyed( const QString & ) ) );
00204 
00205   return dialog;
00206 }
00207 
00208 void KAddressBook::slotEditorDestroyed( const QString &uid )
00209 {
00210 
00211   mEditorDict.remove( uid );
00212 }
00213 
00214 void KAddressBook::save()
00215 {
00216   KABC::StdAddressBook *b = dynamic_cast<KABC::StdAddressBook*>(mDocument);
00217   if (!b || !b->save())
00218   {
00219     QString text = i18n("There was an error while attempting to save the "
00220                         "address book. Please check that some other application is "
00221                         "not using it. ");
00222 
00223     KMessageBox::error(this, text, i18n("Unable to Save"));
00224     return;
00225   }
00226 
00227   emit modified(false);
00228 }
00229 
00230 void KAddressBook::readConfig()
00231 {
00232   mViewManager->readConfig();
00233 }
00234 
00235 void KAddressBook::writeConfig()
00236 {
00237   mViewManager->writeConfig();
00238 }
00239 
00240 KAddressBook::~KAddressBook()
00241 {
00242   writeConfig();
00243 
00244   delete mDocument;
00245 }
00246 
00247 void KAddressBook::undo()
00248 {
00249   UndoStack::instance()->undo();
00250 
00251   // Refresh the view
00252   mViewManager->refresh();
00253 }
00254 
00255 void KAddressBook::redo()
00256 {
00257   RedoStack::instance()->redo();
00258 
00259   // Refresh the view
00260   mViewManager->refresh();
00261 }
00262 
00263 void KAddressBook::importKDE2()
00264 {
00265   if (!QFile::exists(locateLocal("data", "kabc/std.vcf") )) {
00266     KMessageBox::sorry( this, i18n("Couldn't find a KDE 2 address book.") );
00267     return;
00268   }
00269 
00270   int result = KMessageBox::questionYesNoCancel( this,
00271       i18n("Override previously imported entries?"),
00272       i18n("Import KDE 2 Addressbook"));
00273 
00274   if ( !result ) return;
00275 
00276   KProcess proc;
00277 
00278   if ( result == KMessageBox::Yes ) {
00279     proc << "kab2kabc";
00280     proc << "--override";
00281   } else if ( result == KMessageBox::No ) {
00282     proc << "kab2kabc";
00283   } else {
00284     kdDebug() << "KAddressBook::importKDE2(): Unknow return value." << endl;
00285   }
00286 
00287   proc.start( KProcess::Block );
00288 
00289   mDocument->load();
00290   mViewManager->refresh();
00291 }
00292 
00293 void KAddressBook::importCSV()
00294 {
00295 
00296   ContactImportDialog *dialog = new ContactImportDialog(mDocument, this);
00297 
00298   if ( dialog->exec() )
00299       mViewManager->refresh();
00300   delete dialog;
00301 
00302   emit modified( true );
00303 }
00304 
00305 void KAddressBook::importVCardSimple()
00306 {
00307   importVCard( QString::null, true );
00308 }
00309 
00310 void KAddressBook::importVCard( const QString &file, bool showDialog )
00311 {
00312   QString fileName;
00313 
00314   if ( file )
00315     fileName = file;
00316   else
00317     fileName = KFileDialog::getOpenFileName( QString::null,
00318                                                   "*.vcf|vCards", 0,
00319                                                   i18n( "Select vCard to Import" ) );
00320 
00321   if ( !fileName.isEmpty() ) {
00322     KABC::VCardConverter converter;
00323     QFile file( fileName );
00324 
00325     file.open( IO_ReadOnly );
00326     QByteArray rawData = file.readAll();
00327     file.close();
00328 
00329     QString data = QString::fromUtf8( rawData.data(), rawData.size() + 1 );
00330     QStringList dataList = QStringList::split( "\r\n\r\n", data );
00331 
00332     QStringList::Iterator it;
00333     for ( it = dataList.begin(); it != dataList.end(); ++it ) {
00334       KABC::Addressee addr;
00335       bool ok = false;
00336       if ( (*it).contains( "VERSION:3.0" ) ) {
00337         ok = converter.vCardToAddressee( *it, addr, KABC::VCardConverter::v3_0 );
00338       } else if ( (*it).contains( "VERSION:2.1" ) ) {
00339         ok = converter.vCardToAddressee( *it, addr, KABC::VCardConverter::v2_1 );
00340       } else {
00341         KMessageBox::sorry( this, i18n( "Not supported vCard version!" ) );
00342         continue;
00343       }
00344 
00345       if ( !addr.isEmpty() && ok ) {
00346         // Add it to the document, then let the user edit it. We use a
00347         // PwNewCommand so the user can undo it.
00348         PwNewCommand *command = new PwNewCommand( mDocument, addr );
00349         UndoStack::instance()->push( command );
00350         RedoStack::instance()->clear();
00351 
00352         mViewManager->refresh();
00353 
00354         if ( showDialog )
00355           editAddressee( addr.uid() );
00356 
00357         emit modified( true );
00358       } else {
00359         QString text = i18n( "The selected file does not appear to be a valid vCard. "
00360                              "Please check the file and try again." );
00361 
00362         KMessageBox::sorry( this, text, i18n( "vCard Import Failed" ) );
00363       }
00364     }
00365   }
00366 }
00367 
00368 void KAddressBook::exportCSV()
00369 {
00370   QString fileName = KFileDialog::getSaveFileName("addressbook.csv");
00371   if ( fileName.isEmpty())
00372       return;
00373   QFile outFile(fileName);
00374   if ( outFile.open(IO_WriteOnly) )
00375   {    // file opened successfully
00376     QTextStream t( &outFile );        // use a text stream
00377 
00378     KABC::AddressBook::Iterator iter;
00379     KABC::Field::List fields = mDocument->fields();
00380     KABC::Field::List::Iterator fieldIter;
00381     bool first = true;
00382 
00383     // First output the column headings
00384     for (fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter)
00385     {
00386       if (!first)
00387         t << ",";
00388 
00389       t << "\"" << (*fieldIter)->label() << "\"";
00390       first = false;
00391     }
00392     t << "\n";
00393 
00394     // Then all the addressee objects
00395     KABC::Addressee a;
00396     for (iter = mDocument->begin(); iter != mDocument->end(); ++iter)
00397     {
00398       a = *iter;
00399       first = true;
00400 
00401       for (fieldIter = fields.begin(); fieldIter != fields.end(); ++fieldIter)
00402       {
00403         if (!first)
00404           t << ",";
00405 
00406         t << "\"" << (*fieldIter)->value( a ).replace( QRegExp("\n"), "\\n" ) << "\"";
00407         first = false;
00408       }
00409 
00410       t << "\n";
00411     }
00412 
00413     outFile.close();
00414   }
00415 }
00416 
00417 void KAddressBook::exportVCard30()
00418 {
00419   exportVCard( KABC::VCardConverter::v3_0 );
00420 }
00421 
00422 void KAddressBook::exportVCard( KABC::VCardConverter::Version )
00423 {
00424   KABC::Addressee::List addrList;
00425 
00426   QStringList uids = viewManager()->selectedUids();
00427   if ( uids.count() == 0 )
00428     return;
00429 
00430   for ( uint i = 0; i < uids.count(); ++i ) {
00431     KABC::Addressee addr;
00432     addr = mDocument->findByUid( uids[ i ] );
00433     if ( !addr.isEmpty() )
00434       addrList.append( addr );
00435   }
00436 
00437   if ( addrList.count() == 0 )
00438     return;
00439 
00440   QString name;
00441   if ( addrList.count() == 1 )
00442     name = addrList[ 0 ].givenName() + "_" + addrList[ 0 ].familyName() + ".vcf";
00443   else
00444     name = "addressbook.vcf";
00445 
00446   QString fileName = KFileDialog::getSaveFileName( name );
00447   if ( fileName.isEmpty() )
00448       return;
00449 
00450   QFile outFile(fileName);
00451   if ( !outFile.open( IO_WriteOnly ) ) {
00452     QString text = i18n( "<qt>Unable to open file <b>%1</b> for export!</qt>" );
00453     KMessageBox::error( this, text.arg( fileName ) );
00454     return;
00455   }
00456 
00457   QTextStream t( &outFile ); // use a text stream
00458   t.setEncoding( QTextStream::UnicodeUTF8 );
00459 
00460   KABC::Addressee::List::Iterator it;
00461   for ( it = addrList.begin(); it != addrList.end(); ++it )
00462   {
00463     KABC::VCardConverter converter;
00464     QString vcard;
00465 
00466     converter.addresseeToVCard( *it, vcard );
00467     t << vcard << "\r\n\r\n";
00468   }
00469 
00470   outFile.close();
00471 }
00472 
00473 QString KAddressBook::getNameByPhone( QString phone )
00474 {
00475   QRegExp r("[/*/-]");
00476 
00477   bool found = false;
00478   QString ownerName = "";
00479   KABC::AddressBook::Iterator iter;
00480   KABC::PhoneNumber::List::Iterator phoneIter;
00481   KABC::PhoneNumber::List phoneList;
00482   for (iter = mDocument->begin(); !found && (iter != mDocument->end()); ++iter)
00483   {
00484     phoneList = (*iter).phoneNumbers();
00485     for (phoneIter = phoneList.begin();
00486          !found && (phoneIter != phoneList.end());
00487          ++phoneIter)
00488     {
00489       // Get rid of separator chars so just the numbers are compared.
00490       if ((*phoneIter).number().replace( r, "" ) == phone.replace( r, "" ))
00491       {
00492       ownerName = (*iter).formattedName();
00493       found = true;
00494       }
00495     }
00496   }
00497 
00498   return ownerName;
00499 }
00500 
00501 void KAddressBook::addresseeSelected(const QString &uid)
00502 {
00503     emit addresseeSelected(uid != QString::null);
00504 }
00505 
00506 void KAddressBook::addresseeExecuted(const QString &uid)
00507 {
00508     // WORK_TO_DO: find a way to decide this (quickedit will
00509     // become a part of the details view)
00510   if ( uid != QString::null && !mViewManager->isQuickEditVisible() )
00511     editAddressee(uid);
00512 }
00513 
00514 void KAddressBook::addresseeModified(const KABC::Addressee &a)
00515 {
00516 
00517   Command *command = 0;
00518   QString uid;
00519 
00520   // check if it exists already
00521   KABC::Addressee origA = mDocument->findByUid(a.uid());
00522   if (origA.isEmpty()) {
00523     // Must be new
00524     command = new PwNewCommand(mDocument, a);
00525   } else {
00526     // Must be an edit
00527     command = new PwEditCommand(mDocument, origA, a);
00528     uid = a.uid();
00529   }
00530   UndoStack::instance()->push(command);
00531   RedoStack::instance()->clear();
00532 
00533   mViewManager->refresh(uid);
00534 
00535   emit modified(true);
00536 }
00537 
00538 void KAddressBook::viewModified()
00539 {
00540     emit modified(true);
00541 }
00542 void KAddressBook::configure()
00543 {
00544   if ( !mPrefsDialog ) {
00545     mPrefsDialog = new PrefsDialog( this );
00546     connect(mPrefsDialog, SIGNAL(configChanged()), SLOT(configChanged()));
00547   }
00548 
00549   // Save the current config so we do not loose anything if the user
00550   // accepts
00551   writeConfig();
00552 
00553   mPrefsDialog->show();
00554   mPrefsDialog->raise();
00555 }
00556 
00557 void KAddressBook::slotOpenLDAPDialog()
00558 {
00559   if( !mLdapSearchDialog ) {
00560     mLdapSearchDialog = new LDAPSearchDialogImpl( mDocument, this);
00561     connect( mLdapSearchDialog, SIGNAL( addresseesAdded() ),
00562              this, SLOT( slotLDAPRefresh() ) );
00563   } else
00564     mLdapSearchDialog->rereadConfig();
00565 
00566   if( mLdapSearchDialog->isOK() )
00567     mLdapSearchDialog->exec();
00568 }
00569 
00570 // This slot is used by the LDAP dialog to make sure we refresh the view
00571 void KAddressBook::slotLDAPRefresh()
00572 {
00573   emit modified(true);
00574   mViewManager->refresh();
00575 }
00576 
00577 
00578 void KAddressBook::print()
00579 {
00580     // ----- first set up the KPrinter object (rationale: The print
00581     // styles need the device metrics etc to print correctly, thus the
00582     // printer has to be selected before the style can be configured:
00583     KPrinter printer;
00584     if(!printer.setup(this))
00585     {
00586         return;
00587     }
00588 
00589     KABPrinting::PrintingWizard *wizard=
00590         KABPrinting::producePrintingWizard(&printer, mDocument,
00591                                            mViewManager->selectedUids(),
00592                                            this);
00593     // remember: the actual printing is done in the overloaded accept
00594     // slot of the printing wizard (to keep the interface lean and
00595     // mean), thus you do not need to do anything in case this returns
00596     // true:
00597     wizard->exec();
00598     delete wizard;
00599 }
00600 
00601 void KAddressBook::configChanged()
00602 {
00603   readConfig();
00604 }
00605 
00606 void KAddressBook::slotAddressBookChanged()
00607 {
00608 
00609   QDictIterator<AddresseeEditorDialog> it( mEditorDict );
00610   while ( it.current() ) {
00611     if ( it.current()->dirty() ) {
00612       QString text = i18n( "Data has been changed externally. Unsaved "
00613                            "changes will be lost." );
00614       KMessageBox::information( this, text );
00615     }
00616     it.current()->setAddressee( mDocument->findByUid( it.currentKey() ) );
00617     ++it;
00618   }
00619 
00620   mViewManager->refresh();
00621 }
00622 
00623 void KAddressBook::configureFilters()
00624 {
00625   FilterDialog dlg( this );
00626 
00627   dlg.setFilters( mViewManager->filters() );
00628 
00629   if ( dlg.exec() )
00630     mViewManager->filtersChanged( dlg.filters() );
00631 }
00632 
00633 void KAddressBook::setIncSearchWidget(IncSearchWidget *w)
00634 {
00635     mIncSearchWidget=w;
00636     connect(w, SIGNAL(incSearch(const QString&, int)),
00637             mViewManager, SLOT(incSearch(const QString&, int)));
00638     connect(mViewManager, SIGNAL(setIncSearchFields(const QStringList&)),
00639             w, SLOT(setFields(const QStringList&)));
00640 }
00641 
00642 #include "kaddressbook.moc"
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sun Feb 15 11:40:37 2004 by doxygen 1.3.5 written by Dimitri van Heesch, © 1997-2001