Commit 0482c442 authored by Volker Krause's avatar Volker Krause
Browse files

Factor out the autosave code to be used by other single-file resources.

svn path=/trunk/KDE/kdepim/akonadi/; revision=867916
parent 6b57b089
include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/shared )
set ( AKONADI_SINGLEFILERESOURCE_SHARED_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/shared/singlefileresourcebase.cpp
)
if ( XSLTPROC_EXECUTABLE )
add_subdirectory( knut )
add_subdirectory( ical )
......
/*
Copyright (c) 2008 Bertjan Broeksema <b.broeksema@kdemail.net>
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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.
*/
#ifndef AKONADI_SINGLEFILERESOURCE_H
#define AKONADI_SINGLEFILERESOURCE_H
#include "singlefileresourcebase.h"
#include <KLocale>
namespace Akonadi
{
/**
* Base class for single file based resources.
*/
template <typename Settings>
class SingleFileResource : public SingleFileResourceBase
{
public:
SingleFileResource( const QString &id ) : SingleFileResourceBase( id )
{
}
/**
* Indicate that there are pending changes.
*/
void fileDirty()
{
if( Settings::self()->autosave() && !mDirtyTimer.isActive() ) {
mDirtyTimer.setInterval( Settings::self()->autosaveInterval() * 60 * 1000 );
mDirtyTimer.start();
}
}
/**
* Read changes from the backend file.
*/
void readFile()
{
// if we have something loaded already, make sure we write that back in case the settings changed
if ( !mCurrentUrl.isEmpty() )
writeFile();
if ( Settings::self()->path().isEmpty() ) {
emit status( Broken, i18n( "No file selected." ) );
return;
}
// FIXME: Make this asynchronous by using a KIO file job.
// See: http://api.kde.org/4.x-api/kdelibs-apidocs/kio/html/namespaceKIO.html
// NOTE: Test what happens with remotefile -> save, close before save is finished.
mCurrentUrl = KUrl( Settings::self()->path() );
if ( !readFromFile( mCurrentUrl.path() ) ) {
mCurrentUrl = KUrl();
return;
}
emit status( Idle, i18n( "Data loaded from '%1'.", mCurrentUrl.url() ) );
}
/**
* Write changes to the backend file.
*/
void writeFile()
{
if ( Settings::self()->readOnly() ) {
emit error( i18n( "Trying to write to a read-only file: '%1'", Settings::self()->path() ) );
return;
}
mDirtyTimer.stop();
// FIXME: Make asynchronous.
// We don't use the Settings::self()->path() here as that might have changed
// and in that case it would probably cause data lose.
if ( mCurrentUrl.isEmpty() ) {
emit status( Broken, i18n( "No file specified." ) );
return;
}
if ( !writeToFile( mCurrentUrl.path() ) )
return;
emit status( Idle, i18n( "Data successfully saved to '%1'.", mCurrentUrl.url() ) );
}
};
}
#endif
/*
Copyright (c) 2008 Bertjan Broeksema <b.broeksema@kdemail.net>
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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 "singlefileresourcebase.h"
using namespace Akonadi;
SingleFileResourceBase::SingleFileResourceBase( const QString & id ) :
ResourceBase( id )
{
connect( &mDirtyTimer, SIGNAL(timeout()), SLOT(writeFile()) );
mDirtyTimer.setSingleShot( true );
connect( this, SIGNAL(reconfigure()), SLOT(readFile()) );
QTimer::singleShot( 0, this, SLOT(readFile()) );
}
#include "singlefileresourcebase.moc"
/*
Copyright (c) 2008 Volker Krause <vkrause@kde.org>
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.
*/
#ifndef AKONADI_SINGLEFILERESOURCEBASE_H
#define AKONADI_SINGLEFILERESOURCEBASE_H
#include <akonadi/resourcebase.h>
#include <KDE/KUrl>
#include <QtCore/QTimer>
namespace Akonadi
{
/**
* Base class for single file based resources.
* @see SingleFileResource
*/
class SingleFileResourceBase : public ResourceBase
{
Q_OBJECT
public:
SingleFileResourceBase( const QString &id );
public Q_SLOTS:
virtual void readFile() = 0;
virtual void writeFile() = 0;
protected:
/**
* Reimplement to read your data from the given file.
* The file is always local, loading from the network is done
* automatically if needed.
*/
virtual bool readFromFile( const QString &fileName ) = 0;
/**
* Reimplement to write your data to the given file.
* The file is always local, storing back to the network url is done
* automatically when needed.
*/
virtual bool writeToFile( const QString &fileName ) = 0;
protected:
QTimer mDirtyTimer;
KUrl mCurrentUrl;
};
}
#endif
......@@ -9,6 +9,7 @@ set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${KDE4_ENABLE_EXCEPTIONS}" )
########### next target ###############
set( vcardresource_SRCS
${AKONADI_SINGLEFILERESOURCE_SHARED_SOURCES}
configdialog.cpp
vcardresource.cpp
)
......
......@@ -20,7 +20,6 @@
#include "vcardresource.h"
#include "configdialog.h"
#include "settings.h"
#include "settingsadaptor.h"
#include <akonadi/changerecorder.h>
......@@ -34,17 +33,12 @@
using namespace Akonadi;
VCardResource::VCardResource( const QString &id )
: ResourceBase( id )
: SingleFileResource<Settings>( id )
{
new SettingsAdaptor( Settings::self() );
QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
Settings::self(), QDBusConnection::ExportAdaptors );
changeRecorder()->itemFetchScope().fetchFullPayload();
connect( this, SIGNAL(reloadConfiguration()), SLOT(loadAddressees()) );
loadAddressees();
connect( &mWriteWhenDirtyTimer, SIGNAL( timeout() ), this, SLOT( storeAddressees() ) );
mWriteWhenDirtyTimer.setSingleShot( true );
}
VCardResource::~VCardResource()
......@@ -68,12 +62,8 @@ bool VCardResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArr
void VCardResource::aboutToQuit()
{
const QString fileName = Settings::self()->path();
if ( fileName.isEmpty() )
emit error( i18n( "No filename specified." ) );
else if ( !storeAddressees() )
emit error( i18n( "Failed to save address book file to %1", fileName ) );
// TODO: we need to delay termination whehn writeToFile() becomes async!
writeFile();
Settings::self()->writeConfig();
}
......@@ -84,7 +74,7 @@ void VCardResource::configure( WId windowId )
KWindowSystem::setMainWindow( &dlg, windowId );
dlg.exec();
loadAddressees();
readFile();
synchronize();
}
......@@ -101,7 +91,7 @@ void VCardResource::itemAdded( const Akonadi::Item &item, const Akonadi::Collect
i.setRemoteId( addressee.uid() );
changeCommitted( i );
startAutoSaveTimer();
fileDirty();
} else {
changeProcessed();
}
......@@ -120,7 +110,7 @@ void VCardResource::itemChanged( const Akonadi::Item &item, const QSet<QByteArra
i.setRemoteId( addressee.uid() );
changeCommitted( i );
startAutoSaveTimer();
fileDirty();
} else {
changeProcessed();
}
......@@ -131,7 +121,7 @@ void VCardResource::itemRemoved(const Akonadi::Item & item)
if ( mAddressees.contains( item.remoteId() ) )
mAddressees.remove( item.remoteId() );
startAutoSaveTimer();
fileDirty();
changeProcessed();
}
......@@ -154,13 +144,13 @@ void VCardResource::retrieveItems( const Akonadi::Collection & col )
{
// VCard does not support folders so we can savely ignore the collection
Q_UNUSED( col );
Item::List items;
// FIXME: Check if the KIO::Job is done and was successfull, if so send the
// items, otherwise set a bool and in the result slot of the job send the
// items if the bool is set.
foreach ( const KABC::Addressee &addressee, mAddressees ) {
Item item;
item.setRemoteId( addressee.uid() );
......@@ -171,23 +161,10 @@ void VCardResource::retrieveItems( const Akonadi::Collection & col )
itemsRetrieved( items );
}
bool VCardResource::loadAddressees()
bool VCardResource::readFromFile( const QString &fileName )
{
if ( !mAddressees.isEmpty() )
storeAddressees();
mAddressees.clear();
const QString fileName = Settings::self()->path();
if ( fileName.isEmpty() ) {
emit status( Broken, i18n( "No vCard file specified." ) );
return false;
}
// FIXME: Make this asynchronous by using a KIO file job.
// See: http://api.kde.org/4.x-api/kdelibs-apidocs/kio/html/namespaceKIO.html
// NOTE: Test what happens with remotefile -> save, close before save is finished.
QFile file( KUrl( fileName ).path() );
if ( !file.open( QIODevice::ReadOnly ) ) {
emit status( Broken, i18n( "Unable to open vCard file '%1'.", fileName ) );
......@@ -202,28 +179,11 @@ bool VCardResource::loadAddressees()
mAddressees.insert( list[ i ].uid(), list[ i ] );
}
// From here we are using probably a new URL so update mCurrentlyUsedUrl
mCurrentlyUsedUrl = KUrl::fromPath( fileName );
emit status( Idle );
return true;
}
bool VCardResource::storeAddressees()
bool VCardResource::writeToFile( const QString &fileName )
{
if ( Settings::self()->readOnly() )
return true;
// FIXME: Make asynchronous.
// We don't use the Settings::self()->path() here as that might have changed
// and in that case it would probably cause data lose.
const QString fileName = mCurrentlyUsedUrl.path();
if ( fileName.isEmpty() ) {
emit status( Broken, i18n( "No vCard file specified." ) );
return false;
}
QFile file( fileName );
if ( !file.open( QIODevice::WriteOnly ) ) {
emit status( Broken, i18n( "Unable to open vCard file '%1'.", fileName ) );
......@@ -238,15 +198,6 @@ bool VCardResource::storeAddressees()
return true;
}
void VCardResource::startAutoSaveTimer()
{
if( Settings::self()->autosave() && !mWriteWhenDirtyTimer.isActive() )
{
mWriteWhenDirtyTimer.setInterval( Settings::self()->autosaveInterval() * 60 * 1000 );
mWriteWhenDirtyTimer.start();
}
}
AKONADI_RESOURCE_MAIN( VCardResource )
#include "vcardresource.moc"
......@@ -20,14 +20,13 @@
#ifndef VCARDRESOURCE_H
#define VCARDRESOURCE_H
#include <QtCore/QTimer>
#include <akonadi/resourcebase.h>
#include "singlefileresource.h"
#include "settings.h"
#include <kabc/addressee.h>
#include <kabc/vcardconverter.h>
class VCardResource : public Akonadi::ResourceBase, public Akonadi::AgentBase::Observer
class VCardResource : public Akonadi::SingleFileResource<Settings>, public Akonadi::AgentBase::Observer
{
Q_OBJECT
......@@ -37,6 +36,8 @@ class VCardResource : public Akonadi::ResourceBase, public Akonadi::AgentBase::O
public Q_SLOTS:
virtual void configure( WId windowId );
bool readFromFile( const QString &fileName );
bool writeToFile( const QString &fileName );
protected Q_SLOTS:
void retrieveCollections();
......@@ -50,19 +51,9 @@ class VCardResource : public Akonadi::ResourceBase, public Akonadi::AgentBase::O
virtual void itemChanged( const Akonadi::Item &item, const QSet<QByteArray> &parts );
virtual void itemRemoved( const Akonadi::Item &item );
private Q_SLOTS:
bool loadAddressees();
bool storeAddressees();
private:
void startAutoSaveTimer();
private:
QMap<QString, KABC::Addressee> mAddressees;
KABC::VCardConverter mConverter;
KUrl mCurrentlyUsedUrl;
QTimer mWriteWhenDirtyTimer;
};
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment