kabc Library API Documentation

resourcefile.cpp

00001 /*
00002     This file is part of libkabc.
00003 
00004     Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
00005 
00006     This library is free software; you can redistribute it and/or
00007     modify it under the terms of the GNU Library General Public
00008     License as published by the Free Software Foundation; either
00009     version 2 of the License, or (at your option) any later version.
00010 
00011     This library is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     Library General Public License for more details.
00015 
00016     You should have received a copy of the GNU Library General Public License
00017     along with this library; see the file COPYING.LIB.  If not, write to
00018     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00019     Boston, MA 02111-1307, USA.
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 class ResourceFile::ResourceFilePrivate
00050 {
00051   public:
00052     KIO::Job *mLoadJob;
00053     bool mIsLoading;
00054 
00055     KIO::Job *mSaveJob;
00056     bool mIsSaving;
00057 };
00058 
00059 ResourceFile::ResourceFile( const KConfig *config )
00060   : Resource( config ), mFormat( 0 ), mLocalTempFile( 0 ),
00061     mAsynchronous( false ), d( new ResourceFilePrivate )
00062 {
00063   QString fileName, formatName;
00064 
00065   if ( config ) {
00066     fileName = config->readPathEntry( "FileName", StdAddressBook::fileName() );
00067     formatName = config->readEntry( "FileFormat", "vcard" );
00068   } else {
00069     fileName = StdAddressBook::fileName();
00070     formatName = "vcard";
00071   }
00072 
00073   init( fileName, formatName );
00074 }
00075 
00076 ResourceFile::ResourceFile( const QString &fileName,
00077                             const QString &formatName )
00078   : Resource( 0 ), mFormat( 0 ), mLocalTempFile( 0 ),
00079     mAsynchronous( false ), d( new ResourceFilePrivate )
00080 {
00081   init( fileName, formatName );
00082 }
00083 
00084 void ResourceFile::init( const QString &fileName, const QString &formatName )
00085 {
00086   d->mLoadJob = 0;
00087   d->mIsLoading = false;
00088   d->mSaveJob = 0;
00089   d->mIsSaving = false;
00090 
00091   mFormatName = formatName;
00092 
00093   FormatFactory *factory = FormatFactory::self();
00094   mFormat = factory->format( mFormatName );
00095 
00096   if ( !mFormat ) {
00097     mFormatName = "vcard";
00098     mFormat = factory->format( mFormatName );
00099   }
00100 
00101   connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( fileChanged() ) );
00102   connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( fileChanged() ) );
00103   connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( fileChanged() ) );
00104 
00105   setFileName( fileName );
00106 
00107   mLock = 0;
00108 }
00109 
00110 ResourceFile::~ResourceFile()
00111 {
00112   if ( d->mIsLoading )
00113     d->mLoadJob->kill();
00114   if ( d->mIsSaving )
00115     d->mSaveJob->kill();
00116 
00117   delete d;
00118   d = 0;
00119   delete mFormat;
00120   mFormat = 0;
00121   delete mLocalTempFile;
00122   mLocalTempFile = 0;
00123 }
00124 
00125 void ResourceFile::writeConfig( KConfig *config )
00126 {
00127   Resource::writeConfig( config );
00128 
00129   if ( mFileName == StdAddressBook::fileName() )
00130     config->deleteEntry( "FileName" );
00131   else
00132     config->writePathEntry( "FileName", mFileName );
00133 
00134   config->writeEntry( "FileFormat", mFormatName );
00135 }
00136 
00137 Ticket *ResourceFile::requestSaveTicket()
00138 {
00139   kdDebug(5700) << "ResourceFile::requestSaveTicket()" << endl;
00140 
00141   if ( !addressBook() ) return 0;
00142 
00143   delete mLock;
00144   mLock = new Lock( mFileName );
00145 
00146   if ( mLock->lock() ) {
00147     addressBook()->emitAddressBookLocked();
00148   } else {
00149     addressBook()->error( mLock->error() );
00150     kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock file '"
00151                   << mFileName << "': " << mLock->error() << endl;
00152     return 0;
00153   }
00154 
00155   return createTicket( this );
00156 }
00157 
00158 void ResourceFile::releaseSaveTicket( Ticket *ticket )
00159 {
00160   delete ticket;
00161 
00162   delete mLock;
00163   mLock = 0;
00164 
00165   addressBook()->emitAddressBookUnlocked();
00166 }
00167 
00168 bool ResourceFile::doOpen()
00169 {
00170   QFile file( mFileName );
00171 
00172   if ( !file.exists() ) {
00173     // try to create the file
00174     bool ok = file.open( IO_WriteOnly );
00175     if ( ok )
00176       file.close();
00177 
00178     return ok;
00179   } else {
00180     if ( readOnly() ) {
00181       if ( !file.open( IO_ReadOnly ) )
00182         return false;
00183     } else {
00184       if ( !file.open( IO_ReadWrite ) )
00185         return false;
00186     }
00187 
00188     if ( file.size() == 0 ) {
00189       file.close();
00190       return true;
00191     }
00192 
00193     bool ok = mFormat->checkFormat( &file );
00194     file.close();
00195 
00196     return ok;
00197   }
00198 }
00199 
00200 void ResourceFile::doClose()
00201 {
00202 }
00203 
00204 bool ResourceFile::load()
00205 {
00206   kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
00207 
00208   mAsynchronous = false;
00209 
00210   QFile file( mFileName );
00211   if ( !file.open( IO_ReadOnly ) ) {
00212     addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) );
00213     return false;
00214   }
00215 
00216   return mFormat->loadAll( addressBook(), this, &file );
00217 }
00218 
00219 bool ResourceFile::asyncLoad()
00220 {
00221   mAsynchronous = true;
00222 
00223   if ( mLocalTempFile ) {
00224     kdDebug(5700) << "stale temp file detected " << mLocalTempFile->name() << endl;
00225     delete mLocalTempFile;
00226   }
00227 
00228   mLocalTempFile = new KTempFile();
00229   mLocalTempFile->setAutoDelete( true );
00230   mTempFile = mLocalTempFile->name();
00231 
00232   KURL dest, src;
00233   dest.setPath( mTempFile );
00234   src.setPath( mFileName );
00235 
00236   KIO::Scheduler::checkSlaveOnHold( true );
00237   d->mLoadJob = KIO::file_copy( src, dest, -1, true, false, false );
00238   d->mIsLoading = true;
00239   connect( d->mLoadJob, SIGNAL( result( KIO::Job* ) ),
00240            this, SLOT( downloadFinished( KIO::Job* ) ) );
00241 
00242   return true;
00243 }
00244 
00245 bool ResourceFile::save( Ticket * )
00246 {
00247   kdDebug(5700) << "ResourceFile::save()" << endl;
00248 
00249   // create backup file
00250   QString extension = "_" + QString::number( QDate::currentDate().dayOfWeek() );
00251   (void) KSaveFile::backupFile( mFileName, QString::null /*directory*/,
00252                                 extension );
00253 
00254   mDirWatch.stopScan();
00255   KSaveFile saveFile( mFileName );
00256   bool ok = false;
00257   if ( saveFile.status() == 0 && saveFile.file() )
00258   {
00259     mFormat->saveAll( addressBook(), this, saveFile.file() );
00260     ok = saveFile.close();
00261   }
00262 
00263   if ( !ok )
00264     addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
00265   mDirWatch.startScan();
00266 
00267   return ok;
00268 }
00269 
00270 bool ResourceFile::asyncSave( Ticket * )
00271 {
00272   QFile file( mTempFile );
00273 
00274   if ( !file.open( IO_WriteOnly ) ) {
00275     emit savingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
00276     return false;
00277   }
00278 
00279   mDirWatch.stopScan();
00280   mFormat->saveAll( addressBook(), this, &file );
00281   file.close();
00282 
00283   KURL src, dest;
00284   src.setPath( mTempFile );
00285   dest.setPath( mFileName );
00286 
00287   KIO::Scheduler::checkSlaveOnHold( true );
00288   d->mSaveJob = KIO::file_copy( src, dest, -1, true, false, false );
00289   d->mIsSaving = true;
00290   connect( d->mSaveJob, SIGNAL( result( KIO::Job* ) ),
00291            this, SLOT( uploadFinished( KIO::Job* ) ) );
00292 
00293   return true;
00294 }
00295 
00296 void ResourceFile::setFileName( const QString &fileName )
00297 {
00298   mDirWatch.stopScan();
00299   if ( mDirWatch.contains( mFileName ) )
00300     mDirWatch.removeFile( mFileName );
00301 
00302   mFileName = fileName;
00303 
00304   mDirWatch.addFile( mFileName );
00305   mDirWatch.startScan();
00306 }
00307 
00308 QString ResourceFile::fileName() const
00309 {
00310   return mFileName;
00311 }
00312 
00313 void ResourceFile::setFormat( const QString &format )
00314 {
00315   mFormatName = format;
00316   delete mFormat;
00317 
00318   FormatFactory *factory = FormatFactory::self();
00319   mFormat = factory->format( mFormatName );
00320 }
00321 
00322 QString ResourceFile::format() const
00323 {
00324   return mFormatName;
00325 }
00326 
00327 void ResourceFile::fileChanged()
00328 {
00329   if ( !addressBook() )
00330     return;
00331 
00332   clear();
00333   if ( mAsynchronous )
00334     asyncLoad();
00335   else {
00336     load();
00337     kdDebug() << "addressBookChanged() " << endl;
00338     addressBook()->emitAddressBookChanged();
00339   }
00340 }
00341 
00342 void ResourceFile::removeAddressee( const Addressee &addr )
00343 {
00344   QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/photos/" ) + addr.uid() ) );
00345   QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/logos/" ) + addr.uid() ) );
00346   QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) );
00347 
00348   mAddrMap.erase( addr.uid() );
00349 }
00350 
00351 void ResourceFile::downloadFinished( KIO::Job* )
00352 {
00353   d->mIsLoading = false;
00354 
00355   if ( !mLocalTempFile )
00356     emit loadingError( this, i18n( "Download failed in some way!" ) );
00357 
00358   QFile file( mTempFile );
00359   if ( !file.open( IO_ReadOnly ) ) {
00360     emit loadingError( this, i18n( "Unable to open file '%1'." ).arg( mTempFile ) );
00361     return;
00362   }
00363 
00364   if ( !mFormat->loadAll( addressBook(), this, &file ) )
00365     emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mTempFile ) );
00366   else
00367     emit loadingFinished( this );
00368 }
00369 
00370 void ResourceFile::uploadFinished( KIO::Job *job )
00371 {
00372   d->mIsSaving = false;
00373 
00374   if ( job->error() )
00375     emit savingError( this, job->errorString() );
00376   else
00377     emit savingFinished( this );
00378   mDirWatch.startScan();
00379 }
00380 
00381 #include "resourcefile.moc"
KDE Logo
This file is part of the documentation for kabc Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Fri Apr 22 16:06:55 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003