Commit 6da3f2ab authored by Volker Krause's avatar Volker Krause
Browse files

Add file monitoring and conflict handling in case of pending changed in

Akonadi while the file was changed on disk.

Basically works but shows that we lack a way to invalidate the Akonadi
cache in case we only deliver partial items in retrieveItems().

svn path=/trunk/KDE/kdepim/akonadi/; revision=875748
parent d619e4a5
......@@ -93,7 +93,7 @@ void ICalResource::configure( WId windowId )
dlg.setFilter( "*.ics *.ical|" + i18nc("Filedialog filter for *.ics *.ical", "iCal Calendar File" ) );
dlg.setCaption( i18n("Select Calendar") );
if ( dlg.exec() == QDialog::Accepted ) {
readFile();
reloadFile();
synchronize();
}
}
......
......@@ -25,6 +25,7 @@
#include <akonadi/collectiondisplayattribute.h>
#include <KDirWatch>
#include <KLocale>
#include <QFile>
......@@ -59,9 +60,8 @@ class SingleFileResource : public SingleFileResourceBase
*/
void readFile()
{
// if we have something loaded already, make sure we write that back in case the settings changed
if ( !mCurrentUrl.isEmpty() )
writeFile();
if ( KDirWatch::self()->contains( mCurrentUrl.path() ) )
KDirWatch::self()->removeFile( mCurrentUrl.path() );
const bool nameWasChanged = mCurrentUrl.fileName() != name() && !mCurrentUrl.isEmpty();
......@@ -95,6 +95,8 @@ class SingleFileResource : public SingleFileResourceBase
return;
}
if ( Settings::self()->monitorFile() )
KDirWatch::self()->addFile( mCurrentUrl.path() );
emit status( Idle, i18n( "Data loaded from '%1'.", mCurrentUrl.prettyUrl() ) );
}
......@@ -119,7 +121,10 @@ class SingleFileResource : public SingleFileResourceBase
return;
}
if ( !writeToFile( mCurrentUrl.path() ) )
KDirWatch::self()->stopScan();
const bool writeResult = writeToFile( mCurrentUrl.path() );
KDirWatch::self()->startScan();
if ( !writeResult )
return;
emit status( Idle, i18n( "Data successfully saved to '%1'.", mCurrentUrl.prettyUrl() ) );
......
......@@ -24,6 +24,13 @@
#include <akonadi/collectiondisplayattribute.h>
#include <akonadi/itemfetchscope.h>
#include <KDebug>
#include <KDirWatch>
#include <KLocale>
#include <KStandardDirs>
#include <QDir>
using namespace Akonadi;
SingleFileResourceBase::SingleFileResourceBase( const QString & id ) :
......@@ -32,11 +39,13 @@ SingleFileResourceBase::SingleFileResourceBase( const QString & id ) :
connect( &mDirtyTimer, SIGNAL(timeout()), SLOT(writeFile()) );
mDirtyTimer.setSingleShot( true );
connect( this, SIGNAL(reloadConfiguration()), SLOT(readFile()) );
connect( this, SIGNAL(reloadConfiguration()), SLOT(reloadFile()) );
QTimer::singleShot( 0, this, SLOT(readFile()) );
changeRecorder()->itemFetchScope().fetchFullPayload();
changeRecorder()->fetchCollection( true );
connect( KDirWatch::self(), SIGNAL(dirty(QString)), SLOT(fileChanged(QString)) );
}
void SingleFileResourceBase::setSupportedMimetypes(const QStringList & mimeTypes, const QString &icon)
......@@ -58,4 +67,38 @@ void SingleFileResourceBase::collectionChanged(const Akonadi::Collection & colle
setName( newName );
}
void SingleFileResourceBase::reloadFile()
{
// if we have something loaded already, make sure we write that back in case the settings changed
if ( !mCurrentUrl.isEmpty() )
writeFile();
readFile();
}
void SingleFileResourceBase::fileChanged(const QString & fileName)
{
if ( fileName != mCurrentUrl.path() )
return;
// handle conflicts
if ( mDirtyTimer.isActive() && !mCurrentUrl.isEmpty() ) {
const KUrl prevUrl = mCurrentUrl;
int i = 0;
QString lostFoundFileName;
do {
lostFoundFileName = KStandardDirs::locateLocal( "data", identifier() + QDir::separator()
+ prevUrl.fileName() + "-" + QString::number( ++i ) );
} while ( KStandardDirs::exists( lostFoundFileName ) );
mCurrentUrl = KUrl( lostFoundFileName );
writeFile();
emit warning( i18n( "The file '%1' was changed on disk while there were still pending changes in Akonadi. "
"To avoid dataloss, a backup of the internal changes has been created at '%2'.",
prevUrl.prettyUrl(), mCurrentUrl.prettyUrl() ) );
mCurrentUrl = prevUrl;
}
readFile();
synchronize();
}
#include "singlefileresourcebase.moc"
......@@ -47,6 +47,7 @@ class SingleFileResourceBase : public ResourceBase, public Akonadi::AgentBase::O
void collectionChanged( const Akonadi::Collection &collection );
public Q_SLOTS:
void reloadFile();
virtual void readFile() = 0;
virtual void writeFile() = 0;
......@@ -70,6 +71,9 @@ class SingleFileResourceBase : public ResourceBase, public Akonadi::AgentBase::O
KUrl mCurrentUrl;
QStringList mSupportedMimetypes;
QString mCollectionIcon;
private Q_SLOTS:
void fileChanged( const QString &fileName );
};
}
......
......@@ -71,7 +71,7 @@ void VCardResource::configure( WId windowId )
dlg.setFilter( "*.vcf|" + i18nc("Filedialog filter for *.vcf", "vCard Addressbook File" ) );
dlg.setCaption( i18n("Select Addressbook") );
if ( dlg.exec() == QDialog::Accepted ) {
readFile();
reloadFile();
synchronize();
}
}
......
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