diff --git a/kabc/stdaddressbook.cpp b/kabc/stdaddressbook.cpp index 9607e5204..7c4548c27 100644 --- a/kabc/stdaddressbook.cpp +++ b/kabc/stdaddressbook.cpp @@ -1,247 +1,251 @@ /* This file is part of libkabc. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "stdaddressbook.h" #include "resource.h" #include "kresources/manager.h" #include #include #include #include #include #include #include using namespace KABC; class StdAddressBook::Private { public: Private( StdAddressBook *parent ) : mParent( parent ) { } void init( bool asynchronous ); bool saveAll(); StdAddressBook *mParent; static bool mAutomaticSave; }; static StdAddressBook *s_gStdAddressBook = 0; bool StdAddressBook::Private::mAutomaticSave = true; static void deleteGlobalStdAddressBook() { if ( s_gStdAddressBook ) { delete s_gStdAddressBook; s_gStdAddressBook = 0; } } QString StdAddressBook::fileName() { return KStandardDirs::locateLocal( "data", "kabc/std.vcf" ); } QString StdAddressBook::directoryName() { return KStandardDirs::locateLocal( "data", "kabc/stdvcf" ); } StdAddressBook *StdAddressBook::self() { kDebug(); - if ( !s_gStdAddressBook ) { - s_gStdAddressBook = new StdAddressBook(); - - // We don't use a global static here for two reasons: - // - // 1. The K_GLOBAL_STATIC does not allow two different constructor calls, - // which we need because there are two self() methods - // - // 2. There are problems with the destruction order: The destructor of - // StdAddressBook calls save(), which for LDAP address books, needs KIO - // (more specific: KProtocolInfo) to be still alive. However, with a global - // static, KProtocolInfo is already deleted, and the app will crash. - // - // qAddPostRoutine deletes the objects when the QApplication is destroyed, - // which is earlier than the global statics, so this will work. - qAddPostRoutine( deleteGlobalStdAddressBook ); - } - - return s_gStdAddressBook; + // delegate to other self() method since the only difference + // was the constructor being used and their only difference is + // what they pass to Private::init() + return self( false ); } StdAddressBook *StdAddressBook::self( bool asynchronous ) { - kDebug(); + kDebug() << "asynchronous=" << asynchronous; if ( !s_gStdAddressBook ) { - s_gStdAddressBook = new StdAddressBook( asynchronous ); + s_gStdAddressBook = new StdAddressBook( asynchronous, false ); - // See comment in the other self() method for this. + // We don't use a global static here for this reason: + // + // There are problems with the destruction order: The destructor of + // StdAddressBook calls save(), which for LDAP address books, needs KIO + // (more specific: KProtocolInfo) to be still alive. However, with a global + // static, KProtocolInfo is already deleted, and the app will crash. + // + // qAddPostRoutine deletes the objects when the QApplication is destroyed, + // which is earlier than the global statics, so this will work. qAddPostRoutine( deleteGlobalStdAddressBook ); + + s_gStdAddressBook->d->init( asynchronous ); } return s_gStdAddressBook; } StdAddressBook::StdAddressBook() : AddressBook( "" ), d( new Private( this ) ) { kDebug(); d->init( false ); } StdAddressBook::StdAddressBook( bool asynchronous ) : AddressBook( "" ), d( new Private( this ) ) { kDebug(); d->init( asynchronous ); } +StdAddressBook::StdAddressBook( bool asynchronous, bool doInit ) + : AddressBook( "" ), d( new Private( this ) ) +{ + kDebug(); + + if ( doInit ) + d->init( asynchronous ); +} + StdAddressBook::~StdAddressBook() { if ( Private::mAutomaticSave ) { d->saveAll(); } delete d; } void StdAddressBook::Private::init( bool asynchronous ) { KRES::Manager *manager = mParent->resourceManager(); KRES::Manager::ActiveIterator it; for ( it = manager->activeBegin(); it != manager->activeEnd(); ++it ) { (*it)->setAddressBook( mParent ); if ( !(*it)->open() ) { mParent->error( QString( "Unable to open resource '%1'!" ).arg( (*it)->resourceName() ) ); continue; } mParent->connect( *it, SIGNAL( loadingFinished( Resource* ) ), mParent, SLOT( resourceLoadingFinished( Resource* ) ) ); mParent->connect( *it, SIGNAL( savingFinished( Resource* ) ), mParent, SLOT( resourceSavingFinished( Resource* ) ) ); mParent->connect( *it, SIGNAL( loadingError( Resource*, const QString& ) ), mParent, SLOT( resourceLoadingError( Resource*, const QString& ) ) ); mParent->connect( *it, SIGNAL( savingError( Resource*, const QString& ) ), mParent, SLOT( resourceSavingError( Resource*, const QString& ) ) ); } Resource *res = mParent->standardResource(); if ( !res ) { res = manager->createResource( "file" ); if ( res ) { mParent->addResource( res ); } else { kDebug() << "No resource available!!!"; } } mParent->setStandardResource( res ); manager->writeConfig(); if ( asynchronous ) { mParent->asyncLoad(); } else { mParent->load(); } } bool StdAddressBook::Private::saveAll() { kDebug(); bool ok = true; KRES::Manager::ActiveIterator it; KRES::Manager *manager = mParent->resourceManager(); for ( it = manager->activeBegin(); it != manager->activeEnd(); ++it ) { if ( !(*it)->readOnly() && (*it)->isOpen() ) { Ticket *ticket = mParent->requestSaveTicket( *it ); if ( !ticket ) { mParent->error( i18n( "Unable to save to resource '%1'. It is locked.", (*it)->resourceName() ) ); return false; } if ( !mParent->AddressBook::save( ticket ) ) { ok = false; mParent->releaseSaveTicket( ticket ); } } } return ok; } bool StdAddressBook::save() { kDebug(); if ( s_gStdAddressBook ) { return s_gStdAddressBook->d->saveAll(); } else { return true; } } void StdAddressBook::close() { delete s_gStdAddressBook; s_gStdAddressBook = 0; } void StdAddressBook::setAutomaticSave( bool enable ) { Private::mAutomaticSave = enable; } bool StdAddressBook::automaticSave() { return Private::mAutomaticSave; } Addressee StdAddressBook::whoAmI() const { KConfig _config( "kabcrc" ); KConfigGroup config(&_config, "General" ); return findByUid( config.readEntry( "WhoAmI" ) ); } void StdAddressBook::setWhoAmI( const Addressee &addr ) { KConfig _config( "kabcrc" ); KConfigGroup config(&_config, "General" ); config.writeEntry( "WhoAmI", addr.uid() ); } diff --git a/kabc/stdaddressbook.h b/kabc/stdaddressbook.h index 0be737069..199760da9 100644 --- a/kabc/stdaddressbook.h +++ b/kabc/stdaddressbook.h @@ -1,145 +1,150 @@ /* This file is part of libkabc. Copyright (c) 2001 Cornelius Schumacher This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KABC_STDADDRESSBOOK_H #define KABC_STDADDRESSBOOK_H #include "addressbook.h" namespace KABC { /** Standard KDE address book This class provides access to the standard KDE address book shared by all applications. It's implemented as a singleton. Use self() to get the address book object. On the first self() call the address book also gets loaded. Example: \code KABC::AddressBook *ab = KABC::StdAddressBook::self(); AddressBook::Ticket *ticket = ab->requestSaveTicket(); if ( ticket ) { KABC::AddressBook::Iterator it; for ( it = ab->begin(); it != ab->end(); ++it ) { kDebug(5700) << "UID=" << (*it).uid(); // do some other stuff } KABC::StdAddressBook::save( ticket ); } \endcode */ class KABC_EXPORT StdAddressBook : public AddressBook { public: /** Destructor. */ ~StdAddressBook(); /** Returns the standard addressbook object. It also loads all resources of the users standard address book synchronously. */ static StdAddressBook *self(); /** This is the same as above, but with specified behaviour of resource loading. @param asynchronous When true, the resources are loaded asynchronous, that means you have the data foremost the addressBookChanged() signal has been emitted. So connect to this signal when using this method! */ static StdAddressBook *self( bool asynchronous ); /** Saves the standard address book to disk. @deprecated Use AddressBook::save( Ticket* ) instead */ static KDE_DEPRECATED bool save(); /** Returns the default file name for vcard-based addressbook */ static QString fileName(); /** Returns the default directory name for vcard-based addressbook */ static QString directoryName(); /** Sets the automatic save property of the address book. @param state If true, the address book is saved automatically at destruction time, otherwise you have to call AddressBook::save( Ticket* ). */ static void setAutomaticSave( bool state ); /** Closes the address book. Depending on automaticSave() it will save the address book first. */ static void close(); /** Returns whether the address book is saved at destruction time. See also setAutomaticSave(). */ static bool automaticSave(); /** Returns the contact, that is associated with the owner of the address book. This contact should be used by other programs to access user specific data. */ Addressee whoAmI() const; /** Sets the users contact. See whoAmI() for more information. @param addr The users contact. */ void setWhoAmI( const Addressee &addr ); protected: StdAddressBook(); StdAddressBook( bool asynchronous ); private: + // needed another constructor for delaying Private::init() to right + // after the instance creation. Cannot change the other two since they + // are protected and might be called by subclasses + StdAddressBook( bool asynchronous, bool doInit ); + class Private; Private *const d; }; } #endif