diff --git a/kabc/plugins/file/resourcefile.cpp b/kabc/plugins/file/resourcefile.cpp index d752041a3..c14f5852c 100644 --- a/kabc/plugins/file/resourcefile.cpp +++ b/kabc/plugins/file/resourcefile.cpp @@ -1,461 +1,466 @@ /* This file is part of libkabc. Copyright (c) 2001,2003 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 "resourcefile.h" #include "resourcefileconfig.h" #include "kabc/formatfactory.h" #include "kabc/stdaddressbook.h" #include "kabc/lock.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KABC; typedef QList< QPair > MissingEntryList; class ResourceFile::ResourceFilePrivate { public: QMap< QString, MissingEntryList > mMissingEntries; }; ResourceFile::ResourceFile() : Resource(), mFormat( 0 ), mTempFile( 0 ), mAsynchronous( false ), d( new ResourceFilePrivate ) { QString fileName, formatName; fileName = StdAddressBook::fileName(); formatName = "vcard"; init( fileName, formatName ); } ResourceFile::ResourceFile( const KConfigGroup &group ) : Resource( group ), mFormat( 0 ), mTempFile( 0 ), mAsynchronous( false ), d( new ResourceFilePrivate ) { QString fileName, formatName; fileName = group.readPathEntry( "FileName", StdAddressBook::fileName() ); formatName = group.readEntry( "FileFormat", "vcard" ); init( fileName, formatName ); } ResourceFile::ResourceFile( const QString &fileName, const QString &formatName ) : Resource(), mFormat( 0 ), mTempFile( 0 ), mAsynchronous( false ), d( new ResourceFilePrivate ) { init( fileName, formatName ); } void ResourceFile::init( const QString &fileName, const QString &formatName ) { mFormatName = formatName; FormatFactory *factory = FormatFactory::self(); mFormat = factory->format( mFormatName ); if ( !mFormat ) { mFormatName = "vcard"; mFormat = factory->format( mFormatName ); } connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( fileChanged(const QString&) ) ); connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( fileChanged(const QString&) ) ); connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( fileChanged(const QString&) ) ); setFileName( fileName ); mDirWatch.addFile( KStandardDirs::locateLocal( "data", "kabc/distlists" ) ); mLock = 0; } ResourceFile::~ResourceFile() { delete d; d = 0; delete mFormat; mFormat = 0; } void ResourceFile::writeConfig( KConfigGroup &group ) { Resource::writeConfig( group ); if ( mFileName == StdAddressBook::fileName() ) { group.deleteEntry( "FileName" ); } else { group.writePathEntry( "FileName", mFileName ); } group.writeEntry( "FileFormat", mFormatName ); } Ticket *ResourceFile::requestSaveTicket() { kDebug(); if ( !addressBook() ) { return 0; } delete mLock; mLock = new Lock( mFileName ); if ( mLock->lock() ) { addressBook()->emitAddressBookLocked(); } else { addressBook()->error( mLock->error() ); kDebug() << "Unable to lock file '" << mFileName << "':" << mLock->error(); return 0; } return createTicket( this ); } void ResourceFile::releaseSaveTicket( Ticket *ticket ) { delete ticket; delete mLock; mLock = 0; addressBook()->emitAddressBookUnlocked(); } bool ResourceFile::doOpen() { QFile file( mFileName ); if ( !file.exists() ) { // try to create the file bool ok = file.open( QIODevice::WriteOnly ); if ( ok ) { file.close(); } return ok; } else { QFileInfo fileInfo( mFileName ); if ( readOnly() || !fileInfo.isWritable() ) { if ( !file.open( QIODevice::ReadOnly ) ) { return false; } } else { if ( !file.open( QIODevice::ReadWrite ) ) { return false; } } if ( file.size() == 0 ) { file.close(); return true; } bool ok = mFormat->checkFormat( &file ); file.close(); return ok; } } void ResourceFile::doClose() { } bool ResourceFile::load() { kDebug() << mFileName << "'"; mAsynchronous = false; QFile file( mFileName ); if ( !file.open( QIODevice::ReadOnly ) ) { addressBook()->error( i18n( "Unable to open file '%1'.", mFileName ) ); return false; } if ( !clearAndLoad( &file ) ) { addressBook()->error( i18n( "Problems during parsing file '%1'.", mFileName ) ); return false; } return true; } bool ResourceFile::clearAndLoad( QFile *file ) { clear(); bool addresseesOk = mFormat->loadAll( addressBook(), this, file ); bool listsOk = loadDistributionLists(); return addresseesOk && listsOk; } bool ResourceFile::asyncLoad() { mAsynchronous = true; load(); QTimer::singleShot( 0, this, SLOT( emitLoadingFinished() ) ); return true; } bool ResourceFile::save( Ticket *ticket ) { Q_UNUSED( ticket ); kDebug(); // create backup file QString extension = '_' + QString::number( QDate::currentDate().dayOfWeek() ); (void) KSaveFile::simpleBackupFile( mFileName, QString(), extension ); mDirWatch.stopScan(); KSaveFile saveFile( mFileName ); bool ok = false; if ( saveFile.open() ) { saveToFile( &saveFile ); ok = saveFile.finalize(); } if ( !ok ) { addressBook()->error( i18n( "Unable to save file '%1'.", mFileName ) ); } mDirWatch.startScan(); return ok; } bool ResourceFile::asyncSave( Ticket *ticket ) { kDebug(); save( ticket ); QTimer::singleShot( 0, this, SLOT( emitSavingFinished() ) ); return true; } void ResourceFile::emitLoadingFinished() { emit loadingFinished( this ); } void ResourceFile::emitSavingFinished() { emit savingFinished( this ); } bool ResourceFile::loadDistributionLists() { KConfig cfg( KStandardDirs::locateLocal( "data", "kabc/distlists" ) ); KConfigGroup cg( &cfg, "DistributionLists" ); const QStringList entryList = cg.keyList(); d->mMissingEntries.clear(); QStringList::ConstIterator it; for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) { const QString name = *it; const QStringList value = cg.readEntry( name, QStringList() ); kDebug() << name << ":" << value.join( "," ); DistributionList *list = new DistributionList( this, name ); MissingEntryList missingEntries; QStringList::ConstIterator entryIt = value.constBegin(); while ( entryIt != value.constEnd() ) { QString id = *entryIt++; QString email = entryIt != value.constEnd() ? *entryIt : QString(); if ( email.isEmpty() && !email.isNull() ) { email = QString(); } kDebug() << "----- Entry" << id; Addressee a = addressBook()->findByUid( id ); if ( !a.isEmpty() ) { list->insertEntry( a, email ); } else { missingEntries.append( qMakePair( id, email ) ); } if ( entryIt == value.constEnd() ) { break; } ++entryIt; } d->mMissingEntries.insert( name, missingEntries ); } return true; } void ResourceFile::saveDistributionLists() { kDebug(); KConfig cfg( KStandardDirs::locateLocal( "data", "kabc/distlists" ) ); KConfigGroup cg( &cfg, "DistributionLists" ); cg.deleteGroup(); QMapIterator it( mDistListMap ); while ( it.hasNext() ) { DistributionList *list = it.next().value(); kDebug() << " Saving '" << list->name() << "'"; QStringList value; const DistributionList::Entry::List entries = list->entries(); DistributionList::Entry::List::ConstIterator it; for ( it = entries.begin(); it != entries.end(); ++it ) { value.append( (*it).addressee().uid() ); value.append( (*it).email() ); } if ( d->mMissingEntries.find( list->name() ) != d->mMissingEntries.end() ) { const MissingEntryList missList = d->mMissingEntries[ list->name() ]; MissingEntryList::ConstIterator missIt; for ( missIt = missList.begin(); missIt != missList.end(); ++missIt ) { value.append( (*missIt).first ); value.append( (*missIt).second ); } } cg.writeEntry( list->name(), value ); } cg.sync(); } void ResourceFile::saveToFile( QFile *file ) { mFormat->saveAll( addressBook(), this, file ); saveDistributionLists(); } void ResourceFile::setFileName( const QString &fileName ) { mDirWatch.stopScan(); if ( mDirWatch.contains( mFileName ) ) { mDirWatch.removeFile( mFileName ); } mFileName = fileName; mDirWatch.addFile( mFileName ); mDirWatch.startScan(); } QString ResourceFile::fileName() const { return mFileName; } void ResourceFile::setFormat( const QString &format ) { mFormatName = format; delete mFormat; FormatFactory *factory = FormatFactory::self(); mFormat = factory->format( mFormatName ); } QString ResourceFile::format() const { return mFormatName; } void ResourceFile::fileChanged( const QString &path ) { kDebug() << path; if ( !addressBook() ) { return; } if ( path == KStandardDirs::locateLocal( "data", "kabc/distlists" ) ) { // clear old distribution lists - qDeleteAll( mDistListMap ); + // take a copy of mDistListMap, then clear it and finally qDeleteAll + // the copy to avoid problems with removeDistributionList() called by + // ~DistributionList(). + DistributionListMap tempDistListMap( mDistListMap ); + mDistListMap.clear(); + qDeleteAll( tempDistListMap ); loadDistributionLists(); kDebug() << "addressBookChanged()"; addressBook()->emitAddressBookChanged(); return; } // clear(); // moved to clearAndLoad() if ( mAsynchronous ) { asyncLoad(); } else { load(); kDebug() << "addressBookChanged()"; addressBook()->emitAddressBookChanged(); } } void ResourceFile::removeAddressee( const Addressee &addr ) { QFile::remove( QFile::encodeName( KStandardDirs::locateLocal( "data", "kabc/photos/" ) + addr.uid() ) ); QFile::remove( QFile::encodeName( KStandardDirs::locateLocal( "data", "kabc/logos/" ) + addr.uid() ) ); QFile::remove( QFile::encodeName( KStandardDirs::locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) ); mAddrMap.remove( addr.uid() ); } #include "resourcefile.moc" diff --git a/kabc/resource.cpp b/kabc/resource.cpp index 294216f62..392d7bba2 100644 --- a/kabc/resource.cpp +++ b/kabc/resource.cpp @@ -1,452 +1,452 @@ /* 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 "resource.h" #include #include using namespace KABC; class Ticket::Private { public: Private( Resource *resource ) : mResource( resource ) { } Resource *mResource; }; Ticket::Ticket( Resource *resource ) : d( new Private( resource ) ) { } Ticket::~Ticket() { delete d; } Resource *Ticket::resource() { return d->mResource; } class Resource::Iterator::Private { public: Addressee::Map::Iterator mIt; }; class Resource::ConstIterator::Private { public: Addressee::Map::ConstIterator mIt; }; Resource::Iterator::Iterator() : d( new Private ) { } Resource::Iterator::Iterator( const Resource::Iterator &other ) : d( new Private ) { d->mIt = other.d->mIt; } Resource::Iterator &Resource::Iterator::operator=( const Resource::Iterator &other ) { if ( this != &other ) { d->mIt = other.d->mIt; } return *this; } Resource::Iterator::~Iterator() { delete d; } const Addressee &Resource::Iterator::operator*() const { return d->mIt.value(); } Addressee &Resource::Iterator::operator*() { return d->mIt.value(); } Resource::Iterator &Resource::Iterator::operator++() { (d->mIt)++; return *this; } Resource::Iterator &Resource::Iterator::operator++( int ) { (d->mIt)++; return *this; } Resource::Iterator &Resource::Iterator::operator--() { (d->mIt)--; return *this; } Resource::Iterator &Resource::Iterator::operator--( int ) { (d->mIt)--; return *this; } bool Resource::Iterator::operator==( const Iterator &it ) const { return d->mIt == it.d->mIt; } bool Resource::Iterator::operator!=( const Iterator &it ) const { return d->mIt != it.d->mIt; } Resource::ConstIterator::ConstIterator() : d( new Private ) { } Resource::ConstIterator::ConstIterator( const Resource::ConstIterator &other ) : d( new Private ) { d->mIt = other.d->mIt; } Resource::ConstIterator::ConstIterator( const Resource::Iterator &other ) : d( new Private ) { d->mIt = other.d->mIt; } Resource::ConstIterator &Resource::ConstIterator::operator=( const Resource::ConstIterator &other ) { if ( this != &other ) { d->mIt = other.d->mIt; } return *this; } Resource::ConstIterator::~ConstIterator() { delete d; } const Addressee &Resource::ConstIterator::operator*() const { return *(d->mIt); } Resource::ConstIterator &Resource::ConstIterator::operator++() { (d->mIt)++; return *this; } Resource::ConstIterator &Resource::ConstIterator::operator++( int ) { (d->mIt)++; return *this; } Resource::ConstIterator &Resource::ConstIterator::operator--() { --(d->mIt); return *this; } Resource::ConstIterator &Resource::ConstIterator::operator--( int ) { --(d->mIt); return *this; } bool Resource::ConstIterator::operator==( const ConstIterator &it ) const { return d->mIt == it.d->mIt; } bool Resource::ConstIterator::operator!=( const ConstIterator &it ) const { return d->mIt != it.d->mIt; } class Resource::Private { public: Private() : mAddressBook( 0 ) { } AddressBook *mAddressBook; }; Resource::Resource() : KRES::Resource(), d( new Private ) { } Resource::Resource( const KConfigGroup &group ) : KRES::Resource( group ), d( new Private ) { } Resource::~Resource() { + clear(); delete d; - qDeleteAll( mDistListMap ); } Resource::Iterator Resource::begin() { Iterator it; it.d->mIt = mAddrMap.begin(); return it; } Resource::ConstIterator Resource::begin() const { ConstIterator it; it.d->mIt = mAddrMap.constBegin(); return it; } Resource::Iterator Resource::end() { Iterator it; it.d->mIt = mAddrMap.end(); return it; } Resource::ConstIterator Resource::end() const { ConstIterator it; it.d->mIt = mAddrMap.constEnd(); return it; } void Resource::writeConfig( KConfigGroup &group ) { KRES::Resource::writeConfig( group ); } void Resource::setAddressBook( AddressBook *ab ) { d->mAddressBook = ab; } AddressBook *Resource::addressBook() { return d->mAddressBook; } Ticket *Resource::createTicket( Resource *resource ) { return new Ticket( resource ); } void Resource::insertAddressee( const Addressee &addr ) { mAddrMap.insert( addr.uid(), addr ); } void Resource::removeAddressee( const Addressee &addr ) { mAddrMap.remove( addr.uid() ); } Addressee Resource::findByUid( const QString &uid ) { Addressee::Map::ConstIterator it = mAddrMap.constFind( uid ); if ( it != mAddrMap.constEnd() ) { return it.value(); } return Addressee(); } Addressee::List Resource::findByName( const QString &name ) { Addressee::List results; ConstIterator it; for ( it = begin(); it != end(); ++it ) { if ( name == (*it).name() ) { results.append( *it ); } } return results; } Addressee::List Resource::findByEmail( const QString &email ) { Addressee::List results; const QString lowerEmail = email.toLower(); ConstIterator it; for ( it = begin(); it != end(); ++it ) { const QStringList mailList = (*it).emails(); for ( QStringList::ConstIterator ite = mailList.begin(); ite != mailList.end(); ++ite ) { if ( lowerEmail == (*ite).toLower() ) { results.append( *it ); } } } return results; } Addressee::List Resource::findByCategory( const QString &category ) { Addressee::List results; ConstIterator it; for ( it = begin(); it != end(); ++it ) { if ( (*it).hasCategory( category ) ) { results.append( *it ); } } return results; } void Resource::clear() { mAddrMap.clear(); // take a copy of mDistListMap, then clear it and finally qDeleteAll // the copy to avoid problems with removeDistributionList() called by // ~DistributionList(). DistributionListMap tempDistListMap( mDistListMap ); mDistListMap.clear(); qDeleteAll( tempDistListMap ); } void Resource::insertDistributionList( DistributionList *list ) { Q_ASSERT( list ); mDistListMap.insert( list->identifier(), list ); } void Resource::removeDistributionList( DistributionList *list ) { Q_ASSERT( list ); DistributionListMap::iterator it = mDistListMap.find( list->identifier() ); if ( it != mDistListMap.end() ) { if ( it.value() == list ) { mDistListMap.erase( it ); } } } DistributionList *Resource::findDistributionListByIdentifier( const QString &identifier ) { return mDistListMap.value( identifier ); } DistributionList *Resource::findDistributionListByName( const QString &name, Qt::CaseSensitivity caseSensitivity ) { QString searchName = name; if ( caseSensitivity == Qt::CaseInsensitive ) { searchName = name.toLower(); } DistributionListMap::const_iterator it = mDistListMap.constBegin(); DistributionListMap::const_iterator endIt = mDistListMap.constEnd(); for ( ; it != endIt; ++it ) { if ( caseSensitivity == Qt::CaseSensitive ) { if ( searchName == it.value()->name() ) { return it.value(); } } else { if ( searchName == it.value()->name().toLower() ) { return it.value(); } } } return 0; } QList Resource::allDistributionLists() { return mDistListMap.values(); } QStringList Resource::allDistributionListNames() const { QStringList results; DistributionListMap::const_iterator it = mDistListMap.constBegin(); DistributionListMap::const_iterator endIt = mDistListMap.constEnd(); for ( ; it != endIt; ++it ) { results += it.value()->name(); } return results; } bool Resource::asyncLoad() { bool ok = load(); if ( !ok ) { emit loadingError( this, i18n( "Loading resource '%1' failed.", resourceName() ) ); } else { emit loadingFinished( this ); } return ok; } bool Resource::asyncSave( Ticket *ticket ) { bool ok = save( ticket ); if ( !ok ) { emit savingError( this, i18n( "Saving resource '%1' failed.", resourceName() ) ); } else { emit savingFinished( this ); } return ok; } #include "resource.moc"