Warning, file /office/calligra/libs/kross/KoScriptingOdf.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /***************************************************************************
0002   KoScriptingOdf.cpp
0003  * This file is part of the KDE project
0004  * copyright (C) 2007 Sebastian Sauer <mail@dipe.org>
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU Library General Public
0008  * License as published by the Free Software Foundation; either
0009  * version 2 of the License, or (at your option) any later version.
0010  *
0011  * This program is distributed in the hope that it will be useful,
0012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014  * Library General Public License for more details.
0015  *
0016  * You should have received a copy of the GNU Library General Public License
0017  * along with this program; see the file COPYING.  If not, write to
0018  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020  ***************************************************************************/
0021 
0022 #include "KoScriptingOdf.h"
0023 
0024 #include "KoKrossDebug.h"
0025 
0026 #include <KoStore.h>
0027 #include <KoOdfWriteStore.h>
0028 #include <KoPartAdaptor.h>
0029 #include <KoEmbeddedDocumentSaver.h>
0030 
0031 #include <QBuffer>
0032 
0033 /************************************************************************************************
0034  * KoScriptingOdfReader
0035  */
0036 
0037 KoScriptingOdfReader::KoScriptingOdfReader(KoScriptingOdfStore *store, const KoXmlDocument &doc)
0038     : QObject(store),
0039     m_store(store),
0040     m_doc(doc),
0041     m_level(0)
0042 {
0043 }
0044 
0045 KoScriptingOdfReader::~KoScriptingOdfReader()
0046 {
0047 }
0048 
0049 void KoScriptingOdfReader::start()
0050 {
0051     KoXmlElement elem = m_doc.documentElement();
0052     handleElement(elem);
0053     setCurrentElement(KoXmlElement());
0054     setLevel(0);
0055 }
0056 
0057 QString KoScriptingOdfReader::nameFilter() const
0058 {
0059     return m_filter;
0060 }
0061 
0062 void KoScriptingOdfReader::setNameFilter(const QString &name, bool regularExpression)
0063 {
0064     m_filter = name.isEmpty() ? QString() : name;
0065     m_filterRegExp = regularExpression ? QRegExp(name, Qt::CaseInsensitive) : QRegExp();
0066 }
0067 
0068 KoScriptingOdfStore *KoScriptingOdfReader::store() const
0069 {
0070     return m_store;
0071 }
0072 
0073 KoXmlDocument KoScriptingOdfReader::doc() const
0074 {
0075     return m_doc;
0076 }
0077 
0078 KoXmlElement KoScriptingOdfReader::currentElement() const
0079 {
0080     return m_currentElement;
0081 }
0082 
0083 QString KoScriptingOdfReader::name() const
0084 {
0085     return m_currentElement.tagName(); /*.nodeName();*/
0086 }
0087 
0088 QString KoScriptingOdfReader::namespaceURI() const
0089 {
0090     return m_currentElement.namespaceURI();
0091 }
0092 
0093 int KoScriptingOdfReader::level() const
0094 {
0095     return m_level;
0096 }
0097 
0098 #ifndef KOXML_USE_QDOM
0099 QStringList KoScriptingOdfReader::attributeNames()
0100 {
0101     return m_currentElement.attributeNames();
0102 }
0103 #endif
0104 
0105 QString KoScriptingOdfReader::attribute(const QString &name, const QString &defaultValue) const
0106 {
0107     return m_currentElement.attribute(name, defaultValue);
0108 }
0109 
0110 QString KoScriptingOdfReader::attributeNS(const QString &namespaceURI, const QString &localName, const QString &defaultValue) const
0111 {
0112     return m_currentElement.attributeNS(namespaceURI, localName, defaultValue);
0113 }
0114 
0115 bool KoScriptingOdfReader::hasAttribute(const QString &name) const
0116 {
0117     return m_currentElement.hasAttribute(name);
0118 }
0119 
0120 bool KoScriptingOdfReader::hasAttributeNS(const QString &namespaceURI, const QString &localName) const
0121 {
0122     return m_currentElement.hasAttributeNS(namespaceURI, localName);
0123 }
0124 
0125 bool KoScriptingOdfReader::isNull() const
0126 {
0127     return m_currentElement.isNull();
0128 }
0129 
0130 bool KoScriptingOdfReader::isElement() const
0131 {
0132     return m_currentElement.isElement();
0133 }
0134 
0135 QString KoScriptingOdfReader::text() const
0136 {
0137     return m_currentElement.text();
0138 }
0139 
0140 bool KoScriptingOdfReader::hasChildren() const {
0141 #ifdef KOXML_USE_QDOM
0142     const int count = m_currentElement.childNodes().count();
0143 #else
0144     const int count = m_currentElement.childNodesCount();
0145 #endif
0146     if (count < 1)
0147         return false;
0148     if (count == 1 && m_currentElement.firstChild().isText())
0149         return false;
0150     return true;
0151 }
0152 
0153 void KoScriptingOdfReader::emitOnElement()
0154 {
0155 emit onElement();
0156 }
0157 
0158 void KoScriptingOdfReader::setCurrentElement(const KoXmlElement &elem)
0159 {
0160     m_currentElement = elem;
0161 }
0162 
0163 void KoScriptingOdfReader::setLevel(int level)
0164 {
0165     m_level = level;
0166 }
0167 
0168 void KoScriptingOdfReader::handleElement(KoXmlElement &elem, int level)
0169 {
0170     bool ok = m_filter.isNull();
0171     if (! ok) {
0172         if (m_filterRegExp.isEmpty())
0173             ok = m_filter == elem.tagName();
0174         else
0175             ok = m_filterRegExp.exactMatch(elem.tagName());
0176     }
0177     if (ok) {
0178         setCurrentElement(elem);
0179         setLevel(level);
0180         emitOnElement();
0181     }
0182     level++;
0183     KoXmlElement e;
0184     forEachElement(e, elem)
0185         handleElement(e, level); // recursive
0186 }
0187 
0188 KoScriptingOdfManifestReader::KoScriptingOdfManifestReader(KoScriptingOdfStore *store, const KoXmlDocument &doc)
0189     : KoScriptingOdfReader(store, doc)
0190 {
0191     KoXmlElement elem = doc.documentElement();
0192     KoXmlElement e;
0193     forEachElement(e, elem)
0194         if (e.tagName() == "manifest:file-entry")
0195             m_entries << QPair<QString,QString>(e.attribute("manifest:media-type"), e.attribute("manifest:full-path"));
0196 }
0197 
0198 QStringList KoScriptingOdfManifestReader::paths(const QString &type) const
0199 {
0200     QStringList list;
0201     for (QList<QPair<QString,QString> >::ConstIterator it = m_entries.begin(); it != m_entries.end(); ++it)
0202         if (type.isEmpty() || type == (*it).first )
0203             list << (*it).second;
0204     return list;
0205 }
0206 
0207 #ifndef NDEBUG
0208 void dumpElem(KoXmlElement elem, int level=0)
0209 {
0210     QString prefix;
0211     for (int i = 0; i < level; ++i)
0212         prefix+="  ";
0213     debugKoKross  << QString("%1  %2").arg(prefix).arg(elem.tagName());
0214 #ifndef KOXML_USE_QDOM
0215     foreach (const QString &s, elem.attributeNames())
0216         debugKoKross  << QString("%1    %2 = %3").arg(prefix).arg(s).arg(elem.attribute(s));
0217 #endif
0218     level++;
0219     KoXmlElement e;
0220     forEachElement(e, elem)
0221         dumpElem(e,level);
0222 }
0223 #endif
0224 
0225 KoScriptingOdfStylesReader::KoScriptingOdfStylesReader(KoScriptingOdfStore *store, const KoXmlDocument &doc)
0226     : KoScriptingOdfReader(store, doc)
0227 {
0228     //dumpElem( doc.documentElement() );
0229 }
0230 
0231 KoScriptingOdfContentReader::KoScriptingOdfContentReader(KoScriptingOdfStore *store, const KoXmlDocument &doc)
0232     : KoScriptingOdfReader(store, doc)
0233 {
0234     //dumpElem( doc.documentElement() );
0235 }
0236 
0237 /************************************************************************************************
0238  * KoScriptingOdfStore
0239  */
0240 
0241 KoStore *KoScriptingOdfStore::getReadStore()
0242 {
0243     QByteArray ba = getByteArray();
0244     if (ba.isNull()) {
0245         warnKoKross  << "KoScriptingOdfStore::getReadStore() Failed to fetch ByteArray";
0246         return 0;
0247     }
0248     if (m_readStore ) {
0249         //debugKoKross <<"KoScriptingOdfStore::getReadStore() Return cached store";
0250         Q_ASSERT(m_readDevice);
0251         return m_readStore;
0252     }
0253     //debugKoKross <<"KoScriptingOdfStore::getReadStore() Return new store";
0254     Q_ASSERT(!m_readDevice);
0255     m_readDevice = new QBuffer(&m_byteArray);
0256     m_readStore = KoStore::createStore(m_readDevice, KoStore::Read, "KrossScript", KoStore::Tar);
0257     return m_readStore;
0258 }
0259 
0260 QByteArray KoScriptingOdfStore::getByteArray()
0261 {
0262     if (! m_byteArray.isNull())
0263         return m_byteArray;
0264     if (m_readStore) {
0265         //debugKoKross  << "KoScriptingOdfStore::getByteArray() Cleaning prev cached store up.";
0266         if (m_readStore->isOpen() ) {
0267             //debugKoKross  << "KoScriptingOdfStore::getByteArray() Closing prev cached store.";
0268             m_readStore->close();
0269         }
0270         delete m_readStore;
0271         m_readStore = 0;
0272     }
0273     if (m_readDevice) {
0274         //debugKoKross  << "KoScriptingOdfStore::getByteArray() Cleaning prev cached device up.";
0275         delete m_readDevice;
0276         m_readDevice = 0;
0277     }
0278     if (! m_document) {
0279         //warnKoKross  << "KoScriptingOdfStore::getByteArray() No document defined.";
0280         return QByteArray();
0281     }
0282 
0283     //debugKoKross  << "KoScriptingOdfStore::getByteArray() Reading ByteArray.";
0284     QBuffer buffer(&m_byteArray);
0285     KoStore *store = KoStore::createStore(&buffer, KoStore::Write, "KrossScript", KoStore::Tar);
0286     KoOdfWriteStore odfStore(store);
0287     odfStore.manifestWriter("");
0288     KoEmbeddedDocumentSaver embeddedSaver;
0289     KoDocument::SavingContext documentContext(odfStore, embeddedSaver);
0290     QByteArray mime = getMimeType();
0291     if (! m_document->saveOdf(documentContext)) {
0292         warnKoKross  << "KoScriptingOdfStore::open() Failed to save Oasis to ByteArray";
0293         m_byteArray = QByteArray();
0294     }
0295     //odfStore.closeContentWriter();
0296     odfStore.closeManifestWriter();
0297     delete store;
0298     return m_byteArray;
0299 }
0300 
0301 QByteArray KoScriptingOdfStore::getMimeType() const
0302 {
0303     return "application/vnd.oasis.opendocument.text"; //odt
0304     //return "application/vnd.oasis.opendocument.spreadsheet"; //ods
0305     //return "application/vnd.oasis.opendocument.presentation"; //odp
0306     //return "pplication/vnd.oasis.opendocument.graphics"; //odg
0307     //return "application/vnd.oasis.opendocument.chart"; //odc
0308     //return "application/vnd.oasis.opendocument.formula"; //odf
0309     //return "application/vnd.oasis.opendocument.image"; //odi
0310 }
0311 
0312 KoScriptingOdfStore::KoScriptingOdfStore(QObject *parent, KoDocument *doc)
0313     : QObject(parent),
0314     m_document(doc),
0315     m_documentAdaptor(0),
0316     m_readStore(0),
0317     m_readDevice(0),
0318     m_reader(0)
0319 {
0320 }
0321 
0322 KoScriptingOdfStore::~KoScriptingOdfStore()
0323 {
0324     delete m_readStore;
0325     delete m_readDevice;
0326     delete m_reader;
0327 }
0328 
0329 //KoStore *KoScriptingOdfStore::readStore() const { return getReadStore(); }
0330 //QIODevice *KoScriptingOdfStore::readDevice() const { return readDevice; }
0331 
0332 bool KoScriptingOdfStore::hasFile(const QString &fileName)
0333 {
0334     KoStore *store = getReadStore();
0335     bool retval = store ? store->hasFile(fileName) : false;
0336     delete store;
0337     return retval;
0338 }
0339 
0340 bool KoScriptingOdfStore::isOpen() const
0341 {
0342     return m_readStore && m_readStore->isOpen();
0343 }
0344 
0345 QObject *KoScriptingOdfStore::open(const QString &fileName)
0346 {
0347     delete m_reader; m_reader = 0;
0348     KoStore *store = getReadStore();
0349     if (! store)
0350         return 0;
0351     if (store->isOpen())
0352         store->close();
0353     if (! store->open(fileName)) {
0354         warnKoKross <<"KoScriptingOdfStore::openFile() Failed to open file:"<<fileName;
0355         return 0;
0356     }
0357     //debugKoKross <<"KoScriptingOdfStore::openFile() fileName="<<fileName<<" store->isOpen="<<store->isOpen()<<endl;
0358     Q_ASSERT(store->device());
0359 
0360     //KoOasisStore oasisStore(store);
0361     KoXmlDocument doc;
0362 
0363     QString errorMsg;
0364     int errorLine, errorColumn;
0365     if (! doc.setContent(store->device(), &errorMsg, &errorLine, &errorColumn)) {
0366        warnKoKross << "Parse-Error message" << errorMsg << "line" << errorLine << "col" << errorColumn;
0367        delete store;
0368        return 0;
0369     }
0370 
0371     const QString tagName = doc.documentElement().tagName();
0372     debugKoKross <<"KoScriptingOdfStore::open documentElement.tagName="<<tagName;
0373     if (tagName == "office:document-content")
0374         m_reader = new KoScriptingOdfContentReader(this, doc);
0375     if (tagName == "office:document-styles")
0376         m_reader = new KoScriptingOdfStylesReader(this, doc);
0377     else if (tagName == "manifest:manifest")
0378         m_reader = new KoScriptingOdfManifestReader(this, doc);
0379     else
0380         m_reader = new KoScriptingOdfReader(this, doc);
0381     
0382     delete store;
0383     
0384     return m_reader;
0385 }
0386 
0387 bool KoScriptingOdfStore::close()
0388 {
0389     if (! m_readStore || ! m_readStore->isOpen())
0390         return true;
0391     return m_readStore->close();
0392 }
0393 
0394 QByteArray KoScriptingOdfStore::extract(const QString &fileName)
0395 {
0396     KoStore *store = getReadStore();
0397     if (! store)
0398         return QByteArray();
0399     if (store->isOpen())
0400         store->close();
0401     QByteArray data;
0402     bool ok = store->extractFile(fileName, data);
0403     delete store;
0404     return ok ? data : QByteArray();
0405 }
0406 
0407 bool KoScriptingOdfStore::extractToFile(const QString &fileName, const QString &toFileName)
0408 {
0409     KoStore *store = getReadStore();
0410     if (! store)
0411         return false;
0412     if (store->isOpen())
0413         store->close();
0414     bool retval = store->extractFile(fileName, toFileName);
0415     delete store;
0416     return retval;
0417 }
0418 
0419 QObject *KoScriptingOdfStore::document() const
0420 {
0421     if (m_documentAdaptor)
0422         return m_documentAdaptor;
0423     return m_document;
0424 }
0425 
0426 bool KoScriptingOdfStore::setDocument(QObject *document)
0427 {
0428     bool ok = true;
0429     m_documentAdaptor = dynamic_cast<KoPartAdaptor*>(document);
0430     if (m_documentAdaptor) {
0431         m_document = dynamic_cast<KoDocument*>(m_documentAdaptor->parent());
0432         Q_ASSERT(m_document);
0433     } else {
0434         if (KoDocument *doc = dynamic_cast<KoDocument*>(document)) {
0435             m_document = doc;
0436         } else {
0437             m_document = 0;
0438             ok = false;
0439         }
0440         m_documentAdaptor = 0;
0441     }
0442     return ok;
0443 }