Writing of basic layout info to zionworx files
[kworship.git] / kworship / filters / zionworx / KwZionworxFilter.cpp
blobe8f5975265a63e3efcdfb1497af7975ae7e32e40
1 /***************************************************************************
2 * This file is part of KWorship. *
3 * Copyright 2008 James Hogan <james@albanarts.com> *
4 * *
5 * KWorship is free software: you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation, either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * KWorship 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 *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with KWorship. If not, write to the Free Software Foundation, *
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
18 ***************************************************************************/
20 /**
21 * @file KwZionworxFilter.cpp
22 * @brief Main Zionworx load and save filter.
23 * @author James Hogan <james@albanarts.com>
26 #include "KwZionworxFilter.h"
27 #include "KwPascalStream.h"
28 #include <KwDocument.h>
29 #include <KwArchive.h>
30 #include <KwPlaylistList.h>
31 #include <KwPlaylistText.h>
32 #include <KwPlaylistSong.h>
33 #include <KwBiblePlaylistItem.h>
34 #include <KwPlaylistPresentation.h>
35 #include <KwCssStyleRule.h>
36 #include <KwDisplayStyles.h>
38 #include <VTable.h>
40 #include <KUrl>
41 #include <KMessageBox>
42 #include <KLocale>
43 #include <KSaveFile>
45 #include <QFile>
46 #include <QDomDocument>
47 #include <QDomElement>
48 #include <QPen>
50 #include <inttypes.h>
53 * Constructors + destructor
56 /// Primary constructor.
57 KwZionworxFilter::KwZionworxFilter()
58 : KwLoadSaveFilter()
60 m_importMimeTypes += "application/x-zionworx+xml";
61 m_exportMimeTypes += "application/x-zionworx+xml";
64 /// Destructor.
65 KwZionworxFilter::~KwZionworxFilter()
70 * Main interface
73 KwDocument* KwZionworxFilter::load(const KUrl& url, const QString& mimeType)
75 /// @todo Handle non-local files
76 if (!url.isLocalFile())
78 KMessageBox::error(0,
79 i18n("Non-local loads not yet supported"),
80 i18n("KWorship"));
81 return 0;
84 KwDocument* doc = 0;
86 if (mimeType == "application/x-zionworx+xml")
88 QFile file(url.toLocalFile());
89 if (file.open(QIODevice::ReadOnly))
91 QDomDocument domDoc;
92 if (domDoc.setContent(&file))
94 QDomElement root = domDoc.documentElement();
95 QDomElement versionEl = root.firstChildElement("ZionWorx");
96 if (root.tagName() != "Root" || versionEl.isNull())
98 KMessageBox::error(0,
99 i18n("Doesn't look like a ZionWorx playlist"),
100 i18n("KWorship"));
102 else
104 bool versionOk = false;
105 double version = versionEl.attribute("Version").toDouble(&versionOk);
106 if (!versionOk || version != 2.6)
108 KMessageBox::error(0,
109 i18n("Only version 2.6 is supported (version is %1)").arg(versionEl.attribute("Version", "unspecified")),
110 i18n("KWorship"));
112 else
114 doc = new KwDocument(this, mimeType, url);
115 KwPlaylistList* list = new KwPlaylistList();
116 doc->setPlaylist(list);
118 QDomNodeList playlistNodes = root.elementsByTagName("TPlayListNode");
119 for (int i = 0; i < playlistNodes.count(); ++i)
121 QDomElement playlistNode = playlistNodes.at(i).toElement();
122 QDomElement item = playlistNode.firstChildElement("PlayListItem");
123 if (!item.isNull())
125 KwPlaylistItem* newItem = 0;
126 QString biDiText = item.firstChildElement("BiDiMode").text();
127 bool rightToLeft = (biDiText == "bdRightToLeft");
128 QString itemType = item.firstChildElement("ItemType").text();
129 if (itemType == "siPowerPoint")
131 KwPlaylistPresentation* powerpoint = new KwPlaylistPresentation(QUrl(item.firstChildElement("FilenameRelative").text()));
132 powerpoint->setTitle(item.firstChildElement("Title").text());
133 newItem = powerpoint;
135 else if (itemType == "siSong")
137 KwPlaylistText* song = new KwPlaylistText(item.firstChildElement("Title").text(),
138 item.firstChildElement("Lyrics").text().split("\n\n"));
139 newItem = song;
141 else if (itemType == "siQuickNote")
143 KwPlaylistText* note = new KwPlaylistText(item.firstChildElement("Title").text(),
144 readStringList(item.firstChildElement("QuickNote")));
145 newItem = note;
147 else if (itemType == "siBible")
149 bool error = true;
150 QStringList verses = readStringList(item.firstChildElement("Verses"));
151 // Try and understand the passage referred to on the first line.
152 static QRegExp rePassage("^(.*)\\s+(\\d+)(:(\\d+)(-(\\d+))?)?\\s+\\(([^\\)]*)\\).*");
153 if (verses.size() >= 1 && rePassage.exactMatch(verses[0]))
155 error = false;
156 QString bookName = rePassage.cap(1);
157 QString moduleName = rePassage.cap(7);
158 /// @todo Try and get a more accurate set of book ids
159 int bookNum = 0;
160 int chapterNum = rePassage.cap(2).toInt();
161 bool validVerse;
162 int firstVerse = rePassage.cap(4).toInt(&validVerse);
163 if (!validVerse)
165 firstVerse = 1;
167 int nextVerse = firstVerse;
168 QStringList verseHeadings;
169 QStringList verseContents;
170 QStringList tempHeadings;
171 for (int i = 1; i < verses.size(); ++i)
173 const QString& verse = verses[i];
174 // See if it starts with a number, otherwise its a heading
175 static QRegExp reVerseLine("^(\\d+)\\.\\s*(\\S.*)$");
176 if (reVerseLine.exactMatch(verse))
178 int verseNum = reVerseLine.cap(1).toInt();
179 if (verseNum != nextVerse)
181 error = true;
183 nextVerse++;
185 if (!tempHeadings.isEmpty())
187 verseHeadings += QString("<h4>%1</h4>").arg(tempHeadings.join("<br />\n"));
189 else
191 verseHeadings += QString();
193 verseContents += reVerseLine.cap(2);
194 tempHeadings = QStringList();
196 else
198 tempHeadings += verse;
201 if (error)
203 KMessageBox::error(0,
204 i18n("Problems were encountered reading numbered verses in bible passage %1").arg(item.firstChildElement("Title").text()),
205 i18n("KWorship"));
207 else
209 KwBiblePlaylistItem* bible = new KwBiblePlaylistItem();
210 KwBiblePassage& passage = bible->passage();
211 passage.setSource(QString(), moduleName, rightToLeft);
212 passage.initBooks(bookNum,1);
213 passage.initBook(bookNum, bookName, chapterNum, 1);
214 passage.initChapter(bookNum, chapterNum, firstVerse, verseContents.size());
215 for (int i = 0; i < verseContents.size(); ++i)
217 passage.initVerse(bookNum, chapterNum, firstVerse+i, verseHeadings[i], verseContents[i]);
219 newItem = bible;
222 if (error)
224 KwPlaylistText* bible = new KwPlaylistText(item.firstChildElement("Title").text(),
225 verses);
226 newItem = bible;
230 if (0 != newItem)
232 QDomElement overlayStyleEl = playlistNode.firstChildElement("OverlayStyle");
233 if (!overlayStyleEl.isNull())
235 KwCssStyleSheet* styleRules = new KwCssStyleSheet;
236 KwCssStyleRule overlayStyle;
239 QDomElement fontEl = overlayStyleEl.firstChildElement("Font");
240 if (!fontEl.isNull())
242 QFont font;
243 QDomElement fontHeightEl = fontEl.firstChildElement("Height");
244 if (!fontHeightEl.isNull())
246 bool ok;
247 int height = fontHeightEl.text().toInt(&ok);
248 if (ok)
250 font.setPointSize(abs(height));
253 QDomElement fontNameEl = fontEl.firstChildElement("Name");
254 /// @todo Remember font name
255 /// @todo Use font names
256 QDomElement fontStyleEl = fontEl.firstChildElement("Style");
257 if (!fontStyleEl.isNull())
259 static QRegExp reFontStyleList("^\\s*\\[(.*)\\]\\s*$");
260 if (reFontStyleList.exactMatch(fontStyleEl.text()))
262 QStringList styles = reFontStyleList.cap(1).split(",");
263 foreach (QString style, styles)
265 style = style.trimmed();
266 if (style == "fsBold")
268 font.setWeight(QFont::Bold);
270 else if (style == "fsItalic")
272 font.setStyle(QFont::StyleItalic);
278 overlayStyle.setStyle<QFont>("text.character.font", font);
280 QDomElement fontColorEl = fontEl.firstChildElement("Color");
281 if (!fontColorEl.isNull())
283 bool ok;
284 QColor colour = readColour(fontColorEl, &ok);
285 if (ok)
287 overlayStyle.setStyle<QBrush>("text.character.brush", QBrush(colour));
291 QDomElement textStyleEl = overlayStyleEl.firstChildElement("TextStyle");
292 if (!textStyleEl.isNull())
294 QString style = textStyleEl.text();
295 if (style == "tsShadow")
297 overlayStyle.setStyle<bool>("text.character.shadow.enabled", true);
299 else if (style == "tsOutline")
301 overlayStyle.setStyle<bool>("text.character.outline.enabled", true);
304 QDomElement textAlignmentEl = overlayStyleEl.firstChildElement("TextAlignment");
306 // Shadow
307 QDomElement shadowWidthEl = overlayStyleEl.firstChildElement("ShadowWidth");
308 if (!shadowWidthEl.isNull())
310 bool ok;
311 int offset = shadowWidthEl.text().toInt(&ok);
312 if (ok)
314 overlayStyle.setStyle<int>("text.character.shadow.offset", offset);
317 QDomElement shadowColorEl = overlayStyleEl.firstChildElement("ShadowColor");
318 if (!shadowColorEl.isNull())
320 bool ok;
321 QColor colour = readColour(shadowColorEl, &ok);
322 if (ok)
324 overlayStyle.setStyle<QBrush>("text.character.shadow.brush", QBrush(colour));
328 // Outline
329 QDomElement outlineWidthEl = overlayStyleEl.firstChildElement("OutlineWidth");
330 int outlineWidth = 1;
331 if (!outlineWidthEl.isNull())
333 bool ok;
334 int width = outlineWidthEl.text().toInt(&ok);
335 if (ok)
337 outlineWidth = width;
340 QDomElement outlineColorEl = overlayStyleEl.firstChildElement("OutlineColor");
341 QColor outlineColour = Qt::black;
342 if (!outlineColorEl.isNull())
344 bool ok;
345 QColor colour = readColour(outlineColorEl, &ok);
346 if (ok)
348 outlineColour = colour;
351 overlayStyle.setStyle<QPen>("text.character.outline.pen", QPen(outlineColour, outlineWidth));
353 QDomElement fillColorEl = overlayStyleEl.firstChildElement("FillColor");
354 if (!fillColorEl.isNull())
356 bool ok;
357 QColor colour = readColour(fillColorEl, &ok);
358 if (ok)
360 overlayStyle.setStyle<QBrush>("background.brush", QBrush(colour));
363 QDomElement imageFilenameEl = overlayStyleEl.firstChildElement("ImageFilename");
364 //overlayStyle.setStyle<KwResourceLink>("background.image.src", KUrl("file:///home/james/media/images/projector/misc/bible.jpg"));
365 QDomElement imageAlignmentEl = overlayStyleEl.firstChildElement("ImageAlignment");
367 // Margins
368 QDomElement marginRightEl = overlayStyleEl.firstChildElement("MarginRight");
369 if (!marginRightEl.isNull())
371 bool ok;
372 float margin = marginRightEl.text().toFloat(&ok);
373 if (ok)
375 overlayStyle.setStyle<float>("text.layout.margins.right", margin);
378 QDomElement marginLeftEl = overlayStyleEl.firstChildElement("MarginLeft");
379 if (!marginLeftEl.isNull())
381 bool ok;
382 float margin = marginLeftEl.text().toFloat(&ok);
383 if (ok)
385 overlayStyle.setStyle<float>("text.layout.margins.left", margin);
388 QDomElement marginTopEl = overlayStyleEl.firstChildElement("MarginTop");
389 if (!marginTopEl.isNull())
391 bool ok;
392 float margin = marginTopEl.text().toFloat(&ok);
393 if (ok)
395 overlayStyle.setStyle<float>("text.layout.margins.top", margin);
398 QDomElement marginBottomEl = overlayStyleEl.firstChildElement("MarginBottom");
399 if (!marginBottomEl.isNull())
401 bool ok;
402 float margin = marginBottomEl.text().toFloat(&ok);
403 if (ok)
405 overlayStyle.setStyle<float>("text.layout.margins.bottom", margin);
409 styleRules->addRule(overlayStyle);
410 newItem->addStyleSheet(styleRules);
413 list->addItem(newItem);
415 else
417 KMessageBox::error(0,
418 i18n("Unrecognised item type \"%1\"").arg(itemType),
419 i18n("KWorship"));
424 doc->setModified(false);
428 else
430 KMessageBox::error(0,
431 i18n("Invalid XML"),
432 i18n("KWorship"));
436 else
438 Q_ASSERT(!"Unsupported mime type");
441 return doc;
444 /// Contains implementations of export functions.
445 class KwZionworxFilter::ExportToDom
447 public:
449 /// Write a colour to a string.
450 static QString writeColour(const QColor& colour, bool wierd)
452 /// @todo Use symbolic colours when possible
453 if (wierd)
455 return QString::number((int32_t)((colour.red() << 16) | (colour.green() << 8) | colour.blue() | 0xFF000000));
457 else
459 return QString::number((int32_t)(colour.red() | (colour.green() << 8) | (colour.blue() << 16)));
462 static QDomElement createPlaylistNode(QDomDocument& document, QDomElement& element)
464 QDomElement node = document.createElement("TPlayListNode");
465 element.appendChild(node);
466 return node;
468 static QDomElement createOverlayStyle(QDomDocument& document, QDomElement& element, const KwPlaylistItem* item)
470 QDomElement style = document.createElement("OverlayStyle");
472 style.appendChild(document.createTextNode("(TOverlayStyle)"));
474 QDomElement fontEl = document.createElement("Font");
476 fontEl.appendChild(document.createTextNode("(TFont)"));
478 QFont font = KwDisplayStyles::text::character::font(item);
479 QStringList textStyles;
480 if (font.italic())
482 textStyles += "fsItalic";
484 if (font.bold())
486 textStyles += "fsBold";
489 /// @todo find out what this element does, restore from saved
490 QDomElement charsetEl = document.createElement("Charset");
491 charsetEl.appendChild(document.createTextNode("ANSI_CHARSET"));
492 fontEl.appendChild(charsetEl);
494 QDomElement colorEl = document.createElement("Color");
495 colorEl.appendChild(document.createTextNode(writeColour(KwDisplayStyles::text::character::brush(item).color(), false)));
496 fontEl.appendChild(colorEl);
498 /// @todo Handle if font is specified in pixels
499 QDomElement heightEl = document.createElement("Height");
500 heightEl.appendChild(document.createTextNode(QString::number(-font.pointSize())));
501 fontEl.appendChild(heightEl);
503 /// @todo Get a sensible font name here
504 QDomElement nameEl = document.createElement("Name");
505 nameEl.appendChild(document.createTextNode("Tahoma"));
506 fontEl.appendChild(nameEl);
508 QDomElement StyleEl = document.createElement("Style");
509 StyleEl.appendChild(document.createTextNode(QString("[%1]").arg(textStyles.join(","))));
510 fontEl.appendChild(StyleEl);
512 style.appendChild(fontEl);
514 bool outline = KwDisplayStyles::text::character::outline::enabled(item);
515 bool shadow = KwDisplayStyles::text::character::shadow::enabled(item);
516 QDomElement textStyleEl = document.createElement("TextStyle");
517 textStyleEl.appendChild(document.createTextNode(outline ? "tsOutline" : shadow ? "tsShadow" : "tsPlain"));
518 style.appendChild(textStyleEl);
520 /// @todo Implement text alignment saving
521 QDomElement textAlignmentEl = document.createElement("TextAlignment");
522 textAlignmentEl.appendChild(document.createTextNode("taLeft"));
523 style.appendChild(textAlignmentEl);
525 QDomElement shadowWidthEl = document.createElement("ShadowWidth");
526 shadowWidthEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::character::shadow::offset(item))));
527 style.appendChild(shadowWidthEl);
529 QDomElement shadowColorEl = document.createElement("ShadowColor");
530 shadowColorEl.appendChild(document.createTextNode(writeColour(KwDisplayStyles::text::character::shadow::brush(item).color(), true)));
531 style.appendChild(shadowColorEl);
533 QDomElement outlineWidthEl = document.createElement("OutlineWidth");
534 outlineWidthEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::character::outline::pen(item).width())));
535 style.appendChild(outlineWidthEl);
537 QDomElement outlineColorEl = document.createElement("OutlineColor");
538 outlineColorEl.appendChild(document.createTextNode(writeColour(KwDisplayStyles::text::character::outline::pen(item).color(), true)));
539 style.appendChild(outlineColorEl);
541 QDomElement fillColorEl = document.createElement("FillColor");
542 fillColorEl.appendChild(document.createTextNode(writeColour(KwDisplayStyles::background::brush(item).color(), false)));
543 style.appendChild(fillColorEl);
545 /// @todo Implement image filename saving
546 if (0)
548 QDomElement imageFilenameEl = document.createElement("ImageFilename");
549 imageFilenameEl.appendChild(document.createTextNode(""));
550 style.appendChild(imageFilenameEl);
553 /// @todo Implement image alignment saving
554 QDomElement imageAlignmentEl = document.createElement("ImageAlignment");
555 imageAlignmentEl.appendChild(document.createTextNode("iaStretch"));
556 style.appendChild(imageAlignmentEl);
558 QDomElement marginRightEl = document.createElement("MarginRight");
559 marginRightEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::layout::margins::right(item))));
560 style.appendChild(marginRightEl);
562 QDomElement marginLeftEl = document.createElement("MarginLeft");
563 marginLeftEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::layout::margins::left(item))));
564 style.appendChild(marginLeftEl);
566 QDomElement marginTopEl = document.createElement("MarginTop");
567 marginTopEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::layout::margins::top(item))));
568 style.appendChild(marginTopEl);
570 QDomElement marginBottomEl = document.createElement("MarginBottom");
571 marginBottomEl.appendChild(document.createTextNode(QString::number(KwDisplayStyles::text::layout::margins::bottom(item))));
572 style.appendChild(marginBottomEl);
574 element.appendChild(style);
575 return style;
577 static QDomElement createPlaylistItem(QDomDocument& document, QDomElement& element,
578 const QString& type, const QString& title, bool rightToLeft)
580 QDomElement item = document.createElement("PlayListItem");
582 QDomElement typeEl = document.createElement("ItemType");
583 typeEl.appendChild(document.createTextNode(type));
584 item.appendChild(typeEl);
587 QDomElement titleEl = document.createElement("Title");
588 titleEl.appendChild(document.createTextNode(title));
589 item.appendChild(titleEl);
592 QDomElement biDiEl = document.createElement("BiDiMode");
593 biDiEl.appendChild(document.createTextNode(rightToLeft ? "bdRightToLeft" : "bdLeftToRight"));
594 item.appendChild(biDiEl);
596 element.appendChild(item);
597 return item;
599 static int list(const KwPlaylistList* self, QDomDocument& document, QDomElement& element)
601 for (int i = 0; i < self->getItemCount(); ++i)
603 call(self->getItem(i), document, element);
605 return 0;
607 static int song(const KwPlaylistSong* self, QDomDocument& document, QDomElement& element)
609 QDomElement node = createPlaylistNode(document, element);
610 QDomElement style = createOverlayStyle(document, node, self);
611 return 0;
613 static int note(const KwPlaylistText* self, QDomDocument& document, QDomElement& element)
615 QDomElement node = createPlaylistNode(document, element);
616 QDomElement style = createOverlayStyle(document, node, self);
617 return 0;
619 static int bible(const KwBiblePlaylistItem* self, QDomDocument& document, QDomElement& element)
621 QDomElement node = createPlaylistNode(document, element);
622 QDomElement style = createOverlayStyle(document, node, self);
623 const KwBiblePassage& passage = self->passage();
624 QDomElement item = createPlaylistItem(document, node,
625 "siBible", passage.textualKey(),
626 passage.isRightToLeft());
628 QDomElement versesEl = document.createElement("Verses");
629 versesEl.appendChild(document.createTextNode("(TTntStringList)"));
631 QDomElement definedPropsEl = document.createElement("DefinedProperties");
632 QByteArray propsData;
633 KwPascalStream data(&propsData, QIODevice::WriteOnly);
635 QStringList verses;
636 verses << passage.textualKey();
637 for (int book = passage.firstBookNumber(); book <= passage.lastBookNumber(); ++book)
639 for (int chap = passage.firstChapterNumber(book); chap <= passage.lastChapterNumber(book); ++chap)
641 for (int verse = passage.firstVerseNumber(book, chap); verse <= passage.lastVerseNumber(book, chap); ++verse)
643 const QString& headings = passage.verseHeadings(book, chap, verse, true);
644 if (!headings.isEmpty())
646 verses += headings;
648 const QString& content = passage.verseContent(book, chap, verse, true);
649 if (!content.isEmpty())
651 verses += i18nc("Verse number, bible verse, for zionworx export", "%1. %2").arg(verse).arg(content);
656 data.writeProperty("Strings", verses);
658 propsData = propsData.toBase64();
659 definedPropsEl.appendChild(document.createTextNode(propsData));
660 versesEl.appendChild(definedPropsEl);
662 item.appendChild(versesEl);
663 return 0;
665 static int presentation(const KwPlaylistPresentation* self, QDomDocument& document, QDomElement& element)
667 QDomElement node = createPlaylistNode(document, element);
668 QDomElement item = createPlaylistItem(document, node,
669 "siPowerPoint", self->title(),
670 false);
672 return 0;
675 static void init()
677 static bool done = false;
678 if (!done)
680 call.addImplementation(&list);
681 call.addImplementation(&song);
682 call.addImplementation(&note);
683 call.addImplementation(&bible);
684 call.addImplementation(&presentation);
685 done = true;
689 typedef VTable<const KwPlaylistItem, int (*)(QDomDocument& document, QDomElement& element)> ExportVTable;
690 static ExportVTable call;
692 KwZionworxFilter::ExportToDom::ExportVTable KwZionworxFilter::ExportToDom::call;
694 bool KwZionworxFilter::save(KwDocument* doc, const KUrl& url, const QString& mimeType)
696 /// @todo Handle non-local files
697 if (!url.isLocalFile())
699 KMessageBox::error(0,
700 i18n("Non-local loads not yet supported"),
701 i18n("KWorship"));
702 return false;
704 KSaveFile file;
705 file.setFileName(url.toLocalFile());
706 if (!file.open(QFile::WriteOnly))
708 KMessageBox::error(0,
709 i18n("Cannot write file %1:\n%2.")
710 .arg(file.fileName())
711 .arg(file.errorString()),
712 i18n("KWorship"));
713 return false;
716 // Create document
717 QDomDocument domDoc;
718 QDomElement root = domDoc.createElement("Root");
719 domDoc.appendChild(root);
721 // Version element
722 QDomElement version = domDoc.createElement("ZionWorx");
723 version.setAttribute("Version", 2.6);
724 version.setAttribute("FullFilename", url.toLocalFile());
725 root.appendChild(version);
727 // Playlist nodes element
728 QDomElement playlist = domDoc.createElement("PlayListNodes");
729 ExportToDom::init();
730 ExportToDom::call(doc->playlist(), domDoc, playlist);
731 root.appendChild(playlist);
733 // Write document to file
734 QByteArray xml = domDoc.toByteArray(2);
735 file.write(xml, xml.size());
737 if (!file.finalize())
739 KMessageBox::error(0,
740 i18n("Cannot finalize file %1:\n%2.")
741 .arg(file.fileName())
742 .arg(file.errorString()),
743 i18n("KWorship"));
744 return false;
747 doc->setModified(false);
749 return true;
753 * Virtual interface
756 void KwZionworxFilter::v_saveLimitations(KwDocument* doc, const QString& mimeType, Limitations* o_limitations)
758 /// @todo Implement KwZionworxFilter::v_saveLimitations
759 Q_ASSERT(false);
763 * Private functions
766 /// Read a TTntStringList from DOM.
767 QStringList KwZionworxFilter::readStringList(const QDomElement& el) const
769 // Go straight to the <DefinedProperties>
770 QDomElement definedProperties = el.firstChildElement("DefinedProperties");
771 if (!definedProperties.isNull())
773 const QByteArray buf = QByteArray::fromBase64(definedProperties.text().toAscii());
775 KwPascalStream stream(&buf);
776 QByteArray name;
777 QVariant value;
778 while (!stream.atEnd())
780 stream.readProperty(name, value);
781 if (name == "Strings")
783 // Turn into a QStringList
784 QStringList result;
785 foreach (QVariant item, value.toList())
787 result += item.toString();
789 return result;
793 return QStringList();
796 /// Read a colour from DOM.
797 QColor KwZionworxFilter::readColour(const QDomElement& el, bool* ok) const
799 bool isOk = false;
801 static QHash<QString, QColor> colours;
802 static bool inited = false;
803 if (!inited)
805 colours["clWhite"] = Qt::white;
806 colours["clBlack"] = Qt::black;
807 colours["clRed"] = Qt::red;
808 colours["clDarkRed"] = Qt::darkRed;
809 colours["clGreen"] = Qt::green;
810 colours["clDarkGreen"] = Qt::darkGreen;
811 colours["clBlue"] = Qt::blue;
812 colours["clDarkBlue"] = Qt::darkBlue;
813 colours["clCyan"] = Qt::cyan;
814 colours["clDarkCyan"] = Qt::darkCyan;
815 colours["clMagenta"] = Qt::magenta;
816 colours["clDarkMagenta"] = Qt::darkMagenta;
817 colours["clYellow"] = Qt::yellow;
818 colours["clDarkGray"] = Qt::darkYellow;
819 colours["clGray"] = Qt::gray;
820 colours["clDarkGray"] = Qt::darkGray;
821 colours["clLightGray"] = Qt::lightGray;
822 inited = true;
825 QString colourName = el.text();
826 QColor result;
827 uint32_t colourNum = colourName.toInt(&isOk);
828 if (isOk)
830 // 0xff in msb apparently changes byte order
831 if (((colourNum >> 24) & 0xFF) == 0xFF)
833 // least significant byte is blue, followed by green and red
834 result.setRgb((colourNum >> 16) & 0xFF,
835 (colourNum >> 8) & 0xFF,
836 colourNum & 0xFF);
838 else
840 // least significant byte is red, followed by green and blue
841 result.setRgb( colourNum & 0xFF,
842 (colourNum >> 8) & 0xFF,
843 (colourNum >> 16) & 0xFF);
846 else if (colours.contains(colourName))
848 result = colours[colourName];
849 isOk = true;
852 if (0 != ok)
854 *ok = isOk;
856 return result;