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 }