1 /*
2 For general Scribus (>=1.3.2) copyright and licensing information please refer
3 to the COPYING file provided with the program. Following this notice may exist
4 a copyright and/or license notice that predates the release of Scribus 1.3.2
5 for which a new license (GPL+exception) is in place.
6 */
7 /***************************************************************************
8 -------------------
9 begin : Sun Jan 3 2016
10 copyright : (C) 2016 by Franz Schmid
11 email : Franz.Schmid@altmuehlnet.de
12 ***************************************************************************/
13 #include "importodt.h"
14
15 #include <QApplication>
16 #include <QByteArray>
17 #include <QScopedPointer>
18
19 #include "scribusdoc.h"
20 #include "styles/charstyle.h"
21 #include "styles/paragraphstyle.h"
22 #include "third_party/zip/scribus_zip.h"
23 #include "prefsmanager.h"
24 #include "scclocale.h"
25 #include "ui/missing.h"
26 #include "util.h"
27
28
FileFormatName()29 QString FileFormatName()
30 {
31 return QObject::tr("ODT Document");
32 }
33
FileExtensions()34 QStringList FileExtensions()
35 {
36 QStringList ret;
37 ret.append("odt");
38 ret.append("fodt");
39 return ret;
40 }
41
GetText2(const QString & filename,const QString & encoding,bool textOnly,bool prefix,bool append,PageItem * textItem)42 void GetText2(const QString& filename, const QString& encoding, bool textOnly, bool prefix, bool append, PageItem *textItem)
43 {
44 ODTIm* docxim = new ODTIm(filename, textItem, textOnly, prefix, append);
45 delete docxim;
46 }
47
ODTIm(const QString & fileName,PageItem * textItem,bool textOnly,bool prefix,bool append)48 ODTIm::ODTIm(const QString& fileName, PageItem *textItem, bool textOnly, bool prefix, bool append)
49 {
50 m_Doc = textItem->doc();
51 m_item = textItem;
52 m_prefixName = prefix;
53 m_append = append;
54 QFileInfo fi = QFileInfo(fileName);
55 QString ext = fi.suffix().toLower();
56 if (ext == "fodt")
57 {
58 QByteArray f;
59 loadRawText(fileName, f);
60 QDomDocument designMapDom;
61 QString errorMsg;
62 int errorLine = 0;
63 int errorColumn = 0;
64 if (!designMapDom.setContent(f, &errorMsg, &errorLine, &errorColumn))
65 {
66 qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
67 return;
68 }
69 if (textOnly)
70 parseRawDocReferenceXML(designMapDom);
71 else
72 parseDocReferenceXML(designMapDom);
73 }
74 else
75 {
76 uz = new ScZipHandler();
77 if (uz)
78 {
79 if (!uz->open(fileName))
80 {
81 delete uz;
82 QByteArray f;
83 loadRawText(fileName, f);
84 QDomDocument designMapDom;
85 QString errorMsg;
86 int errorLine = 0;
87 int errorColumn = 0;
88 if (designMapDom.setContent(f, &errorMsg, &errorLine, &errorColumn))
89 {
90 if (textOnly)
91 parseRawDocReferenceXML(designMapDom);
92 else
93 parseDocReferenceXML(designMapDom);
94 }
95 else
96 {
97 qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
98 return;
99 }
100 }
101 else
102 {
103 if (textOnly)
104 {
105 if (uz->contains("content.xml"))
106 parseRawDocReference("content.xml");
107 }
108 else
109 {
110 if (uz->contains("styles.xml"))
111 {
112 if (parseStyleSheets("styles.xml"))
113 {
114 if (uz->contains("content.xml"))
115 parseDocReference("content.xml");
116 }
117 }
118 else
119 {
120 if (uz->contains("content.xml"))
121 parseDocReference("content.xml");
122 }
123 }
124 uz->close();
125 delete uz;
126 }
127 }
128 }
129 textItem->itemText.trim();
130 textItem->itemText.invalidateLayout();
131 }
132
~ODTIm()133 ODTIm::~ODTIm()
134 {
135 }
136
137 /* Raw Text import */
138
parseRawDocReference(const QString & designMap)139 bool ODTIm::parseRawDocReference(const QString& designMap)
140 {
141 QByteArray xmlData;
142 QDomDocument designMapDom;
143 if (!uz->read(designMap, xmlData))
144 return false;
145
146 QString errorMsg;
147 int errorLine = 0;
148 int errorColumn = 0;
149 if (!designMapDom.setContent(xmlData, false, &errorMsg, &errorLine, &errorColumn))
150 {
151 qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
152 return false;
153 }
154 return parseRawDocReferenceXML(designMapDom);
155 }
156
parseRawDocReferenceXML(QDomDocument & designMapDom)157 bool ODTIm::parseRawDocReferenceXML(QDomDocument &designMapDom)
158 {
159 QDomElement docElem = designMapDom.documentElement();
160 for (QDomElement drawPag = docElem.firstChildElement(); !drawPag.isNull(); drawPag = drawPag.nextSiblingElement())
161 {
162 if (drawPag.tagName() == "office:body")
163 {
164 for (QDomElement sp = drawPag.firstChildElement(); !sp.isNull(); sp = sp.nextSiblingElement() )
165 {
166 if (sp.tagName() == "office:text")
167 {
168 parseRawText(sp, m_item);
169 }
170 }
171 }
172 }
173 return true;
174 }
175
parseRawTextSpan(QDomElement & elem,PageItem * item,ParagraphStyle & tmpStyle,CharStyle & tmpCStyle,int & posC)176 void ODTIm::parseRawTextSpan(QDomElement &elem, PageItem* item, ParagraphStyle &tmpStyle, CharStyle &tmpCStyle, int &posC)
177 {
178 if (!elem.hasChildNodes())
179 return;
180
181 for (QDomNode spn = elem.firstChild(); !spn.isNull(); spn = spn.nextSibling())
182 {
183 QString txt = "";
184 QDomElement spEl = spn.toElement();
185 if (spn.nodeName() == "#text")
186 txt = spn.nodeValue();
187 else if (spn.nodeName() == "text:span")
188 parseRawTextSpan(spEl, item, tmpStyle, tmpCStyle, posC);
189 else if (spn.nodeName() == "text:s")
190 {
191 if (spEl.hasAttribute("text:c"))
192 {
193 int n = spEl.attribute("text:c").toInt();
194 for (int nn = 0; nn < n; nn++)
195 {
196 txt += " ";
197 }
198 }
199 else
200 txt = " ";
201 }
202 else if (spn.nodeName() == "text:tab")
203 txt = SpecialChars::TAB;
204 else if (spn.nodeName() == "text:line-break")
205 txt = SpecialChars::LINEBREAK;
206 if (!txt.isEmpty())
207 {
208 txt.replace(QChar(0xAD), SpecialChars::SHYPHEN);
209 txt.replace(QChar(0x2011), SpecialChars::NBHYPHEN);
210 txt.replace(QChar(0xA0), SpecialChars::NBSPACE);
211 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
212 }
213 }
214 }
215
parseRawTextParagraph(QDomNode & elem,PageItem * item,ParagraphStyle & newStyle,int & posC)216 void ODTIm::parseRawTextParagraph(QDomNode &elem, PageItem* item, ParagraphStyle &newStyle, int &posC)
217 {
218 CharStyle tmpCStyle = newStyle.charStyle();
219 if (elem.hasChildNodes())
220 {
221 for (QDomNode spn = elem.firstChild(); !spn.isNull(); spn = spn.nextSibling())
222 {
223 QString txt = "";
224 QDomElement spEl = spn.toElement();
225 if (spn.nodeName() == "#text")
226 txt = spn.nodeValue();
227 else if (spn.nodeName() == "text:span")
228 parseRawTextSpan(spEl, item, newStyle, tmpCStyle, posC);
229 else if (spn.nodeName() == "text:s")
230 {
231 if (spEl.hasAttribute("text:c"))
232 {
233 int n = spEl.attribute("text:c").toInt();
234 for (int nn = 0; nn < n; nn++)
235 {
236 txt += " ";
237 }
238 }
239 else
240 txt = " ";
241 }
242 else if (spn.nodeName() == "text:tab")
243 txt = SpecialChars::TAB;
244 else if (spn.nodeName() == "text:line-break")
245 txt = SpecialChars::LINEBREAK;
246 if (!txt.isEmpty())
247 {
248 txt.replace(QChar(0xAD), SpecialChars::SHYPHEN);
249 txt.replace(QChar(0x2011), SpecialChars::NBHYPHEN);
250 txt.replace(QChar(0xA0), SpecialChars::NBSPACE);
251 insertChars(item, txt, newStyle, tmpCStyle, posC);
252 }
253 }
254 }
255 item->itemText.insertChars(posC, SpecialChars::PARSEP);
256 item->itemText.applyStyle(posC, newStyle);
257 posC = item->itemText.length();
258 }
259
parseRawText(QDomElement & elem,PageItem * item)260 void ODTIm::parseRawText(QDomElement &elem, PageItem* item)
261 {
262 QString pStyleD = CommonStrings::DefaultParagraphStyle;
263 ParagraphStyle newStyle;
264 newStyle.setDefaultStyle(false);
265 newStyle.setParent(pStyleD);
266 if (!m_append)
267 {
268 item->itemText.clear();
269 item->itemText.setDefaultStyle(newStyle);
270 }
271 int posC = item->itemText.length();
272 for (QDomNode para = elem.firstChild(); !para.isNull(); para = para.nextSibling())
273 {
274 if ((para.nodeName() == "text:p") || (para.nodeName() == "text:h"))
275 parseRawTextParagraph(para, item, newStyle, posC);
276 else if (para.nodeName() == "text:list")
277 {
278 if (!para.hasChildNodes())
279 continue;
280 for (QDomNode spn = para.firstChild(); !spn.isNull(); spn = spn.nextSibling())
281 {
282 if (spn.nodeName() == "text:list-item")
283 {
284 if (!spn.hasChildNodes())
285 continue;
286 for (QDomNode spp = spn.firstChild(); !spp.isNull(); spp = spp.nextSibling())
287 {
288 if (spp.nodeName() == "text:p")
289 {
290 parseRawTextParagraph(spp, item, newStyle, posC);
291 }
292 }
293 }
294 }
295 }
296 else if (para.nodeName() == "text:section")
297 {
298 if (!para.hasChildNodes())
299 continue;
300 for (QDomNode spn = para.firstChild(); !spn.isNull(); spn = spn.nextSibling())
301 {
302 if (spn.nodeName() == "text:p")
303 {
304 parseRawTextParagraph(spn, item, newStyle, posC);
305 }
306 }
307 }
308 }
309 }
310
311 /* Styled Text import */
312
parseStyleSheets(const QString & designMap)313 bool ODTIm::parseStyleSheets(const QString& designMap)
314 {
315 QByteArray xmlData;
316 QDomDocument designMapDom;
317 if (!uz->read(designMap, xmlData))
318 return false;
319
320 QString errorMsg;
321 int errorLine = 0;
322 int errorColumn = 0;
323 if (!designMapDom.setContent(xmlData, false, &errorMsg, &errorLine, &errorColumn))
324 {
325 qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
326 return false;
327 }
328 return parseStyleSheetsXML(designMapDom);
329 }
330
parseStyleSheetsXML(QDomDocument & designMapDom)331 bool ODTIm::parseStyleSheetsXML(QDomDocument &designMapDom)
332 {
333 QDomElement docElem = designMapDom.documentElement();
334 for (QDomElement sp = docElem.firstChildElement(); !sp.isNull(); sp = sp.nextSiblingElement() )
335 {
336 if (sp.tagName() == "office:font-face-decls")
337 {
338 for (QDomElement spf = sp.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement() )
339 {
340 if (spf.tagName() == "style:font-face")
341 {
342 if (!spf.attribute("style:name").isEmpty())
343 {
344 QString fontFamily = spf.attribute("svg:font-family");
345 if (fontFamily.startsWith(QChar('\'')))
346 fontFamily = fontFamily.mid(1);
347 if (fontFamily.endsWith(QChar('\'')))
348 fontFamily.chop(1);
349 m_fontMap.insert(spf.attribute("style:name"), fontFamily);
350 }
351 }
352 }
353 }
354 else if (sp.tagName() == "office:styles")
355 parseStyles(sp, "styles");
356 else if (sp.tagName() == "office:automatic-styles")
357 parseStyles(sp, "auto");
358 }
359 return true;
360 }
361
parseStyles(QDomElement & sp,const QString & type)362 void ODTIm::parseStyles(QDomElement &sp, const QString& type)
363 {
364 for (QDomElement spd = sp.firstChildElement(); !spd.isNull(); spd = spd.nextSiblingElement() )
365 {
366 if (spd.tagName() == "style:default-style")
367 {
368 DrawStyle currStyle;
369 currStyle.styleOrigin = AttributeValue(type);
370 for (QDomElement spe = spd.firstChildElement(); !spe.isNull(); spe = spe.nextSiblingElement() )
371 {
372 if (spe.tagName() == "style:paragraph-properties")
373 {
374 currStyle.margin_top = AttributeValue(spe.attribute("fo:margin-top", ""));
375 currStyle.margin_bottom = AttributeValue(spe.attribute("fo:margin-bottom", ""));
376 currStyle.margin_left = AttributeValue(spe.attribute("fo:margin-left", ""));
377 currStyle.margin_right = AttributeValue(spe.attribute("fo:margin-right", ""));
378 currStyle.textIndent = AttributeValue(spe.attribute("fo:text-indent", ""));
379 currStyle.textAlign = AttributeValue(spe.attribute("fo:text-align", ""));
380 currStyle.lineHeight = AttributeValue(spe.attribute("fo:line-height", ""));
381 currStyle.parBackgroundColor = AttributeValue(spe.attribute("fo:background-color", ""));
382 currStyle.breakAfter = AttributeValue(spe.attribute("fo:break-after", ""));
383 currStyle.breakBefore = AttributeValue(spe.attribute("fo:break-before", ""));
384 if (spe.hasChildNodes())
385 {
386 for (QDomElement spt = spe.firstChildElement(); !spt.isNull(); spt = spt.nextSiblingElement() )
387 {
388 if (spt.tagName() == "style:tab-stops")
389 {
390 QString tabDists = "";
391 QString tabTypes = "";
392 for (QDomElement spte = spt.firstChildElement(); !spte.isNull(); spte = spte.nextSiblingElement() )
393 {
394 if (spte.tagName() == "style:tab-stop")
395 {
396 if (spte.hasAttribute("style:position"))
397 tabDists.append(spte.attribute("style:position") + ";");
398 else
399 tabDists.append("0;");
400 if (spte.hasAttribute("style:type"))
401 tabTypes.append(spte.attribute("style:type") + " ");
402 else
403 tabTypes.append("left ");
404 }
405 }
406 currStyle.tabDists = AttributeValue(tabDists);
407 currStyle.tabTypes = AttributeValue(tabTypes);
408 }
409 }
410 }
411 }
412 else if (spe.tagName() == "style:text-properties")
413 {
414 currStyle.fontName = AttributeValue(spe.attribute("style:font-name", ""));
415 if (!currStyle.fontName.valid)
416 currStyle.fontName = AttributeValue(spe.attribute("fo:font-family", ""));
417 currStyle.fontSize = AttributeValue(spe.attribute("fo:font-size", ""));
418 currStyle.fontColor = AttributeValue(spe.attribute("fo:color", ""));
419 currStyle.fontStyle = AttributeValue(spe.attribute("fo:font-style", ""));
420 currStyle.fontWeight = AttributeValue(spe.attribute("fo:font-weight", ""));
421 currStyle.textBackgroundColor = AttributeValue(spe.attribute("fo:background-color", ""));
422 currStyle.textPos = AttributeValue(spe.attribute("style:text-position", ""));
423 currStyle.textOutline = AttributeValue(spe.attribute("style:text-outline", ""));
424 currStyle.textUnderline = AttributeValue(spe.attribute("style:text-underline-style", ""));
425 currStyle.textUnderlineWords = AttributeValue(spe.attribute("style:text-underline-mode", ""));
426 currStyle.textUnderlineColor = AttributeValue(spe.attribute("style:text-underline-color", ""));
427 currStyle.textStrikeThrough = AttributeValue(spe.attribute("style:text-line-through-style", ""));
428 currStyle.textShadow = AttributeValue(spe.attribute("fo:text-shadow", ""));
429 currStyle.fontVariant = AttributeValue(spe.attribute("fo:font-variant", ""));
430 }
431 }
432 if (spd.attribute("style:family") == "paragraph")
433 parDefaultStyle = currStyle;
434 else if (spd.attribute("style:family") == "text")
435 txtDefaultStyle = currStyle;
436 }
437 else if (spd.tagName() == "style:style")
438 {
439 DrawStyle currStyle;
440 currStyle.parentStyle = AttributeValue(spd.attribute("style:parent-style-name", ""));
441 if (!currStyle.parentStyle.valid)
442 {
443 if (spd.attribute("style:family") == "paragraph")
444 currStyle = parDefaultStyle;
445 else if (spd.attribute("style:family") == "text")
446 currStyle = txtDefaultStyle;
447 }
448 currStyle.styleType = AttributeValue(spd.attribute("style:family", ""));
449 currStyle.styleOrigin = AttributeValue(type);
450 for (QDomElement spe = spd.firstChildElement(); !spe.isNull(); spe = spe.nextSiblingElement() )
451 {
452 if (spe.tagName() == "style:paragraph-properties")
453 {
454 currStyle.margin_top = AttributeValue(spe.attribute("fo:margin-top", ""));
455 currStyle.margin_bottom = AttributeValue(spe.attribute("fo:margin-bottom", ""));
456 currStyle.margin_left = AttributeValue(spe.attribute("fo:margin-left", ""));
457 currStyle.margin_right = AttributeValue(spe.attribute("fo:margin-right", ""));
458 currStyle.textIndent = AttributeValue(spe.attribute("fo:text-indent", ""));
459 currStyle.textAlign = AttributeValue(spe.attribute("fo:text-align", ""));
460 currStyle.lineHeight = AttributeValue(spe.attribute("fo:line-height", ""));
461 currStyle.parBackgroundColor = AttributeValue(spe.attribute("fo:background-color", ""));
462 currStyle.breakAfter = AttributeValue(spe.attribute("fo:break-after", ""));
463 currStyle.breakBefore = AttributeValue(spe.attribute("fo:break-before", ""));
464 if (spe.hasChildNodes())
465 {
466 for (QDomElement spt = spe.firstChildElement(); !spt.isNull(); spt = spt.nextSiblingElement() )
467 {
468 if (spt.tagName() == "style:tab-stops")
469 {
470 QString tabDists = "";
471 QString tabTypes = "";
472 for (QDomElement spte = spt.firstChildElement(); !spte.isNull(); spte = spte.nextSiblingElement() )
473 {
474 if (spte.tagName() == "style:tab-stop")
475 {
476 if (spte.hasAttribute("style:position"))
477 tabDists.append(spte.attribute("style:position") + ";");
478 else
479 tabDists.append("0;");
480 if (spte.hasAttribute("style:type"))
481 tabTypes.append(spte.attribute("style:type") + " ");
482 else
483 tabTypes.append("left ");
484 }
485 }
486 currStyle.tabDists = AttributeValue(tabDists);
487 currStyle.tabTypes = AttributeValue(tabTypes);
488 }
489 }
490 }
491 }
492 else if (spe.tagName() == "style:text-properties")
493 {
494 currStyle.fontName = AttributeValue(spe.attribute("style:font-name", ""));
495 if (!currStyle.fontName.valid)
496 currStyle.fontName = AttributeValue(spe.attribute("fo:font-family", ""));
497 currStyle.fontSize = AttributeValue(spe.attribute("fo:font-size", ""));
498 currStyle.fontColor = AttributeValue(spe.attribute("fo:color", ""));
499 currStyle.fontStyle = AttributeValue(spe.attribute("fo:font-style", ""));
500 currStyle.fontWeight = AttributeValue(spe.attribute("fo:font-weight", ""));
501 currStyle.textBackgroundColor = AttributeValue(spe.attribute("fo:background-color", ""));
502 currStyle.textPos = AttributeValue(spe.attribute("style:text-position", ""));
503 currStyle.textOutline = AttributeValue(spe.attribute("style:text-outline", ""));
504 currStyle.textUnderline = AttributeValue(spe.attribute("style:text-underline-style", ""));
505 currStyle.textUnderlineWords = AttributeValue(spe.attribute("style:text-underline-mode", ""));
506 currStyle.textUnderlineColor = AttributeValue(spe.attribute("style:text-underline-color", ""));
507 currStyle.textStrikeThrough = AttributeValue(spe.attribute("style:text-line-through-style", ""));
508 currStyle.textShadow = AttributeValue(spe.attribute("fo:text-shadow", ""));
509 currStyle.fontVariant = AttributeValue(spe.attribute("fo:font-variant", ""));
510 }
511 }
512 currStyle.displayName = AttributeValue(spd.attribute("style:display-name", ""));
513 m_Styles.insert(spd.attribute("style:name"), currStyle);
514 if (type == "styles")
515 {
516 ObjStyleODT tmpOStyle;
517 resolveStyle(tmpOStyle, spd.attribute("style:name"));
518 if (spd.attribute("style:family") == "paragraph")
519 {
520 ParagraphStyle newStyle;
521 newStyle.erase();
522 newStyle.setDefaultStyle(false);
523 newStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
524 QString styleName = spd.attribute("style:name");
525 if (currStyle.displayName.valid)
526 styleName = currStyle.displayName.value;
527 if (m_prefixName)
528 newStyle.setName(m_item->itemName() + "_" + styleName);
529 else
530 newStyle.setName(styleName);
531 QString parentName = CommonStrings::DefaultParagraphStyle;
532 if (currStyle.parentStyle.valid)
533 {
534 if (m_Styles.contains(currStyle.parentStyle.value))
535 {
536 DrawStyle pStyle = m_Styles[currStyle.parentStyle.value];
537 parentName = currStyle.parentStyle.value;
538 if (pStyle.displayName.valid)
539 parentName = pStyle.displayName.value;
540 }
541 }
542 if (m_prefixName)
543 newStyle.setParent(m_item->itemName() + "_" + parentName);
544 else
545 newStyle.setParent(parentName);
546 applyParagraphStyle(newStyle, tmpOStyle);
547 applyCharacterStyle(newStyle.charStyle(), tmpOStyle);
548 StyleSet<ParagraphStyle>tmp;
549 tmp.create(newStyle);
550 m_Doc->redefineStyles(tmp, false);
551 }
552 else if (spd.attribute("style:family") == "text")
553 {
554 CharStyle newStyle;
555 newStyle.setDefaultStyle(false);
556 QString styleName = spd.attribute("style:name");
557 if (currStyle.displayName.valid)
558 styleName = currStyle.displayName.value;
559 if (m_prefixName)
560 newStyle.setName(m_item->itemName() + "_" + styleName);
561 else
562 newStyle.setName(styleName);
563 newStyle.setParent(CommonStrings::DefaultCharacterStyle);
564 applyCharacterStyle(newStyle, tmpOStyle);
565 StyleSet<CharStyle> temp;
566 temp.create(newStyle);
567 m_Doc->redefineCharStyles(temp, false);
568 }
569 }
570 }
571 }
572 }
573
parseDocReference(const QString & designMap)574 bool ODTIm::parseDocReference(const QString& designMap)
575 {
576 QByteArray xmlData;
577 QDomDocument designMapDom;
578 if (!uz->read(designMap, xmlData))
579 return false;
580
581 QString errorMsg;
582 int errorLine = 0;
583 int errorColumn = 0;
584 if (!designMapDom.setContent(xmlData, false, &errorMsg, &errorLine, &errorColumn))
585 {
586 qDebug() << "Error loading File" << errorMsg << "at Line" << errorLine << "Column" << errorColumn;
587 return false;
588 }
589 return parseDocReferenceXML(designMapDom);
590 }
591
parseDocReferenceXML(QDomDocument & designMapDom)592 bool ODTIm::parseDocReferenceXML(QDomDocument &designMapDom)
593 {
594 QDomElement docElem = designMapDom.documentElement();
595 for (QDomElement drawPag = docElem.firstChildElement(); !drawPag.isNull(); drawPag = drawPag.nextSiblingElement())
596 {
597 if (drawPag.tagName() == "office:font-face-decls")
598 {
599 for (QDomElement spf = drawPag.firstChildElement(); !spf.isNull(); spf = spf.nextSiblingElement() )
600 {
601 if (spf.tagName() == "style:font-face")
602 {
603 if (!spf.attribute("style:name").isEmpty())
604 {
605 QString fontFamily = spf.attribute("svg:font-family");
606 if (fontFamily.startsWith(QChar('\'')))
607 fontFamily = fontFamily.mid(1);
608 if (fontFamily.endsWith(QChar('\'')))
609 fontFamily.chop(1);
610 m_fontMap.insert(spf.attribute("style:name"), fontFamily);
611 }
612 }
613 }
614 }
615 else if (drawPag.tagName() == "office:styles")
616 parseStyles(drawPag, "styles");
617 else if (drawPag.tagName() == "office:automatic-styles")
618 parseStyles(drawPag, "auto");
619 else if (drawPag.tagName() == "office:body")
620 {
621 for (QDomElement sp = drawPag.firstChildElement(); !sp.isNull(); sp = sp.nextSiblingElement() )
622 {
623 if (sp.tagName() == "office:text")
624 {
625 ObjStyleODT tmpOStyle;
626 resolveStyle(tmpOStyle, "standard");
627 parseText(sp, m_item, tmpOStyle);
628 }
629 }
630 }
631 }
632 return true;
633 }
634
parseTextSpan(QDomElement & elem,PageItem * item,ParagraphStyle & tmpStyle,CharStyle & tmpCStyle,ObjStyleODT & tmpOStyle,int & posC)635 void ODTIm::parseTextSpan(QDomElement &elem, PageItem* item, ParagraphStyle &tmpStyle, CharStyle &tmpCStyle, ObjStyleODT &tmpOStyle, int &posC)
636 {
637 ObjStyleODT odtStyle = tmpOStyle;
638 CharStyle cStyle = tmpCStyle;
639
640 QString textStyleName = elem.attribute("text:style-name");
641 if (textStyleName.length() > 0)
642 {
643 resolveStyle(odtStyle, textStyleName);
644 m_textStylesStack.push(textStyleName);
645 }
646
647 applyCharacterStyle(cStyle, odtStyle);
648 if (!elem.hasChildNodes())
649 return;
650
651 for (QDomNode spn = elem.firstChild(); !spn.isNull(); spn = spn.nextSibling())
652 {
653 QString txt = "";
654 QDomElement spEl = spn.toElement();
655 if (spn.nodeName() == "#text")
656 txt = spn.nodeValue();
657 else if (spn.nodeName() == "text:span")
658 parseTextSpan(spEl, item, tmpStyle, cStyle, odtStyle, posC);
659 else if (spn.nodeName() == "text:s")
660 {
661 if (spEl.hasAttribute("text:c"))
662 {
663 int n = spEl.attribute("text:c").toInt();
664 for (int nn = 0; nn < n; nn++)
665 {
666 txt += " ";
667 }
668 }
669 else
670 txt = " ";
671 }
672 else if (spn.nodeName() == "text:tab")
673 txt = SpecialChars::TAB;
674 else if (spn.nodeName() == "text:line-break")
675 txt = SpecialChars::LINEBREAK;
676 if (!txt.isEmpty())
677 {
678 txt.replace(QChar(0xAD), SpecialChars::SHYPHEN);
679 txt.replace(QChar(0x2011), SpecialChars::NBHYPHEN);
680 txt.replace(QChar(0xA0), SpecialChars::NBSPACE);
681 insertChars(item, txt, tmpStyle, cStyle, posC);
682 }
683 }
684
685 if (textStyleName.length() > 0)
686 m_textStylesStack.pop();
687 }
688
parseTextParagraph(QDomNode & elem,PageItem * item,ParagraphStyle & newStyle,ObjStyleODT & tmpOStyle,int & posC)689 void ODTIm::parseTextParagraph(QDomNode &elem, PageItem* item, ParagraphStyle &newStyle, ObjStyleODT &tmpOStyle, int &posC)
690 {
691 ParagraphStyle tmpStyle = newStyle;
692 CharStyle tmpCStyle = tmpStyle.charStyle();
693 ObjStyleODT pStyle = tmpOStyle;
694 QString parStyleName = "";
695
696 QString pStyleName = elem.toElement().attribute("text:style-name");
697 if (pStyleName.length() > 0)
698 {
699 resolveStyle(pStyle, pStyleName);
700 if (m_Styles.contains(pStyleName))
701 {
702 DrawStyle currStyle = m_Styles[pStyleName];
703 if (currStyle.styleOrigin.value == "styles")
704 {
705 if (m_prefixName)
706 {
707 parStyleName = m_item->itemName() + "_" + pStyleName;
708 if (currStyle.displayName.valid)
709 parStyleName = m_item->itemName() + "_" + currStyle.displayName.value;
710 }
711 else
712 {
713 parStyleName = pStyleName;
714 if (currStyle.displayName.valid)
715 parStyleName = currStyle.displayName.value;
716 }
717 }
718 }
719 m_textStylesStack.push(pStyleName);
720 }
721 if ((pStyle.breakBefore == "column") && (item->itemText.length() > 0))
722 {
723 QString txt = SpecialChars::COLBREAK;
724 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
725 }
726 else if ((pStyle.breakBefore == "page") && (item->itemText.length() > 0))
727 {
728 QString txt = SpecialChars::FRAMEBREAK;
729 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
730 }
731 applyParagraphStyle(tmpStyle, pStyle);
732 if (elem.hasChildNodes())
733 {
734 for (QDomNode spn = elem.firstChild(); !spn.isNull(); spn = spn.nextSibling())
735 {
736 if (!parStyleName.isEmpty())
737 {
738 tmpStyle.setParent(parStyleName);
739 applyParagraphStyle(tmpStyle, pStyle);
740 tmpCStyle = tmpStyle.charStyle();
741 applyCharacterStyle(tmpCStyle, pStyle);
742 }
743 else
744 {
745 tmpStyle = newStyle;
746 applyParagraphStyle(tmpStyle, pStyle);
747 tmpCStyle = tmpStyle.charStyle();
748 applyCharacterStyle(tmpCStyle, pStyle);
749 }
750 QString txt = "";
751 ObjStyleODT cStyle = pStyle;
752 QDomElement spEl = spn.toElement();
753 if (spn.nodeName() == "#text")
754 txt = spn.nodeValue();
755 else if (spn.nodeName() == "text:span")
756 parseTextSpan(spEl, item, tmpStyle, tmpCStyle, cStyle, posC);
757 else if (spn.nodeName() == "text:s")
758 {
759 if (spEl.hasAttribute("text:c"))
760 {
761 int n = spEl.attribute("text:c").toInt();
762 for (int nn = 0; nn < n; nn++)
763 {
764 txt += " ";
765 }
766 }
767 else
768 txt = " ";
769 }
770 else if (spn.nodeName() == "text:tab")
771 txt = SpecialChars::TAB;
772 else if (spn.nodeName() == "text:line-break")
773 txt = SpecialChars::LINEBREAK;
774 if (!txt.isEmpty())
775 {
776 txt.replace(QChar(0xAD), SpecialChars::SHYPHEN);
777 txt.replace(QChar(0x2011), SpecialChars::NBHYPHEN);
778 txt.replace(QChar(0xA0), SpecialChars::NBSPACE);
779 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
780 }
781 }
782 }
783 /* if (pStyle.lineHeight < 0.0)
784 tmpStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
785 else
786 {
787 tmpStyle.setLineSpacingMode(ParagraphStyle::FixedLineSpacing);
788 if (pStyle.absLineHeight)
789 tmpStyle.setLineSpacing(tmpOStyle.lineHeight);
790 else
791 tmpStyle.setLineSpacing(tmpOStyle.lineHeight * tmpOStyle.fontSize);
792 } */
793 if (pStyle.breakAfter == "column")
794 {
795 QString txt = SpecialChars::COLBREAK;
796 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
797 }
798 else if (pStyle.breakAfter == "page")
799 {
800 QString txt = SpecialChars::FRAMEBREAK;
801 insertChars(item, txt, tmpStyle, tmpCStyle, posC);
802 }
803 item->itemText.insertChars(posC, SpecialChars::PARSEP);
804 item->itemText.applyStyle(posC, tmpStyle);
805 posC = item->itemText.length();
806
807 if (pStyleName.length() > 0)
808 m_textStylesStack.pop();
809 }
810
parseText(QDomElement & elem,PageItem * item,ObjStyleODT & tmpOStyle)811 void ODTIm::parseText(QDomElement &elem, PageItem* item, ObjStyleODT &tmpOStyle)
812 {
813 QString pStyleD = CommonStrings::DefaultParagraphStyle;
814 ParagraphStyle newStyle;
815 newStyle.setDefaultStyle(false);
816 newStyle.setParent(pStyleD);
817 ParagraphStyle ttx = m_Doc->paragraphStyle(pStyleD);
818 CharStyle nstyle = ttx.charStyle();
819 newStyle.setLineSpacingMode(ParagraphStyle::AutomaticLineSpacing);
820 newStyle.setLineSpacing(nstyle.fontSize() / 10.0);
821 if (!m_append)
822 {
823 item->itemText.clear();
824 item->itemText.setDefaultStyle(newStyle);
825 item->setFirstLineOffset(FLOPFontAscent);
826 }
827 int posC = item->itemText.length();
828 for (QDomNode para = elem.firstChild(); !para.isNull(); para = para.nextSibling())
829 {
830 if ((para.nodeName() == "text:p") || (para.nodeName() == "text:h"))
831 parseTextParagraph(para, item, newStyle, tmpOStyle, posC);
832 else if (para.nodeName() == "text:list")
833 {
834 if (!para.hasChildNodes())
835 continue;
836 for (QDomNode spn = para.firstChild(); !spn.isNull(); spn = spn.nextSibling())
837 {
838 if (spn.nodeName() == "text:list-item")
839 {
840 if (!spn.hasChildNodes())
841 continue;
842 for (QDomNode spp = spn.firstChild(); !spp.isNull(); spp = spp.nextSibling())
843 {
844 if (spp.nodeName() == "text:p")
845 {
846 parseTextParagraph(spp, item, newStyle, tmpOStyle, posC);
847 }
848 }
849 }
850 }
851 }
852 else if (para.nodeName() == "text:section")
853 {
854 if (!para.hasChildNodes())
855 continue;
856 for (QDomNode spn = para.firstChild(); !spn.isNull(); spn = spn.nextSibling())
857 {
858 if (spn.nodeName() == "text:p")
859 {
860 parseTextParagraph(spn, item, newStyle, tmpOStyle, posC);
861 }
862 }
863 }
864 }
865 }
866
insertChars(PageItem * item,QString & txt,ParagraphStyle & tmpStyle,CharStyle & tmpCStyle,int & posC)867 void ODTIm::insertChars(PageItem *item, QString &txt, ParagraphStyle &tmpStyle, CharStyle &tmpCStyle, int &posC)
868 {
869 if (txt.length() > 0)
870 {
871 item->itemText.insertChars(posC, txt);
872 item->itemText.applyStyle(posC, tmpStyle);
873 item->itemText.applyCharStyle(posC, txt.length(), tmpCStyle);
874 posC = item->itemText.length();
875 txt = "";
876 }
877 }
878
applyCharacterStyle(CharStyle & tmpCStyle,ObjStyleODT & oStyle)879 void ODTIm::applyCharacterStyle(CharStyle &tmpCStyle, ObjStyleODT &oStyle)
880 {
881 tmpCStyle.setFont((*m_Doc->AllFonts)[oStyle.fontName]);
882 tmpCStyle.setFontSize(oStyle.fontSize * 10);
883 tmpCStyle.setFillColor(oStyle.CurrColorText);
884 tmpCStyle.setBackColor(oStyle.CurrColorBText);
885 StyleFlag styleEffects = tmpCStyle.effects();
886 if ((oStyle.textPos.startsWith("super")) || (oStyle.textPos.startsWith("sub")))
887 {
888 if (oStyle.textPos.startsWith("super"))
889 styleEffects |= ScStyle_Superscript;
890 else
891 styleEffects |= ScStyle_Subscript;
892 }
893 if (oStyle.textOutline == "true")
894 {
895 styleEffects |= ScStyle_Outline;
896 tmpCStyle.setOutlineWidth(30);
897 tmpCStyle.setFillColor("White");
898 tmpCStyle.setStrokeColor(oStyle.CurrColorText);
899 }
900 if (oStyle.textUnderline)
901 {
902 styleEffects |= ScStyle_Underline;
903 tmpCStyle.setUnderlineOffset(-1);
904 tmpCStyle.setUnderlineWidth(-1);
905 tmpCStyle.setStrokeColor(oStyle.textUnderlineColor);
906 }
907 if (oStyle.textStrikeThrough)
908 {
909 if (oStyle.textUnderlineWords)
910 styleEffects |= ScStyle_UnderlineWords;
911 else
912 styleEffects |= ScStyle_Strikethrough;
913 tmpCStyle.setStrikethruOffset(-1);
914 tmpCStyle.setStrikethruWidth(-1);
915 tmpCStyle.setStrokeColor(oStyle.CurrColorText);
916 }
917 if (oStyle.textShadow)
918 {
919 styleEffects |= ScStyle_Shadowed;
920 tmpCStyle.setShadowXOffset(30);
921 tmpCStyle.setShadowYOffset(-30);
922 tmpCStyle.setStrokeColor(oStyle.CurrColorText);
923 }
924 if (oStyle.textSmallCaps)
925 {
926 styleEffects |= ScStyle_SmallCaps;
927 }
928 tmpCStyle.setFeatures(styleEffects.featureList());
929 if ((oStyle.fontStyle == "italic") && (oStyle.fontWeight == "bold"))
930 setFontstyle(tmpCStyle, 3);
931 else if ((oStyle.fontStyle == "oblique") && (oStyle.fontWeight == "bold"))
932 setFontstyle(tmpCStyle, 4);
933 else if (oStyle.fontStyle == "italic")
934 setFontstyle(tmpCStyle, 0);
935 else if (oStyle.fontStyle == "oblique")
936 setFontstyle(tmpCStyle, 1);
937 else if (oStyle.fontWeight == "bold")
938 setFontstyle(tmpCStyle, 2);
939 }
940
applyParagraphStyle(ParagraphStyle & tmpStyle,ObjStyleODT & oStyle)941 void ODTIm::applyParagraphStyle(ParagraphStyle &tmpStyle, ObjStyleODT &oStyle)
942 {
943 tmpStyle.setAlignment(oStyle.textAlign);
944 tmpStyle.setLeftMargin(oStyle.margin_left);
945 tmpStyle.setRightMargin(oStyle.margin_right);
946 tmpStyle.setFirstIndent(oStyle.textIndent);
947 tmpStyle.setGapAfter(oStyle.margin_bottom);
948 tmpStyle.setGapBefore(oStyle.margin_top);
949 tmpStyle.setBackgroundColor(oStyle.CurrColorBPara);
950 tmpStyle.setTabValues(oStyle.tabStops);
951 }
952
resolveStyle(ObjStyleODT & tmpOStyle,const QString & pAttrs)953 void ODTIm::resolveStyle(ObjStyleODT &tmpOStyle, const QString& pAttrs)
954 {
955 if (m_Styles.contains(pAttrs))
956 {
957 DrawStyle actStyle;
958 DrawStyle currStyle = m_Styles[pAttrs];
959 QStringList parents;
960 while (currStyle.parentStyle.valid)
961 {
962 if (m_Styles.contains(currStyle.parentStyle.value))
963 {
964 parents.prepend(currStyle.parentStyle.value);
965 currStyle = m_Styles[currStyle.parentStyle.value];
966 }
967 else
968 break;
969 }
970 parents.append(pAttrs);
971 if (!parents.isEmpty())
972 {
973 for (int p = 0; p < parents.count(); p++)
974 {
975 currStyle = m_Styles[parents[p]];
976 if (currStyle.fontName.valid)
977 actStyle.fontName = AttributeValue(currStyle.fontName.value);
978 if (currStyle.fontSize.valid)
979 {
980 if (currStyle.fontSize.value.right(1) == "%")
981 {
982 double perc = parseUnit(currStyle.fontSize.value);
983 if (actStyle.fontSize.valid)
984 {
985 double value = parseUnit(actStyle.fontSize.value) * perc;
986 actStyle.fontSize = AttributeValue(QString("%1pt").arg(value));
987 }
988 }
989 else
990 actStyle.fontSize = AttributeValue(currStyle.fontSize.value);
991 }
992 if (currStyle.fontStyle.valid)
993 actStyle.fontStyle = AttributeValue(currStyle.fontStyle.value);
994 if (currStyle.fontWeight.valid)
995 actStyle.fontWeight = AttributeValue(currStyle.fontWeight.value);
996 if (currStyle.margin_top.valid)
997 actStyle.margin_top = AttributeValue(currStyle.margin_top.value);
998 if (currStyle.margin_bottom.valid)
999 actStyle.margin_bottom = AttributeValue(currStyle.margin_bottom.value);
1000 if (currStyle.margin_left.valid)
1001 actStyle.margin_left = AttributeValue(currStyle.margin_left.value);
1002 if (currStyle.margin_right.valid)
1003 actStyle.margin_right = AttributeValue(currStyle.margin_right.value);
1004 if (currStyle.textIndent.valid)
1005 actStyle.textIndent = AttributeValue(currStyle.textIndent.value);
1006 if (currStyle.textAlign.valid)
1007 actStyle.textAlign = AttributeValue(currStyle.textAlign.value);
1008 if (currStyle.textPos.valid)
1009 actStyle.textPos = AttributeValue(currStyle.textPos.value);
1010 if (currStyle.textOutline.valid)
1011 actStyle.textOutline = AttributeValue(currStyle.textOutline.value);
1012 if (currStyle.textUnderline.valid)
1013 actStyle.textUnderline = AttributeValue(currStyle.textUnderline.value);
1014 if (currStyle.textUnderlineWords.valid)
1015 actStyle.textUnderlineWords = AttributeValue(currStyle.textUnderlineWords.value);
1016 if (currStyle.textUnderlineColor.valid)
1017 actStyle.textUnderlineColor = AttributeValue(currStyle.textUnderlineColor.value);
1018 if (currStyle.textStrikeThrough.valid)
1019 actStyle.textStrikeThrough = AttributeValue(currStyle.textStrikeThrough.value);
1020 if (currStyle.textShadow.valid)
1021 actStyle.textShadow = AttributeValue(currStyle.textShadow.value);
1022 if (currStyle.fontVariant.valid)
1023 actStyle.fontVariant = AttributeValue(currStyle.fontVariant.value);
1024 if (currStyle.lineHeight.valid)
1025 actStyle.lineHeight = AttributeValue(currStyle.lineHeight.value);
1026 if (currStyle.fontColor.valid)
1027 actStyle.fontColor = AttributeValue(currStyle.fontColor.value);
1028 if (currStyle.textBackgroundColor.valid)
1029 actStyle.textBackgroundColor = AttributeValue(currStyle.textBackgroundColor.value);
1030 if (currStyle.parBackgroundColor.valid)
1031 actStyle.parBackgroundColor = AttributeValue(currStyle.parBackgroundColor.value);
1032 if (currStyle.verticalAlignment.valid)
1033 actStyle.verticalAlignment = AttributeValue(currStyle.verticalAlignment.value);
1034 if (currStyle.tabDists.valid)
1035 actStyle.tabDists = AttributeValue(currStyle.tabDists.value);
1036 if (currStyle.tabTypes.valid)
1037 actStyle.tabTypes = AttributeValue(currStyle.tabTypes.value);
1038 if (currStyle.breakAfter.valid)
1039 actStyle.breakAfter = AttributeValue(currStyle.breakAfter.value);
1040 if (currStyle.breakBefore.valid)
1041 actStyle.breakBefore = AttributeValue(currStyle.breakBefore.value);
1042 }
1043 }
1044 if (actStyle.textBackgroundColor.valid)
1045 {
1046 if (actStyle.textBackgroundColor.value == "transparent")
1047 tmpOStyle.CurrColorBText = CommonStrings::None;
1048 else
1049 tmpOStyle.CurrColorBText = parseColor(actStyle.textBackgroundColor.value);
1050 }
1051 else
1052 tmpOStyle.CurrColorBText = CommonStrings::None;
1053 if (actStyle.parBackgroundColor.valid)
1054 {
1055 if (actStyle.parBackgroundColor.value == "transparent")
1056 tmpOStyle.CurrColorBPara = CommonStrings::None;
1057 else
1058 tmpOStyle.CurrColorBPara = parseColor(actStyle.parBackgroundColor.value);
1059 }
1060 else
1061 tmpOStyle.CurrColorBPara = CommonStrings::None;
1062 if (actStyle.fontName.valid)
1063 {
1064 if (m_fontMap.contains(actStyle.fontName.value))
1065 tmpOStyle.fontName = m_fontMap[actStyle.fontName.value];
1066 else
1067 tmpOStyle.fontName = actStyle.fontName.value;
1068 if (!PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.contains(tmpOStyle.fontName))
1069 {
1070 tmpOStyle.fontName = constructFontName(tmpOStyle.fontName, "");
1071 m_fontMap[actStyle.fontName.value] = tmpOStyle.fontName;
1072 }
1073 }
1074 else
1075 {
1076 QString fontName;
1077 QStack<QString> textStyleStack = m_textStylesStack;
1078 while (!textStyleStack.isEmpty())
1079 {
1080 QString styleName = textStyleStack.pop();
1081 if (!m_Styles.contains(styleName))
1082 continue;
1083 const DrawStyle& odtStyle = m_Styles[styleName];
1084 if (odtStyle.fontName.valid)
1085 {
1086 if (m_fontMap.contains(odtStyle.fontName.value))
1087 tmpOStyle.fontName = m_fontMap[odtStyle.fontName.value];
1088 else
1089 tmpOStyle.fontName = constructFontName(odtStyle.fontName.value, "");
1090 if (!PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.contains(tmpOStyle.fontName))
1091 {
1092 tmpOStyle.fontName = constructFontName(tmpOStyle.fontName, "");
1093 m_fontMap[odtStyle.fontName.value] = tmpOStyle.fontName;
1094 }
1095 fontName = tmpOStyle.fontName;
1096 break;
1097 }
1098 if (odtStyle.parentStyle.valid)
1099 {
1100 QVector<QString> parentStyles;
1101 DrawStyle drawStyle = odtStyle;
1102 while (drawStyle.parentStyle.valid)
1103 {
1104 if (!m_Styles.contains(drawStyle.parentStyle.value))
1105 break;
1106 parentStyles.prepend(drawStyle.parentStyle.value);
1107 drawStyle = m_Styles[drawStyle.parentStyle.value];
1108 }
1109 if (parentStyles.count() > 0)
1110 textStyleStack += parentStyles;
1111 }
1112 }
1113 if (txtDefaultStyle.fontName.valid && fontName.isEmpty())
1114 {
1115 tmpOStyle.fontName = constructFontName(txtDefaultStyle.fontName.value, "");
1116 m_fontMap[txtDefaultStyle.fontName.value] = tmpOStyle.fontName;
1117 fontName = tmpOStyle.fontName;
1118 }
1119 if (parDefaultStyle.fontName.valid && fontName.isEmpty())
1120 {
1121 tmpOStyle.fontName = constructFontName(parDefaultStyle.fontName.value, "");
1122 m_fontMap[parDefaultStyle.fontName.value] = tmpOStyle.fontName;
1123 fontName = tmpOStyle.fontName;
1124 }
1125 }
1126 if (actStyle.fontStyle.valid)
1127 tmpOStyle.fontStyle = actStyle.fontStyle.value;
1128 if (actStyle.fontWeight.valid)
1129 tmpOStyle.fontWeight = actStyle.fontWeight.value;
1130 if (actStyle.fontSize.valid)
1131 tmpOStyle.fontSize = parseUnit(actStyle.fontSize.value);
1132 if (actStyle.fontColor.valid)
1133 tmpOStyle.CurrColorText = parseColor(actStyle.fontColor.value);
1134 if (actStyle.margin_top.valid)
1135 tmpOStyle.margin_top = parseUnit(actStyle.margin_top.value);
1136 if (actStyle.margin_bottom.valid)
1137 tmpOStyle.margin_bottom = parseUnit(actStyle.margin_bottom.value);
1138 if (actStyle.margin_left.valid)
1139 tmpOStyle.margin_left = parseUnit(actStyle.margin_left.value);
1140 if (actStyle.margin_right.valid)
1141 tmpOStyle.margin_right = parseUnit(actStyle.margin_right.value);
1142 if (actStyle.textIndent.valid)
1143 tmpOStyle.textIndent = parseUnit(actStyle.textIndent.value);
1144 if (actStyle.textAlign.valid)
1145 {
1146 QString attValue = actStyle.textAlign.value;
1147 if ((attValue == "left") || (attValue == "start"))
1148 tmpOStyle.textAlign = ParagraphStyle::LeftAligned;
1149 else if (attValue == "center")
1150 tmpOStyle.textAlign = ParagraphStyle::Centered;
1151 else if ((attValue == "right") || (attValue == "end"))
1152 tmpOStyle.textAlign = ParagraphStyle::RightAligned;
1153 else if (attValue == "justify")
1154 tmpOStyle.textAlign = ParagraphStyle::Justified;
1155 }
1156 if (actStyle.verticalAlignment.valid)
1157 {
1158 if (actStyle.verticalAlignment.value == "middle")
1159 tmpOStyle.verticalAlignment = 1;
1160 else if (actStyle.verticalAlignment.value == "bottom")
1161 tmpOStyle.verticalAlignment = 2;
1162 }
1163 if (actStyle.textPos.valid)
1164 tmpOStyle.textPos = actStyle.textPos.value;
1165 if (actStyle.textOutline.valid)
1166 tmpOStyle.textOutline = actStyle.textOutline.value;
1167 if (actStyle.textUnderline.valid)
1168 tmpOStyle.textUnderline = actStyle.textUnderline.value != "none";
1169 if (actStyle.textUnderlineWords.valid)
1170 tmpOStyle.textUnderlineWords = actStyle.textUnderlineWords.value != "continuous";
1171 if (actStyle.textUnderlineColor.valid)
1172 {
1173 if (actStyle.textUnderlineColor.value == "font-color")
1174 tmpOStyle.textUnderlineColor = tmpOStyle.CurrColorText;
1175 else
1176 tmpOStyle.textUnderlineColor = parseColor(actStyle.textUnderlineColor.value);
1177 }
1178 if (actStyle.textStrikeThrough.valid)
1179 tmpOStyle.textStrikeThrough = actStyle.textStrikeThrough.value != "none";
1180 if (actStyle.textShadow.valid)
1181 tmpOStyle.textShadow = actStyle.textShadow.value != "none";
1182 if (actStyle.fontVariant.valid)
1183 tmpOStyle.textSmallCaps = actStyle.fontVariant.value == "small-caps";
1184 if (actStyle.lineHeight.valid)
1185 {
1186 if (actStyle.lineHeight.value == "normal")
1187 tmpOStyle.lineHeight = -1.0;
1188 else if (actStyle.lineHeight.value.right(1) != "%")
1189 {
1190 tmpOStyle.lineHeight = parseUnit(actStyle.lineHeight.value);
1191 tmpOStyle.absLineHeight = true;
1192 }
1193 else
1194 {
1195 tmpOStyle.lineHeight = parseUnit(actStyle.lineHeight.value) * tmpOStyle.fontSize;
1196 tmpOStyle.absLineHeight = false;
1197 }
1198 }
1199 if ((actStyle.tabDists.valid) && (actStyle.tabTypes.valid))
1200 {
1201 QStringList dists = actStyle.tabDists.value.split(";", Qt::SkipEmptyParts);
1202 QStringList types = actStyle.tabTypes.value.split(" ", Qt::SkipEmptyParts);
1203 if (dists.count() == types.count())
1204 {
1205 tmpOStyle.tabStops.clear();
1206 ParagraphStyle::TabRecord tb;
1207 for (int a = 0; a < dists.count(); a++)
1208 {
1209 tb.tabPosition = parseUnit(dists[a]);
1210 if (types[a] == "left")
1211 tb.tabType = 0;
1212 else if (types[a] == "center")
1213 tb.tabType = 4;
1214 else if (types[a] == "right")
1215 tb.tabType = 1;
1216 else if (types[a] == "char")
1217 tb.tabType = 3;
1218 tmpOStyle.tabStops.append(tb);
1219 }
1220 }
1221 }
1222 if (actStyle.breakAfter.valid)
1223 tmpOStyle.breakAfter = actStyle.breakAfter.value;
1224 if (actStyle.breakBefore.valid)
1225 tmpOStyle.breakBefore = actStyle.breakBefore.value;
1226 }
1227 }
1228
parseUnit(const QString & unit)1229 double ODTIm::parseUnit(const QString &unit)
1230 {
1231 QString unitval=unit;
1232 if (unit.isEmpty())
1233 return 0.0;
1234 if (unit.right( 2 ) == "pt")
1235 unitval.replace( "pt", "" );
1236 else if (unit.right( 2 ) == "cm")
1237 unitval.replace( "cm", "" );
1238 else if (unit.right( 2 ) == "mm")
1239 unitval.replace( "mm" , "" );
1240 else if (unit.right( 2 ) == "in")
1241 unitval.replace( "in", "" );
1242 else if (unit.right( 2 ) == "px")
1243 unitval.replace( "px", "" );
1244 else if (unit.right( 1 ) == "%" )
1245 unitval.replace( "%", "" );
1246 double value = ScCLocale::toDoubleC(unitval);
1247 if (unit.right( 2 ) == "pt" )
1248 {}/* value = value; */ //no change
1249 else if (unit.right( 2 ) == "cm")
1250 value = ( value / 2.54 ) * 72;
1251 else if (unit.right( 2 ) == "mm")
1252 value = ( value / 25.4 ) * 72;
1253 else if (unit.right( 2 ) == "in")
1254 value = value * 72;
1255 else if (unit.right( 2 ) == "px")
1256 {}/* value = value; */ //no change
1257 else if (unit.right( 1 ) == "%")
1258 value = value / 100.0;
1259 return value;
1260 }
1261
parseColor(const QString & s)1262 QString ODTIm::parseColor( const QString &s )
1263 {
1264 QColor c;
1265 QString ret = CommonStrings::None;
1266 if ((s == "") || s.isEmpty())
1267 return ret;
1268 if (s.startsWith( "rgb(" ))
1269 {
1270 QString parse = s.trimmed();
1271 QStringList colors = parse.split( ',', Qt::SkipEmptyParts );
1272 QString r = colors[0].right( ( colors[0].length() - 4 ) );
1273 QString g = colors[1];
1274 QString b = colors[2].left( ( colors[2].length() - 1 ) );
1275 if (r.contains( "%" ))
1276 {
1277 r.chop(1);
1278 r = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(r) ) / 100.0 ) ) );
1279 }
1280 if (g.contains( "%" ))
1281 {
1282 g.chop(1);
1283 g = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(g) ) / 100.0 ) ) );
1284 }
1285 if (b.contains( "%" ))
1286 {
1287 b.chop(1);
1288 b = QString::number( static_cast<int>( ( static_cast<double>( 255 * ScCLocale::toDoubleC(b) ) / 100.0 ) ) );
1289 }
1290 c = QColor(r.toInt(), g.toInt(), b.toInt());
1291 }
1292 else
1293 c.setNamedColor( s.trimmed() );
1294 ScColor tmp;
1295 tmp.fromQColor(c);
1296 tmp.setSpotColor(false);
1297 tmp.setRegistrationColor(false);
1298 QString fNam = m_Doc->PageColors.tryAddColor("FromOdt"+c.name(), tmp);
1299 ret = fNam;
1300 return ret;
1301 }
1302
constructFontName(const QString & fontBaseName,const QString & fontStyle)1303 QString ODTIm::constructFontName(const QString& fontBaseName, const QString& fontStyle)
1304 {
1305 QString fontName;
1306 SCFontsIterator it(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts);
1307 for ( ; it.hasNext(); it.next())
1308 {
1309 if (fontBaseName.toLower() != it.current().family().toLower())
1310 continue;
1311
1312 // found the font family, now go for the style
1313 QStringList slist = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.fontMap[it.current().family()];
1314 slist.sort();
1315 if (slist.count() > 0)
1316 {
1317 for (int a = 0; a < slist.count(); a++)
1318 {
1319 if (fontStyle.toLower() == slist[a].toLower())
1320 {
1321 fontName = it.current().family() + " " + slist[a];
1322 return fontName;
1323 }
1324 }
1325 int reInd = slist.indexOf("Regular");
1326 if (reInd < 0)
1327 fontName = it.current().family() + " " + slist[0];
1328 else
1329 fontName = it.current().family() + " " + slist[reInd];
1330 return fontName;
1331 }
1332 fontName = it.current().family();
1333 return fontName;
1334 }
1335
1336 // Still no font found
1337 QString family = fontBaseName;
1338 if (!fontStyle.isEmpty())
1339 family += " " + fontStyle;
1340 if (PrefsManager::instance().appPrefs.fontPrefs.GFontSub.contains(family))
1341 {
1342 fontName = PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family];
1343 return fontName;
1344 }
1345
1346 qApp->changeOverrideCursor(QCursor(Qt::ArrowCursor));
1347 QScopedPointer<MissingFont> dia(new MissingFont(nullptr, family, m_Doc));
1348 if (dia->exec())
1349 fontName = dia->getReplacementFont();
1350 else
1351 fontName = m_Doc->itemToolPrefs().textFont;
1352 PrefsManager::instance().appPrefs.fontPrefs.GFontSub[family] = fontName;
1353 qApp->changeOverrideCursor(QCursor(Qt::WaitCursor));
1354
1355 return fontName;
1356 }
1357
setFontstyle(CharStyle & tmpCStyle,int kind)1358 void ODTIm::setFontstyle(CharStyle &tmpCStyle, int kind)
1359 {
1360 int posC = m_item->itemText.length();
1361 m_item->itemText.insertChars(posC, "B");
1362 m_item->itemText.applyCharStyle(posC, 1, tmpCStyle);
1363 QString fam = m_item->itemText.charStyle(posC).font().family();
1364 m_item->itemText.removeChars(posC, 1);
1365 if (fam.isEmpty())
1366 return;
1367 QStringList slist = PrefsManager::instance().appPrefs.fontPrefs.AvailFonts.fontMap[fam];
1368 if (kind == 0)
1369 {
1370 if (slist.contains("Italic"))
1371 tmpCStyle.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[fam + " Italic"]);
1372 }
1373 else if (kind == 1)
1374 {
1375 if (slist.contains("Oblique"))
1376 tmpCStyle.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[fam + " Oblique"]);
1377 }
1378 else if (kind == 2)
1379 {
1380 if (slist.contains("Bold"))
1381 tmpCStyle.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[fam + " Bold"]);
1382 }
1383 else if (kind == 3)
1384 {
1385 if (slist.contains("Bold Italic"))
1386 tmpCStyle.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[fam + " Bold Italic"]);
1387 }
1388 else if (kind == 4)
1389 {
1390 if (slist.contains("Bold Oblique"))
1391 tmpCStyle.setFont(PrefsManager::instance().appPrefs.fontPrefs.AvailFonts[fam + " Bold Oblique"]);
1392 }
1393 }
1394