00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "resourcenet.h"
00022 #include "resourcenetconfig.h"
00023
00024 #include "kabc/addressbook.h"
00025 #include "kabc/formatfactory.h"
00026 #include "kabc/stdaddressbook.h"
00027
00028 #include <kio/netaccess.h>
00029 #include <kio/scheduler.h>
00030 #include <kdebug.h>
00031 #include <klocale.h>
00032 #include <ksavefile.h>
00033 #include <ktemporaryfile.h>
00034 #include <kurlrequester.h>
00035 #include <kconfiggroup.h>
00036
00037 #include <QtCore/QFile>
00038
00039 using namespace KABC;
00040
00041 class ResourceNet::ResourceNetPrivate
00042 {
00043 public:
00044 KIO::Job *mLoadJob;
00045 bool mIsLoading;
00046
00047 KIO::Job *mSaveJob;
00048 bool mIsSaving;
00049 };
00050
00051 ResourceNet::ResourceNet()
00052 : Resource(), mFormat( 0 ),
00053 mTempFile( 0 ),
00054 d( new ResourceNetPrivate )
00055 {
00056 init( KUrl(), "vcard" );
00057 }
00058
00059 ResourceNet::ResourceNet( const KConfigGroup &group )
00060 : Resource( group ), mFormat( 0 ),
00061 mTempFile( 0 ),
00062 d( new ResourceNetPrivate )
00063 {
00064 init( KUrl( group.readPathEntry( "NetUrl", QString() ) ), group.readEntry( "NetFormat" ) );
00065 }
00066
00067 ResourceNet::ResourceNet( const KUrl &url, const QString &format )
00068 : Resource(), mFormat( 0 ),
00069 mTempFile( 0 ),
00070 d( new ResourceNetPrivate )
00071 {
00072 init( url, format );
00073 }
00074
00075 void ResourceNet::init( const KUrl &url, const QString &format )
00076 {
00077 d->mLoadJob = 0;
00078 d->mIsLoading = false;
00079 d->mSaveJob = 0;
00080 d->mIsSaving = false;
00081
00082 mFormatName = format;
00083
00084 FormatFactory *factory = FormatFactory::self();
00085 mFormat = factory->format( mFormatName );
00086 if ( !mFormat ) {
00087 mFormatName = "vcard";
00088 mFormat = factory->format( mFormatName );
00089 }
00090
00091 setUrl( url );
00092 }
00093
00094 ResourceNet::~ResourceNet()
00095 {
00096 if ( d->mIsLoading ) {
00097 d->mLoadJob->kill();
00098 }
00099 if ( d->mIsSaving ) {
00100 d->mSaveJob->kill();
00101 }
00102
00103 delete d;
00104 d = 0;
00105
00106 delete mFormat;
00107 mFormat = 0;
00108
00109 deleteLocalTempFile();
00110 }
00111
00112 void ResourceNet::writeConfig( KConfigGroup &group )
00113 {
00114 Resource::writeConfig( group );
00115
00116 group.writePathEntry( "NetUrl", mUrl.url() );
00117 group.writeEntry( "NetFormat", mFormatName );
00118 }
00119
00120 Ticket *ResourceNet::requestSaveTicket()
00121 {
00122 kDebug(5700) << "ResourceNet::requestSaveTicket()";
00123
00124 return createTicket( this );
00125 }
00126
00127 void ResourceNet::releaseSaveTicket( Ticket *ticket )
00128 {
00129 delete ticket;
00130 }
00131
00132 bool ResourceNet::doOpen()
00133 {
00134 return true;
00135 }
00136
00137 void ResourceNet::doClose()
00138 {
00139 }
00140
00141 bool ResourceNet::load()
00142 {
00143 QString tempFile;
00144
00145 if ( !KIO::NetAccess::download( mUrl, tempFile, 0 ) ) {
00146 addressBook()->error( i18n( "Unable to download file '%1'.", mUrl.prettyUrl() ) );
00147 return false;
00148 }
00149
00150 QFile file( tempFile );
00151 if ( !file.open( QIODevice::ReadOnly ) ) {
00152 addressBook()->error( i18n( "Unable to open file '%1'.", tempFile ) );
00153 KIO::NetAccess::removeTempFile( tempFile );
00154 return false;
00155 }
00156
00157 bool result = clearAndLoad( &file );
00158 if ( !result ) {
00159 addressBook()->error( i18n( "Problems during parsing file '%1'.", tempFile ) );
00160 }
00161
00162 KIO::NetAccess::removeTempFile( tempFile );
00163
00164 return result;
00165 }
00166
00167 bool ResourceNet::clearAndLoad( QFile *file )
00168 {
00169 clear();
00170 return mFormat->loadAll( addressBook(), this, file );
00171 }
00172
00173 bool ResourceNet::asyncLoad()
00174 {
00175 if ( d->mIsLoading ) {
00176 abortAsyncLoading();
00177 }
00178
00179 if ( d->mIsSaving ) {
00180 kWarning(5700) << "Aborted asyncLoad() because we're still saving!";
00181 return false;
00182 }
00183
00184 bool ok = createLocalTempFile();
00185
00186 if ( !ok ) {
00187 emit loadingError( this, i18n( "Unable to open file '%1'.", mTempFile->fileName() ) );
00188 deleteLocalTempFile();
00189 return false;
00190 }
00191
00192 KUrl dest;
00193 dest.setPath( mTempFile->fileName() );
00194
00195 KIO::Scheduler::checkSlaveOnHold( true );
00196 d->mLoadJob = KIO::file_copy( mUrl, dest, -1, KIO::Overwrite | KIO::HideProgressInfo );
00197 d->mIsLoading = true;
00198 connect( d->mLoadJob, SIGNAL( result( KJob* ) ),
00199 this, SLOT( downloadFinished( KJob* ) ) );
00200
00201 return true;
00202 }
00203
00204 void ResourceNet::abortAsyncLoading()
00205 {
00206 kDebug(5700) << "ResourceNet::abortAsyncLoading()";
00207
00208 if ( d->mLoadJob ) {
00209 d->mLoadJob->kill();
00210 d->mLoadJob = 0;
00211 }
00212
00213 deleteLocalTempFile();
00214 d->mIsLoading = false;
00215 }
00216
00217 void ResourceNet::abortAsyncSaving()
00218 {
00219 kDebug(5700) << "ResourceNet::abortAsyncSaving()";
00220
00221 if ( d->mSaveJob ) {
00222 d->mSaveJob->kill();
00223 d->mSaveJob = 0;
00224 }
00225
00226 deleteLocalTempFile();
00227 d->mIsSaving = false;
00228 }
00229
00230 bool ResourceNet::save( Ticket *ticket )
00231 {
00232 Q_UNUSED( ticket );
00233 kDebug(5700) << "ResourceNet::save()";
00234
00235 if ( d->mIsSaving ) {
00236 abortAsyncSaving();
00237 }
00238
00239 KTemporaryFile tempFile;
00240 bool ok = tempFile.open();
00241
00242 if ( ok ) {
00243 saveToFile( &tempFile );
00244 }
00245
00246 if ( !ok ) {
00247 addressBook()->error( i18n( "Unable to save file '%1'.", tempFile.fileName() ) );
00248 return false;
00249 }
00250
00251 ok = KIO::NetAccess::upload( tempFile.fileName(), mUrl, 0 );
00252 if ( !ok ) {
00253 addressBook()->error( i18n( "Unable to upload to '%1'.", mUrl.prettyUrl() ) );
00254 }
00255
00256 return ok;
00257 }
00258
00259 bool ResourceNet::asyncSave( Ticket *ticket )
00260 {
00261 Q_UNUSED( ticket );
00262 kDebug(5700) << "ResourceNet::asyncSave()";
00263
00264 if ( d->mIsSaving ) {
00265 abortAsyncSaving();
00266 }
00267
00268 if ( d->mIsLoading ) {
00269 kWarning(5700) << "Aborted asyncSave() because we're still loading!";
00270 return false;
00271 }
00272
00273 bool ok = createLocalTempFile();
00274 if ( ok ) {
00275 saveToFile( mTempFile );
00276 }
00277
00278 if ( !ok ) {
00279 emit savingError( this, i18n( "Unable to save file '%1'.", mTempFile->fileName() ) );
00280 deleteLocalTempFile();
00281 return false;
00282 }
00283
00284 KUrl src;
00285 src.setPath( mTempFile->fileName() );
00286
00287 KIO::Scheduler::checkSlaveOnHold( true );
00288 d->mIsSaving = true;
00289 d->mSaveJob = KIO::file_copy( src, mUrl, -1, KIO::Overwrite | KIO::HideProgressInfo );
00290 connect( d->mSaveJob, SIGNAL( result( KJob* ) ),
00291 this, SLOT( uploadFinished( KJob* ) ) );
00292
00293 return true;
00294 }
00295
00296 bool ResourceNet::createLocalTempFile()
00297 {
00298 deleteStaleTempFile();
00299 mTempFile = new KTemporaryFile();
00300 return mTempFile->open();
00301 }
00302
00303 void ResourceNet::deleteStaleTempFile()
00304 {
00305 if ( hasTempFile() ) {
00306 kDebug(5700) << "stale temp file detected" << mTempFile->fileName();
00307 deleteLocalTempFile();
00308 }
00309 }
00310
00311 void ResourceNet::deleteLocalTempFile()
00312 {
00313 delete mTempFile;
00314 mTempFile = 0;
00315 }
00316
00317 void ResourceNet::saveToFile( QFile *file )
00318 {
00319 mFormat->saveAll( addressBook(), this, file );
00320 }
00321
00322 void ResourceNet::setUrl( const KUrl &url )
00323 {
00324 mUrl = url;
00325 }
00326
00327 KUrl ResourceNet::url() const
00328 {
00329 return mUrl;
00330 }
00331
00332 void ResourceNet::setFormat( const QString &name )
00333 {
00334 mFormatName = name;
00335 if ( mFormat ) {
00336 delete mFormat;
00337 }
00338
00339 FormatFactory *factory = FormatFactory::self();
00340 mFormat = factory->format( mFormatName );
00341 }
00342
00343 QString ResourceNet::format() const
00344 {
00345 return mFormatName;
00346 }
00347
00348 void ResourceNet::downloadFinished( KJob *job )
00349 {
00350 Q_UNUSED( job );
00351 kDebug(5700) << "ResourceNet::downloadFinished()";
00352
00353 d->mIsLoading = false;
00354
00355 if ( !hasTempFile() ) {
00356 emit loadingError( this, i18n( "Download failed, could not create temporary file" ) );
00357 return;
00358 }
00359
00360 QFile file( mTempFile->fileName() );
00361 if ( file.open( QIODevice::ReadOnly ) ) {
00362 if ( clearAndLoad( &file ) ) {
00363 emit loadingFinished( this );
00364 } else {
00365 emit loadingError( this, i18n( "Problems during parsing file '%1'.",
00366 mTempFile->fileName() ) );
00367 }
00368 } else {
00369 emit loadingError( this, i18n( "Unable to open file '%1'.",
00370 mTempFile->fileName() ) );
00371 }
00372
00373 deleteLocalTempFile();
00374 }
00375
00376 void ResourceNet::uploadFinished( KJob *job )
00377 {
00378 kDebug(5700) << "ResourceFile::uploadFinished()";
00379
00380 d->mIsSaving = false;
00381
00382 if ( job->error() ) {
00383 emit savingError( this, job->errorString() );
00384 } else {
00385 emit savingFinished( this );
00386 }
00387
00388 deleteLocalTempFile();
00389 }
00390
00391 #include "resourcenet.moc"