resourcefile.cpp
/*
This file is part of libkabc.
Copyright (c) 2001,2003 Cornelius Schumacher <schumacher@kde.org>
Copyright (c) 2006 Tom Abers <tomalbers@kde.nl>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <qfile.h>
#include <qfileinfo.h>
#include <qtimer.h>
#include <kapplication.h>
#include <kconfig.h>
#include <kdebug.h>
#include <kio/scheduler.h>
#include <klocale.h>
#include <ksavefile.h>
#include <kstandarddirs.h>
#include "formatfactory.h"
#include "resourcefileconfig.h"
#include "stdaddressbook.h"
#include "lock.h"
#include "resourcefile.h"
using namespace KABC;
ResourceFile::ResourceFile( const KConfig *config )
: Resource( config ), mFormat( 0 ),
mAsynchronous( false )
{
QString fileName, formatName;
if ( config ) {
fileName = config->readPathEntry( "FileName", StdAddressBook::fileName() );
formatName = config->readEntry( "FileFormat", "vcard" );
} else {
fileName = StdAddressBook::fileName();
formatName = "vcard";
}
init( fileName, formatName );
}
ResourceFile::ResourceFile( const QString &fileName,
const QString &formatName )
: Resource( 0 ), mFormat( 0 ),
mAsynchronous( false )
{
init( fileName, formatName );
}
void ResourceFile::init( const QString &fileName, const QString &formatName )
{
mFormatName = formatName;
FormatFactory *factory = FormatFactory::self();
mFormat = factory->format( mFormatName );
if ( !mFormat ) {
mFormatName = "vcard";
mFormat = factory->format( mFormatName );
}
connect( &mDirWatch, SIGNAL( dirty(const QString&) ), SLOT( fileChanged() ) );
connect( &mDirWatch, SIGNAL( created(const QString&) ), SLOT( fileChanged() ) );
connect( &mDirWatch, SIGNAL( deleted(const QString&) ), SLOT( fileChanged() ) );
setFileName( fileName );
mLock = 0;
}
ResourceFile::~ResourceFile()
{
delete mFormat;
mFormat = 0;
}
void ResourceFile::writeConfig( KConfig *config )
{
Resource::writeConfig( config );
if ( mFileName == StdAddressBook::fileName() )
config->deleteEntry( "FileName" );
else
config->writePathEntry( "FileName", mFileName );
config->writeEntry( "FileFormat", mFormatName );
}
Ticket *ResourceFile::requestSaveTicket()
{
kdDebug(5700) << "ResourceFile::requestSaveTicket()" << endl;
if ( !addressBook() ) return 0;
delete mLock;
mLock = new Lock( mFileName );
if ( mLock->lock() ) {
addressBook()->emitAddressBookLocked();
} else {
addressBook()->error( mLock->error() );
kdDebug(5700) << "ResourceFile::requestSaveTicket(): Unable to lock file '"
<< mFileName << "': " << mLock->error() << endl;
return 0;
}
return createTicket( this );
}
void ResourceFile::releaseSaveTicket( Ticket *ticket )
{
delete ticket;
delete mLock;
mLock = 0;
addressBook()->emitAddressBookUnlocked();
}
bool ResourceFile::doOpen()
{
QFile file( mFileName );
if ( !file.exists() ) {
// try to create the file
bool ok = file.open( IO_WriteOnly );
if ( ok )
file.close();
return ok;
} else {
QFileInfo fileInfo( mFileName );
if ( readOnly() || !fileInfo.isWritable() ) {
if ( !file.open( IO_ReadOnly ) )
return false;
} else {
if ( !file.open( IO_ReadWrite ) )
return false;
}
if ( file.size() == 0 ) {
file.close();
kdDebug() << "File size is zero. Evaluating backups" << endl;
for (int i=0; i!=20; i++)
{
QFile backup( mFileName + "__" + QString::number(i) );
kdDebug() << "Evaluating" << backup.name() << " size: " << backup.size() << endl;
if ( backup.size() != 0 )
{
kdDebug() << "Restoring backup " << i << endl;
const QString src = mFileName + "__" + QString::number(i);
const QString dest = mFileName;
// remove dest
QFile::remove( dest );
// copy src to dest
if ( backup.open( IO_ReadOnly ) ) {
const QByteArray data = backup.readAll();
QFile out( dest );
if ( out.open( IO_WriteOnly ) ) {
out.writeBlock( data );
out.close();
}
backup.close();
}
return true;
}
}
return true;
}
bool ok = mFormat->checkFormat( &file );
file.close();
return ok;
}
}
void ResourceFile::doClose()
{
}
bool ResourceFile::load()
{
kdDebug(5700) << "ResourceFile::load(): '" << mFileName << "'" << endl;
mAsynchronous = false;
QFile file( mFileName );
if ( !file.open( IO_ReadOnly ) ) {
addressBook()->error( i18n( "Unable to open file '%1'." ).arg( mFileName ) );
return false;
}
clear();
return mFormat->loadAll( addressBook(), this, &file );
}
bool ResourceFile::asyncLoad()
{
kdDebug(5700) << "ResourceFile::asyncLoad()" << endl;
mAsynchronous = true;
bool ok = load();
if ( !ok )
emitLoadingError();
else
emitLoadingFinished();
return true;
}
bool ResourceFile::save( Ticket * )
{
kdDebug(5700) << "ResourceFile::save()" << endl;
// Only do the logrotate dance when the __0 file is not 0 bytes.
QFile file( mFileName + "__0" );
if ( file.size() != 0 ) {
const QString last = mFileName + "__20";
kdDebug() << "deleting " << last << endl;
QFile::remove( last );
for (int i=19; i>=0; i--)
{
const QString src = mFileName + "__" + QString::number(i);
const QString dest = mFileName + "__" + QString::number(i+1);
kdDebug() << "moving " << src << " -> " << dest << endl;
// copy src to dest
QFile in( src );
if ( in.open( IO_ReadOnly ) ) {
const QByteArray data = in.readAll();
QFile out( dest );
if ( out.open( IO_WriteOnly ) ) {
out.writeBlock( data );
out.close();
}
in.close();
}
// remove src
QFile::remove( src );
}
} else
kdDebug() << "Not starting logrotate __0 is 0 bytes." << endl;
QString extension = "__0";
(void) KSaveFile::backupFile( mFileName, QString::null /*directory*/,
extension );
mDirWatch.stopScan();
KSaveFile saveFile( mFileName );
bool ok = false;
if ( saveFile.status() == 0 && saveFile.file() ) {
mFormat->saveAll( addressBook(), this, saveFile.file() );
ok = saveFile.close();
}
if ( !ok ) {
saveFile.abort();
addressBook()->error( i18n( "Unable to save file '%1'." ).arg( mFileName ) );
}
mDirWatch.startScan();
return ok;
}
bool ResourceFile::asyncSave( Ticket *ticket )
{
kdDebug(5700) << "ResourceFile::asyncSave()" << endl;
bool ok = save( ticket );
if ( !ok )
QTimer::singleShot( 0, this, SLOT( emitSavingError() ) );
else
QTimer::singleShot( 0, this, SLOT( emitSavingFinished() ) );
return ok;
}
void ResourceFile::setFileName( const QString &fileName )
{
mDirWatch.stopScan();
if ( mDirWatch.contains( mFileName ) )
mDirWatch.removeFile( mFileName );
mFileName = fileName;
mDirWatch.addFile( mFileName );
mDirWatch.startScan();
}
QString ResourceFile::fileName() const
{
return mFileName;
}
void ResourceFile::setFormat( const QString &format )
{
mFormatName = format;
delete mFormat;
FormatFactory *factory = FormatFactory::self();
mFormat = factory->format( mFormatName );
}
QString ResourceFile::format() const
{
return mFormatName;
}
void ResourceFile::fileChanged()
{
kdDebug(5700) << "ResourceFile::fileChanged(): " << mFileName << endl;
if ( !addressBook() )
return;
if ( mAsynchronous )
asyncLoad();
else {
load();
kdDebug() << "addressBookChanged() " << endl;
addressBook()->emitAddressBookChanged();
}
}
void ResourceFile::removeAddressee( const Addressee &addr )
{
QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/photos/" ) + addr.uid() ) );
QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/logos/" ) + addr.uid() ) );
QFile::remove( QFile::encodeName( locateLocal( "data", "kabc/sounds/" ) + addr.uid() ) );
mAddrMap.erase( addr.uid() );
}
void ResourceFile::emitSavingFinished()
{
emit savingFinished( this );
}
void ResourceFile::emitSavingError()
{
emit savingError( this, i18n( "Unable to save file '%1'." ).arg( mFileName ) );
}
void ResourceFile::emitLoadingFinished()
{
emit loadingFinished( this );
}
void ResourceFile::emitLoadingError()
{
emit loadingError( this, i18n( "Problems during parsing file '%1'." ).arg( mFileName ) );
}
#include "resourcefile.moc"
KABC::FormatFactory
Class for loading format plugins.
Definition: formatfactory.h:57
KABC::FormatFactory::self
static FormatFactory * self()
Returns the global format factory.
Definition: formatfactory.cpp:38
KSaveFile::status
int status() const
KABC::ResourceFile::ResourceFile
ResourceFile(const KConfig *cfg)
Constructor.
Definition: resourcefile.cpp:49
KABC::Lock
This class provides locking functionality for a file, directory or an arbitrary string-represented re...
Definition: lock.h:35
locateLocal
QString locateLocal(const char *type, const QString &filename, const KInstance *instance=KGlobal::instance())
KABC::ResourceFile::save
virtual bool save(Ticket *ticket)
Saves all addresses from address book to file.
Definition: resourcefile.cpp:243
KSaveFile
KABC::StdAddressBook::fileName
static QString fileName()
Returns the default file name for vcard-based addressbook.
Definition: stdaddressbook.cpp:43
KABC::ResourceFile::requestSaveTicket
virtual Ticket * requestSaveTicket()
Requests a save ticket, that is used by save()
Definition: resourcefile.cpp:113
kdDebug
kdbgstream kdDebug(int area=0)
KSaveFile::abort
void abort()
klocale.h
KABC::Ticket
Helper class for handling coordinated save of address books.
Definition: resource.h:37
KConfig::readPathEntry
QString readPathEntry(const QString &pKey, const QString &aDefault=QString::null) const
KSaveFile::close
bool close()
KABC::ResourceFile::fileName
QString fileName() const
Return name of file used for loading and saving the address book.
Definition: resourcefile.cpp:331
KABC::ResourceFile::~ResourceFile
~ResourceFile()
Destructor.
Definition: resourcefile.cpp:95
KABC::ResourceFile::load
virtual bool load()
Loads all addressees from file to the address book.
Definition: resourcefile.cpp:210
KABC::ResourceFile::doOpen
virtual bool doOpen()
Tries to open the file and checks for the proper format.
Definition: resourcefile.cpp:144
KABC::ResourceFile::doClose
virtual void doClose()
Closes the file again.
Definition: resourcefile.cpp:206
KABC::ResourceFile::writeConfig
virtual void writeConfig(KConfig *cfg)
Writes the config back.
Definition: resourcefile.cpp:101
KSaveFile::backupFile
static bool backupFile(const QString &filename, const QString &backupDir=QString::null, const QString &backupExtension=QString::fromLatin1("~"))
KABC::Lock::lock
virtual bool lock()
Lock resource.
Definition: lock.cpp:81
KSaveFile::file
QFile * file()
KABC::FormatFactory::format
FormatPlugin * format(const QString &type)
Returns a pointer to a format object or a null pointer if format type doesn't exist.
Definition: formatfactory.cpp:109
KConfig::writePathEntry
void writePathEntry(const QString &pKey, const QString &path, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
KABC::ResourceFile::format
QString format() const
Returns the format name.
Definition: resourcefile.cpp:345
KConfig::deleteEntry
void deleteEntry(const QString &pKey, bool bNLS=false, bool bGlobal=false)
KABC::Addressee
address book entry
Definition: addressee.src.h:74
KABC::ResourceFile::removeAddressee
virtual void removeAddressee(const Addressee &addr)
Remove a addressee from its source.
Definition: resourcefile.cpp:366
KConfig
KABC::FormatPlugin::loadAll
virtual bool loadAll(AddressBook *, Resource *, QFile *file)=0
Load whole addressbook from file.
KConfig::readEntry
QString readEntry(const QString &pKey, const QString &aDefault=QString::null) const
KABC::ResourceFile::setFileName
void setFileName(const QString &)
Set name of file to be used for saving.
Definition: resourcefile.cpp:319
KABC::FormatPlugin::checkFormat
virtual bool checkFormat(QFile *file) const =0
Checks if given file contains the right format.
KABC::Addressee::uid
QString uid() const
Return unique identifier.
Definition: addressee.src.cpp:173
KABC::FormatPlugin::saveAll
virtual void saveAll(AddressBook *, Resource *, QFile *file)=0
Save whole addressbook to file.
endl
kndbgstream & endl(kndbgstream &s)
KConfig::writeEntry
void writeEntry(const QString &pKey, const QString &pValue, bool bPersistent=true, bool bGlobal=false, bool bNLS=false)
KABC::ResourceFile::setFormat
void setFormat(const QString &name)
Sets a new format by name.
Definition: resourcefile.cpp:336

KDE Home | KDE Accessibility Home | Description of Access Keys