1 /* This file is part of the KDE project
2 
3    Copyright (C) 2013 Inge Wallin            <inge@lysator.liu.se>
4    Copyright (C) 2013 Mojtaba Shahi Senobari <mojtaba.shahi3000@gmail.com>
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Library General Public
8    License as published by the Free Software Foundation; either
9    version 2 of the License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Library General Public License for more details.
15 
16    You should have received a copy of the GNU Library General Public License
17    along with this library; see the file COPYING.LIB.  If not, write to
18    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19    Boston, MA 02110-1301, USA.
20 */
21 
22 
23 // Own
24 #include "OdtReaderWikiBackend.h"
25 
26 // Calligra
27 #include <KoXmlReader.h>
28 
29 #include <KoOdfStyleManager.h>
30 #include <KoOdfStyle.h>
31 #include <KoOdfListStyle.h>
32 #include <KoOdfStyleProperties.h>
33 
34 // This filter
35 #include "OdfReaderWikiContext.h"
36 #include "WikiExportDebug.h"
37 
38 
39 #if 1
40 #define DEBUG_BACKEND() \
41     debugWiki << (reader.isStartElement() ? "start": (reader.isEndElement() ? "end" : "other")) \
42     << reader.qualifiedName().toString()
43 #else
44 #define DEBUG_BACKEND() \
45     //NOTHING
46 #endif
47 
48 
49 // ================================================================
50 //                 class OdtReaderWikiBackend
51 
52 
OdtReaderWikiBackend()53 OdtReaderWikiBackend::OdtReaderWikiBackend()
54     : OdfTextReaderBackend()
55 {
56 }
57 
~OdtReaderWikiBackend()58 OdtReaderWikiBackend::~OdtReaderWikiBackend()
59 {
60 }
61 
62 
63 // ----------------------------------------------------------------
64 // Text level functions: paragraphs, headings, sections, frames, objects, etc
65 
66 
elementTextH(KoXmlStreamReader & reader,OdfReaderContext * context)67 void OdtReaderWikiBackend::elementTextH(KoXmlStreamReader &reader,
68                                         OdfReaderContext *context)
69 {
70     DEBUG_BACKEND();
71     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
72     if (!wikiContext) {
73         return;
74     }
75 
76     if (reader.isStartElement()) {
77         wikiContext->outlineLevel = reader.attributes().value("text:outline-level").toString().toInt();
78         outputHeadingLevel(wikiContext);
79     }
80     else {
81         outputHeadingLevel(wikiContext);
82         wikiContext->outStream << "\n";
83 
84         wikiContext->outlineLevel = 0;
85     }
86 }
87 
elementTextP(KoXmlStreamReader & reader,OdfReaderContext * context)88 void OdtReaderWikiBackend::elementTextP(KoXmlStreamReader &reader,
89                                         OdfReaderContext *context)
90 {
91     DEBUG_BACKEND();
92     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
93     if (!wikiContext) {
94         return;
95     }
96 
97     if (reader.isStartElement()) {
98         QString stylename = reader.attributes().value("text:style-name").toString();
99 
100         KoOdfStyle *style = wikiContext->styleManager()->style(stylename, "paragraph");
101         //Push style to stack
102         wikiContext->pushStyle(style);
103         outputTextStyle(reader, wikiContext);
104     } else {
105         outputTextStyle(reader, wikiContext);
106         wikiContext->popStyle();
107 
108         // At the end of a paragraph, output two newlines.
109         wikiContext->outStream << "\n";
110     }
111 }
112 
113 // ----------------------------------------------------------------
114 // Paragraph level functions: spans, annotations, notes, text content itself, etc.
115 
elementTextSpan(KoXmlStreamReader & reader,OdfReaderContext * context)116 void OdtReaderWikiBackend::elementTextSpan(KoXmlStreamReader &reader,
117                                            OdfReaderContext *context)
118 {
119     DEBUG_BACKEND();
120     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
121     if (!wikiContext) {
122         return;
123     }
124 
125     if (reader.isStartElement()) {
126         QString stylename = reader.attributes().value("text:style-name").toString();
127         KoOdfStyle *style = wikiContext->styleManager()->style(stylename, "text");
128         //Push style to stack
129         wikiContext->pushStyle(style);
130 
131         outputTextStyle(reader, wikiContext);
132     }
133     else {
134         outputTextStyle(reader, wikiContext);
135         wikiContext->popStyle();
136     }
137 }
138 
elementTextList(KoXmlStreamReader & reader,OdfReaderContext * context)139 void OdtReaderWikiBackend::elementTextList(KoXmlStreamReader &reader, OdfReaderContext *context)
140 {
141     DEBUG_BACKEND();
142     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
143     if (!wikiContext) {
144         return;
145     }
146 
147     if (reader.isStartElement()) {
148         QString stylename = reader.attributes().value("text:style-name").toString();
149         KoOdfListStyle *listStyle = wikiContext->styleManager()->listStyle(stylename);
150         if (listStyle) {
151             wikiContext->pushListStyle(listStyle);
152         }
153         wikiContext->listLevelCounter++;
154     }
155     else {
156         if (wikiContext->listLevelCounter == wikiContext->listStyleStack.count()) {
157             wikiContext->popListStyle();
158         }
159         wikiContext->listLevelCounter--;
160     }
161 }
162 
elementTextS(KoXmlStreamReader & reader,OdfReaderContext * context)163 void OdtReaderWikiBackend::elementTextS(KoXmlStreamReader &reader,
164                                         OdfReaderContext *context)
165 {
166     DEBUG_BACKEND();
167     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
168     if (!wikiContext) {
169         return;
170     }
171 
172     // Find out number of spaces.
173     QString dummy = reader.attributes().value("text:c").toString();
174     bool ok;
175     quint32  numSpaces = dummy.toUInt(&ok);
176     if (!ok)
177         numSpaces = 1;
178 
179     // Output the required number of spaces.
180     for (quint32 i = 0; i < numSpaces; ++i) {
181         wikiContext->outStream << ' ';
182     }
183 }
184 
elementTextListItem(KoXmlStreamReader & reader,OdfReaderContext * context)185 void OdtReaderWikiBackend::elementTextListItem(KoXmlStreamReader &reader,
186                                                OdfReaderContext *context)
187 {
188     DEBUG_BACKEND();
189     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
190     if (!wikiContext) {
191         return;
192     }
193 
194     if (reader.isStartElement()) {
195         KoOdfListStyle *listStyle = wikiContext->popListStyle();
196         char symbol;
197         if (listStyle->listLevelStyleType() == "text:list-level-style-bullet") {
198             symbol = '*';
199         }
200         else if (listStyle->listLevelStyleType() == "text:list-level-style-number") {
201             symbol = '#';
202         }
203         wikiContext->pushListStyle(listStyle);
204 
205         for (int level = 0; level < wikiContext->listLevelCounter; ++level) {
206             wikiContext->outStream << symbol;
207         }
208         wikiContext->outStream << ' ';
209     }
210     else {
211         wikiContext->outStream << '\n';
212     }
213 
214 }
215 
characterData(KoXmlStreamReader & reader,OdfReaderContext * context)216 void OdtReaderWikiBackend::characterData(KoXmlStreamReader &reader, OdfReaderContext *context)
217 {
218     DEBUG_BACKEND();
219     OdfReaderWikiContext *wikiContext = dynamic_cast<OdfReaderWikiContext*>(context);
220     if (!wikiContext) {
221         return;
222     }
223 
224     wikiContext->outStream << reader.text().toString();
225 }
226 
227 
228 // ----------------------------------------------------------------
229 //                         private functions
230 
231 
outputTextStyle(KoXmlStreamReader & reader,OdfReaderWikiContext * wikiContext)232 void OdtReaderWikiBackend::outputTextStyle(KoXmlStreamReader &reader,
233                                            OdfReaderWikiContext *wikiContext)
234 {
235     KoOdfStyle *style = wikiContext->popStyle();
236     KoOdfStyleProperties *styleProperties = style->properties().value("style:text-properties");
237     if (!styleProperties) {
238         wikiContext->pushStyle(style);
239         return;
240     }
241 
242     // Output italic and bold.
243     QString fontWeightProperty = "fo:font-weight";
244     QString fontStyleProperty = "fo:font-style";
245     if ((styleProperties->attribute(fontWeightProperty) == "bold")
246         && (styleProperties->attribute(fontStyleProperty) == "italic"))
247     {
248         wikiContext->outStream << "'''''";
249     } else if (styleProperties->attribute(fontWeightProperty) == "bold") {
250         wikiContext->outStream << "'''";
251     } else if (styleProperties->attribute(fontStyleProperty) == "italic") {
252         wikiContext->outStream << "''";
253     }
254 
255     QString textPositionProperty = "style:text-position";
256     QString textLineThroughProperty = "style:text-line-through-style";
257     if (reader.isStartElement()) {
258         // Output strikeout text.
259         if (styleProperties->attribute(textLineThroughProperty) == "solid") {
260             wikiContext->outStream << "<s>";
261         }
262         // Output sub and super script.
263         if (styleProperties->attribute(textPositionProperty) == "sub") {
264            wikiContext->outStream << "<sub>";
265         }
266         else if (styleProperties->attribute(textPositionProperty) == "super") {
267             wikiContext->outStream << "<sup>";
268         }
269     }
270     else {
271         if (styleProperties->attribute(textLineThroughProperty)== "solid") {
272             wikiContext->outStream << "</s>";
273         }
274         if (styleProperties->attribute(textPositionProperty) == "sub") {
275            wikiContext->outStream << "</sub>";
276         }
277         else if (styleProperties->attribute(textPositionProperty) == "super") {
278             wikiContext->outStream << "</sup>";
279         }
280     }
281     wikiContext->pushStyle(style);
282 }
283 
outputHeadingLevel(OdfReaderWikiContext * wikiContext)284 void OdtReaderWikiBackend::outputHeadingLevel(OdfReaderWikiContext *wikiContext)
285 {
286     int level = wikiContext->outlineLevel;
287     if (level == 1) {
288         wikiContext->outStream << "==";
289     }
290     else if (level == 2) {
291         wikiContext->outStream << "===";
292     }
293     else if (level == 3) {
294         wikiContext->outStream  << "====";
295     }
296 }
297