File indexing completed on 2024-12-01 13:11:45

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