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 }