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
33 #include <KoStore.h>
34 #include <KoXmlStreamReader.h>
35 #include <KoXmlNS.h>
36 #include <KoXmlWriter.h> // For copyXmlElement
37 #include <KoOdfReadStore.h>
38
39 // Reader library
40 #include "OdfReader.h"
41 #include "OdfDrawReaderBackend.h"
42 #include "OdfReaderContext.h"
43 #include "OdfReaderDebug.h"
44
45
46 #if 1
47 static int debugIndent = 0;
48 #define DEBUGSTART() \
49 ++debugIndent; \
50 DEBUG_READING("entering")
51 #define DEBUGEND() \
52 DEBUG_READING("exiting"); \
53 --debugIndent
54 #define DEBUG_READING(param) \
55 debugOdfReader << QString("%1").arg(" ", debugIndent * 2) << param << ": " \
56 << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \
57 << reader.qualifiedName().toString()
58 #else
59 #define DEBUGSTART() \
60 // NOTHING
61 #define DEBUGEND() \
62 // NOTHING
63 #define DEBUG_READING(param) \
64 // NOTHING
65 #endif
66
67
OdfDrawReader()68 OdfDrawReader::OdfDrawReader()
69 : m_parent(0)
70 , m_backend(0)
71 , m_context(0)
72 {
73 }
74
~OdfDrawReader()75 OdfDrawReader::~OdfDrawReader()
76 {
77 }
78
79
80 // ----------------------------------------------------------------
81 // setters
82
83
setParent(OdfReader * parent)84 void OdfDrawReader::setParent(OdfReader *parent)
85 {
86 m_parent = parent;
87 }
88
setBackend(OdfDrawReaderBackend * backend)89 void OdfDrawReader::setBackend(OdfDrawReaderBackend *backend)
90 {
91 m_backend = backend;
92 }
93
setContext(OdfReaderContext * context)94 void OdfDrawReader::setContext(OdfReaderContext *context)
95 {
96 m_context = context;
97 }
98
99
100 // ----------------------------------------------------------------
101 // namespace dr3d
102
103
readElementDr3dScene(KoXmlStreamReader & reader)104 void OdfDrawReader::readElementDr3dScene(KoXmlStreamReader &reader)
105 {
106 DEBUGSTART();
107 m_backend->elementDr3dScene(reader, m_context);
108
109 // <dr3d:scene> has the following children in ODF 1.2:
110 // [done] <dr3d:cube> 10.5.4
111 // [done] <dr3d:extrude> 10.5.6
112 // [done] <dr3d:light> 10.5.3
113 // [done] <dr3d:rotate> 10.5.7
114 // [done] <dr3d:scene> 10.5.2
115 // [done] <dr3d:sphere> 10.5.5
116
117 // <draw:glue-point> 10.3.16
118 // <svg:desc> 10.3.18
119 // <svg:title> 10.3.17.
120 //
121 while (reader.readNextStartElement()) {
122 QString tagName = reader.qualifiedName().toString();
123
124 if (tagName == "dr3d:cube") {
125 readElementDr3dCube(reader);
126 }
127 else if (tagName == "dr3d:extrude") {
128 readElementDr3dExtrude(reader);
129 }
130 else if (tagName == "dr3d:light") {
131 readElementDr3dLight(reader);
132 }
133 else if (tagName == "dr3d:rotate") {
134 readElementDr3dRotate(reader);
135 }
136 else if (tagName == "dr3d:scene") {
137 readElementDr3dScene(reader);
138 }
139 else if (tagName == "dr3d:sphere") {
140 readElementDr3dSphere(reader);
141 }
142 //... MORE else if () HERE
143 else {
144 reader.skipCurrentElement();
145 }
146 }
147
148 m_backend->elementDr3dScene(reader, m_context);
149 DEBUGEND();
150 }
151
IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader,Dr3dLight)152 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dLight) // ODF 1.2 10.5.3
153 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dCube) // ODF 1.2 10.5.4
154 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dSphere) // ODF 1.2 10.5.5
155 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dExtrude) // ODF 1.2 10.5.6
156 IMPLEMENT_READER_FUNCTION_NO_CHILDREN(OdfDrawReader, Dr3dRotate) // ODF 1.2 10.5.7
157
158
159 // ================================================================
160 // namespace draw
161
162
163 // ----------------------------------------------------------------
164
165
166 #if 0
167 // This is a template function for the reader library.
168 // Copy this one and change the name and fill in the code.
169 void OdfDrawReader::readElementNamespaceTagname(KoXmlStreamReader &reader)
170 {
171 DEBUGSTART();
172 m_backend->elementNamespaceTagname(reader, m_context);
173
174 // <namespace:tagname> has the following children in ODF 1.2:
175 // FILL IN THE CHILDREN LIKE THIS EXAMPLE (taken from office:document-content):
176 // <office:automatic-styles> 3.15.3
177 // <office:body> 3.3
178 // <office:font-face-decls> 3.14
179 // <office:scripts> 3.12.
180 while (reader.readNextStartElement()) {
181 QString tagName = reader.qualifiedName().toString();
182
183 if (tagName == "office:automatic-styles") {
184 // FIXME: NYI
185 reader.skipCurrentElement();
186 }
187 else if (tagName == "office:body") {
188 readElementOfficeBody(reader);
189 }
190 ... MORE else if () HERE
191 else {
192 reader.skipCurrentElement();
193 }
194 }
195
196 m_backend->elementNamespaceTagname(reader, m_context);
197 DEBUGEND();
198 }
199 #endif
200
201
202 void OdfDrawReader::readCommonGraphicsElements(KoXmlStreamReader &reader)
203 {
204 DEBUGSTART();
205
206 // This is a function common to all draw elements so no backend function
207 // should be called here.
208
209 // The common graphics elements are:
210 // [done] <dr3d:scene> 10.5.2
211 // [done] <draw:a> 10.4.12
212 // [done] <draw:caption> 10.3.11
213 // [done] <draw:circle> 10.3.8
214 // [done] <draw:connector> 10.3.10
215 // <draw:control> 10.3.13
216 // <draw:custom-shape> 10.6.1
217 // [done] <draw:ellipse> 10.3.9
218 // [done] <draw:frame> 10.4.2
219 // <draw:g> 10.3.15
220 // [done] <draw:line> 10.3.3
221 // [done] <draw:measure> 10.3.12
222 // <draw:page-thumbnail> 10.3.14
223 // [path] <draw:path> 10.3.7
224 // [done] <draw:polygon> 10.3.5
225 // [done] <draw:polyline> 10.3.4
226 // [done] <draw:rect> 10.3.2
227 // [done] <draw:regular-polygon> 10.3.6
228
229 QString tagName = reader.qualifiedName().toString();
230 //debugOdfReader << "list child:" << tagName;
231 if (tagName == "dr3d:scene") {
232 readElementDr3dScene(reader);
233 }
234 else if (tagName == "draw:a") {
235 readElementDrawA(reader);
236 }
237 else if (tagName == "draw:caption") {
238 readElementDrawCaption(reader);
239 }
240 else if (tagName == "draw:circle") {
241 readElementDrawCircle(reader);
242 }
243 else if (tagName == "draw:connector") {
244 readElementDrawConnector(reader);
245 }
246 else if (tagName == "draw:ellipse") {
247 readElementDrawEllipse(reader);
248 }
249 else if (tagName == "draw:frame") {
250 readElementDrawFrame(reader);
251 }
252 else if (tagName == "draw:line") {
253 readElementDrawLine(reader);
254 }
255 else if (tagName == "draw:measure") {
256 readElementDrawMeasure(reader);
257 }
258 else if (tagName == "draw:path") {
259 readElementDrawPath(reader);
260 }
261 else if (tagName == "draw:polygon") {
262 readElementDrawPolygon(reader);
263 }
264 else if (tagName == "draw:polyline") {
265 readElementDrawPolyline(reader);
266 }
267 else if (tagName == "draw:rect") {
268 readElementDrawRect(reader);
269 }
270 else if (tagName == "draw:regular-polygon") {
271 readElementDrawRegularPolygon(reader);
272 }
273 else {
274 // FIXME: Should this perhaps be skipCurrentElement()?
275 readUnknownElement(reader);
276 }
277
278 DEBUGEND();
279 }
280
readElementDrawA(KoXmlStreamReader & reader)281 void OdfDrawReader::readElementDrawA(KoXmlStreamReader &reader)
282 {
283 DEBUGSTART();
284 m_backend->elementDrawA(reader, m_context);
285
286 // <draw:a> has all the normal drawing children.
287 readCommonGraphicsElements(reader);
288
289 m_backend->elementDrawA(reader, m_context);
290 DEBUGEND();
291 }
292
293
294 #define IMPLEMENT_GRAPHIC_OBJECT(object) \
295 void OdfDrawReader::readElementDraw##object(KoXmlStreamReader &reader) \
296 { \
297 DEBUGSTART(); \
298 m_backend->elementDraw##object(reader, m_context); \
299 \
300 readGraphicsObjectChildren(reader); \
301 \
302 m_backend->elementDraw##object(reader, m_context); \
303 DEBUGEND(); \
304 }
305
306 IMPLEMENT_GRAPHIC_OBJECT(Rect) // ODF 1.2 10.3.2
IMPLEMENT_GRAPHIC_OBJECT(Line)307 IMPLEMENT_GRAPHIC_OBJECT(Line) // ODF 1.2 10.3.3
308 IMPLEMENT_GRAPHIC_OBJECT(Polyline) // ODF 1.2 10.3.4
309 IMPLEMENT_GRAPHIC_OBJECT(Polygon) // ODF 1.2 10.3.5
310 IMPLEMENT_GRAPHIC_OBJECT(RegularPolygon) // ODF 1.2 10.3.6
311 IMPLEMENT_GRAPHIC_OBJECT(Path) // ODF 1.2 10.3.7
312 IMPLEMENT_GRAPHIC_OBJECT(Circle) // ODF 1.2 10.3.8
313 IMPLEMENT_GRAPHIC_OBJECT(Ellipse) // ODF 1.2 10.3.9
314 IMPLEMENT_GRAPHIC_OBJECT(Connector) // ODF 1.2 10.3.10
315 IMPLEMENT_GRAPHIC_OBJECT(Caption) // ODF 1.2 10.3.11
316 IMPLEMENT_GRAPHIC_OBJECT(Measure) // ODF 1.2 10.3.12
317
318
319 void OdfDrawReader::readGraphicsObjectChildren(KoXmlStreamReader &reader)
320 {
321 // No backend calls in this function
322
323 // <draw:circle>, <draw:rect>, etc have the following children in ODF 1.2:
324 // <draw:glue-point> 10.3.16
325 // <office:event-listeners> 10.3.19
326 // <svg:desc> 10.3.18
327 // <svg:title> 10.3.17
328 // [done] <text:list> 5.3.1
329 // [done] <text:p> 5.1.3.
330 while (reader.readNextStartElement()) {
331 QString tagName = reader.qualifiedName().toString();
332
333 if (tagName == "draw:glue-point") {
334 // FIXME: NYI
335 reader.skipCurrentElement();
336 //readElementOfficeDrawGluePoint(reader);
337 }
338 else if (tagName == "office:event-listeners") {
339 // FIXME: NYI
340 reader.skipCurrentElement();
341 //readElementOfficeEventListeners(reader);
342 }
343 else if (reader.prefix() == "svg") {
344 if (tagName == "svg:desc") {
345 // FIXME: NYI
346 reader.skipCurrentElement();
347 //readElementSvgDesc(reader);
348 }
349 else if (tagName == "svg:title") {
350 // FIXME: NYI
351 reader.skipCurrentElement();
352 //readElementSvgTitle(reader);
353 }
354 else {
355 reader.skipCurrentElement();
356 }
357 } // namespace svg
358 else if (reader.prefix() == "text") {
359 OdfTextReader *textReader = m_parent->textReader();
360 if (!textReader) {
361 reader.skipCurrentElement();
362 }
363 else if (tagName == "text:list") {
364 textReader->readElementTextList(reader);
365 }
366 else if (tagName == "text:p") {
367 textReader->readElementTextP(reader);
368 }
369 else {
370 reader.skipCurrentElement();
371 }
372 } // namespace text
373 else {
374 reader.skipCurrentElement();
375 }
376 }
377 }
378
379
380 // ----------------------------------------------------------------
381 // Frames
382
383
readElementDrawFrame(KoXmlStreamReader & reader)384 void OdfDrawReader::readElementDrawFrame(KoXmlStreamReader &reader)
385 {
386 DEBUGSTART();
387 m_backend->elementDrawFrame(reader, m_context);
388
389 // <draw:frame> has the following children in ODF 1.2:
390 // <draw:applet> 10.4.7
391 // <draw:contour-path> 10.4.11.3
392 // <draw:contour-polygon> 10.4.11.2
393 // <draw:floating-frame> 10.4.10
394 // <draw:glue-point> 10.3.16
395 // <draw:image> 10.4.4
396 // <draw:image-map> 10.4.13.2
397 // [done] <draw:object> 10.4.6.2
398 // [done] <draw:object-ole> 10.4.6.3
399 // <draw:plugin> 10.4.8
400 // <draw:text-box> 10.4.3
401 // <office:event-listeners> 10.3.19
402 // <svg:desc> 10.3.18
403 // <svg:title> 10.3.17
404 // [done] <table:table> 9.1.2
405 //
406 while (reader.readNextStartElement()) {
407 QString tagName = reader.qualifiedName().toString();
408
409 if (tagName == "draw:image") {
410 // FIXME: NYI
411 reader.skipCurrentElement();
412 }
413 else if (tagName == "draw:object") {
414 readElementDrawObject(reader);
415 }
416 else if (tagName == "draw:object-ole") {
417 readElementDrawObjectOle(reader);
418 }
419 //... MORE else if () HERE
420 else if (tagName == "table:table") {
421 OdfTextReader *textReader = m_parent->textReader();
422 if (textReader) {
423 textReader->readElementTableTable(reader);
424 }
425 else {
426 reader.skipCurrentElement();
427 }
428 }
429 else {
430 reader.skipCurrentElement();
431 }
432 }
433
434 m_backend->elementDrawFrame(reader, m_context);
435 DEBUGEND();
436 }
437
readElementDrawObject(KoXmlStreamReader & reader)438 void OdfDrawReader::readElementDrawObject(KoXmlStreamReader &reader)
439 {
440 DEBUGSTART();
441 m_backend->elementDrawObject(reader, m_context);
442
443 // <draw:object> has the following children in ODF 1.2:
444 // <math:math> 14.5
445 // <office:document> 3.1.2
446 while (reader.readNextStartElement()) {
447 QString tagName = reader.qualifiedName().toString();
448
449 if (tagName == "math:math") {
450 // FIXME: NYI
451 reader.skipCurrentElement();
452 }
453 else if (tagName == "office:document") {
454 // FIXME: NYI
455 reader.skipCurrentElement();
456 }
457 else {
458 // Shouldn't happen.
459 reader.skipCurrentElement();
460 }
461 }
462
463 m_backend->elementDrawObject(reader, m_context);
464 DEBUGEND();
465 }
466
readElementDrawObjectOle(KoXmlStreamReader & reader)467 void OdfDrawReader::readElementDrawObjectOle(KoXmlStreamReader &reader)
468 {
469 DEBUGSTART();
470 m_backend->elementDrawObjectOle(reader, m_context);
471
472 // <draw:object-ole> has the following children in ODF 1.2:
473 // <office:binary-data> 10.4.5
474 while (reader.readNextStartElement()) {
475 QString tagName = reader.qualifiedName().toString();
476
477 if (tagName == "office:binary-data") {
478 // FIXME: NYI
479 reader.skipCurrentElement();
480 }
481 else {
482 // Shouldn't happen.
483 reader.skipCurrentElement();
484 }
485 }
486
487 m_backend->elementDrawObjectOle(reader, m_context);
488 DEBUGEND();
489 }
490
491
492 // ----------------------------------------------------------------
493 // Other functions
494
495
readUnknownElement(KoXmlStreamReader & reader)496 void OdfDrawReader::readUnknownElement(KoXmlStreamReader &reader)
497 {
498 DEBUGSTART();
499
500 #if 0 // FIXME: Fix this
501 if (m_context->isInsideParagraph()) {
502 // readParagraphContents expect to have the reader point to the
503 // contents of the paragraph so we have to read past the draw:p
504 // start tag here.
505 reader.readNext();
506 readParagraphContents(reader);
507 }
508 else {
509 while (reader.readNextStartElement()) {
510 readTextLevelElement(reader);
511 }
512 }
513 #else
514 reader.skipCurrentElement();
515 #endif
516
517 DEBUGEND();
518 }
519