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 }