resourcefile.cpp00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <signal.h>
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #include <unistd.h>
00027
00028 #include <qfile.h>
00029 #include <qfileinfo.h>
00030 #include <qtimer.h>
00031
00032 #include <kapplication.h>
00033 #include <kconfig.h>
00034 #include <kdebug.h>
00035 #include <kio/scheduler.h>
00036 #include <klocale.h>
00037 #include <ksavefile.h>
00038 #include <kstandarddirs.h>
00039
00040 #include "formatfactory.h"
00041 #include "resourcefileconfig.h"
00042 #include "stdaddressbook.h"
00043 #include "lock.h"
00044
00045 #include "resourcefile.h"
00046
00047 using namespace KABC;
00048
00049 ResourceFile::ResourceFile( const KConfig *config )
00050 : Resource( config ), mFormat( 0 ),
00051 mAsynchronous( false )
00052 {
00053 QString fileName, formatName;
00054
00055 if ( config ) {
00056 fileName = config->readPathEntry( "FileName", StdAddressBook::fileName() );
00057 formatName = config->readEntry( "FileFormat", "vcard" );
00058 } else {
00059 fileName = StdAddressBook::fileName();
00060 formatName = "vcard";
00061 }
00062
00063 init( fileName, formatName );
00064 }
00065
00066 ResourceFile::ResourceFile( const QString &fileName,
00067 const QString &formatName )
00068 : Resource( 0 ), mFormat( 0 ),
00069 mAsynchronous( false )
00070 {
00071 init( fileName, formatName );
00072 }
00073
00074 void ResourceFile::init( const QString &fileName, const QString &formatName )
00075 {
00076 mFormatName = formatName;
00077
00078 FormatFactory *factory = FormatFactory::self();
00079 mFormat = factory->format( mFormatName );
00080
00081 if ( !mFormat ) {
00082 mFormatName = "vcard";
00083 mFormat = factory->format( mFormatName );
00084 }
00085
00086 connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( fileChanged() ) );
00087 connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( fileChanged() ) );
00088 connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( fileChanged() ) );
00089
00090 setFileName( fileName );
00091
00092 mLock = 0;
00093 }
00094
00095 ResourceFile::~ResourceFile()
00096 {
00097 delete mFormat;
00098 mFormat = 0;
00099 }
00100
00101 void ResourceFile::writeConfig( KConfig *config )
00102 {
00103 Resource::writeConfig( config );
00104
00105 if ( mFileName == StdAddressBook::fileName() )
00106 config->deleteEntry( "FileName" );
00107 else
00108 config->writePathEntry( "FileName", mFileName );
00109
00110 config->writeEntry( "FileFormat", mFormatName );
00111 }
00112
00113 Ticket *ResourceFile::requestSaveTicket()
00114 {
00115 kdDebug(5700) << "ResourceFile::requestSaveTicket()" << endl;
00116
00117 if ( !addressBook() ) return 0;
00118
00119 delete mLock;
00120 mLock = new Lock( mFileName );
00121
00122 if ( mLock->lock() ) {
00123 addressBook()->emitAddressBookLocked();
00124 } else {
00125 addressBook()->error( mLock->error() );
00126 kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock file '"
00127 << mFileName << "': " << mLock->error() << endl;
00128 return 0;
00129 }
00130
00131 return createTicket( this );
00132 }
00133
00134 void ResourceFile::releaseSaveTicket( Ticket *ticket )
00135 {
00136 delete ticket;
00137
00138 delete mLock;
00139 mLock = 0;
00140
00141 addressBook()->emitAddressBookUnlocked();
00142 }
00143
00144 bool ResourceFile::doOpen()
00145 {
00146 QFile file( mFileName );
00147
00148 if ( !file.exists() ) {
00149
00150 bool ok = file.open( IO_WriteOnly );
00151 if ( ok )
00152 file.close();
00153
00154 return ok;
00155 } else {
00156 QFileInfo fileInfo( mFileName );
00157 if ( readOnly() || !fileInfo.isWritable() ) {
00158 if ( !file.open( IO_ReadOnly ) )
00159 return false;
00160 } else {
00161 if ( !file.open( IO_ReadWrite ) )
00162 return false;
00163 }
00164
00165 if ( file.size() == 0 ) {
00166 file.close();
00167 #if 0
00168 kdDebug() << "File size is zero. Evaluating backups" << endl;
00169 for (int i=0; i!=20; i++)
00170 {
00171 QFile backup( mFileName + "__" + QString::number(i) );
00172 kdDebug() << "Evaluating" << backup.name() << " size: " << backup.size() << endl;
00173 if ( backup.size() != 0 )
00174 {
00175 kdDebug() << "Restoring backup " << i << endl;
00176 const QString src = mFileName + "__" + QString::number(i);
00177 const QString dest = mFileName;
00178
00179
00180 QFile::remove( dest );
00181
00182
00183 if ( backup.open( IO_ReadOnly ) ) {
00184 const QByteArray data = backup.readAll();
00185
00186 QFile out( dest );
00187 if ( out.open( IO_WriteOnly ) ) {
00188 out.writeBlock( data );
00189 out.close();
00190 }
00191
00192 backup.close();
00193 }
00194 return true;
00195 }
00196 }
00197 #endif
00198 return true;
00199 }
00200
00201 bool ok = mFormat->checkFormat( &file );
00202 file.close();
00203
00204 return ok;
00205 }
00206 }
00207
00208 void ResourceFile::doClose()
00209 {
00210 }
00211
00212 bool ResourceFile::load()
00213 {
00214 kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
00215
00216 mAsynchronous = false;
00217
00218 QFile file( mFileName );
00219 if ( !file.open( IO_ReadOnly ) ) {
00220 addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) );
00221 return false;
00222 }
00223
00224 clear();
00225
00226 return mFormat->loadAll( addressBook(), this, &file );
00227 }
00228
00229 bool ResourceFile::asyncLoad()
00230 {
00231 kdDebug(5700) << "ResourceFile::asyncLoad()" << endl;
00232
00233 mAsynchronous = true;
00234
00235 bool ok = load();
00236
00237 if ( !ok )
00238 emitLoadingError();
00239 else
00240 emitLoadingFinished();
00241
00242 return true;
00243 }
00244
00245 bool ResourceFile::save( Ticket * )
00246 {
00247 kdDebug(5700) << "ResourceFile::save()" << endl;
00248
00249
00250 QString extension = "_" + QString::number( QDate::currentDate().dayOfWeek() );
00251 #if 0
00252
00253 QFile file( mFileName + "__0" );
00254 if ( file.size() != 0 ) {
00255 const QString last = mFileName + "__20";
00256 kdDebug() << "deleting " << last << endl;
00257
00258 QFile::remove( last );
00259
00260 for (int i=19; i>=0; i--)
00261 {
00262 const QString src = mFileName + "__" + QString::number(i);
00263 const QString dest = mFileName + "__" + QString::number(i+1);
00264 kdDebug() << "moving " << src << " -> " << dest << endl;
00265
00266
00267 QFile in( src );
00268 if ( in.open( IO_ReadOnly ) ) {
00269 const QByteArray data = in.readAll();
00270
00271 QFile out( dest );
00272 if ( out.open( IO_WriteOnly ) ) {
00273 out.writeBlock( data );
00274 out.close();
00275 }
00276
00277 in.close();
00278 }
00279
00280
00281 QFile::remove( src );
00282 }
00283 } else
00284 kdDebug() << "Not starting logrotate __0 is 0 bytes." << endl;
00285
00286 QString extension = "__0";
00287 #endif
00288 (void) KSaveFile::backupFile( mFileName, QString::null ,
00289 extension );
00290
00291 mDirWatch.stopScan();
00292
00293 KSaveFile saveFile( mFileName );
00294 bool ok = false;
00295
00296 if ( saveFile.status() == 0 && saveFile.file() ) {
00297 mFormat->saveAll( addressBook(), this, saveFile.file() );
00298 ok = saveFile.close();
00299 }
00300
00301 if ( !ok ) {
00302 saveFile.abort();
00303 addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00304 }
00305
00306 mDirWatch.startScan();
00307
00308 return ok;
00309 }
00310
00311 bool ResourceFile::asyncSave( Ticket *ticket )
00312 {
00313 kdDebug(5700) << "ResourceFile::asyncSave()" << endl;
00314
00315 bool ok = save( ticket );
00316
00317 if ( !ok )
00318 QTimer::singleShot( 0, this, SLOT( emitSavingError() ) );
00319 else
00320 QTimer::singleShot( 0, this, SLOT( emitSavingFinished() ) );
00321
00322 return ok;
00323 }
00324
00325 void ResourceFile::setFileName( const QString &fileName )
00326 {
00327 mDirWatch.stopScan();
00328 if ( mDirWatch.contains( mFileName ) )
00329 mDirWatch.removeFile( mFileName );
00330
00331 mFileName = fileName;
00332
00333 mDirWatch.addFile( mFileName );
00334 mDirWatch.startScan();
00335 }
00336
00337 QString ResourceFile::fileName() const
00338 {
00339 return mFileName;
00340 }
00341
00342 void ResourceFile::setFormat( const QString &format )
00343 {
00344 mFormatName = format;
00345 delete mFormat;
00346
00347 FormatFactory *factory = FormatFactory::self();
00348 mFormat = factory->format( mFormatName );
00349 }
00350
00351 QString ResourceFile::format() const
00352 {
00353 return mFormatName;
00354 }
00355
00356 void ResourceFile::fileChanged()
00357 {
00358 kdDebug(5700) << "ResourceFile::fileChanged(): " << mFileName << endl;
00359
00360 if ( !addressBook() )
00361 return;
00362
00363 if ( mAsynchronous )
00364 asyncLoad();
00365 else {
00366 load();
00367 kdDebug() << "addressBookChanged() " << endl;
00368 addressBook()->emitAddressBookChanged();
00369 }
00370 }
00371
00372 void ResourceFile::removeAddressee( const Addressee &addr )
00373 {
00374 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/photos/" ) + addr.uid() ) );
00375 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/logos/" ) + addr.uid() ) );
00376 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) );
00377
00378 mAddrMap.erase( addr.uid() );
00379 }
00380
00381 void ResourceFile::emitSavingFinished()
00382 {
00383 emit savingFinished( this );
00384 }
00385
00386 void ResourceFile::emitSavingError()
00387 {
00388 emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00389 }
00390
00391 void ResourceFile::emitLoadingFinished()
00392 {
00393 emit loadingFinished( this );
00394 }
00395
00396 void ResourceFile::emitLoadingError()
00397 {
00398 emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mFileName ) );
00399 }
00400
00401 #include "resourcefile.moc"
|