kde-playground/kdepimlibs/akonadi/xml/xmlwritejob.cpp
2015-04-14 21:49:29 +00:00

159 lines
4.3 KiB
C++

/*
Copyright (c) 2009 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 "xmlwritejob.h"
#include "xmldocument.h"
#include "xmlwriter.h"
#include <akonadi/collection.h>
#include <akonadi/collectionfetchjob.h>
#include <akonadi/item.h>
#include <akonadi/itemfetchjob.h>
#include <akonadi/itemfetchscope.h>
#include <KDebug>
#include <QDomElement>
#include <QFile>
#include <QStack>
using namespace Akonadi;
namespace Akonadi {
class XmlWriteJobPrivate {
public:
XmlWriteJobPrivate( XmlWriteJob* parent ) : q( parent ) {}
XmlWriteJob* const q;
Collection::List roots;
QStack<Collection::List> pendingSiblings;
QStack<QDomElement> elementStack;
QString fileName;
XmlDocument document;
void collectionFetchResult( KJob* job );
void processCollection();
void itemFetchResult( KJob* job );
void processItems();
};
}
void XmlWriteJobPrivate::collectionFetchResult(KJob* job)
{
if ( job->error() )
return;
CollectionFetchJob *fetch = dynamic_cast<CollectionFetchJob*>( job );
Q_ASSERT( fetch );
if ( fetch->collections().isEmpty() ) {
processItems();
} else {
pendingSiblings.push( fetch->collections() );
processCollection();
}
}
void XmlWriteJobPrivate::processCollection()
{
if ( !pendingSiblings.isEmpty() && pendingSiblings.top().isEmpty() ) {
pendingSiblings.pop();
if ( pendingSiblings.isEmpty() ) {
q->done();
return;
}
processItems();
return;
}
if ( pendingSiblings.isEmpty() ) {
q->done();
return;
}
const Collection current = pendingSiblings.top().first();
kDebug() << "Writing " << current.name() << "into" << elementStack.top().attribute( QLatin1String("name") );
elementStack.push( XmlWriter::writeCollection( current, elementStack.top() ) );
CollectionFetchJob *subfetch = new CollectionFetchJob( current, CollectionFetchJob::FirstLevel, q );
q->connect( subfetch, SIGNAL(result(KJob*)), q, SLOT(collectionFetchResult(KJob*)) );
}
void XmlWriteJobPrivate::processItems()
{
const Collection collection = pendingSiblings.top().first();
ItemFetchJob *fetch = new ItemFetchJob( collection, q );
fetch->fetchScope().fetchAllAttributes();
fetch->fetchScope().fetchFullPayload();
q->connect( fetch, SIGNAL(result(KJob*)), q, SLOT(itemFetchResult(KJob*)) );
}
void XmlWriteJobPrivate::itemFetchResult(KJob* job)
{
if ( job->error() )
return;
ItemFetchJob *fetch = dynamic_cast<ItemFetchJob*>( job );
Q_ASSERT( fetch );
foreach ( const Item &item, fetch->items() )
XmlWriter::writeItem( item, elementStack.top() );
pendingSiblings.top().removeFirst();
elementStack.pop();
processCollection();
}
XmlWriteJob::XmlWriteJob(const Collection& root, const QString& fileName, QObject* parent) :
Job( parent ),
d( new XmlWriteJobPrivate( this ) )
{
d->roots.append( root );
d->fileName = fileName;
}
XmlWriteJob::XmlWriteJob(const Collection::List& roots, const QString& fileName, QObject* parent) :
Job( parent ),
d( new XmlWriteJobPrivate( this ) )
{
d->roots = roots;
d->fileName = fileName;
}
XmlWriteJob::~XmlWriteJob()
{
delete d;
}
void XmlWriteJob::doStart()
{
d->elementStack.push( d->document.document().documentElement() );
CollectionFetchJob *job = new CollectionFetchJob( d->roots, this );
connect( job, SIGNAL(result(KJob*)), SLOT(collectionFetchResult(KJob*)) );
}
void XmlWriteJob::done() // cannot be in the private class due to emitResult()
{
if ( !d->document.writeToFile( d->fileName ) ) {
setError( Unknown );
setErrorText( d->document.lastError() );
}
emitResult();
}
#include "moc_xmlwritejob.cpp"