File indexing completed on 2025-04-20 13:00:01
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