File indexing completed on 2024-12-08 12:56:12
0001 /* This file is part of the KDE project 0002 0003 Copyright (C) 2012-2013 Inge Wallin <inge@lysator.liu.se> 0004 0005 This library is free software; you can redistribute it and/or 0006 modify it under the terms of the GNU Library General Public 0007 License as published by the Free Software Foundation; either 0008 version 2 of the License, or (at your option) any later version. 0009 0010 This library is distributed in the hope that it will be useful, 0011 but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0013 Library General Public License for more details. 0014 0015 You should have received a copy of the GNU Library General Public License 0016 along with this library; see the file COPYING.LIB. If not, write to 0017 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0018 Boston, MA 02110-1301, USA. 0019 */ 0020 0021 0022 // Own 0023 #include "OdfTextReader.h" 0024 0025 // Qt 0026 #include <QStringList> 0027 #include <QBuffer> 0028 0029 // KF5 0030 #include <klocalizedstring.h> 0031 0032 // Calligra 0033 #include <KoStore.h> 0034 #include <KoXmlStreamReader.h> 0035 #include <KoXmlNS.h> 0036 #include <KoXmlWriter.h> // For copyXmlElement 0037 #include <KoOdfReadStore.h> 0038 0039 // Reader library 0040 #include "OdfReader.h" 0041 #include "OdfDrawReaderBackend.h" 0042 #include "OdfReaderContext.h" 0043 #include "OdfReaderDebug.h" 0044 0045 0046 #if 1 0047 static int debugIndent = 0; 0048 #define DEBUGSTART() \ 0049 ++debugIndent; \ 0050 DEBUG_READING("entering") 0051 #define DEBUGEND() \ 0052 DEBUG_READING("exiting"); \ 0053 --debugIndent 0054 #define DEBUG_READING(param) \ 0055 debugOdfReader << QString("%1").arg(" ", debugIndent * 2) << param << ": " \ 0056 << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \ 0057 << reader.qualifiedName().toString() 0058 #else 0059 #define DEBUGSTART() \ 0060 // NOTHING 0061 #define DEBUGEND() \ 0062 // NOTHING 0063 #define DEBUG_READING(param) \ 0064 // NOTHING 0065 #endif 0066 0067 0068 OdfDrawReader::OdfDrawReader() 0069 : m_parent(0) 0070 , m_backend(0) 0071 , m_context(0) 0072 { 0073 } 0074 0075 OdfDrawReader::~OdfDrawReader() 0076 { 0077 } 0078 0079 0080 // ---------------------------------------------------------------- 0081 // setters 0082 0083 0084 void OdfDrawReader::setParent(OdfReader *parent) 0085 { 0086 m_parent = parent; 0087 } 0088 0089 void OdfDrawReader::setBackend(OdfDrawReaderBackend *backend) 0090 { 0091 m_backend = backend; 0092 } 0093 0094 void OdfDrawReader::setContext(OdfReaderContext *context) 0095 { 0096 m_context = context; 0097 } 0098 0099 0100 // ---------------------------------------------------------------- 0101 // namespace dr3d 0102 0103 0104 void OdfDrawReader::readElementDr3dScene(KoXmlStreamReader &reader) 0105 { 0106 DEBUGSTART(); 0107 m_backend->elementDr3dScene(reader, m_context); 0108 0109 // <dr3d:scene> has the following children in ODF 1.2: 0110 // [done] <dr3d:cube> 10.5.4 0111 // [done] <dr3d:extrude> 10.5.6 0112 // [done] <dr3d:light> 10.5.3 0113 // [done] <dr3d:rotate> 10.5.7 0114 // [done] <dr3d:scene> 10.5.2 0115 // [done] <dr3d:sphere> 10.5.5 0116 0117 // <draw:glue-point> 10.3.16 0118 // <svg:desc> 10.3.18 0119 // <svg:title> 10.3.17. 0120 // 0121 while (reader.readNextStartElement()) { 0122 QString tagName = reader.qualifiedName().toString(); 0123 0124 if (tagName == "dr3d:cube") { 0125 readElementDr3dCube(reader); 0126 } 0127 else if (tagName == "dr3d:extrude") { 0128 readElementDr3dExtrude(reader); 0129 } 0130 else if (tagName == "dr3d:light") { 0131 readElementDr3dLight(reader); 0132 } 0133 else if (tagName == "dr3d:rotate") { 0134 readElementDr3dRotate(reader); 0135 } 0136 else if (tagName == "dr3d:scene") { 0137 readElementDr3dScene(reader); 0138 } 0139 else if (tagName == "dr3d:sphere") { 0140 readElementDr3dSphere(reader); 0141 } 0142 //... MORE else if () HERE 0143 else { 0144 reader.skipCurrentElement(); 0145 } 0146 } 0147 0148 m_backend->elementDr3dScene(reader, m_context); 0149 DEBUGEND(); 0150 } 0151 0152 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dLight) // ODF 1.2 10.5.3 0153 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dCube) // ODF 1.2 10.5.4 0154 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dSphere) // ODF 1.2 10.5.5 0155 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dExtrude) // ODF 1.2 10.5.6 0156 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dRotate) // ODF 1.2 10.5.7 0157 0158 0159 // ================================================================ 0160 // namespace draw 0161 0162 0163 // ---------------------------------------------------------------- 0164 0165 0166 #if 0 0167 // This is a template function for the reader library. 0168 // Copy this one and change the name and fill in the code. 0169 void OdfDrawReader::readElementNamespaceTagname(KoXmlStreamReader &reader) 0170 { 0171 DEBUGSTART(); 0172 m_backend->elementNamespaceTagname(reader, m_context); 0173 0174 // <namespace:tagname> has the following children in ODF 1.2: 0175 // FILL IN THE CHILDREN LIKE THIS EXAMPLE (taken from office:document-content): 0176 // <office:automatic-styles> 3.15.3 0177 // <office:body> 3.3 0178 // <office:font-face-decls> 3.14 0179 // <office:scripts> 3.12. 0180 while (reader.readNextStartElement()) { 0181 QString tagName = reader.qualifiedName().toString(); 0182 0183 if (tagName == "office:automatic-styles") { 0184 // FIXME: NYI 0185 reader.skipCurrentElement(); 0186 } 0187 else if (tagName == "office:body") { 0188 readElementOfficeBody(reader); 0189 } 0190 ... MORE else if () HERE 0191 else { 0192 reader.skipCurrentElement(); 0193 } 0194 } 0195 0196 m_backend->elementNamespaceTagname(reader, m_context); 0197 DEBUGEND(); 0198 } 0199 #endif 0200 0201 0202 void OdfDrawReader::readCommonGraphicsElements(KoXmlStreamReader &reader) 0203 { 0204 DEBUGSTART(); 0205 0206 // This is a function common to all draw elements so no backend function 0207 // should be called here. 0208 0209 // The common graphics elements are: 0210 // [done] <dr3d:scene> 10.5.2 0211 // [done] <draw:a> 10.4.12 0212 // [done] <draw:caption> 10.3.11 0213 // [done] <draw:circle> 10.3.8 0214 // [done] <draw:connector> 10.3.10 0215 // <draw:control> 10.3.13 0216 // <draw:custom-shape> 10.6.1 0217 // [done] <draw:ellipse> 10.3.9 0218 // [done] <draw:frame> 10.4.2 0219 // <draw:g> 10.3.15 0220 // [done] <draw:line> 10.3.3 0221 // [done] <draw:measure> 10.3.12 0222 // <draw:page-thumbnail> 10.3.14 0223 // [path] <draw:path> 10.3.7 0224 // [done] <draw:polygon> 10.3.5 0225 // [done] <draw:polyline> 10.3.4 0226 // [done] <draw:rect> 10.3.2 0227 // [done] <draw:regular-polygon> 10.3.6 0228 0229 QString tagName = reader.qualifiedName().toString(); 0230 //debugOdfReader << "list child:" << tagName; 0231 if (tagName == "dr3d:scene") { 0232 readElementDr3dScene(reader); 0233 } 0234 else if (tagName == "draw:a") { 0235 readElementDrawA(reader); 0236 } 0237 else if (tagName == "draw:caption") { 0238 readElementDrawCaption(reader); 0239 } 0240 else if (tagName == "draw:circle") { 0241 readElementDrawCircle(reader); 0242 } 0243 else if (tagName == "draw:connector") { 0244 readElementDrawConnector(reader); 0245 } 0246 else if (tagName == "draw:ellipse") { 0247 readElementDrawEllipse(reader); 0248 } 0249 else if (tagName == "draw:frame") { 0250 readElementDrawFrame(reader); 0251 } 0252 else if (tagName == "draw:line") { 0253 readElementDrawLine(reader); 0254 } 0255 else if (tagName == "draw:measure") { 0256 readElementDrawMeasure(reader); 0257 } 0258 else if (tagName == "draw:path") { 0259 readElementDrawPath(reader); 0260 } 0261 else if (tagName == "draw:polygon") { 0262 readElementDrawPolygon(reader); 0263 } 0264 else if (tagName == "draw:polyline") { 0265 readElementDrawPolyline(reader); 0266 } 0267 else if (tagName == "draw:rect") { 0268 readElementDrawRect(reader); 0269 } 0270 else if (tagName == "draw:regular-polygon") { 0271 readElementDrawRegularPolygon(reader); 0272 } 0273 else { 0274 // FIXME: Should this perhaps be skipCurrentElement()? 0275 readUnknownElement(reader); 0276 } 0277 0278 DEBUGEND(); 0279 } 0280 0281 void OdfDrawReader::readElementDrawA(KoXmlStreamReader &reader) 0282 { 0283 DEBUGSTART(); 0284 m_backend->elementDrawA(reader, m_context); 0285 0286 // <draw:a> has all the normal drawing children. 0287 readCommonGraphicsElements(reader); 0288 0289 m_backend->elementDrawA(reader, m_context); 0290 DEBUGEND(); 0291 } 0292 0293 0294 #define IMPLEMENT_GRAPHIC_OBJECT(object) \ 0295 void OdfDrawReader::readElementDraw##object(KoXmlStreamReader &reader) \ 0296 { \ 0297 DEBUGSTART(); \ 0298 m_backend->elementDraw##object(reader, m_context); \ 0299 \ 0300 readGraphicsObjectChildren(reader); \ 0301 \ 0302 m_backend->elementDraw##object(reader, m_context); \ 0303 DEBUGEND(); \ 0304 } 0305 0306 IMPLEMENT_GRAPHIC_OBJECT(Rect) // ODF 1.2 10.3.2 0307 IMPLEMENT_GRAPHIC_OBJECT(Line) // ODF 1.2 10.3.3 0308 IMPLEMENT_GRAPHIC_OBJECT(Polyline) // ODF 1.2 10.3.4 0309 IMPLEMENT_GRAPHIC_OBJECT(Polygon) // ODF 1.2 10.3.5 0310 IMPLEMENT_GRAPHIC_OBJECT(RegularPolygon) // ODF 1.2 10.3.6 0311 IMPLEMENT_GRAPHIC_OBJECT(Path) // ODF 1.2 10.3.7 0312 IMPLEMENT_GRAPHIC_OBJECT(Circle) // ODF 1.2 10.3.8 0313 IMPLEMENT_GRAPHIC_OBJECT(Ellipse) // ODF 1.2 10.3.9 0314 IMPLEMENT_GRAPHIC_OBJECT(Connector) // ODF 1.2 10.3.10 0315 IMPLEMENT_GRAPHIC_OBJECT(Caption) // ODF 1.2 10.3.11 0316 IMPLEMENT_GRAPHIC_OBJECT(Measure) // ODF 1.2 10.3.12 0317 0318 0319 void OdfDrawReader::readGraphicsObjectChildren(KoXmlStreamReader &reader) 0320 { 0321 // No backend calls in this function 0322 0323 // <draw:circle>, <draw:rect>, etc have the following children in ODF 1.2: 0324 // <draw:glue-point> 10.3.16 0325 // <office:event-listeners> 10.3.19 0326 // <svg:desc> 10.3.18 0327 // <svg:title> 10.3.17 0328 // [done] <text:list> 5.3.1 0329 // [done] <text:p> 5.1.3. 0330 while (reader.readNextStartElement()) { 0331 QString tagName = reader.qualifiedName().toString(); 0332 0333 if (tagName == "draw:glue-point") { 0334 // FIXME: NYI 0335 reader.skipCurrentElement(); 0336 //readElementOfficeDrawGluePoint(reader); 0337 } 0338 else if (tagName == "office:event-listeners") { 0339 // FIXME: NYI 0340 reader.skipCurrentElement(); 0341 //readElementOfficeEventListeners(reader); 0342 } 0343 else if (reader.prefix() == "svg") { 0344 if (tagName == "svg:desc") { 0345 // FIXME: NYI 0346 reader.skipCurrentElement(); 0347 //readElementSvgDesc(reader); 0348 } 0349 else if (tagName == "svg:title") { 0350 // FIXME: NYI 0351 reader.skipCurrentElement(); 0352 //readElementSvgTitle(reader); 0353 } 0354 else { 0355 reader.skipCurrentElement(); 0356 } 0357 } // namespace svg 0358 else if (reader.prefix() == "text") { 0359 OdfTextReader *textReader = m_parent->textReader(); 0360 if (!textReader) { 0361 reader.skipCurrentElement(); 0362 } 0363 else if (tagName == "text:list") { 0364 textReader->readElementTextList(reader); 0365 } 0366 else if (tagName == "text:p") { 0367 textReader->readElementTextP(reader); 0368 } 0369 else { 0370 reader.skipCurrentElement(); 0371 } 0372 } // namespace text 0373 else { 0374 reader.skipCurrentElement(); 0375 } 0376 } 0377 } 0378 0379 0380 // ---------------------------------------------------------------- 0381 // Frames 0382 0383 0384 void OdfDrawReader::readElementDrawFrame(KoXmlStreamReader &reader) 0385 { 0386 DEBUGSTART(); 0387 m_backend->elementDrawFrame(reader, m_context); 0388 0389 // <draw:frame> has the following children in ODF 1.2: 0390 // <draw:applet> 10.4.7 0391 // <draw:contour-path> 10.4.11.3 0392 // <draw:contour-polygon> 10.4.11.2 0393 // <draw:floating-frame> 10.4.10 0394 // <draw:glue-point> 10.3.16 0395 // <draw:image> 10.4.4 0396 // <draw:image-map> 10.4.13.2 0397 // [done] <draw:object> 10.4.6.2 0398 // [done] <draw:object-ole> 10.4.6.3 0399 // <draw:plugin> 10.4.8 0400 // <draw:text-box> 10.4.3 0401 // <office:event-listeners> 10.3.19 0402 // <svg:desc> 10.3.18 0403 // <svg:title> 10.3.17 0404 // [done] <table:table> 9.1.2 0405 // 0406 while (reader.readNextStartElement()) { 0407 QString tagName = reader.qualifiedName().toString(); 0408 0409 if (tagName == "draw:image") { 0410 // FIXME: NYI 0411 reader.skipCurrentElement(); 0412 } 0413 else if (tagName == "draw:object") { 0414 readElementDrawObject(reader); 0415 } 0416 else if (tagName == "draw:object-ole") { 0417 readElementDrawObjectOle(reader); 0418 } 0419 //... MORE else if () HERE 0420 else if (tagName == "table:table") { 0421 OdfTextReader *textReader = m_parent->textReader(); 0422 if (textReader) { 0423 textReader->readElementTableTable(reader); 0424 } 0425 else { 0426 reader.skipCurrentElement(); 0427 } 0428 } 0429 else { 0430 reader.skipCurrentElement(); 0431 } 0432 } 0433 0434 m_backend->elementDrawFrame(reader, m_context); 0435 DEBUGEND(); 0436 } 0437 0438 void OdfDrawReader::readElementDrawObject(KoXmlStreamReader &reader) 0439 { 0440 DEBUGSTART(); 0441 m_backend->elementDrawObject(reader, m_context); 0442 0443 // <draw:object> has the following children in ODF 1.2: 0444 // <math:math> 14.5 0445 // <office:document> 3.1.2 0446 while (reader.readNextStartElement()) { 0447 QString tagName = reader.qualifiedName().toString(); 0448 0449 if (tagName == "math:math") { 0450 // FIXME: NYI 0451 reader.skipCurrentElement(); 0452 } 0453 else if (tagName == "office:document") { 0454 // FIXME: NYI 0455 reader.skipCurrentElement(); 0456 } 0457 else { 0458 // Shouldn't happen. 0459 reader.skipCurrentElement(); 0460 } 0461 } 0462 0463 m_backend->elementDrawObject(reader, m_context); 0464 DEBUGEND(); 0465 } 0466 0467 void OdfDrawReader::readElementDrawObjectOle(KoXmlStreamReader &reader) 0468 { 0469 DEBUGSTART(); 0470 m_backend->elementDrawObjectOle(reader, m_context); 0471 0472 // <draw:object-ole> has the following children in ODF 1.2: 0473 // <office:binary-data> 10.4.5 0474 while (reader.readNextStartElement()) { 0475 QString tagName = reader.qualifiedName().toString(); 0476 0477 if (tagName == "office:binary-data") { 0478 // FIXME: NYI 0479 reader.skipCurrentElement(); 0480 } 0481 else { 0482 // Shouldn't happen. 0483 reader.skipCurrentElement(); 0484 } 0485 } 0486 0487 m_backend->elementDrawObjectOle(reader, m_context); 0488 DEBUGEND(); 0489 } 0490 0491 0492 // ---------------------------------------------------------------- 0493 // Other functions 0494 0495 0496 void OdfDrawReader::readUnknownElement(KoXmlStreamReader &reader) 0497 { 0498 DEBUGSTART(); 0499 0500 #if 0 // FIXME: Fix this 0501 if (m_context->isInsideParagraph()) { 0502 // readParagraphContents expect to have the reader point to the 0503 // contents of the paragraph so we have to read past the draw:p 0504 // start tag here. 0505 reader.readNext(); 0506 readParagraphContents(reader); 0507 } 0508 else { 0509 while (reader.readNextStartElement()) { 0510 readTextLevelElement(reader); 0511 } 0512 } 0513 #else 0514 reader.skipCurrentElement(); 0515 #endif 0516 0517 DEBUGEND(); 0518 }