tdeabc
resourcefile.cpp
00001
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 <tqfile.h>
00029 #include <tqfileinfo.h>
00030 #include <tqtimer.h>
00031
00032 #include <tdeapplication.h>
00033 #include <tdeconfig.h>
00034 #include <kdebug.h>
00035 #include <tdeio/scheduler.h>
00036 #include <tdelocale.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 TDEABC;
00048
00049 ResourceFile::ResourceFile( const TDEConfig *config )
00050 : Resource( config ), mFormat( 0 ),
00051 mAsynchronous( false )
00052 {
00053 TQString 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 TQString &fileName,
00067 const TQString &formatName )
00068 : Resource( 0 ), mFormat( 0 ),
00069 mAsynchronous( false )
00070 {
00071 init( fileName, formatName );
00072 }
00073
00074 void ResourceFile::init( const TQString &fileName, const TQString &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, TQT_SIGNAL( dirty(const TQString&) ), TQT_SLOT( fileChanged() ) );
00087 connect( &mDirWatch, TQT_SIGNAL( created(const TQString&) ), TQT_SLOT( fileChanged() ) );
00088 connect( &mDirWatch, TQT_SIGNAL( deleted(const TQString&) ), TQT_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( TDEConfig *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 TQFile 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 TQFileInfo 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 kdDebug(5700) << "File size is zero. Evaluating backups" << endl;
00168 for (int i=0; i!=20; i++)
00169 {
00170 TQFile backup( mFileName + "__" + TQString::number(i) );
00171 kdDebug(5700) << "Evaluating" << backup.name() << " size: " << backup.size() << endl;
00172 if ( backup.size() != 0 )
00173 {
00174 kdDebug(5700) << "Restoring backup " << i << endl;
00175 const TQString src = mFileName + "__" + TQString::number(i);
00176 const TQString dest = mFileName;
00177
00178
00179 if ( ! backup.open( IO_ReadOnly ) ) {
00180
00181 kdDebug(5700) << "can not open source for reading " << src << endl;
00182 continue;
00183 }
00184
00185
00186 TQFile::remove( dest );
00187
00188 TQString text;
00189 TQTextStream instream( &backup );
00190 instream.setEncoding( TQTextStream::UnicodeUTF8 );
00191 text = instream.read();
00192 backup.close();
00193
00194 TQFile out( dest );
00195 if ( ! out.open( IO_WriteOnly ) ) {
00196
00197 kdDebug(5700) << "can not open target for writing " << dest << endl;
00198 continue;
00199 }
00200 TQTextStream outstream( &out );
00201 outstream.setEncoding( TQTextStream::UnicodeUTF8 );
00202 outstream << text;
00203 out.close();
00204
00205 return true;
00206 }
00207 }
00208 return true;
00209 }
00210
00211 bool ok = mFormat->checkFormat( &file );
00212 file.close();
00213
00214 return ok;
00215 }
00216 }
00217
00218 void ResourceFile::doClose()
00219 {
00220 }
00221
00222 bool ResourceFile::load()
00223 {
00224 kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
00225
00226 mAsynchronous = false;
00227
00228 TQFile file( mFileName );
00229 if ( !file.open( IO_ReadOnly ) ) {
00230 addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) );
00231 return false;
00232 }
00233
00234 clear();
00235
00236 return mFormat->loadAll( addressBook(), this, &file );
00237 }
00238
00239 bool ResourceFile::asyncLoad()
00240 {
00241 kdDebug(5700) << "ResourceFile::asyncLoad()" << endl;
00242
00243 mAsynchronous = true;
00244
00245 bool ok = load();
00246
00247 if ( !ok )
00248 emitLoadingError();
00249 else
00250 emitLoadingFinished();
00251
00252 return true;
00253 }
00254
00255 bool ResourceFile::save( Ticket * )
00256 {
00257 kdDebug(5700) << "ResourceFile::save()" << endl;
00258
00259
00260 TQFile file( mFileName + "__0" );
00261 if ( file.size() != 0 ) {
00262 const TQString last = mFileName + "__20";
00263 kdDebug(5700) << "deleting " << last << endl;
00264
00265 TQFile::remove( last );
00266
00267 for (int i=19; i>=0; i--)
00268 {
00269 const TQString src = mFileName + "__" + TQString::number(i);
00270 const TQString dest = mFileName + "__" + TQString::number(i+1);
00271 kdDebug() << "moving " << src << " -> " << dest << endl;
00272
00273
00274 TQFile in( src );
00275 if ( ! in.exists() )
00276 continue;
00277 if ( ! in.open( IO_ReadOnly ) ) {
00278
00279 kdDebug(5700) << "can not open source for reading " << src << endl;
00280 return false;
00281 }
00282 TQString text;
00283 TQTextStream instream( &in );
00284
00285 instream.setEncoding( TQTextStream::UnicodeUTF8 );
00286 text = instream.read();
00287 in.close();
00288
00289 TQFile out( dest );
00290 if ( ! out.open( IO_WriteOnly ) ) {
00291
00292 kdDebug(5700) << "can not open target for writing " << dest << endl;
00293 return false;
00294 }
00295 TQTextStream outstream( &out );
00296 outstream.setEncoding( TQTextStream::UnicodeUTF8 );
00297 outstream << text;
00298 out.close();
00299
00300
00301 TQFile::remove( src );
00302 }
00303 } else
00304 kdDebug(5700) << "Not starting logrotate __0 is 0 bytes." << endl;
00305
00306 TQString extension = "__0";
00307 (void) KSaveFile::backupFile( mFileName, TQString::null ,
00308 extension );
00309 mDirWatch.stopScan();
00310
00311 KSaveFile saveFile( mFileName );
00312 bool ok = false;
00313
00314 if ( saveFile.status() == 0 && saveFile.file() ) {
00315 mFormat->saveAll( addressBook(), this, saveFile.file() );
00316 ok = saveFile.close();
00317 }
00318
00319 if ( !ok ) {
00320 saveFile.abort();
00321 addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00322 }
00323
00324 mDirWatch.startScan();
00325
00326 return ok;
00327 }
00328
00329 bool ResourceFile::asyncSave( Ticket *ticket )
00330 {
00331 kdDebug(5700) << "ResourceFile::asyncSave()" << endl;
00332
00333 bool ok = save( ticket );
00334
00335 if ( !ok )
00336 TQTimer::singleShot( 0, this, TQT_SLOT( emitSavingError() ) );
00337 else
00338 TQTimer::singleShot( 0, this, TQT_SLOT( emitSavingFinished() ) );
00339
00340 return ok;
00341 }
00342
00343 void ResourceFile::setFileName( const TQString &fileName )
00344 {
00345 mDirWatch.stopScan();
00346 if ( mDirWatch.contains( mFileName ) )
00347 mDirWatch.removeFile( mFileName );
00348
00349 mFileName = fileName;
00350
00351 mDirWatch.addFile( mFileName );
00352 mDirWatch.startScan();
00353 }
00354
00355 TQString ResourceFile::fileName() const
00356 {
00357 return mFileName;
00358 }
00359
00360 void ResourceFile::setFormat( const TQString &format )
00361 {
00362 mFormatName = format;
00363 delete mFormat;
00364
00365 FormatFactory *factory = FormatFactory::self();
00366 mFormat = factory->format( mFormatName );
00367 }
00368
00369 TQString ResourceFile::format() const
00370 {
00371 return mFormatName;
00372 }
00373
00374 void ResourceFile::fileChanged()
00375 {
00376 kdDebug(5700) << "ResourceFile::fileChanged(): " << mFileName << endl;
00377
00378 if ( !addressBook() )
00379 return;
00380
00381 if ( mAsynchronous )
00382 asyncLoad();
00383 else {
00384 load();
00385 kdDebug() << "addressBookChanged() " << endl;
00386 addressBook()->emitAddressBookChanged();
00387 }
00388 }
00389
00390 void ResourceFile::removeAddressee( const Addressee &addr )
00391 {
00392 TQFile::remove( TQFile::encodeName( locateLocal( "data", "tdeabc/photos/" ) + addr.uid() ) );
00393 TQFile::remove( TQFile::encodeName( locateLocal( "data", "tdeabc/logos/" ) + addr.uid() ) );
00394 TQFile::remove( TQFile::encodeName( locateLocal( "data", "tdeabc/sounds/" ) + addr.uid() ) );
00395
00396 mAddrMap.erase( addr.uid() );
00397 }
00398
00399 void ResourceFile::emitSavingFinished()
00400 {
00401 emit savingFinished( this );
00402 }
00403
00404 void ResourceFile::emitSavingError()
00405 {
00406 emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00407 }
00408
00409 void ResourceFile::emitLoadingFinished()
00410 {
00411 emit loadingFinished( this );
00412 }
00413
00414 void ResourceFile::emitLoadingError()
00415 {
00416 emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mFileName ) );
00417 }
00418
00419 #include "resourcefile.moc"