KoOasisStore.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 David Faure <faure@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 * Boston, MA 02110-1301, USA.
17*/
18
19#include "KoOasisStore.h"
20
21#include "KoDocument.h"
22#include "KoXmlNS.h"
23#include "KoDom.h"
24#include <KoStore.h>
25#include <KoStoreDevice.h>
26#include <KoXmlWriter.h>
27
28#include <tdetempfile.h>
29#include <kdebug.h>
30#include <tdelocale.h>
31
32#include <tqfile.h>
33#include <tqxml.h>
34#include <tqbuffer.h>
35
37 : m_store( store ),
38 m_storeDevice( 0 ),
39 m_contentWriter( 0 ),
40 m_bodyWriter( 0 ),
41 m_manifestWriter( 0 ),
42 m_contentTmpFile( 0 )
43{
44}
45
46KoOasisStore::~KoOasisStore()
47{
48 // If all the right close methods were called, nothing should remain,
49 // so those deletes are really just in case.
50 Q_ASSERT( !m_contentWriter );
51 delete m_contentWriter;
52 Q_ASSERT( !m_bodyWriter );
53 delete m_bodyWriter;
54 Q_ASSERT( !m_storeDevice );
55 delete m_storeDevice;
56 Q_ASSERT( !m_contentTmpFile );
57 delete m_contentTmpFile;
58 Q_ASSERT( !m_manifestWriter );
59 delete m_manifestWriter;
60}
61
63{
64 if ( !m_contentWriter )
65 {
66 if ( !m_store->open( "content.xml" ) )
67 return 0;
68 m_storeDevice = new KoStoreDevice( m_store );
69 m_contentWriter = KoDocument::createOasisXmlWriter( m_storeDevice, "office:document-content" );
70 }
71 return m_contentWriter;
72}
73
75{
76 if ( !m_bodyWriter )
77 {
78 Q_ASSERT( !m_contentTmpFile );
79 m_contentTmpFile = new KTempFile;
80 m_contentTmpFile->setAutoDelete( true );
81 m_bodyWriter = new KoXmlWriter( m_contentTmpFile->file(), 1 );
82 }
83 return m_bodyWriter;
84}
85
87{
88 Q_ASSERT( m_bodyWriter );
89 Q_ASSERT( m_contentTmpFile );
90
91 delete m_bodyWriter; m_bodyWriter = 0;
92 // copy over the contents from the tempfile to the real one
93 TQFile* tmpFile = m_contentTmpFile->file();
94 tmpFile->close();
95 m_contentWriter->addCompleteElement( tmpFile );
96 m_contentTmpFile->close();
97 delete m_contentTmpFile; m_contentTmpFile = 0;
98
99 Q_ASSERT( m_contentWriter );
100 m_contentWriter->endElement(); // document-content
101 m_contentWriter->endDocument();
102 delete m_contentWriter; m_contentWriter = 0;
103 delete m_storeDevice; m_storeDevice = 0;
104 if ( !m_store->close() ) // done with content.xml
105 return false;
106 return true;
107}
108
110{
111 if ( !m_manifestWriter )
112 {
113 // the pointer to the buffer is already stored in the KoXmlWriter, no need to store it here as well
114 TQBuffer *manifestBuffer = new TQBuffer;
115 manifestBuffer->open( IO_WriteOnly );
116 m_manifestWriter = new KoXmlWriter( manifestBuffer );
117 m_manifestWriter->startDocument( "manifest:manifest" );
118 m_manifestWriter->startElement( "manifest:manifest" );
119 m_manifestWriter->addAttribute( "xmlns:manifest", KoXmlNS::manifest );
120 m_manifestWriter->addManifestEntry( "/", mimeType );
121 }
122 return m_manifestWriter;
123}
124
126{
127 m_manifestWriter->endElement();
128 m_manifestWriter->endDocument();
129 TQBuffer* buffer = static_cast<TQBuffer*>(m_manifestWriter->device());
130 delete m_manifestWriter; m_manifestWriter = 0;
131 bool ok = false;
132 if ( m_store->open( "META-INF/manifest.xml" ) )
133 {
134 TQ_LONG written = m_store->write( buffer->buffer() );
135 ok = ( written == (TQ_LONG)buffer->buffer().size() && m_store->close() );
136 }
137 delete buffer;
138 return ok;
139}
140
141bool KoOasisStore::loadAndParse( const TQString& fileName, TQDomDocument& doc, TQString& errorMessage )
142{
143 //kdDebug(30003) << "loadAndParse: Trying to open " << fileName << endl;
144
145 if (!m_store->open(fileName))
146 {
147 kdWarning(30003) << "Entry " << fileName << " not found!" << endl;
148 errorMessage = i18n( "Could not find %1" ).arg( fileName );
149 return false;
150 }
151 // Error variables for TQDomDocument::setContent
152 TQString errorMsg;
153 int errorLine, errorColumn;
154
155 // We need to be able to see the space in <text:span> </text:span>, this is why
156 // we activate the "report-whitespace-only-CharData" feature.
157 // Unfortunately this leads to lots of whitespace text nodes in between real
158 // elements in the rest of the document, watch out for that.
159 TQXmlInputSource source( m_store->device() );
160 // Copied from TQDomDocumentPrivate::setContent, to change the whitespace thing
161 TQXmlSimpleReader reader;
162 KoDocument::setupXmlReader( reader, true /*namespaceProcessing*/ );
163
164 bool ok = doc.setContent( &source, &reader, &errorMsg, &errorLine, &errorColumn );
165 if ( !ok )
166 {
167 kdError(30003) << "Parsing error in " << fileName << "! Aborting!" << endl
168 << " In line: " << errorLine << ", column: " << errorColumn << endl
169 << " Error message: " << errorMsg << endl;
170 errorMessage = i18n( "Parsing error in the main document at line %1, column %2\nError message: %3" )
171 .arg( errorLine ).arg( errorColumn ).arg( i18n ( "TQXml", errorMsg.utf8() ) );
172 }
173 else
174 {
175 kdDebug(30003) << "File " << fileName << " loaded and parsed" << endl;
176 }
177 m_store->close();
178 return ok;
179}
180
181TQString KoOasisStore::mimeForPath( const TQDomDocument& doc, const TQString& fullPath )
182{
183 TQDomElement docElem = doc.documentElement();
184 TQDomElement elem;
185 forEachElement( elem, docElem )
186 {
187 if ( elem.localName() == "file-entry" && elem.namespaceURI() == KoXmlNS::manifest )
188 {
189 if ( elem.attributeNS( KoXmlNS::manifest, "full-path", TQString() ) == fullPath )
190 return elem.attributeNS( KoXmlNS::manifest, "media-type", TQString() );
191 }
192 }
193 return TQString();
194}
static void setupXmlReader(TQXmlSimpleReader &reader, bool namespaceProcessing=false)
setup the XML reader, so that we don't have to duplicate the code.
static KoXmlWriter * createOasisXmlWriter(TQIODevice *dev, const char *rootElementName)
Return an XML writer for saving Oasis XML into the device dev, including the XML processing instructi...
static TQString mimeForPath(const TQDomDocument &doc, const TQString &fullPath)
Another method for loading: get mimetype from full path, using the manifest.
bool closeManifestWriter()
Close the manifest writer, writing its contents to manifest.xml.
bool closeContentWriter()
This will copy the body into the content writer, delete the bodyWriter and the contentWriter,...
KoXmlWriter * contentWriter()
Open contents.xml for writing and return the KoXmlWriter.
KoXmlWriter * bodyWriter()
Open another KoXmlWriter for writing out the contents into a temporary file, to collect automatic sty...
KoXmlWriter * manifestWriter(const char *mimeType)
Create and return a manifest writer. It will write to a memory buffer.
bool loadAndParse(const TQString &fileName, TQDomDocument &doc, TQString &errorMessage)
A completely unrelated method, for loading a file from an oasis store.
KoOasisStore(KoStore *store)
This class implements a TQIODevice around KoStore, so that it can be used to create a TQDomDocument f...
Saves and loads KOffice documents using various backends.
Definition KoStore.h:40
bool close()
Close the file inside the store.
Definition KoStore.cpp:242
TQIODevice * device() const
Get a device for reading a file from the store directly (slightly faster than read() calls) You need ...
Definition KoStore.cpp:261
bool open(const TQString &name)
Open a new file inside the store.
Definition KoStore.cpp:188
TQ_LONG write(const TQByteArray &_data)
Write data into the currently opened file.
Definition KoStore.cpp:308
A class for writing out XML (to any TQIODevice), with a special attention on performance.
Definition KoXmlWriter.h:37
void startElement(const char *tagName, bool indentInside=true)
Start a new element, as a child of the current element.
void endDocument()
Call this to terminate an XML document.
void startDocument(const char *rootElemName, const char *publicId=0, const char *systemId=0)
Start the XML document.
void endElement()
Terminate the current element.
void addCompleteElement(const char *cstr)
This is quite a special-purpose method, not for everyday use.
void addManifestEntry(const TQString &fullPath, const TQString &mediaType)
Special helper for writing "manifest" files This is equivalent to startElement/2*addAttribute/endElem...
void addAttribute(const char *attrName, const TQString &value)
Overloaded version of addAttribute( const char*, const char* ), which is a bit slower because it need...
Definition KoXmlWriter.h:76