1 /* This file is part of the KDE project
2
3 Copyright (C) 2012-2013 Inge Wallin <inge@lysator.liu.se>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19 */
20
21
22 // Own
23 #include "OdfTextReader.h"
24
25 // Qt
26 #include <QStringList>
27 #include <QBuffer>
28
29 // KF5
30 #include <klocalizedstring.h>
31
32 // Calligra, libodf{,2}
33 #include <KoXmlNS.h>
34 #include <KoXmlStreamReader.h>
35 #include <KoXmlUtils.h>
36
37 // Reader library
38 #include "OdfReader.h"
39 #include "OdfTextReaderBackend.h"
40 #include "OdfReaderContext.h"
41 #include "OdfDrawReader.h"
42 #include "OdfReaderDebug.h"
43
44
45 #if 1
46 static int debugIndent = 0;
47 #define DEBUGSTART() \
48 ++debugIndent; \
49 DEBUG_READING("entering")
50 #define DEBUGEND() \
51 DEBUG_READING("exiting"); \
52 --debugIndent
53 #define DEBUG_READING(param) \
54 debugOdfReader << QString("%1").arg(" ", debugIndent * 2) << param << ": " \
55 << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \
56 << reader.qualifiedName().toString()
57 #else
58 #define DEBUGSTART() \
59 // NOTHING
60 #define DEBUGEND() \
61 // NOTHING
62 #define DEBUG_READING(param) \
63 // NOTHING
64 #endif
65
66
OdfTextReader()67 OdfTextReader::OdfTextReader()
68 : m_parent(0)
69 , m_backend(0)
70 , m_context(0)
71 {
72 }
73
~OdfTextReader()74 OdfTextReader::~OdfTextReader()
75 {
76 }
77
78
79 // ----------------------------------------------------------------
80
81
setParent(OdfReader * parent)82 void OdfTextReader::setParent(OdfReader *parent)
83 {
84 m_parent = parent;
85 }
86
setBackend(OdfTextReaderBackend * backend)87 void OdfTextReader::setBackend(OdfTextReaderBackend *backend)
88 {
89 m_backend = backend;
90 }
91
setContext(OdfReaderContext * context)92 void OdfTextReader::setContext(OdfReaderContext *context)
93 {
94 m_context = context;
95 }
96
97
98 // ----------------------------------------------------------------
99
100
101 #if 0
102 // This is a template function for the reader library.
103 // Copy this one and change the name and fill in the code.
104 void OdfTextReader::readElementNamespaceTagname(KoXmlStreamReader &reader)
105 {
106 DEBUGSTART();
107 m_backend->elementNamespaceTagname(reader, m_context);
108
109 // <namespace:tagname> has the following children in ODF 1.2:
110 // FILL IN THE CHILDREN LIKE THIS EXAMPLE (taken from office:document-content):
111 // <office:automatic-styles> 3.15.3
112 // <office:body> 3.3
113 // <office:font-face-decls> 3.14
114 // <office:scripts> 3.12.
115 while (reader.readNextStartElement()) {
116 QString tagName = reader.qualifiedName().toString();
117
118 if (tagName == "office:automatic-styles") {
119 // FIXME: NYI
120 reader.skipCurrentElement();
121 }
122 else if (tagName == "office:body") {
123 readElementOfficeBody(reader);
124 }
125 ... MORE else if () HERE
126 else {
127 reader.skipCurrentElement();
128 }
129 }
130
131 m_backend->elementNamespaceTagname(reader, m_context);
132 DEBUGEND();
133 }
134 #endif
135
136
137
138
139 // ----------------------------------------------------------------
140 // Text level functions
141
142
143 // This function is a bit special since it doesn't handle a specific
144 // element. Instead it handles the common child elements between a
145 // number of text-level elements.
146 //
readTextLevelElement(KoXmlStreamReader & reader)147 void OdfTextReader::readTextLevelElement(KoXmlStreamReader &reader)
148 {
149 DEBUGSTART();
150
151 // We should not call any backend functions here. That is already
152 // done in the functions that call this one.
153
154 // We define the common elements on the text level as the
155 // following list. They are the basic text level contents that
156 // can be found in a text box (<draw:text-box>) but also in many
157 // other places like <table:table-cell>, <text:section>,
158 // <office:text>, etc.
159 //
160 // The ones that are not text boxes can also have other children
161 // but these are the ones we have found to be the common ones.
162 //
163 // <dr3d:scene> 10.5.2
164 // <draw:a> 10.4.12
165 // <draw:caption> 10.3.11
166 // <draw:circle> 10.3.8
167 // <draw:connector> 10.3.10
168 // <draw:control> 10.3.13
169 // <draw:custom-shape> 10.6.1
170 // <draw:ellipse> 10.3.9
171 // <draw:frame> 10.4.2
172 // <draw:g> 10.3.15
173 // <draw:line> 10.3.3
174 // <draw:measure> 10.3.12
175 // <draw:page-thumbnail> 10.3.14
176 // <draw:path> 10.3.7
177 // <draw:polygon> 10.3.5
178 // <draw:polyline> 10.3.4
179 // <draw:rect> 10.3.2
180 // <draw:regular-polygon> 10.3.6
181 // All of the above are sent to the draw reader.
182 //
183 // [done] <table:table> 9.1.2
184 // <text:alphabetical-index> 8.8
185 // <text:bibliography> 8.9
186 // <text:change> 5.5.7.4
187 // <text:change-end> 5.5.7.3
188 // <text:change-start> 5.5.7.2
189 // [done] <text:h> 5.1.2
190 // <text:illustration-index> 8.4
191 // [done] <text:list> 5.3.1
192 // <text:numbered-paragraph> 5.3.6
193 // <text:object-index> 8.6
194 // [done] <text:p> 5.1.3
195 // <text:section> 5.4
196 // [done] <text:soft-page-break> 5.6
197 // <text:table-index> 8.5
198 // <text:table-of-content> 8.3
199 // <text:user-index> 8.7
200
201 QString tagName = reader.qualifiedName().toString();
202
203 if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
204 OdfDrawReader *drawReader = m_parent->drawReader();
205 if (drawReader) {
206 drawReader->readCommonGraphicsElements(reader);
207 }
208 else {
209 reader.skipCurrentElement();
210 }
211 } // draw | dr3d namespace
212 else if (tagName == "text:h") {
213 readElementTextH(reader);
214 }
215 else if (tagName == "text:p") {
216 readElementTextP(reader);
217 }
218 else if (tagName == "text:list") {
219 readElementTextList(reader);
220 }
221 else if (tagName == "table:table") {
222 readElementTableTable(reader);
223 }
224 else if (tagName == "text:soft-page-break") {
225 readElementTextSoftPageBreak(reader);
226 }
227 else {
228 readUnknownElement(reader);
229 }
230
231 DEBUGEND();
232 }
233
234
readElementTextH(KoXmlStreamReader & reader)235 void OdfTextReader::readElementTextH(KoXmlStreamReader &reader)
236 {
237 DEBUGSTART();
238 m_backend->elementTextH(reader, m_context);
239
240 // The function readParagraphContents() expects to have the reader
241 // point to the contents of the paragraph so we have to read past
242 // the text:h start tag here.
243 reader.readNext();
244 m_context->setIsInsideParagraph(true);
245 readParagraphContents(reader);
246 m_context->setIsInsideParagraph(false);
247
248 m_backend->elementTextH(reader, m_context);
249 DEBUGEND();
250 }
251
readElementTextP(KoXmlStreamReader & reader)252 void OdfTextReader::readElementTextP(KoXmlStreamReader &reader)
253 {
254 DEBUGSTART();
255 m_backend->elementTextP(reader, m_context);
256
257 // The function readParagraphContents() expects to have the reader
258 // point to the contents of the paragraph so we have to read past
259 // the text:p start tag here.
260 reader.readNext();
261 m_context->setIsInsideParagraph(true);
262 readParagraphContents(reader);
263 m_context->setIsInsideParagraph(false);
264
265 m_backend->elementTextP(reader, m_context);
266 DEBUGEND();
267 }
268
readElementTextList(KoXmlStreamReader & reader)269 void OdfTextReader::readElementTextList(KoXmlStreamReader &reader)
270 {
271 DEBUGSTART();
272 m_backend->elementTextList(reader, m_context);
273
274 // <text:list> has the following children in ODF 1.2:
275 // [done] <text:list-header> 5.3.3
276 // [done] <text:list-item> 5.3.4
277
278 m_context->setIsInsideParagraph(true);
279 while (reader.readNextStartElement()) {
280 DEBUG_READING("loop-start");
281
282 QString tagName = reader.qualifiedName().toString();
283 //debugOdfReader << "list child:" << tagName;
284 if (tagName == "text:list-item") {
285 readElementTextListItem(reader);
286 }
287 else if (tagName == "text:list-header") {
288 readElementTextListHeader(reader);
289 }
290 else {
291 readUnknownElement(reader);
292 }
293 DEBUG_READING("loop-end");
294 }
295 m_context->setIsInsideParagraph(false);
296
297 m_backend->elementTextList(reader, m_context);
298 DEBUGEND();
299 }
300
301 // ----------------------------------------------------------------
302 // Tables
303
304
readElementTableTable(KoXmlStreamReader & reader)305 void OdfTextReader::readElementTableTable(KoXmlStreamReader &reader)
306 {
307 DEBUGSTART();
308 m_backend->elementTableTable(reader, m_context);
309
310 // <table:table> has the following children in ODF 1.2:
311 // <office:dde-source> 14.6.5
312 // <office:forms> 13.2
313 // [done] <table:desc> 9.1.14
314 // <table:named-expressions> 9.4.11
315 // <table:scenario> 9.2.7
316 // <table:shapes> 9.2.8
317 // [done] <table:table-column> 9.1.6
318 // [done] <table:table-column-group> 9.1.10
319 // [done] <table:table-columns> 9.1.12
320 // [done] <table:table-header-columns> 9.1.11
321 // [done] <table:table-header-rows> 9.1.7
322 // [done] <table:table-row> 9.1.3
323 // [done] <table:table-row-group> 9.1.9
324 // [done] <table:table-rows> 9.1.8
325 // <table:table-source> 9.2.6
326 // [done] <table:title> 9.1.13
327 // [done] <text:soft-page-break> 5.6
328 while (reader.readNextStartElement()) {
329 QString tagName = reader.qualifiedName().toString();
330
331 if (tagName == "table:table-column") {
332 readElementTableTableColumn(reader);
333 }
334 else if (tagName == "table:table-column-group") {
335 readElementTableTableColumnGroup(reader);
336 }
337 else if (tagName == "table:table-columns") {
338 readElementTableTableColumns(reader);
339 }
340 else if (tagName == "table:table-header-columns") {
341 readElementTableTableHeaderColumns(reader);
342 }
343 else if (tagName == "table:table-header-rows") {
344 readElementTableTableHeaderRows(reader);
345 }
346 else if (tagName == "table:table-row") {
347 readElementTableTableRow(reader);
348 }
349 else if (tagName == "table:table-row-group") {
350 readElementTableTableRowGroup(reader);
351 }
352 else if (tagName == "table:table-rows") {
353 readElementTableTableRows(reader);
354 }
355 else if (tagName == "table:title") {
356 QString value;
357 readCharacterData(reader, value);
358 m_backend->textVariable(tagName, value);
359 }
360 else if (tagName == "table:desc") {
361 QString value;
362 readCharacterData(reader, value);
363 m_backend->textVariable(tagName, value);
364 }
365 else if (tagName == "text:soft-page-break") {
366 readElementTextSoftPageBreak(reader);
367 }
368 else {
369 reader.skipCurrentElement();
370 }
371 }
372
373 m_backend->elementTableTable(reader, m_context);
374 DEBUGEND();
375 }
376
readElementTableTableColumnGroup(KoXmlStreamReader & reader)377 void OdfTextReader::readElementTableTableColumnGroup(KoXmlStreamReader &reader)
378 {
379 DEBUGSTART();
380 m_backend->elementTableTableColumnGroup(reader, m_context);
381
382 // <table:table-column-group> has the following children in ODF 1.2:
383 // <table:table-header-columns> 9.1.11
384 // <table:table-column> 9.1.6
385 // <table:table-column-group> 9.1.10
386 // <table:table-columns> 9.1.12
387 //
388 while (reader.readNextStartElement()) {
389 QString tagName = reader.qualifiedName().toString();
390
391 if (tagName == "table:table-header-columns") {
392 readElementTableTableHeaderColumns(reader);
393 }
394 else if (tagName == "table:table-column") {
395 readElementTableTableColumn(reader);
396 }
397 else if (tagName == "table:table-column-group") {
398 readElementTableTableColumnGroup(reader);
399 }
400 else if (tagName == "table:table-columns") {
401 readElementTableTableColumns(reader);
402 }
403 else {
404 reader.skipCurrentElement();
405 }
406 }
407
408 m_backend->elementTableTableColumnGroup(reader, m_context);
409 DEBUGEND();
410 }
411
readElementTableTableColumns(KoXmlStreamReader & reader)412 void OdfTextReader::readElementTableTableColumns(KoXmlStreamReader &reader)
413 {
414 DEBUGSTART();
415 m_backend->elementTableTableColumns(reader, m_context);
416
417 // <table:table-columns> has the following children in ODF 1.2:
418 // [done] <table:table-column> 9.1.6
419 while (reader.readNextStartElement()) {
420 QString tagName = reader.qualifiedName().toString();
421
422 if (tagName == "table:table-column") {
423 readElementTableTableColumn(reader);
424 }
425 else {
426 reader.skipCurrentElement();
427 }
428 }
429
430 m_backend->elementTableTableColumns(reader, m_context);
431 DEBUGEND();
432 }
433
readElementTableTableHeaderColumns(KoXmlStreamReader & reader)434 void OdfTextReader::readElementTableTableHeaderColumns(KoXmlStreamReader &reader)
435 {
436 DEBUGSTART();
437 m_backend->elementTableTableHeaderColumns(reader, m_context);
438
439 // <table:table-header-columns> has the following children in ODF 1.2:
440 // [done] <table:table-column> 9.1.6
441 while (reader.readNextStartElement()) {
442 QString tagName = reader.qualifiedName().toString();
443
444 if (tagName == "table:table-column") {
445 readElementTableTableColumn(reader);
446 }
447 else {
448 reader.skipCurrentElement();
449 }
450 }
451
452 m_backend->elementTableTableHeaderColumns(reader, m_context);
453 DEBUGEND();
454 }
455
readElementTableTableHeaderRows(KoXmlStreamReader & reader)456 void OdfTextReader::readElementTableTableHeaderRows(KoXmlStreamReader &reader)
457 {
458 DEBUGSTART();
459 m_backend->elementTableTableHeaderRows(reader, m_context);
460
461 // <table:table-header-rows> has the following children in ODF 1.2:
462 // [done] <table:table-row> 9.1.3
463 // [done] <text:soft-page-break> 5.6.
464 while (reader.readNextStartElement()) {
465 QString tagName = reader.qualifiedName().toString();
466
467 if (tagName == "table:table-row") {
468 readElementTableTableRow(reader);
469 }
470 else if (tagName == "text:soft-page-break") {
471 readElementTextSoftPageBreak(reader);
472 }
473 else {
474 reader.skipCurrentElement();
475 }
476 }
477
478 m_backend->elementTableTableHeaderRows(reader, m_context);
479 DEBUGEND();
480 }
481
readElementTableTableColumn(KoXmlStreamReader & reader)482 void OdfTextReader::readElementTableTableColumn(KoXmlStreamReader &reader)
483 {
484 DEBUGSTART();
485 m_backend->elementTableTableColumn(reader, m_context);
486
487 // <table:table-column> has no children in ODF 1.2
488 reader.skipCurrentElement();
489
490 m_backend->elementTableTableColumn(reader, m_context);
491 DEBUGEND();
492 }
493
readElementTableTableRowGroup(KoXmlStreamReader & reader)494 void OdfTextReader::readElementTableTableRowGroup(KoXmlStreamReader &reader)
495 {
496 DEBUGSTART();
497 m_backend->elementTableTableRowGroup(reader, m_context);
498
499 // <table:table-row-group> has the following children in ODF 1.2:
500 // <table:table-header-rows> 9.1.7
501 // <table:table-row> 9.1.3
502 // <table:table-row-group> 9.1.9
503 // <table:table-rows> 9.1.8
504 // <text:soft-page-break> 5.6
505 //
506 while (reader.readNextStartElement()) {
507 QString tagName = reader.qualifiedName().toString();
508
509 if (tagName == "table:table-header-rows") {
510 readElementTableTableHeaderRows(reader);
511 }
512 else if (tagName == "table:table-row") {
513 readElementTableTableRow(reader);
514 }
515 else if (tagName == "table:table-row-group") {
516 readElementTableTableRowGroup(reader);
517 }
518 else if (tagName == "table:table-rows") {
519 readElementTableTableRows(reader);
520 }
521 else if (tagName == "text:soft-page-break") {
522 readElementTextSoftPageBreak(reader);
523 }
524 else {
525 reader.skipCurrentElement();
526 }
527 }
528
529 m_backend->elementTableTableRowGroup(reader, m_context);
530 DEBUGEND();
531 }
532
readElementTableTableRow(KoXmlStreamReader & reader)533 void OdfTextReader::readElementTableTableRow(KoXmlStreamReader &reader)
534 {
535 DEBUGSTART();
536 m_backend->elementTableTableRow(reader, m_context);
537
538 // <table:table-row> has the following children in ODF 1.2:
539 // [done] <table:covered-table-cell> 9.1.5
540 // [done] <table:table-cell> 9.1.4.
541 while (reader.readNextStartElement()) {
542 QString tagName = reader.qualifiedName().toString();
543
544 if (tagName == "table:covered-table-cell") {
545 readElementTableCoveredTableCell(reader);
546 }
547 else if (tagName == "table:table-cell") {
548 readElementTableTableCell(reader);
549 }
550 else {
551 reader.skipCurrentElement();
552 }
553 }
554
555 m_backend->elementTableTableRow(reader, m_context);
556 DEBUGEND();
557 }
558
readElementTableTableRows(KoXmlStreamReader & reader)559 void OdfTextReader::readElementTableTableRows(KoXmlStreamReader &reader)
560 {
561 DEBUGSTART();
562 m_backend->elementTableTableRows(reader, m_context);
563
564 // <table:table-header-rows> has the following children in ODF 1.2:
565 // [done] <table:table-row> 9.1.3
566 // [done] <text:soft-page-break> 5.6.
567 while (reader.readNextStartElement()) {
568 QString tagName = reader.qualifiedName().toString();
569
570 if (tagName == "table:table-row") {
571 readElementTableTableRow(reader);
572 }
573 else if (tagName == "text:soft-page-break") {
574 readElementTextSoftPageBreak(reader);
575 }
576 else {
577 reader.skipCurrentElement();
578 }
579 }
580
581 m_backend->elementTableTableRows(reader, m_context);
582 DEBUGEND();
583 }
584
readElementTableTableCell(KoXmlStreamReader & reader)585 void OdfTextReader::readElementTableTableCell(KoXmlStreamReader &reader)
586 {
587 DEBUGSTART();
588 m_backend->elementTableTableCell(reader, m_context);
589
590 // <table:table-cell> has the following children in ODF 1.2:
591 //
592 // In addition to the text level tags like <text:p> etc that can
593 // be found in any textbox, table cell or similar, it has the
594 // following text document children:
595 //
596 // [done] <office:annotation> 14.1
597 // <table:cell-range-source> 9.3.1
598 // <table:detective> 9.3.2
599
600 while (reader.readNextStartElement()) {
601 DEBUG_READING("loop-start");
602
603 QString tagName = reader.qualifiedName().toString();
604 if (tagName == "office:annotation") {
605 readElementOfficeAnnotation(reader);
606 }
607 else if (tagName == "table:cell-range-source") {
608 // FIXME: NYI
609 reader.skipCurrentElement();
610 }
611 else if (tagName == "table:detective") {
612 // FIXME: NYI
613 reader.skipCurrentElement();
614 }
615 else {
616 readTextLevelElement(reader);
617 }
618 DEBUG_READING("loop-end");
619 }
620
621 m_backend->elementTableTableCell(reader, m_context);
622 DEBUGEND();
623 }
624
readElementTableCoveredTableCell(KoXmlStreamReader & reader)625 void OdfTextReader::readElementTableCoveredTableCell(KoXmlStreamReader &reader)
626 {
627 DEBUGSTART();
628 m_backend->elementTableCoveredTableCell(reader, m_context);
629
630 // <table:covered-table-cell> has the following children in ODF 1.2:
631 //
632 // In addition to the text level tags like <text:p> etc that can
633 // be found in any textbox, table cell or similar, it has the
634 // following text document children:
635 //
636 // [done] <office:annotation> 14.1
637 // <table:cell-range-source> 9.3.1
638 // <table:detective> 9.3.2
639
640 while (reader.readNextStartElement()) {
641 DEBUG_READING("loop-start");
642
643 QString tagName = reader.qualifiedName().toString();
644 if (tagName == "office:annotation") {
645 readElementOfficeAnnotation(reader);
646 }
647 else if (tagName == "table:cell-range-source") {
648 // FIXME: NYI
649 reader.skipCurrentElement();
650 }
651 else if (tagName == "table:detective") {
652 // FIXME: NYI
653 reader.skipCurrentElement();
654 }
655 else {
656 readTextLevelElement(reader);
657 }
658 DEBUG_READING("loop-end");
659 }
660
661 m_backend->elementTableCoveredTableCell(reader, m_context);
662 DEBUGEND();
663 }
664
665
666 // ----------------------------------------------------------------
667 // Paragraph level functions
668
669
670 // This function is a bit special since it doesn't handle a specific
671 // element. Instead it handles the common child elements between a
672 // number of paragraph-level elements.
673 //
readParagraphContents(KoXmlStreamReader & reader)674 void OdfTextReader::readParagraphContents(KoXmlStreamReader &reader)
675 {
676 DEBUGSTART();
677
678 // We enter this function with the reader pointing to the first
679 // element *inside* the paragraph.
680 //
681 // We should not call any backend functions here. That is already
682 // done in the functions that call this one.
683
684 while (!reader.atEnd() && !reader.isEndElement()) {
685 DEBUG_READING("loop-start");
686
687 if (reader.isCharacters()) {
688 //debugOdfReader << "Found character data";
689 m_backend->characterData(reader, m_context);
690 reader.readNext();
691 continue;
692 }
693
694 if (!reader.isStartElement())
695 continue;
696
697 // We define the common elements on the paragraph level as the
698 // following list. They are the basic paragraph level contents that
699 // can be found in a paragraph (text:p), heading (text:h), etc
700 //
701 // The common paragraph level elements are the following in ODF 1.2:
702 //
703 // <dr3d:scene> 10.5.2
704 // <draw:a> 10.4.12
705 // <draw:caption> 10.3.11
706 // <draw:circle> 10.3.8
707 // <draw:connector> 10.3.10
708 // <draw:control> 10.3.13
709 // <draw:custom-shape> 10.6.1
710 // <draw:ellipse> 10.3.9
711 // [done] <draw:frame> 10.4.2
712 // <draw:g> 10.3.15
713 // <draw:line> 10.3.3
714 // <draw:measure> 10.3.12
715 // <draw:page-thumbnail> 10.3.14
716 // <draw:path> 10.3.7
717 // <draw:polygon> 10.3.5
718 // <draw:polyline> 10.3.4
719 // <draw:rect> 10.3.2
720 // <draw:regular-polygon> 10.3.6
721 // All of the above are sent to the draw reader.
722 //
723 // [done] <office:annotation> 14.1
724 // [done] <office:annotation-end> 14.2
725 // <presentation:date-time> 10.9.3.5
726 // <presentation:footer> 10.9.3.3
727 // <presentation:header> 10.9.3.1
728 // [done] <text:a> 6.1.8
729 // <text:alphabetical-index-mark> 8.1.10
730 // <text:alphabetical-index-mark-end> 8.1.9
731 // <text:alphabetical-index-mark-start> 8.1.8
732 // <text:author-initials> 7.3.7.2
733 // <text:author-name> 7.3.7.1
734 // <text:bibliography-mark> 8.1.11
735 // <text:bookmark> 6.2.1.2
736 // <text:bookmark-end> 6.2.1.4
737 // <text:bookmark-ref> 7.7.6
738 // <text:bookmark-start> 6.2.1.3
739 // <text:change> 5.5.7.4
740 // <text:change-end> 5.5.7.3
741 // <text:change-start> 5.5.7.2
742 // <text:chapter> 7.3.8
743 // <text:character-count> 7.5.18.5
744 // <text:conditional-text> 7.7.3
745 // <text:creation-date> 7.5.3
746 // <text:creation-time> 7.5.4
747 // <text:creator> 7.5.17
748 // <text:database-display> 7.6.3
749 // <text:database-name> 7.6.7
750 // <text:database-next> 7.6.4
751 // <text:database-row-number> 7.6.6
752 // <text:database-row-select> 7.6.5
753 // <text:date> 7.3.2
754 // <text:dde-connection> 7.7.12
755 // <text:description> 7.5.5
756 // <text:editing-cycles> 7.5.13
757 // <text:editing-duration> 7.5.14
758 // <text:execute-macro> 7.7.10
759 // <text:expression> 7.4.14
760 // <text:file-name> 7.3.9
761 // <text:hidden-paragraph> 7.7.11
762 // <text:hidden-text> 7.7.4
763 // <text:image-count> 7.5.18.7
764 // <text:initial-creator> 7.5.2
765 // <text:keywords> 7.5.12
766 // [done] <text:line-break> 6.1.5
767 // <text:measure> 7.7.13
768 // <text:meta> 6.1.9
769 // <text:meta-field> 7.5.19
770 // <text:modification-date> 7.5.16
771 // <text:modification-time> 7.5.15
772 // <text:note> 6.3.2
773 // <text:note-ref> 7.7.7
774 // <text:object-count> 7.5.18.8
775 // <text:page-continuation> 7.3.5
776 // <text:page-count> 7.5.18.2
777 // <text:page-number> 7.3.4
778 // <text:page-variable-get> 7.7.1.3
779 // <text:page-variable-set> 7.7.1.2
780 // <text:paragraph-count> 7.5.18.3
781 // <text:placeholder> 7.7.2
782 // <text:print-date> 7.5.8
783 // <text:printed-by> 7.5.9
784 // <text:print-time> 7.5.7
785 // <text:reference-mark> 6.2.2.2
786 // <text:reference-mark-end> 6.2.2.4
787 // <text:reference-mark-start> 6.2.2.3
788 // <text:reference-ref> 7.7.5
789 // <text:ruby> 6.4
790 // [done] <text:s> 6.1.3
791 // <text:script> 7.7.9
792 // <text:sender-city> 7.3.6.13
793 // <text:sender-company> 7.3.6.10
794 // <text:sender-country> 7.3.6.15
795 // <text:sender-email> 7.3.6.7
796 // <text:sender-fax> 7.3.6.9
797 // <text:sender-firstname> 7.3.6.2
798 // <text:sender-initials> 7.3.6.4
799 // <text:sender-lastname> 7.3.6.3
800 // <text:sender-phone-private> 7.3.6.8
801 // <text:sender-phone-work> 7.3.6.11
802 // <text:sender-position> 7.3.6.6
803 // <text:sender-postal-code> 7.3.6.14
804 // <text:sender-state-or-province> 7.3.6.16
805 // <text:sender-street> 7.3.6.12
806 // <text:sender-title> 7.3.6.5
807 // <text:sequence> 7.4.13
808 // <text:sequence-ref> 7.7.8
809 // <text:sheet-name> 7.3.11
810 // [done] <text:soft-page-break> 5.6
811 // [done] <text:span> 6.1.7
812 // <text:subject> 7.5.11
813 // <text:tab> 6.1.4
814 // <text:table-count> 7.5.18.6
815 // <text:table-formula> 7.7.14
816 // <text:template-name> 7.3.10
817 // <text:text-input> 7.4.15
818 // <text:time> 7.3.3
819 // <text:title> 7.5.10
820 // <text:toc-mark> 8.1.4
821 // <text:toc-mark-end> 8.1.3
822 // <text:toc-mark-start> 8.1.2
823 // <text:user-defined> 7.5.6
824 // <text:user-field-get> 7.4.9
825 // <text:user-field-input> 7.4.10
826 // <text:user-index-mark> 8.1.7
827 // <text:user-index-mark-end> 8.1.6
828 // <text:user-index-mark-start> 8.1.5
829 // <text:variable-get> 7.4.5
830 // <text:variable-input> 7.4.6
831 // <text:variable-set> 7.4.4
832 // <text:word-count> 7.5.18.4.
833 //
834 // FIXME: Only very few tags are handled right now.
835
836 QString tagName = reader.qualifiedName().toString();
837
838 if (reader.prefix() == "draw" || reader.prefix() == "dr3d") {
839 OdfDrawReader *drawReader = m_parent->drawReader();
840 if (drawReader) {
841 drawReader->readCommonGraphicsElements(reader);
842 }
843 else {
844 reader.skipCurrentElement();
845 }
846 } // draw | dr3d namespace
847 else if (reader.prefix() == "office") {
848 if (tagName == "office:annotation") {
849 readElementOfficeAnnotation(reader);
850 }
851 else if (tagName == "office:annotation-end") {
852 readElementOfficeAnnotationEnd(reader);
853 }
854 else {
855 // Unknown office: element
856 readUnknownElement(reader);
857 }
858 } // office namespace
859 else if (reader.prefix() == "text") {
860
861 if (tagName == "text:a") {
862 readElementTextA(reader);
863 }
864 else if (tagName == "text:line-break") {
865 readElementTextLineBreak(reader);
866 }
867 else if (tagName == "text:span") {
868 readElementTextSpan(reader);
869 }
870 else if (tagName == "text:s") {
871 readElementTextS(reader);
872 }
873 else if (tagName == "text:soft-page-break") {
874 readElementTextSoftPageBreak(reader);
875 }
876 else {
877 // Unknown text: element
878 readUnknownElement(reader);
879 }
880 } // text namespace
881 else {
882 // Unknown namespace
883 readUnknownElement(reader);
884 }
885
886 // Read past the end tag of the just parsed element.
887 reader.readNext();
888 DEBUG_READING("loop-end");
889 }
890
891 DEBUGEND();
892 }
893
readElementOfficeAnnotation(KoXmlStreamReader & reader)894 void OdfTextReader::readElementOfficeAnnotation(KoXmlStreamReader &reader)
895 {
896 DEBUGSTART();
897 m_backend->elementOfficeAnnotation(reader, m_context);
898
899 // <office:annotation> has the following children in ODF 1.2:
900 // [done] <dc:creator> 4.3.2.7
901 // [done] <dc:date> 4.3.2.10
902 // [done] <meta:date-string> 14.3
903 // [done] <text:list> 5.3.1
904 // [done] <text:p> 5.1.3
905 while (reader.readNextStartElement()) {
906 QString tagName = reader.qualifiedName().toString();
907
908 if (tagName == "dc:creator") {
909 readElementDcCreator(reader);
910 }
911 else if (tagName == "dc:date") {
912 readElementDcDate(reader);
913 }
914 else if (tagName == "meta:date-string") {
915 QString value;
916 readCharacterData(reader, value);
917 m_backend->textVariable(tagName, value);
918 }
919 else if (tagName == "text:list") {
920 readElementTextList(reader);
921 }
922 else if (tagName == "text:p") {
923 readElementTextP(reader);
924 }
925 else {
926 reader.skipCurrentElement();
927 }
928 }
929
930 m_backend->elementOfficeAnnotation(reader, m_context);
931 DEBUGEND();
932 }
933
readElementOfficeAnnotationEnd(KoXmlStreamReader & reader)934 void OdfTextReader::readElementOfficeAnnotationEnd(KoXmlStreamReader &reader)
935 {
936 DEBUGSTART();
937 m_backend->elementOfficeAnnotationEnd(reader, m_context);
938
939 // <office:annotation-end> has no children in ODF 1.2:
940 // FIXME: Skip current element or call parseUnknownElement?
941 reader.skipCurrentElement();
942
943 m_backend->elementOfficeAnnotationEnd(reader, m_context);
944 DEBUGEND();
945 }
946
readElementDcCreator(KoXmlStreamReader & reader)947 void OdfTextReader::readElementDcCreator(KoXmlStreamReader &reader)
948 {
949 DEBUGSTART();
950 m_backend->elementDcCreator(reader, m_context);
951
952 reader.readNext();
953 readParagraphContents(reader);
954
955 m_backend->elementDcCreator(reader, m_context);
956 DEBUGEND();
957 }
958
readElementDcDate(KoXmlStreamReader & reader)959 void OdfTextReader::readElementDcDate(KoXmlStreamReader &reader)
960 {
961 DEBUGSTART();
962 m_backend->elementDcDate(reader, m_context);
963
964 reader.readNext();
965 readParagraphContents(reader);
966
967 m_backend->elementDcDate(reader, m_context);
968 DEBUGEND();
969 }
970
readElementTextA(KoXmlStreamReader & reader)971 void OdfTextReader::readElementTextA(KoXmlStreamReader &reader)
972 {
973 DEBUGSTART();
974 m_backend->elementTextA(reader, m_context);
975
976 // readParagraphContents expect to have the reader point to the
977 // contents of the paragraph so we have to read past the text:a
978 // start tag here.
979 reader.readNext();
980 readParagraphContents(reader);
981
982 m_backend->elementTextA(reader, m_context);
983 DEBUGEND();
984 }
985
readElementTextLineBreak(KoXmlStreamReader & reader)986 void OdfTextReader::readElementTextLineBreak(KoXmlStreamReader &reader)
987 {
988 DEBUGSTART();
989 m_backend->elementTextLineBreak(reader, m_context);
990
991 // This element has no child elements in ODF 1.2.
992 reader.skipCurrentElement();
993
994 m_backend->elementTextLineBreak(reader, m_context);
995 DEBUGEND();
996 }
997
readElementTextS(KoXmlStreamReader & reader)998 void OdfTextReader::readElementTextS(KoXmlStreamReader &reader)
999 {
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
readElementTextSpan(KoXmlStreamReader & reader)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
readElementTextListHeader(KoXmlStreamReader & reader)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
readElementTextListItem(KoXmlStreamReader & reader)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
readElementTextSoftPageBreak(KoXmlStreamReader & reader)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
readUnknownElement(KoXmlStreamReader & reader)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
1149