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