00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <signal.h>
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <unistd.h>
00026
00027 #include <qfile.h>
00028 #include <qregexp.h>
00029 #include <qtimer.h>
00030
00031 #include <kapplication.h>
00032 #include <kconfig.h>
00033 #include <kdebug.h>
00034 #include <kio/scheduler.h>
00035 #include <klocale.h>
00036 #include <ksavefile.h>
00037 #include <kstandarddirs.h>
00038 #include <ktempfile.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 ), mLocalTempFile( 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 ), mLocalTempFile( 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 delete mLocalTempFile;
00100 mLocalTempFile = 0;
00101 }
00102
00103 void ResourceFile::writeConfig( KConfig *config )
00104 {
00105 Resource::writeConfig( config );
00106
00107 if ( mFileName == StdAddressBook::fileName() )
00108 config->deleteEntry( "FileName" );
00109 else
00110 config->writePathEntry( "FileName", mFileName );
00111
00112 config->writeEntry( "FileFormat", mFormatName );
00113 }
00114
00115 Ticket *ResourceFile::requestSaveTicket()
00116 {
00117 kdDebug(5700) << "ResourceFile::requestSaveTicket()" << endl;
00118
00119 if ( !addressBook() ) return 0;
00120
00121 delete mLock;
00122 mLock = new Lock( mFileName );
00123
00124 if ( mLock->lock() ) {
00125 addressBook()->emitAddressBookLocked();
00126 } else {
00127 addressBook()->error( mLock->error() );
00128 kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock file '"
00129 << mFileName << "': " << mLock->error() << endl;
00130 return 0;
00131 }
00132
00133 return createTicket( this );
00134 }
00135
00136 void ResourceFile::releaseSaveTicket( Ticket *ticket )
00137 {
00138 delete ticket;
00139
00140 delete mLock;
00141 mLock = 0;
00142
00143 addressBook()->emitAddressBookUnlocked();
00144 }
00145
00146 bool ResourceFile::doOpen()
00147 {
00148 QFile file( mFileName );
00149
00150 if ( !file.exists() ) {
00151
00152 bool ok = file.open( IO_WriteOnly );
00153 if ( ok )
00154 file.close();
00155
00156 return ok;
00157 } else {
00158 if ( readOnly() ) {
00159 if ( !file.open( IO_ReadOnly ) )
00160 return false;
00161 } else {
00162 if ( !file.open( IO_ReadWrite ) )
00163 return false;
00164 }
00165 if ( file.size() == 0 ) {
00166 file.close();
00167 return true;
00168 }
00169
00170 bool ok = mFormat->checkFormat( &file );
00171 file.close();
00172
00173 return ok;
00174 }
00175 }
00176
00177 void ResourceFile::doClose()
00178 {
00179 }
00180
00181 bool ResourceFile::load()
00182 {
00183 kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
00184
00185 mAsynchronous = false;
00186
00187 QFile file( mFileName );
00188 if ( !file.open( IO_ReadOnly ) ) {
00189 addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) );
00190 return false;
00191 }
00192
00193 return mFormat->loadAll( addressBook(), this, &file );
00194 }
00195
00196 bool ResourceFile::asyncLoad()
00197 {
00198 mAsynchronous = true;
00199
00200 if ( mLocalTempFile ) {
00201 kdDebug(5700) << "stale temp file detected " << mLocalTempFile->name() << endl;
00202 delete mLocalTempFile;
00203 }
00204
00205 mLocalTempFile = new KTempFile();
00206 mLocalTempFile->setAutoDelete( true );
00207 mTempFile = mLocalTempFile->name();
00208
00209 KURL dest, src;
00210 dest.setPath( mTempFile );
00211 src.setPath( mFileName );
00212
00213 KIO::Scheduler::checkSlaveOnHold( true );
00214 KIO::Job * job = KIO::file_copy( src, dest, -1, true, false, false );
00215 connect( job, SIGNAL( result( KIO::Job* ) ),
00216 this, SLOT( downloadFinished( KIO::Job* ) ) );
00217
00218 return true;
00219 }
00220
00221 bool ResourceFile::save( Ticket * )
00222 {
00223 kdDebug(5700) << "ResourceFile::save()" << endl;
00224
00225
00226 QString extension = "_" + QString::number( QDate::currentDate().dayOfWeek() );
00227 (void) KSaveFile::backupFile( mFileName, QString::null ,
00228 extension );
00229
00230 mDirWatch.stopScan();
00231 KSaveFile saveFile( mFileName );
00232 bool ok = false;
00233 if ( saveFile.status() == 0 && saveFile.file() )
00234 {
00235 mFormat->saveAll( addressBook(), this, saveFile.file() );
00236 ok = saveFile.close();
00237 }
00238
00239 if ( !ok )
00240 addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00241 mDirWatch.startScan();
00242
00243 return ok;
00244 }
00245
00246 bool ResourceFile::asyncSave( Ticket * )
00247 {
00248 QFile file( mTempFile );
00249
00250 if ( !file.open( IO_WriteOnly ) ) {
00251 emit savingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
00252 return false;
00253 }
00254
00255 mDirWatch.stopScan();
00256 mFormat->saveAll( addressBook(), this, &file );
00257 file.close();
00258
00259 KURL src, dest;
00260 src.setPath( mTempFile );
00261 dest.setPath( mFileName );
00262
00263 KIO::Scheduler::checkSlaveOnHold( true );
00264 KIO::Job * job = KIO::file_copy( src, dest, -1, true, false, false );
00265 connect( job, SIGNAL( result( KIO::Job* ) ),
00266 this, SLOT( uploadFinished( KIO::Job* ) ) );
00267
00268 return true;
00269 }
00270
00271 void ResourceFile::setFileName( const QString &fileName )
00272 {
00273 mDirWatch.stopScan();
00274 if ( mDirWatch.contains( mFileName ) )
00275 mDirWatch.removeFile( mFileName );
00276
00277 mFileName = fileName;
00278
00279 mDirWatch.addFile( mFileName );
00280 mDirWatch.startScan();
00281 }
00282
00283 QString ResourceFile::fileName() const
00284 {
00285 return mFileName;
00286 }
00287
00288 void ResourceFile::setFormat( const QString &format )
00289 {
00290 mFormatName = format;
00291 delete mFormat;
00292
00293 FormatFactory *factory = FormatFactory::self();
00294 mFormat = factory->format( mFormatName );
00295 }
00296
00297 QString ResourceFile::format() const
00298 {
00299 return mFormatName;
00300 }
00301
00302 void ResourceFile::fileChanged()
00303 {
00304 if ( !addressBook() )
00305 return;
00306
00307 clear();
00308 if ( mAsynchronous )
00309 asyncLoad();
00310 else {
00311 load();
00312 kdDebug() << "addressBookChanged() " << endl;
00313 addressBook()->emitAddressBookChanged();
00314 }
00315 }
00316
00317 void ResourceFile::removeAddressee( const Addressee &addr )
00318 {
00319 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/photos/" ) + addr.uid() ) );
00320 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/logos/" ) + addr.uid() ) );
00321 QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) );
00322
00323 mAddrMap.erase( addr.uid() );
00324 }
00325
00326 void ResourceFile::downloadFinished( KIO::Job* )
00327 {
00328 if ( !mLocalTempFile )
00329 emit loadingError( this, i18n( "Download failed in some way!" ) );
00330
00331 QFile file( mTempFile );
00332 if ( !file.open( IO_ReadOnly ) ) {
00333 emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
00334 return;
00335 }
00336
00337 if ( !mFormat->loadAll( addressBook(), this, &file ) )
00338 emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile ) );
00339 else
00340 emit loadingFinished( this );
00341 }
00342
00343 void ResourceFile::uploadFinished( KIO::Job *job )
00344 {
00345 if ( job->error() )
00346 emit savingError( this, job->errorString() );
00347 else
00348 emit savingFinished( this );
00349 mDirWatch.startScan();
00350 }
00351
00352 #include "resourcefile.moc"