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
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
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
00250
QString extension =
"_" +
QString::number( QDate::currentDate().dayOfWeek() );
00251 (
void)
KSaveFile::backupFile( mFileName, QString::null ,
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"