You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
koffice/lib/kofficecore/KoOasisStore.cpp

195 lines
6.5 KiB

/* This file is part of the KDE project
Copyright (C) 2005 David Faure <faure@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 version 2 as published by the Free Software Foundation.
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 "KoOasisStore.h"
#include "KoDocument.h"
#include "KoXmlNS.h"
#include "KoDom.h"
#include <KoStore.h>
#include <KoStoreDevice.h>
#include <KoXmlWriter.h>
#include <ktempfile.h>
#include <kdebug.h>
#include <klocale.h>
#include <tqfile.h>
#include <tqxml.h>
#include <tqbuffer.h>
KoOasisStore::KoOasisStore( KoStore* store )
: m_store( store ),
m_storeDevice( 0 ),
m_contentWriter( 0 ),
m_bodyWriter( 0 ),
m_manifestWriter( 0 ),
m_contentTmpFile( 0 )
{
}
KoOasisStore::~KoOasisStore()
{
// If all the right close methods were called, nothing should remain,
// so those deletes are really just in case.
Q_ASSERT( !m_contentWriter );
delete m_contentWriter;
Q_ASSERT( !m_bodyWriter );
delete m_bodyWriter;
Q_ASSERT( !m_storeDevice );
delete m_storeDevice;
Q_ASSERT( !m_contentTmpFile );
delete m_contentTmpFile;
Q_ASSERT( !m_manifestWriter );
delete m_manifestWriter;
}
KoXmlWriter* KoOasisStore::contentWriter()
{
if ( !m_contentWriter )
{
if ( !m_store->open( "content.xml" ) )
return 0;
m_storeDevice = new KoStoreDevice( m_store );
m_contentWriter = KoDocument::createOasisXmlWriter( m_storeDevice, "office:document-content" );
}
return m_contentWriter;
}
KoXmlWriter* KoOasisStore::bodyWriter()
{
if ( !m_bodyWriter )
{
Q_ASSERT( !m_contentTmpFile );
m_contentTmpFile = new KTempFile;
m_contentTmpFile->setAutoDelete( true );
m_bodyWriter = new KoXmlWriter( TQT_TQIODEVICE(m_contentTmpFile->file()), 1 );
}
return m_bodyWriter;
}
bool KoOasisStore::closeContentWriter()
{
Q_ASSERT( m_bodyWriter );
Q_ASSERT( m_contentTmpFile );
delete m_bodyWriter; m_bodyWriter = 0;
// copy over the contents from the tempfile to the real one
TQFile* tmpFile = m_contentTmpFile->file();
tmpFile->close();
m_contentWriter->addCompleteElement( TQT_TQIODEVICE(tmpFile) );
m_contentTmpFile->close();
delete m_contentTmpFile; m_contentTmpFile = 0;
Q_ASSERT( m_contentWriter );
m_contentWriter->endElement(); // document-content
m_contentWriter->endDocument();
delete m_contentWriter; m_contentWriter = 0;
delete m_storeDevice; m_storeDevice = 0;
if ( !m_store->close() ) // done with content.xml
return false;
return true;
}
KoXmlWriter* KoOasisStore::manifestWriter( const char* mimeType )
{
if ( !m_manifestWriter )
{
// the pointer to the buffer is already stored in the KoXmlWriter, no need to store it here as well
TQBuffer *manifestBuffer = new TQBuffer;
manifestBuffer->open( IO_WriteOnly );
m_manifestWriter = new KoXmlWriter( TQT_TQIODEVICE(manifestBuffer) );
m_manifestWriter->startDocument( "manifest:manifest" );
m_manifestWriter->startElement( "manifest:manifest" );
m_manifestWriter->addAttribute( "xmlns:manifest", KoXmlNS::manifest );
m_manifestWriter->addManifestEntry( "/", mimeType );
}
return m_manifestWriter;
}
bool KoOasisStore::closeManifestWriter()
{
m_manifestWriter->endElement();
m_manifestWriter->endDocument();
TQBuffer* buffer = TQT_TQBUFFER( static_cast<QIODevice*>(m_manifestWriter->device()) );
delete m_manifestWriter; m_manifestWriter = 0;
bool ok = false;
if ( m_store->open( "META-INF/manifest.xml" ) )
{
TQ_LONG written = m_store->write( buffer->buffer() );
ok = ( written == (TQ_LONG)buffer->buffer().size() && m_store->close() );
}
delete buffer;
return ok;
}
bool KoOasisStore::loadAndParse( const TQString& fileName, TQDomDocument& doc, TQString& errorMessage )
{
//kdDebug(30003) << "loadAndParse: Trying to open " << fileName << endl;
if (!m_store->open(fileName))
{
kdWarning(30003) << "Entry " << fileName << " not found!" << endl;
errorMessage = i18n( "Could not find %1" ).arg( fileName );
return false;
}
// Error variables for TQDomDocument::setContent
TQString errorMsg;
int errorLine, errorColumn;
// We need to be able to see the space in <text:span> </text:span>, this is why
// we activate the "report-whitespace-only-CharData" feature.
// Unfortunately this leads to lots of whitespace text nodes in between real
// elements in the rest of the document, watch out for that.
TQXmlInputSource source( m_store->device() );
// Copied from TQDomDocumentPrivate::setContent, to change the whitespace thing
TQXmlSimpleReader reader;
KoDocument::setupXmlReader( reader, true /*namespaceProcessing*/ );
bool ok = doc.setContent( &source, &reader, &errorMsg, &errorLine, &errorColumn );
if ( !ok )
{
kdError(30003) << "Parsing error in " << fileName << "! Aborting!" << endl
<< " In line: " << errorLine << ", column: " << errorColumn << endl
<< " Error message: " << errorMsg << endl;
errorMessage = i18n( "Parsing error in the main document at line %1, column %2\nError message: %3" )
.arg( errorLine ).arg( errorColumn ).arg( i18n ( "TQXml", errorMsg.utf8() ) );
}
else
{
kdDebug(30003) << "File " << fileName << " loaded and parsed" << endl;
}
m_store->close();
return ok;
}
TQString KoOasisStore::mimeForPath( const TQDomDocument& doc, const TQString& fullPath )
{
TQDomElement docElem = doc.documentElement();
TQDomElement elem;
forEachElement( elem, docElem )
{
if ( elem.localName() == "file-entry" && elem.namespaceURI() == KoXmlNS::manifest )
{
if ( elem.attributeNS( KoXmlNS::manifest, "full-path", TQString() ) == fullPath )
return elem.attributeNS( KoXmlNS::manifest, "media-type", TQString() );
}
}
return TQString();
}