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(), QLatin1String( "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 = QLatin1String( "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();
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 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() << "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();
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();
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();
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 tempFile.flush();
00245 }
00246
00247 if ( !ok ) {
00248 addressBook()->error( i18n( "Unable to save file '%1'.", tempFile.fileName() ) );
00249 return false;
00250 }
00251
00252 ok = KIO::NetAccess::upload( tempFile.fileName(), mUrl, 0 );
00253 if ( !ok ) {
00254 addressBook()->error( i18n( "Unable to upload to '%1'.", mUrl.prettyUrl() ) );
00255 }
00256
00257 return ok;
00258 }
00259
00260 bool ResourceNet::asyncSave( Ticket *ticket )
00261 {
00262 Q_UNUSED( ticket );
00263 kDebug();
00264
00265 if ( d->mIsSaving ) {
00266 abortAsyncSaving();
00267 }
00268
00269 if ( d->mIsLoading ) {
00270 kWarning() << "Aborted asyncSave() because we're still loading!";
00271 return false;
00272 }
00273
00274 bool ok = createLocalTempFile();
00275 if ( ok ) {
00276 saveToFile( mTempFile );
00277 mTempFile->flush();
00278 }
00279
00280 if ( !ok ) {
00281 emit savingError( this, i18n( "Unable to save file '%1'.", mTempFile->fileName() ) );
00282 deleteLocalTempFile();
00283 return false;
00284 }
00285
00286 KUrl src;
00287 src.setPath( mTempFile->fileName() );
00288
00289 KIO::Scheduler::checkSlaveOnHold( true );
00290 d->mIsSaving = true;
00291 d->mSaveJob = KIO::file_copy( src, mUrl, -1, KIO::Overwrite | KIO::HideProgressInfo );
00292 connect( d->mSaveJob, SIGNAL( result( KJob* ) ),
00293 this, SLOT( uploadFinished( KJob* ) ) );
00294
00295 return true;
00296 }
00297
00298 bool ResourceNet::createLocalTempFile()
00299 {
00300 deleteStaleTempFile();
00301 mTempFile = new KTemporaryFile();
00302 return mTempFile->open();
00303 }
00304
00305 void ResourceNet::deleteStaleTempFile()
00306 {
00307 if ( hasTempFile() ) {
00308 kDebug() << "stale temp file detected" << mTempFile->fileName();
00309 deleteLocalTempFile();
00310 }
00311 }
00312
00313 void ResourceNet::deleteLocalTempFile()
00314 {
00315 delete mTempFile;
00316 mTempFile = 0;
00317 }
00318
00319 void ResourceNet::saveToFile( QFile *file )
00320 {
00321 mFormat->saveAll( addressBook(), this, file );
00322 }
00323
00324 void ResourceNet::setUrl( const KUrl &url )
00325 {
00326 mUrl = url;
00327 }
00328
00329 KUrl ResourceNet::url() const
00330 {
00331 return mUrl;
00332 }
00333
00334 void ResourceNet::setFormat( const QString &name )
00335 {
00336 mFormatName = name;
00337 if ( mFormat ) {
00338 delete mFormat;
00339 }
00340
00341 FormatFactory *factory = FormatFactory::self();
00342 mFormat = factory->format( mFormatName );
00343 }
00344
00345 QString ResourceNet::format() const
00346 {
00347 return mFormatName;
00348 }
00349
00350 void ResourceNet::downloadFinished( KJob *job )
00351 {
00352 Q_UNUSED( job );
00353 kDebug();
00354
00355 d->mIsLoading = false;
00356
00357 if ( !hasTempFile() ) {
00358 emit loadingError( this, i18n( "Download failed, could not create temporary file" ) );
00359 return;
00360 }
00361
00362 QFile file( mTempFile->fileName() );
00363 if ( file.open( QIODevice::ReadOnly ) ) {
00364 if ( clearAndLoad( &file ) ) {
00365 emit loadingFinished( this );
00366 } else {
00367 emit loadingError( this, i18n( "Problems during parsing file '%1'.",
00368 mTempFile->fileName() ) );
00369 }
00370 } else {
00371 emit loadingError( this, i18n( "Unable to open file '%1'.",
00372 mTempFile->fileName() ) );
00373 }
00374
00375 deleteLocalTempFile();
00376 }
00377
00378 void ResourceNet::uploadFinished( KJob *job )
00379 {
00380 kDebug();
00381
00382 d->mIsSaving = false;
00383
00384 if ( job->error() ) {
00385 emit savingError( this, job->errorString() );
00386 } else {
00387 emit savingFinished( this );
00388 }
00389
00390 deleteLocalTempFile();
00391 }
00392
00393 #include "resourcenet.moc"