resourcenet.cpp

00001 /*
00002     This file is part of libkabc.
00003     Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
00004 
00005     This library is free software; you can redistribute it and/or
00006     modify it under the terms of the GNU Library General Public
00007     License as published by the Free Software Foundation; either
00008     version 2 of the License, or (at your option) any later version.
00009 
00010     This library is distributed in the hope that it will be useful,
00011     but WITHOUT ANY WARRANTY; without even the implied warranty of
00012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013     Library General Public License for more details.
00014 
00015     You should have received a copy of the GNU Library General Public License
00016     along with this library; see the file COPYING.LIB.  If not, write to
00017     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include <qfile.h>
00022 
00023 #include <kdebug.h>
00024 #include <kio/netaccess.h>
00025 #include <kio/scheduler.h>
00026 #include <klocale.h>
00027 #include <ksavefile.h>
00028 #include <ktempfile.h>
00029 #include <kurlrequester.h>
00030 
00031 #include "addressbook.h"
00032 #include "formatfactory.h"
00033 #include "resourcenetconfig.h"
00034 #include "stdaddressbook.h"
00035 
00036 #include "resourcenet.h"
00037 
00038 using namespace KABC;
00039 
00040 class ResourceNet::ResourceNetPrivate
00041 {
00042   public:
00043     KIO::Job *mLoadJob;
00044     bool mIsLoading;
00045 
00046     KIO::Job *mSaveJob;
00047     bool mIsSaving;
00048 };
00049 
00050 ResourceNet::ResourceNet( const KConfig *config )
00051   : Resource( config ), mFormat( 0 ),
00052     mTempFile( 0 ),
00053     d( new ResourceNetPrivate )
00054 {
00055   if ( config ) {
00056     init( KURL( config->readPathEntry( "NetUrl" ) ), config->readEntry( "NetFormat" ) );
00057   } else {
00058     init( KURL(), "vcard" );
00059   }
00060 }
00061 
00062 ResourceNet::ResourceNet( const KURL &url, const QString &format )
00063   : Resource( 0 ), mFormat( 0 ),
00064     mTempFile( 0 ),
00065     d( new ResourceNetPrivate )
00066 {
00067   init( url, format );
00068 }
00069 
00070 void ResourceNet::init( const KURL &url, const QString &format )
00071 {
00072   d->mLoadJob = 0;
00073   d->mIsLoading = false;
00074   d->mSaveJob = 0;
00075   d->mIsSaving = false;
00076 
00077   mFormatName = format;
00078 
00079   FormatFactory *factory = FormatFactory::self();
00080   mFormat = factory->format( mFormatName );
00081   if ( !mFormat ) {
00082     mFormatName = "vcard";
00083     mFormat = factory->format( mFormatName );
00084   }
00085 
00086   setUrl( url );
00087 }
00088 
00089 ResourceNet::~ResourceNet()
00090 {
00091   if ( d->mIsLoading )
00092     d->mLoadJob->kill();
00093   if ( d->mIsSaving )
00094     d->mSaveJob->kill();
00095 
00096   delete d;
00097   d = 0;
00098 
00099   delete mFormat;
00100   mFormat = 0;
00101 
00102   deleteLocalTempFile();
00103 }
00104 
00105 void ResourceNet::writeConfig( KConfig *config )
00106 {
00107   Resource::writeConfig( config );
00108 
00109   config->writePathEntry( "NetUrl", mUrl.url() );
00110   config->writeEntry( "NetFormat", mFormatName );
00111 }
00112 
00113 Ticket *ResourceNet::requestSaveTicket()
00114 {
00115   kdDebug(5700) << "ResourceNet::requestSaveTicket()" << endl;
00116 
00117   return createTicket( this );
00118 }
00119 
00120 void ResourceNet::releaseSaveTicket( Ticket *ticket )
00121 {
00122   delete ticket;
00123 }
00124 
00125 bool ResourceNet::doOpen()
00126 {
00127   return true;
00128 }
00129 
00130 void ResourceNet::doClose()
00131 {
00132 }
00133 
00134 bool ResourceNet::load()
00135 {
00136   QString tempFile;
00137     
00138   if ( !KIO::NetAccess::download( mUrl, tempFile, 0 ) ) {
00139     addressBook()->error( i18n( "Unable to download file '%1'." ).arg( mUrl.prettyURL() ) );
00140     return false;
00141   }
00142 
00143   QFile file( tempFile );
00144   if ( !file.open( IO_ReadOnly ) ) {
00145     addressBook()->error( i18n( "Unable to open file '%1'." ).arg( tempFile ) );
00146     KIO::NetAccess::removeTempFile( tempFile );
00147     return false;
00148   }
00149 
00150   bool result = clearAndLoad( &file );
00151   if ( !result )
00152       addressBook()->error( i18n( "Problems during parsing file '%1'." ).arg( tempFile ) );
00153 
00154   KIO::NetAccess::removeTempFile( tempFile );
00155   
00156   return result;
00157 }
00158 
00159 bool ResourceNet::clearAndLoad( QFile *file )
00160 {
00161   clear();
00162   return mFormat->loadAll( addressBook(), this, file );
00163 }
00164 
00165 bool ResourceNet::asyncLoad()
00166 {
00167   if ( d->mIsLoading ) {
00168     abortAsyncLoading();
00169   }
00170 
00171   if (d->mIsSaving) {
00172     kdWarning(5700) << "Aborted asyncLoad() because we're still asyncSave()ing!" << endl;
00173     return false;
00174   }
00175   
00176   bool ok = createLocalTempFile();
00177   if ( ok )
00178     ok = mTempFile->close();
00179 
00180   if ( !ok ) {
00181     emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
00182     deleteLocalTempFile();
00183     return false;
00184   }
00185   
00186   KURL dest;
00187   dest.setPath( mTempFile->name() );
00188 
00189   KIO::Scheduler::checkSlaveOnHold( true );
00190   d->mLoadJob = KIO::file_copy( mUrl, dest, -1, true, false, false );
00191   d->mIsLoading = true;
00192   connect( d->mLoadJob, SIGNAL( result( KIO::Job* ) ),
00193            this, SLOT( downloadFinished( KIO::Job* ) ) );
00194 
00195   return true;
00196 }
00197 
00198 void ResourceNet::abortAsyncLoading()
00199 {
00200   kdDebug(5700) << "ResourceNet::abortAsyncLoading()" << endl;
00201 
00202   if ( d->mLoadJob ) {
00203     d->mLoadJob->kill(); // result not emitted
00204     d->mLoadJob = 0;
00205   }
00206 
00207   deleteLocalTempFile();
00208   d->mIsLoading = false;
00209 }
00210 
00211 void ResourceNet::abortAsyncSaving()
00212 {
00213   kdDebug(5700) << "ResourceNet::abortAsyncSaving()" << endl;
00214 
00215   if ( d->mSaveJob ) {
00216     d->mSaveJob->kill(); // result not emitted
00217     d->mSaveJob = 0;
00218   }
00219   
00220   deleteLocalTempFile();
00221   d->mIsSaving = false;
00222 }
00223 
00224 bool ResourceNet::save( Ticket* )
00225 {
00226   kdDebug(5700) << "ResourceNet::save()" << endl;
00227 
00228   if (d->mIsSaving) {
00229     abortAsyncSaving();
00230   }
00231 
00232   KTempFile tempFile;
00233   tempFile.setAutoDelete( true );
00234   bool ok = false;
00235   
00236   if ( tempFile.status() == 0 && tempFile.file() ) {
00237     saveToFile( tempFile.file() );
00238     ok = tempFile.close();
00239   }
00240   
00241   if ( !ok ) {
00242     addressBook()->error( i18n( "Unable to save file '%1'." ).arg( tempFile.name() ) );
00243     return false;
00244   }
00245 
00246   ok = KIO::NetAccess::upload( tempFile.name(), mUrl, 0 );
00247   if ( !ok )
00248     addressBook()->error( i18n( "Unable to upload to '%1'." ).arg( mUrl.prettyURL() ) );
00249   
00250   return ok;
00251 }
00252 
00253 bool ResourceNet::asyncSave( Ticket* )
00254 {
00255   kdDebug(5700) << "ResourceNet::asyncSave()" << endl;
00256 
00257   if (d->mIsSaving) {
00258     abortAsyncSaving();
00259   }
00260 
00261   if (d->mIsLoading) {
00262     kdWarning(5700) << "Aborted asyncSave() because we're still asyncLoad()ing!" << endl;
00263     return false;
00264   }
00265   
00266   bool ok = createLocalTempFile();
00267   if ( ok ) {
00268     saveToFile( mTempFile->file() );
00269     ok = mTempFile->close();
00270   }
00271   
00272   if ( !ok ) {
00273     emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mTempFile->name() ) );
00274     deleteLocalTempFile();
00275     return false;
00276   }
00277 
00278   KURL src;
00279   src.setPath( mTempFile->name() );
00280 
00281   KIO::Scheduler::checkSlaveOnHold( true );
00282   d->mIsSaving = true;
00283   d->mSaveJob = KIO::file_copy( src, mUrl, -1, true, false, false );
00284   connect( d->mSaveJob, SIGNAL( result( KIO::Job* ) ),
00285            this, SLOT( uploadFinished( KIO::Job* ) ) );
00286 
00287   return true;
00288 }
00289 
00290 bool ResourceNet::createLocalTempFile()
00291 {
00292   deleteStaleTempFile();
00293   mTempFile = new KTempFile();
00294   mTempFile->setAutoDelete( true );
00295   return mTempFile->status() == 0;
00296 }
00297 
00298 void ResourceNet::deleteStaleTempFile()
00299 {
00300   if ( hasTempFile() ) {
00301     kdDebug(5700) << "stale temp file detected " << mTempFile->name() << endl;
00302     deleteLocalTempFile();
00303   }
00304 }
00305 
00306 void ResourceNet::deleteLocalTempFile()
00307 {
00308   delete mTempFile;
00309   mTempFile = 0;
00310 }
00311 
00312 void ResourceNet::saveToFile( QFile *file )
00313 {
00314   mFormat->saveAll( addressBook(), this, file );
00315 }
00316 
00317 void ResourceNet::setUrl( const KURL &url )
00318 {
00319   mUrl = url;
00320 }
00321 
00322 KURL ResourceNet::url() const
00323 {
00324   return mUrl;
00325 }
00326 
00327 void ResourceNet::setFormat( const QString &name )
00328 {
00329   mFormatName = name;
00330   if ( mFormat )
00331     delete mFormat;
00332 
00333   FormatFactory *factory = FormatFactory::self();
00334   mFormat = factory->format( mFormatName );
00335 }
00336 
00337 QString ResourceNet::format() const
00338 {
00339   return mFormatName;
00340 }
00341 
00342 void ResourceNet::downloadFinished( KIO::Job* )
00343 {
00344   kdDebug(5700) << "ResourceNet::downloadFinished()" << endl;
00345 
00346   d->mIsLoading = false;
00347 
00348   if ( !hasTempFile() || mTempFile->status() != 0 ) {
00349     emit loadingError( this, i18n( "Download failed in some way!" ) );
00350     return;
00351   }
00352 
00353   QFile file( mTempFile->name() );
00354   if ( file.open( IO_ReadOnly ) ) {
00355     if ( clearAndLoad( &file ) )
00356       emit loadingFinished( this );
00357     else
00358       emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile->name() ) );
00359   }
00360   else {
00361     emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile->name() ) );
00362   }
00363 
00364   deleteLocalTempFile();
00365 }
00366 
00367 void ResourceNet::uploadFinished( KIO::Job *job )
00368 {
00369   kdDebug(5700) << "ResourceFile::uploadFinished()" << endl;
00370 
00371   d->mIsSaving = false;
00372 
00373   if ( job->error() )
00374     emit savingError( this, job->errorString() );
00375   else
00376     emit savingFinished( this );
00377 
00378   deleteLocalTempFile();
00379 }
00380 
00381 #include "resourcenet.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys