File indexing completed on 2024-05-12 16:29:19

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, libodf{,2}
0033 #include <KoXmlNS.h>
0034 #include <KoXmlStreamReader.h>
0035 #include <KoXmlUtils.h>
0036 
0037 // Reader library
0038 #include "OdfReader.h"
0039 #include "OdfTextReaderBackend.h"
0040 #include "OdfReaderContext.h"
0041 #include "OdfDrawReader.h"
0042 #include "OdfReaderDebug.h"
0043 
0044 
0045 #if 1
0046 static int debugIndent = 0;
0047 #define DEBUGSTART() \
0048     ++debugIndent; \
0049     DEBUG_READING("entering")
0050 #define DEBUGEND() \
0051     DEBUG_READING("exiting"); \
0052     --debugIndent
0053 #define DEBUG_READING(param) \
0054     debugOdfReader << QString("%1").arg(" ", debugIndent * 2) << param << ": " \
0055     << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \
0056     << reader.qualifiedName().toString()
0057 #else
0058 #define DEBUGSTART() \
0059     // NOTHING
0060 #define DEBUGEND() \
0061     // NOTHING
0062 #define DEBUG_READING(param) \
0063     // NOTHING
0064 #endif
0065 
0066 
0067 OdfTextReader::OdfTextReader()
0068     : m_parent(0)
0069     , m_backend(0)
0070     , m_context(0)
0071 {
0072 }
0073 
0074 OdfTextReader::~OdfTextReader()
0075 {
0076 }
0077 
0078 
0079 // ----------------------------------------------------------------
0080 
0081 
0082 void OdfTextReader::setParent(OdfReader *parent)
0083 {
0084     m_parent = parent;
0085 }
0086 
0087 void OdfTextReader::setBackend(OdfTextReaderBackend *backend)
0088 {
0089     m_backend = backend;
0090 }
0091 
0092 void OdfTextReader::setContext(OdfReaderContext *context)
0093 {
0094     m_context = context;
0095 }
0096 
0097 
0098 // ----------------------------------------------------------------
0099 
0100 
0101 #if 0
0102 // This is a template function for the reader library.
0103 // Copy this one and change the name and fill in the code.
0104 void OdfTextReader::readElementNamespaceTagname(KoXmlStreamReader &reader)
0105 {
0106    DEBUGSTART();
0107     m_backend->elementNamespaceTagname(reader, m_context);
0108 
0109     // <namespace:tagname> has the following children in ODF 1.2:
0110     //   FILL IN THE CHILDREN LIKE THIS EXAMPLE (taken from office:document-content):
0111     //          <office:automatic-styles> 3.15.3
0112     //          <office:body> 3.3
0113     //          <office:font-face-decls> 3.14
0114     //          <office:scripts> 3.12.
0115     while (reader.readNextStartElement()) {
0116         QString tagName = reader.qualifiedName().toString();
0117         
0118         if (tagName == "office:automatic-styles") {
0119             // FIXME: NYI
0120             reader.skipCurrentElement();
0121         }
0122         else if (tagName == "office:body") {
0123             readElementOfficeBody(reader);
0124         }
0125         ...  MORE else if () HERE
0126         else {
0127             reader.skipCurrentElement();
0128         }
0129     }
0130 
0131     m_backend->elementNamespaceTagname(reader, m_context);
0132     DEBUGEND();
0133 }
0134 #endif
0135 
0136 
0137 
0138 
0139 // ----------------------------------------------------------------
0140 //                         Text level functions
0141 
0142 
0143 // This function is a bit special since it doesn't handle a specific
0144 // element.  Instead it handles the common child elements between a
0145 // number of text-level elements.
0146 //
0147 void OdfTextReader::readTextLevelElement(KoXmlStreamReader &reader)
0148 {
0149     DEBUGSTART();
0150 
0151     // We should not call any backend functions here.  That is already
0152     // done in the functions that call this one.
0153 
0154     // We define the common elements on the text level as the
0155     // following list.  They are the basic text level contents that
0156     // can be found in a text box (<draw:text-box>) but also in many
0157     // other places like <table:table-cell>, <text:section>,
0158     // <office:text>, etc.
0159     //
0160     // The ones that are not text boxes can also have other children
0161     // but these are the ones we have found to be the common ones.
0162     //
0163     //          <dr3d:scene> 10.5.2
0164     //          <draw:a> 10.4.12
0165     //          <draw:caption> 10.3.11
0166     //          <draw:circle> 10.3.8
0167     //          <draw:connector> 10.3.10
0168     //          <draw:control> 10.3.13
0169     //          <draw:custom-shape> 10.6.1
0170     //          <draw:ellipse> 10.3.9
0171     //          <draw:frame> 10.4.2
0172     //          <draw:g> 10.3.15
0173     //          <draw:line> 10.3.3
0174     //          <draw:measure> 10.3.12
0175     //          <draw:page-thumbnail> 10.3.14
0176     //          <draw:path> 10.3.7
0177     //          <draw:polygon> 10.3.5
0178     //          <draw:polyline> 10.3.4
0179     //          <draw:rect> 10.3.2
0180     //          <draw:regular-polygon> 10.3.6
0181     // All of the above are sent to the draw reader.
0182     //
0183     //   [done] <table:table> 9.1.2
0184     //          <text:alphabetical-index> 8.8
0185     //          <text:bibliography> 8.9
0186     //          <text:change> 5.5.7.4
0187     //          <text:change-end> 5.5.7.3
0188     //          <text:change-start> 5.5.7.2
0189     //   [done] <text:h> 5.1.2
0190     //          <text:illustration-index> 8.4
0191     //   [done] <text:list> 5.3.1
0192     //          <text:numbered-paragraph> 5.3.6
0193     //          <text:object-index> 8.6
0194     //   [done] <text:p> 5.1.3
0195     //          <text:section> 5.4
0196     //   [done] <text:soft-page-break> 5.6
0197     //          <text:table-index> 8.5
0198     //          <text:table-of-content> 8.3
0199     //          <text:user-index> 8.7
0200 
0201     QString tagName = reader.qualifiedName().toString();
0202         
0203     if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
0204     OdfDrawReader *drawReader = m_parent->drawReader();
0205     if (drawReader) {
0206         drawReader->readCommonGraphicsElements(reader);
0207     }
0208     else {
0209         reader.skipCurrentElement();
0210     }
0211     } // draw | dr3d namespace
0212     else if (tagName == "text:h") {
0213         readElementTextH(reader);
0214     }
0215     else if (tagName == "text:p") {
0216         readElementTextP(reader);
0217     }
0218     else if (tagName == "text:list") {
0219         readElementTextList(reader);
0220     }
0221     else if (tagName == "table:table") {
0222         readElementTableTable(reader);
0223     }
0224     else if (tagName == "text:soft-page-break") {
0225         readElementTextSoftPageBreak(reader);
0226     }
0227     else {
0228         readUnknownElement(reader);
0229     }
0230 
0231     DEBUGEND();
0232 }
0233 
0234 
0235 void OdfTextReader::readElementTextH(KoXmlStreamReader &reader)
0236 {
0237     DEBUGSTART();
0238     m_backend->elementTextH(reader, m_context);
0239 
0240     // The function readParagraphContents() expects to have the reader
0241     // point to the contents of the paragraph so we have to read past
0242     // the text:h start tag here.
0243     reader.readNext();
0244     m_context->setIsInsideParagraph(true);
0245     readParagraphContents(reader);
0246     m_context->setIsInsideParagraph(false);
0247 
0248     m_backend->elementTextH(reader, m_context);
0249     DEBUGEND();
0250 }
0251 
0252 void OdfTextReader::readElementTextP(KoXmlStreamReader &reader)
0253 {
0254     DEBUGSTART();
0255     m_backend->elementTextP(reader, m_context);
0256 
0257     // The function readParagraphContents() expects to have the reader
0258     // point to the contents of the paragraph so we have to read past
0259     // the text:p start tag here.
0260     reader.readNext();
0261     m_context->setIsInsideParagraph(true);
0262     readParagraphContents(reader);
0263     m_context->setIsInsideParagraph(false);
0264 
0265     m_backend->elementTextP(reader, m_context);
0266     DEBUGEND();
0267 }
0268 
0269 void OdfTextReader::readElementTextList(KoXmlStreamReader &reader)
0270 {
0271     DEBUGSTART();
0272     m_backend->elementTextList(reader, m_context);
0273 
0274     // <text:list> has the following children in ODF 1.2:
0275     //   [done] <text:list-header> 5.3.3
0276     //   [done] <text:list-item> 5.3.4
0277 
0278     m_context->setIsInsideParagraph(true);
0279     while (reader.readNextStartElement()) {
0280         DEBUG_READING("loop-start");
0281 
0282         QString tagName = reader.qualifiedName().toString();
0283         //debugOdfReader << "list child:" << tagName;
0284         if (tagName == "text:list-item") {
0285             readElementTextListItem(reader);
0286         }
0287         else if (tagName == "text:list-header") {
0288             readElementTextListHeader(reader);
0289         }
0290         else {
0291             readUnknownElement(reader);
0292         }
0293         DEBUG_READING("loop-end");
0294     }
0295     m_context->setIsInsideParagraph(false);
0296 
0297     m_backend->elementTextList(reader, m_context);
0298     DEBUGEND();
0299 }
0300 
0301 // ----------------------------------------------------------------
0302 //                             Tables
0303 
0304 
0305 void OdfTextReader::readElementTableTable(KoXmlStreamReader &reader)
0306 {
0307     DEBUGSTART();
0308     m_backend->elementTableTable(reader, m_context);
0309 
0310     // <table:table> has the following children in ODF 1.2:
0311     //          <office:dde-source> 14.6.5
0312     //          <office:forms> 13.2
0313     //   [done] <table:desc> 9.1.14
0314     //          <table:named-expressions> 9.4.11
0315     //          <table:scenario> 9.2.7
0316     //          <table:shapes> 9.2.8
0317     //   [done] <table:table-column> 9.1.6
0318     //   [done] <table:table-column-group> 9.1.10
0319     //   [done] <table:table-columns> 9.1.12
0320     //   [done] <table:table-header-columns> 9.1.11
0321     //   [done] <table:table-header-rows> 9.1.7
0322     //   [done] <table:table-row> 9.1.3
0323     //   [done] <table:table-row-group> 9.1.9
0324     //   [done] <table:table-rows> 9.1.8
0325     //          <table:table-source> 9.2.6
0326     //   [done] <table:title> 9.1.13
0327     //   [done] <text:soft-page-break> 5.6
0328     while (reader.readNextStartElement()) {
0329         QString tagName = reader.qualifiedName().toString();
0330         
0331         if (tagName == "table:table-column") {
0332             readElementTableTableColumn(reader);
0333         }
0334         else if (tagName == "table:table-column-group") {
0335             readElementTableTableColumnGroup(reader);
0336         }
0337         else if (tagName == "table:table-columns") {
0338             readElementTableTableColumns(reader);
0339         }
0340         else if (tagName == "table:table-header-columns") {
0341             readElementTableTableHeaderColumns(reader);
0342         }
0343         else if (tagName == "table:table-header-rows") {
0344             readElementTableTableHeaderRows(reader);
0345         }
0346         else if (tagName == "table:table-row") {
0347             readElementTableTableRow(reader);
0348         }
0349         else if (tagName == "table:table-row-group") {
0350             readElementTableTableRowGroup(reader);
0351         }
0352         else if (tagName == "table:table-rows") {
0353             readElementTableTableRows(reader);
0354         }
0355         else if (tagName == "table:title") {
0356         QString value;
0357         readCharacterData(reader, value);
0358         m_backend->textVariable(tagName, value);
0359         }
0360         else if (tagName == "table:desc") {
0361         QString value;
0362         readCharacterData(reader, value);
0363         m_backend->textVariable(tagName, value);
0364         }
0365         else if (tagName == "text:soft-page-break") {
0366             readElementTextSoftPageBreak(reader);
0367         }
0368         else {
0369             reader.skipCurrentElement();
0370         }
0371     }
0372 
0373     m_backend->elementTableTable(reader, m_context);
0374     DEBUGEND();
0375 }
0376 
0377 void OdfTextReader::readElementTableTableColumnGroup(KoXmlStreamReader &reader)
0378 {
0379    DEBUGSTART();
0380     m_backend->elementTableTableColumnGroup(reader, m_context);
0381 
0382     // <table:table-column-group> has the following children in ODF 1.2:
0383     //          <table:table-header-columns> 9.1.11
0384     //          <table:table-column> 9.1.6
0385     //          <table:table-column-group> 9.1.10
0386     //          <table:table-columns> 9.1.12
0387     //
0388     while (reader.readNextStartElement()) {
0389         QString tagName = reader.qualifiedName().toString();
0390         
0391     if (tagName == "table:table-header-columns") {
0392             readElementTableTableHeaderColumns(reader);
0393         }
0394         else if (tagName == "table:table-column") {
0395             readElementTableTableColumn(reader);
0396         }
0397         else if (tagName == "table:table-column-group") {
0398             readElementTableTableColumnGroup(reader);
0399         }
0400         else if (tagName == "table:table-columns") {
0401             readElementTableTableColumns(reader);
0402         }
0403         else {
0404             reader.skipCurrentElement();
0405         }
0406     }
0407 
0408     m_backend->elementTableTableColumnGroup(reader, m_context);
0409     DEBUGEND();
0410 }
0411 
0412 void OdfTextReader::readElementTableTableColumns(KoXmlStreamReader &reader)
0413 {
0414     DEBUGSTART();
0415     m_backend->elementTableTableColumns(reader, m_context);
0416 
0417     // <table:table-columns> has the following children in ODF 1.2:
0418     //   [done] <table:table-column> 9.1.6
0419     while (reader.readNextStartElement()) {
0420         QString tagName = reader.qualifiedName().toString();
0421         
0422         if (tagName == "table:table-column") {
0423             readElementTableTableColumn(reader);
0424         }
0425         else {
0426             reader.skipCurrentElement();
0427         }
0428     }
0429 
0430     m_backend->elementTableTableColumns(reader, m_context);
0431     DEBUGEND();
0432 }
0433 
0434 void OdfTextReader::readElementTableTableHeaderColumns(KoXmlStreamReader &reader)
0435 {
0436     DEBUGSTART();
0437     m_backend->elementTableTableHeaderColumns(reader, m_context);
0438 
0439     // <table:table-header-columns> has the following children in ODF 1.2:
0440     //   [done] <table:table-column> 9.1.6
0441     while (reader.readNextStartElement()) {
0442         QString tagName = reader.qualifiedName().toString();
0443         
0444         if (tagName == "table:table-column") {
0445             readElementTableTableColumn(reader);
0446         }
0447         else {
0448             reader.skipCurrentElement();
0449         }
0450     }
0451 
0452     m_backend->elementTableTableHeaderColumns(reader, m_context);
0453     DEBUGEND();
0454 }
0455 
0456 void OdfTextReader::readElementTableTableHeaderRows(KoXmlStreamReader &reader)
0457 {
0458     DEBUGSTART();
0459     m_backend->elementTableTableHeaderRows(reader, m_context);
0460 
0461     // <table:table-header-rows> has the following children in ODF 1.2:
0462     //   [done] <table:table-row> 9.1.3
0463     //   [done] <text:soft-page-break> 5.6.
0464     while (reader.readNextStartElement()) {
0465         QString tagName = reader.qualifiedName().toString();
0466         
0467         if (tagName == "table:table-row") {
0468             readElementTableTableRow(reader);
0469         }
0470         else if (tagName == "text:soft-page-break") {
0471             readElementTextSoftPageBreak(reader);
0472         }
0473         else {
0474             reader.skipCurrentElement();
0475         }
0476     }
0477 
0478     m_backend->elementTableTableHeaderRows(reader, m_context);
0479     DEBUGEND();
0480 }
0481 
0482 void OdfTextReader::readElementTableTableColumn(KoXmlStreamReader &reader)
0483 {
0484     DEBUGSTART();
0485     m_backend->elementTableTableColumn(reader, m_context);
0486 
0487     // <table:table-column> has no children in ODF 1.2
0488     reader.skipCurrentElement();
0489 
0490     m_backend->elementTableTableColumn(reader, m_context);
0491     DEBUGEND();
0492 }
0493 
0494 void OdfTextReader::readElementTableTableRowGroup(KoXmlStreamReader &reader)
0495 {
0496    DEBUGSTART();
0497     m_backend->elementTableTableRowGroup(reader, m_context);
0498 
0499     // <table:table-row-group> has the following children in ODF 1.2:
0500     //          <table:table-header-rows> 9.1.7
0501     //          <table:table-row> 9.1.3
0502     //          <table:table-row-group> 9.1.9
0503     //          <table:table-rows> 9.1.8
0504     //          <text:soft-page-break> 5.6
0505    //
0506     while (reader.readNextStartElement()) {
0507         QString tagName = reader.qualifiedName().toString();
0508         
0509     if (tagName == "table:table-header-rows") {
0510             readElementTableTableHeaderRows(reader);
0511         }
0512         else if (tagName == "table:table-row") {
0513             readElementTableTableRow(reader);
0514         }
0515         else if (tagName == "table:table-row-group") {
0516             readElementTableTableRowGroup(reader);
0517         }
0518         else if (tagName == "table:table-rows") {
0519             readElementTableTableRows(reader);
0520         }
0521         else if (tagName == "text:soft-page-break") {
0522             readElementTextSoftPageBreak(reader);
0523         }
0524         else {
0525             reader.skipCurrentElement();
0526         }
0527     }
0528 
0529     m_backend->elementTableTableRowGroup(reader, m_context);
0530     DEBUGEND();
0531 }
0532 
0533 void OdfTextReader::readElementTableTableRow(KoXmlStreamReader &reader)
0534 {
0535     DEBUGSTART();
0536     m_backend->elementTableTableRow(reader, m_context);
0537 
0538     // <table:table-row> has the following children in ODF 1.2:
0539     //   [done] <table:covered-table-cell> 9.1.5
0540     //   [done] <table:table-cell> 9.1.4.
0541     while (reader.readNextStartElement()) {
0542         QString tagName = reader.qualifiedName().toString();
0543         
0544         if (tagName == "table:covered-table-cell") {
0545             readElementTableCoveredTableCell(reader);
0546         }
0547         else if (tagName == "table:table-cell") {
0548             readElementTableTableCell(reader);
0549         }
0550         else {
0551             reader.skipCurrentElement();
0552         }
0553     }
0554 
0555     m_backend->elementTableTableRow(reader, m_context);
0556     DEBUGEND();
0557 }
0558 
0559 void OdfTextReader::readElementTableTableRows(KoXmlStreamReader &reader)
0560 {
0561     DEBUGSTART();
0562     m_backend->elementTableTableRows(reader, m_context);
0563 
0564     // <table:table-header-rows> has the following children in ODF 1.2:
0565     //   [done] <table:table-row> 9.1.3
0566     //   [done] <text:soft-page-break> 5.6.
0567     while (reader.readNextStartElement()) {
0568         QString tagName = reader.qualifiedName().toString();
0569         
0570         if (tagName == "table:table-row") {
0571             readElementTableTableRow(reader);
0572         }
0573         else if (tagName == "text:soft-page-break") {
0574             readElementTextSoftPageBreak(reader);
0575         }
0576         else {
0577             reader.skipCurrentElement();
0578         }
0579     }
0580 
0581     m_backend->elementTableTableRows(reader, m_context);
0582     DEBUGEND();
0583 }
0584 
0585 void OdfTextReader::readElementTableTableCell(KoXmlStreamReader &reader)
0586 {
0587     DEBUGSTART();
0588     m_backend->elementTableTableCell(reader, m_context);
0589 
0590     // <table:table-cell> has the following children in ODF 1.2:
0591     //
0592     // In addition to the text level tags like <text:p> etc that can
0593     // be found in any textbox, table cell or similar, it has the
0594     // following text document children:
0595     //
0596     //   [done] <office:annotation> 14.1
0597     //          <table:cell-range-source> 9.3.1
0598     //          <table:detective> 9.3.2
0599 
0600     while (reader.readNextStartElement()) {
0601         DEBUG_READING("loop-start");
0602         
0603         QString tagName = reader.qualifiedName().toString();
0604         if (tagName == "office:annotation") {
0605         readElementOfficeAnnotation(reader);
0606         }
0607         else if (tagName == "table:cell-range-source") {
0608             // FIXME: NYI
0609             reader.skipCurrentElement();
0610         }
0611         else if (tagName == "table:detective") {
0612             // FIXME: NYI
0613             reader.skipCurrentElement();
0614         }
0615         else {
0616             readTextLevelElement(reader);
0617         }
0618         DEBUG_READING("loop-end");
0619     }
0620 
0621     m_backend->elementTableTableCell(reader, m_context);
0622     DEBUGEND();
0623 }
0624 
0625 void OdfTextReader::readElementTableCoveredTableCell(KoXmlStreamReader &reader)
0626 {
0627     DEBUGSTART();
0628     m_backend->elementTableCoveredTableCell(reader, m_context);
0629 
0630     // <table:covered-table-cell> has the following children in ODF 1.2:
0631     //
0632     // In addition to the text level tags like <text:p> etc that can
0633     // be found in any textbox, table cell or similar, it has the
0634     // following text document children:
0635     //
0636     //   [done] <office:annotation> 14.1
0637     //          <table:cell-range-source> 9.3.1
0638     //          <table:detective> 9.3.2
0639 
0640     while (reader.readNextStartElement()) {
0641         DEBUG_READING("loop-start");
0642         
0643         QString tagName = reader.qualifiedName().toString();
0644         if (tagName == "office:annotation") {
0645         readElementOfficeAnnotation(reader);
0646     }
0647         else if (tagName == "table:cell-range-source") {
0648             // FIXME: NYI
0649             reader.skipCurrentElement();
0650         }
0651         else if (tagName == "table:detective") {
0652             // FIXME: NYI
0653             reader.skipCurrentElement();
0654         }
0655         else {
0656             readTextLevelElement(reader);
0657         }
0658         DEBUG_READING("loop-end");
0659     }
0660 
0661     m_backend->elementTableCoveredTableCell(reader, m_context);
0662     DEBUGEND();
0663 }
0664 
0665 
0666 // ----------------------------------------------------------------
0667 //                     Paragraph level functions
0668 
0669 
0670 // This function is a bit special since it doesn't handle a specific
0671 // element.  Instead it handles the common child elements between a
0672 // number of paragraph-level elements.
0673 //
0674 void OdfTextReader::readParagraphContents(KoXmlStreamReader &reader)
0675 {
0676     DEBUGSTART();
0677 
0678     // We enter this function with the reader pointing to the first
0679     // element *inside* the paragraph.
0680     //
0681     // We should not call any backend functions here.  That is already
0682     // done in the functions that call this one.
0683 
0684     while (!reader.atEnd() && !reader.isEndElement()) {
0685         DEBUG_READING("loop-start");
0686 
0687         if (reader.isCharacters()) {
0688             //debugOdfReader << "Found character data";
0689             m_backend->characterData(reader, m_context);
0690             reader.readNext();
0691             continue;
0692         }
0693 
0694         if (!reader.isStartElement())
0695             continue;
0696 
0697         // We define the common elements on the paragraph level as the
0698         // following list.  They are the basic paragraph level contents that
0699         // can be found in a paragraph (text:p), heading (text:h), etc
0700         //
0701         // The common paragraph level elements are the following in ODF 1.2:
0702         //
0703         //          <dr3d:scene> 10.5.2
0704         //          <draw:a> 10.4.12
0705         //          <draw:caption> 10.3.11
0706         //          <draw:circle> 10.3.8
0707         //          <draw:connector> 10.3.10
0708         //          <draw:control> 10.3.13
0709         //          <draw:custom-shape> 10.6.1
0710         //          <draw:ellipse> 10.3.9
0711         //   [done] <draw:frame> 10.4.2
0712         //          <draw:g> 10.3.15
0713         //          <draw:line> 10.3.3
0714         //          <draw:measure> 10.3.12
0715         //          <draw:page-thumbnail> 10.3.14
0716         //          <draw:path> 10.3.7
0717         //          <draw:polygon> 10.3.5
0718         //          <draw:polyline> 10.3.4
0719         //          <draw:rect> 10.3.2
0720         //          <draw:regular-polygon> 10.3.6
0721     // All of the above are sent to the draw reader.
0722     //
0723         //   [done] <office:annotation> 14.1
0724         //   [done] <office:annotation-end> 14.2
0725         //          <presentation:date-time> 10.9.3.5
0726         //          <presentation:footer> 10.9.3.3
0727         //          <presentation:header> 10.9.3.1
0728         //   [done] <text:a> 6.1.8
0729         //          <text:alphabetical-index-mark> 8.1.10
0730         //          <text:alphabetical-index-mark-end> 8.1.9
0731         //          <text:alphabetical-index-mark-start> 8.1.8
0732         //          <text:author-initials> 7.3.7.2
0733         //          <text:author-name> 7.3.7.1
0734         //          <text:bibliography-mark> 8.1.11
0735         //          <text:bookmark> 6.2.1.2
0736         //          <text:bookmark-end> 6.2.1.4
0737         //          <text:bookmark-ref> 7.7.6
0738         //          <text:bookmark-start> 6.2.1.3
0739         //          <text:change> 5.5.7.4
0740         //          <text:change-end> 5.5.7.3
0741         //          <text:change-start> 5.5.7.2
0742         //          <text:chapter> 7.3.8
0743         //          <text:character-count> 7.5.18.5
0744         //          <text:conditional-text> 7.7.3
0745         //          <text:creation-date> 7.5.3
0746         //          <text:creation-time> 7.5.4
0747         //          <text:creator> 7.5.17
0748         //          <text:database-display> 7.6.3
0749         //          <text:database-name> 7.6.7
0750         //          <text:database-next> 7.6.4
0751         //          <text:database-row-number> 7.6.6
0752         //          <text:database-row-select> 7.6.5
0753         //          <text:date> 7.3.2
0754         //          <text:dde-connection> 7.7.12
0755         //          <text:description> 7.5.5
0756         //          <text:editing-cycles> 7.5.13
0757         //          <text:editing-duration> 7.5.14
0758         //          <text:execute-macro> 7.7.10
0759         //          <text:expression> 7.4.14
0760         //          <text:file-name> 7.3.9
0761         //          <text:hidden-paragraph> 7.7.11
0762         //          <text:hidden-text> 7.7.4
0763         //          <text:image-count> 7.5.18.7
0764         //          <text:initial-creator> 7.5.2
0765         //          <text:keywords> 7.5.12
0766         //   [done] <text:line-break> 6.1.5
0767         //          <text:measure> 7.7.13
0768         //          <text:meta> 6.1.9
0769         //          <text:meta-field> 7.5.19
0770         //          <text:modification-date> 7.5.16
0771         //          <text:modification-time> 7.5.15
0772         //          <text:note> 6.3.2
0773         //          <text:note-ref> 7.7.7
0774         //          <text:object-count> 7.5.18.8
0775         //          <text:page-continuation> 7.3.5
0776         //          <text:page-count> 7.5.18.2
0777         //          <text:page-number> 7.3.4
0778         //          <text:page-variable-get> 7.7.1.3
0779         //          <text:page-variable-set> 7.7.1.2
0780         //          <text:paragraph-count> 7.5.18.3
0781         //          <text:placeholder> 7.7.2
0782         //          <text:print-date> 7.5.8
0783         //          <text:printed-by> 7.5.9
0784         //          <text:print-time> 7.5.7
0785         //          <text:reference-mark> 6.2.2.2
0786         //          <text:reference-mark-end> 6.2.2.4
0787         //          <text:reference-mark-start> 6.2.2.3
0788         //          <text:reference-ref> 7.7.5
0789         //          <text:ruby> 6.4
0790         //   [done] <text:s> 6.1.3
0791         //          <text:script> 7.7.9
0792         //          <text:sender-city> 7.3.6.13
0793         //          <text:sender-company> 7.3.6.10
0794         //          <text:sender-country> 7.3.6.15
0795         //          <text:sender-email> 7.3.6.7
0796         //          <text:sender-fax> 7.3.6.9
0797         //          <text:sender-firstname> 7.3.6.2
0798         //          <text:sender-initials> 7.3.6.4
0799         //          <text:sender-lastname> 7.3.6.3
0800         //          <text:sender-phone-private> 7.3.6.8
0801         //          <text:sender-phone-work> 7.3.6.11
0802         //          <text:sender-position> 7.3.6.6
0803         //          <text:sender-postal-code> 7.3.6.14
0804         //          <text:sender-state-or-province> 7.3.6.16
0805         //          <text:sender-street> 7.3.6.12
0806         //          <text:sender-title> 7.3.6.5
0807         //          <text:sequence> 7.4.13
0808         //          <text:sequence-ref> 7.7.8
0809         //          <text:sheet-name> 7.3.11
0810         //   [done] <text:soft-page-break> 5.6
0811         //   [done] <text:span> 6.1.7
0812         //          <text:subject> 7.5.11
0813         //          <text:tab> 6.1.4
0814         //          <text:table-count> 7.5.18.6
0815         //          <text:table-formula> 7.7.14
0816         //          <text:template-name> 7.3.10
0817         //          <text:text-input> 7.4.15
0818         //          <text:time> 7.3.3
0819         //          <text:title> 7.5.10
0820         //          <text:toc-mark> 8.1.4
0821         //          <text:toc-mark-end> 8.1.3
0822         //          <text:toc-mark-start> 8.1.2
0823         //          <text:user-defined> 7.5.6
0824         //          <text:user-field-get> 7.4.9
0825         //          <text:user-field-input> 7.4.10
0826         //          <text:user-index-mark> 8.1.7
0827         //          <text:user-index-mark-end> 8.1.6
0828         //          <text:user-index-mark-start> 8.1.5
0829         //          <text:variable-get> 7.4.5
0830         //          <text:variable-input> 7.4.6
0831         //          <text:variable-set> 7.4.4
0832         //          <text:word-count> 7.5.18.4.
0833         //        
0834         // FIXME: Only very few tags are handled right now.
0835 
0836         QString tagName = reader.qualifiedName().toString();
0837 
0838     if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
0839         OdfDrawReader *drawReader = m_parent->drawReader();
0840         if (drawReader) {
0841         drawReader->readCommonGraphicsElements(reader);
0842         }
0843         else {
0844         reader.skipCurrentElement();
0845         }
0846         } // draw | dr3d namespace
0847         else if (reader.prefix() == "office") {
0848             if (tagName == "office:annotation") {
0849                 readElementOfficeAnnotation(reader);
0850             }
0851             else if (tagName == "office:annotation-end") {
0852                 readElementOfficeAnnotationEnd(reader);
0853             }
0854             else {
0855                 // Unknown office: element
0856                 readUnknownElement(reader);
0857             }
0858         } // office namespace
0859         else if (reader.prefix() == "text") {
0860 
0861             if (tagName == "text:a") {
0862                 readElementTextA(reader);
0863             }
0864             else if (tagName == "text:line-break") {
0865                 readElementTextLineBreak(reader);
0866             }
0867             else if (tagName == "text:span") {
0868                 readElementTextSpan(reader);
0869             }
0870             else if (tagName == "text:s") {
0871                 readElementTextS(reader);
0872             }
0873             else if (tagName == "text:soft-page-break") {
0874                 readElementTextSoftPageBreak(reader);
0875             }
0876             else {
0877                 // Unknown text: element
0878                 readUnknownElement(reader);
0879             }
0880         } // text namespace
0881         else {
0882             // Unknown namespace
0883             readUnknownElement(reader);
0884         }
0885 
0886         // Read past the end tag of the just parsed element.
0887         reader.readNext();
0888         DEBUG_READING("loop-end");
0889     }
0890 
0891     DEBUGEND();
0892 }
0893 
0894 void OdfTextReader::readElementOfficeAnnotation(KoXmlStreamReader &reader)
0895 {
0896     DEBUGSTART();
0897     m_backend->elementOfficeAnnotation(reader, m_context);
0898 
0899     // <office:annotation> has the following children in ODF 1.2:
0900     //   [done] <dc:creator> 4.3.2.7
0901     //   [done] <dc:date> 4.3.2.10
0902     //   [done] <meta:date-string> 14.3
0903     //   [done] <text:list> 5.3.1
0904     //   [done] <text:p> 5.1.3
0905     while (reader.readNextStartElement()) {
0906         QString tagName = reader.qualifiedName().toString();
0907 
0908         if (tagName == "dc:creator") {
0909             readElementDcCreator(reader);
0910         }
0911         else if (tagName == "dc:date") {
0912             readElementDcDate(reader);
0913         }
0914         else if (tagName == "meta:date-string") {
0915         QString value;
0916         readCharacterData(reader, value);
0917         m_backend->textVariable(tagName, value);
0918         }
0919         else if (tagName == "text:list") {
0920             readElementTextList(reader);
0921         }
0922         else if (tagName == "text:p") {
0923             readElementTextP(reader);
0924         }
0925         else {
0926             reader.skipCurrentElement();
0927         }
0928     }
0929 
0930     m_backend->elementOfficeAnnotation(reader, m_context);
0931     DEBUGEND();
0932 }
0933 
0934 void OdfTextReader::readElementOfficeAnnotationEnd(KoXmlStreamReader &reader)
0935 {
0936     DEBUGSTART();
0937     m_backend->elementOfficeAnnotationEnd(reader, m_context);
0938 
0939     // <office:annotation-end> has no children in ODF 1.2:
0940     // FIXME: Skip current element or call parseUnknownElement?
0941     reader.skipCurrentElement();
0942 
0943     m_backend->elementOfficeAnnotationEnd(reader, m_context);
0944     DEBUGEND();
0945 }
0946 
0947 void OdfTextReader::readElementDcCreator(KoXmlStreamReader &reader)
0948 {
0949     DEBUGSTART();
0950     m_backend->elementDcCreator(reader, m_context);
0951 
0952     reader.readNext();
0953     readParagraphContents(reader);
0954 
0955     m_backend->elementDcCreator(reader, m_context);
0956     DEBUGEND();
0957 }
0958 
0959 void OdfTextReader::readElementDcDate(KoXmlStreamReader &reader)
0960 {
0961     DEBUGSTART();
0962     m_backend->elementDcDate(reader, m_context);
0963 
0964     reader.readNext();
0965     readParagraphContents(reader);
0966 
0967     m_backend->elementDcDate(reader, m_context);
0968     DEBUGEND();
0969 }
0970 
0971 void OdfTextReader::readElementTextA(KoXmlStreamReader &reader)
0972 {
0973     DEBUGSTART();
0974     m_backend->elementTextA(reader, m_context);
0975 
0976     // readParagraphContents expect to have the reader point to the
0977     // contents of the paragraph so we have to read past the text:a
0978     // start tag here.
0979     reader.readNext();
0980     readParagraphContents(reader);
0981 
0982     m_backend->elementTextA(reader, m_context);
0983     DEBUGEND();
0984 }
0985 
0986 void OdfTextReader::readElementTextLineBreak(KoXmlStreamReader &reader)
0987 {
0988     DEBUGSTART();
0989     m_backend->elementTextLineBreak(reader, m_context);
0990 
0991     // This element has no child elements in ODF 1.2.
0992     reader.skipCurrentElement();
0993 
0994     m_backend->elementTextLineBreak(reader, m_context);
0995     DEBUGEND();
0996 }
0997 
0998 void OdfTextReader::readElementTextS(KoXmlStreamReader &reader)
0999 {
1000     DEBUGSTART();
1001     m_backend->elementTextS(reader, m_context);
1002 
1003     // This element has no child elements in ODF 1.2.
1004     reader.skipCurrentElement();
1005 
1006     m_backend->elementTextS(reader, m_context);
1007     DEBUGEND();
1008 }
1009 
1010 void OdfTextReader::readElementTextSpan(KoXmlStreamReader &reader)
1011 {
1012     DEBUGSTART();
1013     m_backend->elementTextSpan(reader, m_context);
1014 
1015     reader.readNext();
1016     readParagraphContents(reader);
1017 
1018     m_backend->elementTextSpan(reader, m_context);
1019     DEBUGEND();
1020 }
1021 
1022 
1023 // ----------------------------------------------------------------
1024 //                        List level functions
1025 
1026 
1027 void OdfTextReader::readElementTextListHeader(KoXmlStreamReader &reader)
1028 {
1029     DEBUGSTART();
1030     m_backend->elementTextListHeader(reader, m_context);
1031 
1032     // <text:list-header> has the following children in ODF 1.2:
1033     //   [done] <text:h> 5.1.2
1034     //   [done] <text:p> 5.1.3
1035     //   [done] <text:list> 5.3.1
1036     //   [done] <text:soft-page-break> 5.6
1037     //          <text:number> 6.1.10
1038     while(reader.readNextStartElement()) {
1039     DEBUG_READING("loop-start");
1040 
1041     QString tagName = reader.qualifiedName().toString();
1042     if (tagName == "text:h") {
1043         readElementTextH(reader);
1044     }
1045     else if (tagName == "text:p") {
1046         readElementTextP(reader);
1047     }
1048     else if (tagName == "text:list") {
1049         readElementTextList(reader);
1050     }
1051         else if (tagName == "text:soft-page-break") {
1052         readElementTextSoftPageBreak(reader);
1053         }
1054         else if (tagName == "text:number") {
1055             // FIXME: NYI
1056             reader.skipCurrentElement();
1057         }
1058     else {
1059         readUnknownElement(reader);
1060     }
1061 
1062     DEBUG_READING("loop-end");
1063     }
1064 
1065     m_backend->elementTextListHeader(reader, m_context);
1066     DEBUGEND();
1067 }
1068 
1069 void OdfTextReader::readElementTextListItem(KoXmlStreamReader &reader)
1070 {
1071     DEBUGSTART();
1072     m_backend->elementTextListItem(reader, m_context);
1073 
1074     // <text:list-item> has the following children in ODF 1.2:
1075     //   [done] <text:h> 5.1.2
1076     //   [done] <text:p> 5.1.3
1077     //   [done] <text:list> 5.3.1
1078     //   [done] <text:soft-page-break> 5.6
1079     //          <text:number> 6.1.10
1080     while(reader.readNextStartElement()) {
1081         DEBUG_READING("loop-start");
1082 
1083         QString tagName = reader.qualifiedName().toString();
1084         debugOdfReader <<tagName;
1085     if (tagName == "text:h") {
1086         readElementTextH(reader);
1087     }
1088     else if (tagName == "text:p") {
1089         readElementTextP(reader);
1090     }
1091         else if (tagName == "text:list") {
1092             readElementTextList(reader);
1093         }
1094         else if (tagName == "text:soft-page-break") {
1095         readElementTextSoftPageBreak(reader);
1096         }
1097         else if (tagName == "text:number") {
1098             //FIXME
1099             reader.skipCurrentElement();
1100         }
1101         else {
1102             readUnknownElement(reader);
1103         }
1104 
1105     DEBUG_READING("loop-end");
1106     }
1107 
1108     m_backend->elementTextListItem(reader, m_context);
1109     DEBUGEND();
1110 }
1111 
1112 // ----------------------------------------------------------------
1113 //                             Other functions
1114 
1115 
1116 void OdfTextReader::readElementTextSoftPageBreak(KoXmlStreamReader &reader)
1117 {
1118     DEBUGSTART();
1119     m_backend->elementTextSoftPageBreak(reader, m_context);
1120 
1121     // <text:soft-page-break> has no children in ODF 1.2
1122     reader.skipCurrentElement();
1123 
1124     m_backend->elementTextSoftPageBreak(reader, m_context);
1125     DEBUGEND();
1126 }
1127 
1128 
1129 void OdfTextReader::readUnknownElement(KoXmlStreamReader &reader)
1130 {
1131     DEBUGSTART();
1132 
1133     if (m_context->isInsideParagraph()) {
1134         // readParagraphContents expect to have the reader point to the
1135         // contents of the paragraph so we have to read past the text:p
1136         // start tag here.
1137         reader.readNext();
1138         readParagraphContents(reader);
1139     }
1140     else {
1141         while (reader.readNextStartElement()) {
1142             readTextLevelElement(reader);
1143         }
1144     }
1145 
1146     DEBUGEND();
1147 }
1148