kabc
resourcefile.cpp
00001 /* 00002 This file is part of libkabc. 00003 00004 Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org> 00005 00006 This library is free software; you can redistribute it and/or 00007 modify it under the terms of the GNU Library General Public 00008 License as published by the Free Software Foundation; either 00009 version 2 of the License, or (at your option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "resourcefile.h" 00023 #include "resourcefileconfig.h" 00024 00025 #include "kabc/formatfactory.h" 00026 #include "kabc/stdaddressbook.h" 00027 #include "kabc/lock.h" 00028 00029 #include <kio/scheduler.h> 00030 #include <kconfiggroup.h> 00031 #include <kdebug.h> 00032 #include <klocale.h> 00033 #include <ksavefile.h> 00034 #include <kstandarddirs.h> 00035 #include <ktemporaryfile.h> 00036 00037 #include <QtCore/QFile> 00038 #include <QtCore/QFileInfo> 00039 00040 #include <sys/types.h> 00041 #include <sys/stat.h> 00042 #include <signal.h> 00043 #include <unistd.h> 00044 00045 using namespace KABC; 00046 00047 typedef QList< QPair<QString, QString> > MissingEntryList; 00048 00049 class ResourceFile::ResourceFilePrivate 00050 { 00051 public: 00052 QMap< QString, MissingEntryList > mMissingEntries; 00053 }; 00054 00055 ResourceFile::ResourceFile() 00056 : Resource(), mFormat( 0 ), mTempFile( 0 ), 00057 mAsynchronous( false ), d( new ResourceFilePrivate ) 00058 { 00059 QString fileName, formatName; 00060 00061 fileName = StdAddressBook::fileName(); 00062 formatName = QLatin1String( "vcard" ); 00063 00064 init( fileName, formatName ); 00065 } 00066 00067 ResourceFile::ResourceFile( const KConfigGroup &group ) 00068 : Resource( group ), mFormat( 0 ), mTempFile( 0 ), 00069 mAsynchronous( false ), d( new ResourceFilePrivate ) 00070 { 00071 QString fileName, formatName; 00072 00073 fileName = group.readPathEntry( "FileName", StdAddressBook::fileName() ); 00074 formatName = group.readEntry( "FileFormat", "vcard" ); 00075 00076 init( fileName, formatName ); 00077 } 00078 00079 ResourceFile::ResourceFile( const QString &fileName, 00080 const QString &formatName ) 00081 : Resource(), mFormat( 0 ), mTempFile( 0 ), 00082 mAsynchronous( false ), d( new ResourceFilePrivate ) 00083 { 00084 init( fileName, formatName ); 00085 } 00086 00087 void ResourceFile::init( const QString &fileName, const QString &formatName ) 00088 { 00089 mFormatName = formatName; 00090 00091 FormatFactory *factory = FormatFactory::self(); 00092 mFormat = factory->format( mFormatName ); 00093 00094 if ( !mFormat ) { 00095 mFormatName = QLatin1String( "vcard" ); 00096 mFormat = factory->format( mFormatName ); 00097 } 00098 00099 connect( &mDirWatch, SIGNAL(dirty(QString)), SLOT(fileChanged(QString)) ); 00100 connect( &mDirWatch, SIGNAL(created(QString)), SLOT(fileChanged(QString)) ); 00101 connect( &mDirWatch, SIGNAL(deleted(QString)), SLOT(fileChanged(QString)) ); 00102 00103 setFileName( fileName ); 00104 00105 mDirWatch.addFile( KStandardDirs::locateLocal( "data", QLatin1String( "kabc/distlists" ) ) ); 00106 00107 mLock = 0; 00108 } 00109 00110 ResourceFile::~ResourceFile() 00111 { 00112 delete d; 00113 d = 0; 00114 delete mFormat; 00115 mFormat = 0; 00116 } 00117 00118 void ResourceFile::writeConfig( KConfigGroup &group ) 00119 { 00120 Resource::writeConfig( group ); 00121 00122 if ( mFileName == StdAddressBook::fileName() ) { 00123 group.deleteEntry( "FileName" ); 00124 } else { 00125 group.writePathEntry( "FileName", mFileName ); 00126 } 00127 00128 group.writeEntry( "FileFormat", mFormatName ); 00129 } 00130 00131 Ticket *ResourceFile::requestSaveTicket() 00132 { 00133 kDebug(); 00134 00135 if ( !addressBook() ) { 00136 return 0; 00137 } 00138 00139 delete mLock; 00140 mLock = new Lock( mFileName ); 00141 00142 if ( mLock->lock() ) { 00143 addressBook()->emitAddressBookLocked(); 00144 } else { 00145 addressBook()->error( mLock->error() ); 00146 kDebug() << "Unable to lock file '" << mFileName 00147 << "':" << mLock->error(); 00148 return 0; 00149 } 00150 00151 return createTicket( this ); 00152 } 00153 00154 void ResourceFile::releaseSaveTicket( Ticket *ticket ) 00155 { 00156 delete ticket; 00157 00158 delete mLock; 00159 mLock = 0; 00160 00161 addressBook()->emitAddressBookUnlocked(); 00162 } 00163 00164 bool ResourceFile::doOpen() 00165 { 00166 QFile file( mFileName ); 00167 00168 if ( !file.exists() ) { 00169 // try to create the file 00170 bool ok = file.open( QIODevice::WriteOnly ); 00171 if ( ok ) { 00172 file.close(); 00173 } 00174 return ok; 00175 } else { 00176 QFileInfo fileInfo( mFileName ); 00177 if ( readOnly() || !fileInfo.isWritable() ) { 00178 if ( !file.open( QIODevice::ReadOnly ) ) { 00179 return false; 00180 } 00181 } else { 00182 if ( !file.open( QIODevice::ReadWrite ) ) { 00183 return false; 00184 } 00185 } 00186 00187 if ( file.size() == 0 ) { 00188 file.close(); 00189 return true; 00190 } 00191 00192 bool ok = mFormat->checkFormat( &file ); 00193 file.close(); 00194 00195 return ok; 00196 } 00197 } 00198 00199 void ResourceFile::doClose() 00200 { 00201 } 00202 00203 bool ResourceFile::load() 00204 { 00205 kDebug() << mFileName << "'"; 00206 00207 mAsynchronous = false; 00208 00209 QFile file( mFileName ); 00210 if ( !file.open( QIODevice::ReadOnly ) ) { 00211 addressBook()->error( i18n( "Unable to open file '%1'.", mFileName ) ); 00212 return false; 00213 } 00214 00215 if ( !clearAndLoad( &file ) ) { 00216 addressBook()->error( i18n( "Problems parsing file '%1'.", mFileName ) ); 00217 return false; 00218 } 00219 00220 return true; 00221 } 00222 00223 bool ResourceFile::clearAndLoad( QFile *file ) 00224 { 00225 clear(); 00226 00227 bool addresseesOk = mFormat->loadAll( addressBook(), this, file ); 00228 00229 bool listsOk = loadDistributionLists(); 00230 00231 return addresseesOk && listsOk; 00232 } 00233 00234 bool ResourceFile::asyncLoad() 00235 { 00236 mAsynchronous = true; 00237 00238 load(); 00239 00240 QTimer::singleShot( 0, this, SLOT(emitLoadingFinished()) ); 00241 00242 return true; 00243 } 00244 00245 bool ResourceFile::save( Ticket *ticket ) 00246 { 00247 Q_UNUSED( ticket ); 00248 kDebug(); 00249 00250 // create backup file 00251 QString extension = QLatin1Char( '_' ) + QString::number( QDate::currentDate().dayOfWeek() ); 00252 (void) KSaveFile::simpleBackupFile( mFileName, QString(), extension ); 00253 00254 mDirWatch.stopScan(); 00255 00256 KSaveFile saveFile( mFileName ); 00257 bool ok = false; 00258 00259 if ( saveFile.open() ) { 00260 saveToFile( &saveFile ); 00261 ok = saveFile.finalize(); 00262 } 00263 00264 if ( !ok ) { 00265 addressBook()->error( i18n( "Unable to save file '%1'.", mFileName ) ); 00266 } 00267 00268 mDirWatch.startScan(); 00269 00270 return ok; 00271 } 00272 00273 bool ResourceFile::asyncSave( Ticket *ticket ) 00274 { 00275 kDebug(); 00276 00277 save( ticket ); 00278 00279 QTimer::singleShot( 0, this, SLOT(emitSavingFinished()) ); 00280 00281 return true; 00282 } 00283 00284 void ResourceFile::emitLoadingFinished() 00285 { 00286 emit loadingFinished( this ); 00287 } 00288 00289 void ResourceFile::emitSavingFinished() 00290 { 00291 emit savingFinished( this ); 00292 } 00293 00294 bool ResourceFile::loadDistributionLists() 00295 { 00296 KConfig cfg( KStandardDirs::locateLocal( "data", QLatin1String( "kabc/distlists" ) ) ); 00297 00298 KConfigGroup cg( &cfg, "DistributionLists" ); 00299 KConfigGroup cgId( &cfg, "DistributionLists-Identifiers" ); 00300 const QStringList entryList = cg.keyList(); 00301 00302 d->mMissingEntries.clear(); 00303 00304 QStringList::ConstIterator it; 00305 for ( it = entryList.constBegin(); it != entryList.constEnd(); ++it ) { 00306 const QString name = *it; 00307 const QStringList value = cg.readEntry( name, QStringList() ); 00308 00309 kDebug() << name << QLatin1Char( ':' ) << value.join( QLatin1String( "," ) ); 00310 00311 DistributionList *list = 0; 00312 if ( cgId.isValid() ) { 00313 const QString identifier = cgId.readEntry( name, QString() ); 00314 if ( !identifier.isEmpty() ) { 00315 list = new DistributionList( this, identifier, name ); 00316 } 00317 } 00318 00319 if ( list == 0 ) { 00320 list = new DistributionList( this, name ); 00321 } 00322 00323 MissingEntryList missingEntries; 00324 QStringList::ConstIterator entryIt = value.constBegin(); 00325 while ( entryIt != value.constEnd() ) { 00326 QString id = *entryIt++; 00327 QString email = entryIt != value.constEnd() ? *entryIt : QString(); 00328 if ( email.isEmpty() && !email.isNull() ) { 00329 email = QString(); //krazy:exclude=nullstrassign 00330 } 00331 00332 kDebug() << "----- Entry" << id; 00333 00334 Addressee a = addressBook()->findByUid( id ); 00335 if ( !a.isEmpty() ) { 00336 list->insertEntry( a, email ); 00337 } else { 00338 missingEntries.append( qMakePair( id, email ) ); 00339 } 00340 00341 if ( entryIt == value.constEnd() ) { 00342 break; 00343 } 00344 ++entryIt; 00345 } 00346 00347 d->mMissingEntries.insert( name, missingEntries ); 00348 } 00349 00350 return true; 00351 } 00352 00353 void ResourceFile::saveDistributionLists() 00354 { 00355 kDebug(); 00356 00357 KConfig cfg( KStandardDirs::locateLocal( "data", QLatin1String( "kabc/distlists" ) ) ); 00358 KConfigGroup cg( &cfg, "DistributionLists" ); 00359 cg.deleteGroup(); 00360 KConfigGroup cgId( &cfg, "DistributionLists-Identifiers" ); 00361 cgId.deleteGroup(); 00362 00363 QMapIterator<QString, DistributionList*> it( mDistListMap ); 00364 while ( it.hasNext() ) { 00365 DistributionList *list = it.next().value(); 00366 kDebug() << " Saving '" << list->name() << "'"; 00367 00368 QStringList value; 00369 const DistributionList::Entry::List entries = list->entries(); 00370 DistributionList::Entry::List::ConstIterator it; 00371 for ( it = entries.begin(); it != entries.end(); ++it ) { 00372 value.append( (*it).addressee().uid() ); 00373 value.append( (*it).email() ); 00374 } 00375 00376 if ( d->mMissingEntries.find( list->name() ) != d->mMissingEntries.end() ) { 00377 const MissingEntryList missList = d->mMissingEntries[ list->name() ]; 00378 MissingEntryList::ConstIterator missIt; 00379 for ( missIt = missList.begin(); missIt != missList.end(); ++missIt ) { 00380 value.append( (*missIt).first ); 00381 value.append( (*missIt).second ); 00382 } 00383 } 00384 00385 cg.writeEntry( list->name(), value ); 00386 cgId.writeEntry( list->name(), list->identifier() ); 00387 } 00388 00389 cfg.sync(); 00390 } 00391 00392 void ResourceFile::saveToFile( QFile *file ) 00393 { 00394 mFormat->saveAll( addressBook(), this, file ); 00395 00396 saveDistributionLists(); 00397 } 00398 00399 void ResourceFile::setFileName( const QString &fileName ) 00400 { 00401 mDirWatch.stopScan(); 00402 if ( mDirWatch.contains( mFileName ) ) { 00403 mDirWatch.removeFile( mFileName ); 00404 } 00405 00406 mFileName = fileName; 00407 00408 mDirWatch.addFile( mFileName ); 00409 mDirWatch.startScan(); 00410 } 00411 00412 QString ResourceFile::fileName() const 00413 { 00414 return mFileName; 00415 } 00416 00417 void ResourceFile::setFormat( const QString &format ) 00418 { 00419 mFormatName = format; 00420 delete mFormat; 00421 00422 FormatFactory *factory = FormatFactory::self(); 00423 mFormat = factory->format( mFormatName ); 00424 } 00425 00426 QString ResourceFile::format() const 00427 { 00428 return mFormatName; 00429 } 00430 00431 void ResourceFile::fileChanged( const QString &path ) 00432 { 00433 kDebug() << path; 00434 00435 if ( !addressBook() ) { 00436 return; 00437 } 00438 00439 if ( path == KStandardDirs::locateLocal( "data", QLatin1String( "kabc/distlists" ) ) ) { 00440 // clear old distribution lists 00441 // take a copy of mDistListMap, then clear it and finally qDeleteAll 00442 // the copy to avoid problems with removeDistributionList() called by 00443 // ~DistributionList(). 00444 DistributionListMap tempDistListMap( mDistListMap ); 00445 mDistListMap.clear(); 00446 qDeleteAll( tempDistListMap ); 00447 00448 loadDistributionLists(); 00449 00450 kDebug() << "addressBookChanged()"; 00451 addressBook()->emitAddressBookChanged(); 00452 00453 return; 00454 } 00455 00456 // clear(); // moved to clearAndLoad() 00457 if ( mAsynchronous ) { 00458 asyncLoad(); 00459 } else { 00460 load(); 00461 kDebug() << "addressBookChanged()"; 00462 addressBook()->emitAddressBookChanged(); 00463 } 00464 } 00465 00466 void ResourceFile::removeAddressee( const Addressee &addr ) 00467 { 00468 QFile::remove( KStandardDirs::locateLocal( 00469 "data", QLatin1String( "kabc/photos/" ) ) + addr.uid() ); 00470 QFile::remove( KStandardDirs::locateLocal( 00471 "data", QLatin1String( "kabc/logos/" ) ) + addr.uid() ); 00472 QFile::remove( KStandardDirs::locateLocal( 00473 "data", QLatin1String( "kabc/sounds/" ) ) + addr.uid() ); 00474 00475 mAddrMap.remove( addr.uid() ); 00476 } 00477 00478 #include "resourcefile.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:10:23 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
Documentation copyright © 1996-2012 The KDE developers.
Generated on Mon Aug 27 2012 22:10:23 by doxygen 1.7.5 written by Dimitri van Heesch, © 1997-2006
KDE's Doxygen guidelines are available online.