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 "OdfChartReaderBackend.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 OdfChartReader::OdfChartReader()
0056     : m_parent(0)
0057     , m_backend(0)
0058     , m_context(0)
0059 {
0060 }
0061 
0062 OdfChartReader::~OdfChartReader()
0063 {
0064 }
0065 
0066 
0067 // ----------------------------------------------------------------
0068 
0069 
0070 void OdfChartReader::setParent(OdfReader *parent)
0071 {
0072     m_parent = parent;
0073 }
0074 
0075 void OdfChartReader::setBackend(OdfChartReaderBackend *backend)
0076 {
0077     m_backend = backend;
0078 }
0079 
0080 void OdfChartReader::setContext(OdfReaderContext *context)
0081 {
0082     m_context = context;
0083 }
0084 
0085 
0086 // ----------------------------------------------------------------
0087 
0088 
0089 void OdfChartReader::readElementOfficeChart(KoXmlStreamReader &reader)
0090 {
0091     DEBUGSTART();
0092     m_backend->elementOfficeChart(reader, m_context);
0093 
0094     // <office:chart> has the following children in ODF 1.2:
0095     //   [done] <chart:chart> 11.1
0096     //          <table:calculation-settings> 9.4.1
0097     //          <table:consolidation> 9.7
0098     //          <table:content-validations> 9.4.4
0099     //          <table:database-ranges> 9.4.14
0100     //          <table:data-pilot-tables> 9.6.2
0101     //          <table:dde-links> 9.8
0102     //          <table:label-ranges> 9.4.10
0103     //          <table:named-expressions> 9.4.11
0104     //          <text:alphabetical-index-auto-mark-file> 8.8.3
0105     //          <text:dde-connection-decls> 14.6.2
0106     //          <text:sequence-decls> 7.4.11
0107     //          <text:user-field-decls> 7.4.7
0108     //          <text:variable-decls> 7.4.2
0109     while (reader.readNextStartElement()) {
0110         QString tagName = reader.qualifiedName().toString();
0111         
0112         if (tagName == "chart:chart") {
0113         readElementChartChart(reader);
0114         }
0115         else if (tagName == "table:calculation-settings") {
0116             // FIXME: NYI
0117             reader.skipCurrentElement();
0118         }
0119         //...  MORE else if () HERE
0120         else {
0121             reader.skipCurrentElement();
0122         }
0123     }
0124 
0125     m_backend->elementOfficeChart(reader, m_context);
0126     DEBUGEND();
0127 }
0128 
0129 void OdfChartReader::readElementChartChart(KoXmlStreamReader &reader)
0130 {
0131     DEBUGSTART();
0132     m_backend->elementChartChart(reader, m_context);
0133 
0134     // <chart:chart> has the following children in ODF 1.2:
0135     //   [done] <chart:footer> 11.2.3
0136     //   [done] <chart:legend> 11.3
0137     //   [done] <chart:plot-area> 11.4
0138     //   [done] <chart:subtitle> 11.2.2
0139     //   [done] <chart:title> 11.2.1
0140     //   [done] <table:table> 9.1.2
0141     while (reader.readNextStartElement()) {
0142         QString tagName = reader.qualifiedName().toString();
0143         
0144         if (tagName == "chart:footer") {
0145         readElementChartFooter(reader);
0146         }
0147         else if (tagName == "chart:subtitle") {
0148         readElementChartSubtitle(reader);
0149         }
0150         else if (tagName == "chart:title") {
0151         readElementChartTitle(reader);
0152         }
0153         else if (tagName == "chart:legend") {
0154         readElementChartLegend(reader);
0155         }
0156         else if (tagName == "chart:plot-area") {
0157         readElementChartPlotArea(reader);
0158         }
0159         else if (tagName == "table:table") {
0160         OdfTextReader *textReader = m_parent->textReader();
0161         if (textReader) {
0162         textReader->readElementTableTable(reader);
0163         }
0164         else {
0165         reader.skipCurrentElement();
0166         }
0167         }
0168         else {
0169             reader.skipCurrentElement();
0170         }
0171     }
0172 
0173     m_backend->elementChartChart(reader, m_context);
0174     DEBUGEND();
0175 }
0176 
0177 #define IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(readername, name)      \
0178 IMPLEMENT_READER_FUNCTION_START(readername, name)                   \
0179     while (reader.readNextStartElement()) {                         \
0180         QString tagName = reader.qualifiedName().toString();        \
0181                                                                     \
0182         if (tagName == "text:p") {                                  \
0183         OdfTextReader *textReader = m_parent->textReader();     \
0184         if (textReader) {                                       \
0185         textReader->readElementTextP(reader);               \
0186         }                                                       \
0187         else {                                                  \
0188         reader.skipCurrentElement();                        \
0189         }                                                       \
0190         }                                                           \
0191         else {                                                      \
0192             reader.skipCurrentElement();                            \
0193         }                                                           \
0194     }                                                               \
0195 IMPLEMENT_READER_FUNCTION_END(name)
0196 
0197 
0198 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartFooter)
0199 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartSubtitle)
0200 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartTitle)
0201 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartLegend)
0202 
0203 
0204 void OdfChartReader::readElementChartPlotArea(KoXmlStreamReader &reader)
0205 {
0206     DEBUGSTART();
0207     m_backend->elementChartPlotArea(reader, m_context);
0208 
0209     // <chart:plot-area> has the following children in ODF 1.2:
0210     //   [done] <chart:wall> 11.6
0211     //   [done] <chart:floor> 11.7
0212     //   [done] <chart:axis> 11.8
0213     //   [done] <chart:series> 11.11
0214     //   [done] <chart:stock-gain-marker> 11.19
0215     //   [done] <chart:stock-loss-marker> 11.20
0216     //   [done] <chart:stock-range-line> 11.21
0217     //          <dr3d:light> 10.5.3
0218     while (reader.readNextStartElement()) {
0219         QString tagName = reader.qualifiedName().toString();
0220         
0221     if (tagName == "chart:wall") {
0222         readElementChartWall(reader);
0223         }
0224         else if (tagName == "chart:floor") {
0225         readElementChartFloor(reader);
0226         }
0227         else if (tagName == "chart:axis") {
0228         readElementChartAxis(reader);
0229         }
0230         else if (tagName == "chart:series") {
0231         readElementChartSeries(reader);
0232         }
0233         else if (tagName == "chart:stock-gain-marker") {
0234         readElementChartStockGainMarker(reader);
0235         }
0236         else if (tagName == "chart:stock-loss-marker") {
0237         readElementChartStockLossMarker(reader);
0238         }
0239         else if (tagName == "chart:stock-range-line") {
0240         readElementChartStockRangeLine(reader);
0241         }
0242         else if (tagName == "dr3d:light") {
0243             // FIXME: NYI
0244             reader.skipCurrentElement();
0245         }
0246         else {
0247             reader.skipCurrentElement();
0248         }
0249     }
0250 
0251     m_backend->elementChartPlotArea(reader, m_context);
0252     DEBUGEND();
0253 }
0254 
0255 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartWall)
0256 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartFloor)
0257 
0258 void OdfChartReader::readElementChartAxis(KoXmlStreamReader &reader)
0259 {
0260     DEBUGSTART();
0261     m_backend->elementChartAxis(reader, m_context);
0262 
0263     // <chart:axis> has the following children in ODF 1.2:
0264     //   [done] <chart:categories> 11.9
0265     //   [done] <chart:grid> 11.10
0266     //   [done] <chart:title> 11.2.1
0267 
0268     while (reader.readNextStartElement()) {
0269         QString tagName = reader.qualifiedName().toString();
0270         
0271         if (tagName == "chart:categories") {
0272         readElementChartCategories(reader);
0273         }
0274         else if (tagName == "chart:grid") {
0275         readElementChartGrid(reader);
0276         }
0277         else if (tagName == "chart:title") {
0278         readElementChartTitle(reader);
0279         }
0280         else {
0281             reader.skipCurrentElement();
0282         }
0283     }
0284 
0285     m_backend->elementChartAxis(reader, m_context);
0286     DEBUGEND();
0287 }
0288 
0289 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartCategories)
0290 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartGrid)
0291 
0292 // ODF 1.2  11.11: <chart:series>
0293 void OdfChartReader::readElementChartSeries(KoXmlStreamReader &reader)
0294 {
0295     DEBUGSTART();
0296     m_backend->elementChartSeries(reader, m_context);
0297 
0298     // <chart:series> has the following children in ODF 1.2:
0299     //   [done] <chart:data-label> 11.14
0300     //   [done] <chart:data-point> 11.13
0301     //   [done] <chart:domain> 11.12
0302     //   [done] <chart:error-indicator> 11.16
0303     //   [done] <chart:mean-value> 11.15
0304     //   [done] <chart:regression-curve> 11.17
0305 
0306     while (reader.readNextStartElement()) {
0307         QString tagName = reader.qualifiedName().toString();
0308         
0309         if (tagName == "chart:data-label") {
0310         readElementChartDataLabel(reader);
0311         }
0312         else if (tagName == "chart:data-point") {
0313         readElementChartDataPoint(reader);
0314         }
0315         else if (tagName == "chart:domain") {
0316         readElementChartDomain(reader);
0317         }
0318         else if (tagName == "chart:error-indicator") {
0319         readElementChartErrorIndicator(reader);
0320         }
0321         else if (tagName == "chart:mean-value") {
0322         readElementChartMeanValue(reader);
0323         }
0324         else if (tagName == "chart:regression-curve") {
0325         readElementChartRegressionCurve(reader);
0326         }
0327         else {
0328             reader.skipCurrentElement();
0329         }
0330     }
0331 
0332     m_backend->elementChartSeries(reader, m_context);
0333     DEBUGEND();
0334 }
0335 
0336 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartDomain)          // ODF 1.2  11.12
0337 IMPLEMENT_READER_FUNCTION_ONE_CHILD(OdfChartReader, ChartDataPoint,
0338                     "chart:data-label", ChartDataLabel)     // ODF 1.2  11.13
0339 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartDataLabel)        // ODF 1.2  11.14
0340 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartMeanValue)       // ODF 1.2  11.15
0341 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartErrorIndicator)  // ODF 1.2  11.16
0342 IMPLEMENT_READER_FUNCTION_ONE_CHILD(OdfChartReader, ChartRegressionCurve,
0343                     "chart:equation", ChartEquation)        // ODF 1.2  11.17
0344 IMPLEMENT_READER_FUNCTION_TEXTP_ONLY(OdfChartReader, ChartEquation)         // ODF 1.2  11.18
0345 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartStockGainMarker) // ODF 1.2  11.19
0346 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartStockLossMarker) // ODF 1.2  11.20
0347 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfChartReader, ChartStockRangeLine)  // ODF 1.2  11.21
0348 
0349 
0350 
0351 // ----------------------------------------------------------------
0352 //                             Other functions
0353 
0354 
0355 void OdfChartReader::readUnknownElement(KoXmlStreamReader &reader)
0356 {
0357     DEBUGSTART();
0358 
0359 #if 0  // FIXME: Fix this
0360     if (m_context->isInsideParagraph()) {
0361         // readParagraphContents expect to have the reader point to the
0362         // contents of the paragraph so we have to read past the chart:p
0363         // start tag here.
0364         reader.readNext();
0365         readParagraphContents(reader);
0366     }
0367     else {
0368         while (reader.readNextStartElement()) {
0369             readTextLevelElement(reader);
0370         }
0371     }
0372 #else
0373     reader.skipCurrentElement();
0374 #endif
0375 
0376     DEBUGEND();
0377 }