8 #include "attributeitem.h"
9 #include "branchitem.h"
11 #include "linkablemapobj.h"
12 #include "mainwindow.h"
15 #include "slideitem.h"
17 #include "taskmodel.h"
18 #include "xlinkitem.h"
20 extern Main *mainWindow;
21 extern Settings settings;
22 extern TaskModel *taskModel;
23 extern QString vymVersion;
25 parseVYMHandler::parseVYMHandler()
27 // Default is to load everything
28 contentFilter = 0x0000; // TODO use filters for all content types below
31 void parseVYMHandler::setContentFilter(const int &c) { contentFilter = c; }
33 bool parseVYMHandler::startDocument()
38 stateStack.append(StateInit);
45 bool parseVYMHandler::startElement(const QString &, const QString &,
47 const QXmlAttributes &atts)
51 qDebug() << "startElement: <" << eName
52 << "> state=" << state
53 << " laststate=" << stateStack.last()
54 << " loadMode=" << loadMode
55 //<<" line=" << QXmlDefaultHandler::lineNumber();
56 << "contentFilter=" << contentFilter;
59 stateStack.append(state);
60 if (state == StateInit && (eName == "vymmap")) {
65 if (loadMode == NewMap || loadMode == DefaultMap) {
73 if (!atts.value("version").isEmpty()) {
74 version = atts.value("version");
75 if (!versionLowerOrEqualThanVym(version)) {
77 0, QObject::tr("Warning: Version Problem"),
79 "<h3>Map is newer than VYM</h3>"
80 "<p>The map you are just trying to load was "
81 "saved using vym %1. "
82 "The version of this vym is %2. "
83 "If you run into problems after pressing "
84 "the ok-button below, updating vym should help.</p>")
88 "<p>The map will be opened readonly, because not "
89 "all information from new maps can be saved with this "
90 "version of vym. Please be careful!"));
91 model->setReadOnly(true);
94 model->setVersion(version);
97 else if (eName == "mapdesign" && state == StateMap) {
98 state = StateMapDesign;
100 else if (eName == "md" && state == StateMapDesign) {
102 readMapDesignCompatibleAttr(atts);
104 else if (eName == "select" && state == StateMap) {
105 state = StateMapSelect;
107 else if (eName == "setting" && state == StateMap) {
108 state = StateMapSetting;
109 if (loadMode == NewMap) {
111 readSettingAttr(atts);
114 else if (eName == "slide" && state == StateMap) {
115 state = StateMapSlide;
116 if (!(contentFilter & SlideContent)) {
117 // Ignore slides during paste
118 lastSlide = model->addSlide();
120 model->relinkSlide(lastSlide, insertPos);
125 else if (eName == "mapcenter" && state == StateMap) {
126 state = StateMapCenter;
127 if (loadMode == NewMap) {
128 // Really use the found mapcenter as MCO in a new map
129 lastBranch = model->createMapCenter();
132 // Treat the found mapcenter as a branch
133 // in an existing map
134 BranchItem *bi = model->getSelectedBranch();
137 if (loadMode == ImportAdd) {
140 lastBranch = model->createBranch(lastBranch);
142 lastBranch = model->addNewBranch(lastBranch, insertPos);
149 insertPos = lastBranch->num() + 1;
150 model->clearItem(lastBranch);
153 BranchItem *pi = bi->parentBranch();
154 lastBranch = model->addNewBranch(pi, insertPos);
160 // if nothing selected, add mapCenter without parent
161 lastBranch = model->createMapCenter();
163 readBranchAttr(atts);
165 else if ((eName == "standardflag" || eName == "standardFlag") &&
166 (state == StateMapCenter || state == StateBranch)) {
167 state = StateStandardFlag;
169 else if (eName == "userflagdef" && state == StateMap) {
170 state = StateUserFlagDef;
171 return (readUserFlagDefAttr(atts));
173 else if (eName == "userflag" &&
174 (state == StateMapCenter || state == StateBranch)) {
175 state = StateUserFlag;
176 return (readUserFlagAttr(atts));
178 else if (eName == "heading" &&
179 (state == StateMapCenter || state == StateBranch ||
180 state == StateInit)) {
181 if (state == StateInit) {
182 // Only read some stuff like VymNote or Heading
183 // e.g. for undo/redo
184 lastBranch = model->getSelectedBranch();
185 if (version.isEmpty())
191 state = StateHeading;
194 if (!atts.value("fonthint").isEmpty())
195 vymtext.setFontHint(atts.value("fonthint"));
196 if (!atts.value("textMode").isEmpty()) {
197 if (atts.value("textMode") == "richText")
198 vymtext.setRichText(true);
200 vymtext.setRichText(false);
202 if (!atts.value("textColor").isEmpty()) {
203 // For compatibility with <= 2.4.0 set both branch and
205 col.setNamedColor(atts.value("textColor"));
206 lastBranch->setHeadingColor(col);
207 vymtext.setColor(col);
209 if (!atts.value("text").isEmpty())
210 vymtext.setText(unquoteQuotes(atts.value("text")));
212 else if (eName == "task" &&
213 (state == StateMapCenter || state == StateBranch)) {
215 lastTask = taskModel->createTask(lastBranch);
216 if (!readTaskAttr(atts))
219 else if (eName == "note" &&
220 (state == StateMapCenter ||
221 state == StateBranch)) { // only for backward compatibility
222 // (<1.4.6). Use htmlnote now.
226 if (!readNoteAttr(atts))
229 else if (eName == "htmlnote" &&
230 state == StateMapCenter) { // only for backward compatibility. Use
232 state = StateHtmlNote;
234 if (!atts.value("fonthint").isEmpty())
235 vymtext.setFontHint(atts.value("fonthint"));
237 else if (eName == "vymnote" &&
238 (state == StateMapCenter || state == StateBranch ||
239 state == StateInit)) {
240 if (state == StateInit)
241 // Only read some stuff like VymNote or Heading
242 // e.g. for undo/redo
244 lastBranch = model->getSelectedBranch();
245 if (version.isEmpty())
248 state = StateVymNote;
251 if (!atts.value("fonthint").isEmpty())
252 vymtext.setFontHint(atts.value("fonthint"));
253 if (!atts.value("textMode").isEmpty()) {
254 if (atts.value("textMode") == "richText")
255 vymtext.setRichText(true);
257 vymtext.setRichText(false);
259 if (!atts.value("text").isEmpty())
260 vymtext.setText(unquoteQuotes(atts.value("text")));
262 else if (eName == "floatimage" &&
263 (state == StateMapCenter || state == StateBranch)) {
265 lastImage = model->createImage(lastBranch);
266 if (!readImageAttr(atts))
269 else if ((eName == "branch" || eName == "floatimage") &&
271 // This is used in vymparts, which have no mapcenter or for undo
273 TreeItem *ti = model->getSelectedItem();
275 // If a vym part is _loaded_ (not imported),
276 // selection==lmo==NULL
277 // Treat it like ImportAdd then...
278 loadMode = ImportAdd;
279 // we really have no MCO at this time
280 lastBranch = model->createMapCenter();
281 model->select(lastBranch);
282 model->setHeadingPlainText("Import");
285 if (ti && ti->isBranchLikeType()) {
286 lastBranch = (BranchItem *)ti;
287 if (eName == "branch") {
289 if (loadMode == ImportAdd) {
290 lastBranch = model->createBranch(lastBranch);
291 model->setLatestAddedItem(lastBranch);
293 model->relinkBranch(lastBranch, (BranchItem *)ti,
297 model->clearItem(lastBranch);
298 readBranchAttr(atts);
300 else if (eName == "floatimage") {
302 lastImage = model->createImage(lastBranch);
303 model->setLatestAddedItem(lastImage);
304 if (!readImageAttr(atts))
313 else if (eName == "branch" && state == StateMapCenter) {
315 lastBranch = model->createBranch(lastBranch);
316 readBranchAttr(atts);
318 else if (eName == "htmlnote" &&
319 state == StateBranch) { // only for backward compatibility. Use
321 state = StateHtmlNote;
323 if (!atts.value("fonthint").isEmpty())
324 vymtext.setFontHint(atts.value("fonthint"));
326 else if (eName == "frame" &&
327 (state == StateBranch || state == StateMapCenter)) {
329 if (!readFrameAttr(atts))
332 else if (eName == "xlink" && state == StateBranch) {
333 // Obsolete after 1.13.2
334 state = StateBranchXLink;
335 if (!readXLinkAttr(atts))
338 else if (eName == "xlink" && state == StateMap) {
340 if (!readLinkNewAttr(atts))
343 else if (eName == "branch" && state == StateBranch) {
344 lastBranch = model->createBranch(lastBranch);
345 readBranchAttr(atts);
347 else if (eName == "html" &&
348 (state == StateHtmlNote ||
349 state == StateNote ||
350 state == StateVymNote)) { // Only for backward compatibility
352 htmldata = "<" + eName;
356 else if (eName == "attribute" &&
357 (state == StateBranch || state == StateMapCenter)) {
358 state = StateAttribute;
359 AttributeItem *ai = new AttributeItem(lastBranch);
361 if (!atts.value("key").isEmpty())
362 ai->setKey(atts.value("key"));
364 QString type = atts.value("type");
365 QString val = atts.value("value");
366 if (!type.isEmpty()) {
367 if (type == "Integer")
368 ai->setValue(val.toInt());
369 else if (type == "String")
371 else if (type == "Undefined") {
373 ai->setAttributeType(AttributeItem::Undefined);
374 qWarning() << "Found attribute type 'Undefined'";
375 } else if (type == "DateTime") {
376 ai->setValue(QDateTime::fromString(val, Qt::ISODate));
378 qWarning() << "Found unknown attribute type: " << type;
380 if (!atts.value("value").isEmpty())
381 ai->setValue(atts.value("value"));
384 model->setAttribute(lastBranch, ai);
386 else if (state == StateHtml) {
387 // Only for backward compatibility
388 // accept all while in html mode,
389 htmldata += "<" + eName;
394 return false; // Error
398 bool parseVYMHandler::endElement(const QString &, const QString &,
399 const QString &eName)
403 lastBranch ? h = lastBranch->getHeadingPlain() : h = "";
404 qDebug() << "endElement </" << eName << "> state=" << state << " lastBranch=" << h;
413 model->emitDataChanged(lastBranch);
414 lastBranch = (BranchItem *)(lastBranch->parent());
417 // Empty branches may not be scrolled
418 // (happens if bookmarks are imported)
419 if (lastBranch->isScrolled() && lastBranch->branchCount() == 0)
420 lastBranch->unScroll();
422 model->emitDataChanged(lastBranch);
423 lastBranch = (BranchItem *)(lastBranch->parent());
424 lastBranch->setLastSelectedBranch(0);
429 if (versionLowerOrEqual(version, "2.4.99") &&
430 htmldata.contains("<html>"))
431 // versions before 2.5.0 didn't use CDATA to save richtext
432 vymtext.setAutoText(htmldata);
434 // Versions 2.5.0 to 2.7.562 had HTML data encoded as CDATA
435 // Later versions use the <vymnote text="..."> attribute,
436 // which is set already in begin element
437 // If both htmldata and vymtext are already available, use the
439 if (vymtext.isEmpty())
440 vymtext.setText(htmldata);
442 lastBranch->setHeading(vymtext);
444 case StateHtmlNote: // Richtext note, needed anyway for backward
446 if (htmldata.contains("<html"))
447 vymtext.setRichText(htmldata);
449 vymtext.setPlainText(htmldata);
450 lastBranch->setNote(vymtext);
457 if (!htmldata.isEmpty()) {
458 if (htmldata.contains("<html"))
459 vymtext.setRichText(htmldata);
461 vymtext.setPlainText(htmldata);
463 lastBranch->setNote(vymtext);
465 case StateMapSetting:
466 // version >= 2.5.0 previously value only as attribut
467 settings.setLocalValue(model->getDestPath(), lastSetting, htmldata);
469 case StateVymNote: // Might be richtext or plaintext with
471 if (versionLowerOrEqual(version, "2.4.99") &&
472 htmldata.contains("<html>"))
473 // versions before 2.5.0 didn't use CDATA to save richtext
474 vymtext.setAutoText(htmldata);
476 // Versions 2.5.0 to 2.7.562 had HTML data encoded as CDATA
477 // Later versions use the <vymnote text="..."> attribute,
478 // which is set already in begin element
479 // If both htmldata and vymtext are already available, use the
481 if (vymtext.isEmpty())
482 vymtext.setText(htmldata);
484 lastBranch->setNote(vymtext);
487 htmldata += "</" + eName + ">";
489 htmldata.replace("<br></br>", "<br />");
494 state = stateStack.takeLast();
498 bool parseVYMHandler::characters(const QString &ch)
500 // qDebug()<< "xml-vym: characters " << ch << " state=" << state;
502 QString ch_org = quoteMeta(ch);
503 QString ch_simplified = ch.simplified();
512 model->select(ch_simplified);
514 case StateMapSetting:
519 case StateNote: // only in vym <1.4.6
520 htmldata += ch_simplified;
524 case StateStandardFlag:
525 lastBranch->activateStandardFlagByName(ch_simplified);
532 case StateHtmlNote: // Only for compatibility
536 htmldata += ch_simplified;
547 QString parseVYMHandler::errorString()
549 return "the document is not in the VYM file format";
552 bool parseVYMHandler::readMapAttr( const QXmlAttributes &a)
554 if (!a.value("author").isEmpty())
555 model->setAuthor(a.value("author"));
556 if (!a.value("title").isEmpty())
557 model->setTitle(a.value("title"));
558 if (!a.value("comment").isEmpty())
559 model->setComment(unquoteMeta(a.value("comment")));
560 if (!a.value("branchCount").isEmpty()) {
561 branchesTotal = a.value("branchCount").toInt();
562 if (branchesTotal > 10) {
564 mainWindow->setProgressMaximum(branchesTotal);
568 if (!a.value("mapZoomFactor").isEmpty())
569 model->setMapZoomFactor(a.value("mapZoomFactor").toDouble());
570 if (!a.value("mapRotationAngle").isEmpty())
571 model->setMapRotationAngle(a.value("mapRotationAngle").toDouble());
573 return readMapDesignCompatibleAttr(a);
576 bool parseVYMHandler::readMapDesignCompatibleAttr( const QXmlAttributes &a)
578 // Some attributes moved in version 2.9.514 from
579 // <vymmap> to <mapdesign> and <md>
580 // This code here will allow to parse also newer maps.
581 // Some elements though are not available in older versions, especially
582 // <frame frameUsage="outerFrame" ...>
583 // <branch rotHeading=... rotContent=... >
586 if (!a.value("backgroundColor").isEmpty()) {
587 col.setNamedColor(a.value("backgroundColor"));
588 model->setMapBackgroundColor(col);
590 if (!a.value("defaultFont").isEmpty()) {
592 font.fromString(a.value("defaultFont"));
593 model->setMapDefaultFont(font);
595 if (!a.value("selectionColor").isEmpty()) {
596 // Only for compatibility
597 col.setNamedColor(a.value("selectionColor"));
598 model->setSelectionBrushColor(col);
599 model->setSelectionPenColor(col);
600 model->setSelectionPenWidth(1);
602 if (!a.value("selectionPenColor").isEmpty()) {
603 // Introduced in 2.9.12
604 col.setNamedColor(a.value("selectionPenColor"));
605 model->setSelectionPenColor(col);
607 if (!a.value("selectionPenWidth").isEmpty()) {
608 // Introduced in 2.9.12
610 qreal w = a.value("selectionPenWidth").toFloat(&ok);
612 model->setSelectionPenWidth(w);
614 if (!a.value("selectionBrushColor").isEmpty()) {
615 // Introduced in 2.9.12
616 col.setNamedColor(a.value("selectionBrushColor"));
617 model->setSelectionBrushColor(col);
619 if (!a.value("linkColorHint").isEmpty()) {
620 if (a.value("linkColorHint") == "HeadingColor")
621 model->setMapLinkColorHint(LinkableMapObj::HeadingColor);
623 model->setMapLinkColorHint(LinkableMapObj::DefaultColor);
625 if (!a.value("linkStyle").isEmpty())
626 model->setMapLinkStyle(a.value("linkStyle"));
627 if (!a.value("linkColor").isEmpty()) {
628 col.setNamedColor(a.value("linkColor"));
629 model->setMapDefLinkColor(col);
632 QPen pen(model->getMapDefXLinkPen());
633 if (!a.value("defXLinkColor").isEmpty()) {
634 col.setNamedColor(a.value("defXLinkColor"));
637 if (!a.value("defXLinkWidth").isEmpty())
638 pen.setWidth(a.value("defXLinkWidth").toInt());
639 if (!a.value("defXLinkPenStyle").isEmpty()) {
641 Qt::PenStyle ps = penStyle(a.value("defXLinkPenStyle"), ok);
646 model->setMapDefXLinkPen(pen);
648 if (!a.value("defXLinkStyleBegin").isEmpty())
649 model->setMapDefXLinkStyleBegin(a.value("defXLinkStyleBegin"));
650 if (!a.value("defXLinkStyleEnd").isEmpty())
651 model->setMapDefXLinkStyleEnd(a.value("defXLinkStyleEnd"));
655 bool parseVYMHandler::readBranchAttr(const QXmlAttributes &a)
659 mainWindow->addProgressValue((float)branchesCounter / branchesTotal);
666 if (!a.value("scrolled").isEmpty())
667 lastBranch->toggleScroll();
669 if (!a.value("incImgV").isEmpty()) {
670 if (a.value("incImgV") == "true")
671 lastBranch->setIncludeImagesVer(true);
673 lastBranch->setIncludeImagesVer(false);
675 if (!a.value("incImgH").isEmpty()) {
676 if (a.value("incImgH") == "true")
677 lastBranch->setIncludeImagesHor(true);
679 lastBranch->setIncludeImagesHor(false);
681 if (a.value("childrenFreePos") == "true")
682 lastBranch->setChildrenLayout(BranchItem::FreePositioning);
687 bool parseVYMHandler::readFrameAttr(const QXmlAttributes &a)
690 OrnamentedObj *oo = (OrnamentedObj *)(lastMI->getLMO());
695 if (!a.value("frameType").isEmpty())
696 oo->setFrameType(a.value("frameType"));
697 if (!a.value("penColor").isEmpty())
698 oo->setFramePenColor(a.value("penColor"));
699 if (!a.value("brushColor").isEmpty()) {
700 oo->setFrameBrushColor(a.value("brushColor"));
701 lastMI->setBackgroundColor(a.value("brushColor"));
703 if (!a.value("padding").isEmpty()) {
704 x = a.value("padding").toInt(&ok);
706 oo->setFramePadding(x);
708 if (!a.value("borderWidth").isEmpty()) {
709 x = a.value("borderWidth").toInt(&ok);
711 oo->setFrameBorderWidth(x);
713 if (!a.value("includeChildren").isEmpty()) {
714 if (a.value("includeChildren") == "true")
715 oo->setFrameIncludeChildren(true);
717 oo->setFrameIncludeChildren(false);
726 bool parseVYMHandler::readOOAttr(const QXmlAttributes &a)
731 if (!a.value("posX").isEmpty()) { // Introduced in 2.9.501, added here for file compatibility
732 if (!a.value("posY").isEmpty()) {
733 x = a.value("posX").toFloat(&okx);
734 y = a.value("posY").toFloat(&oky);
736 lastMI->setRelPos(QPointF(x, y));
738 return false; // Couldn't read relPos
741 if (!a.value("relPosX").isEmpty()) {
742 if (!a.value("relPosY").isEmpty()) {
743 x = a.value("relPosX").toFloat(&okx);
744 y = a.value("relPosY").toFloat(&oky);
746 lastMI->setRelPos(QPointF(x, y));
748 return false; // Couldn't read relPos
751 if (!a.value("absPosX").isEmpty()) {
752 if (!a.value("absPosY").isEmpty()) {
753 x = a.value("absPosX").toFloat(&okx);
754 y = a.value("absPosY").toFloat(&oky);
756 lastMI->setAbsPos(QPointF(x, y));
758 return false; // Couldn't read absPos
761 if (!a.value("url").isEmpty())
762 lastMI->setURL(a.value("url"));
763 if (!a.value("vymLink").isEmpty())
764 lastMI->setVymLink(a.value("vymLink"));
765 if (!a.value("hideInExport").isEmpty())
766 if (a.value("hideInExport") == "true")
767 lastMI->setHideInExport(true);
769 if (!a.value("hideLink").isEmpty()) {
770 if (a.value("hideLink") == "true")
771 lastMI->setHideLinkUnselected(true);
773 lastMI->setHideLinkUnselected(false);
776 if (!a.value("localTarget").isEmpty())
777 if (a.value("localTarget") == "true")
778 lastMI->toggleTarget();
779 if (!a.value("rotation").isEmpty()) {
780 x = a.value("rotation").toFloat(&okx);
782 lastMI->setRotation(x);
784 return false; // Couldn't read rotation
787 if (!a.value("uuid").isEmpty()) {
788 // While pasting, check for existing UUID
789 if (loadMode != ImportAdd && !model->findUuid(a.value("uuid")))
790 lastMI->setUuid(a.value("uuid"));
796 bool parseVYMHandler::readNoteAttr(const QXmlAttributes &a)
797 { // only for backward compatibility (<1.4.6). Use htmlnote now.
800 if (!a.value("href").isEmpty()) {
802 fn = parseHREF(a.value("href"));
804 QString s; // Reading a note
806 if (!file.open(QIODevice::ReadOnly)) {
807 qWarning() << "parseVYMHandler::readNoteAttr: Couldn't load " + fn;
810 QTextStream stream(&file);
811 stream.setCodec("UTF-8");
813 while (!stream.atEnd()) {
814 lines += stream.readLine() + "\n";
818 if (lines.contains("<html")) {
819 vymtext.setRichText(lines);
821 vymtext.setPlainText(lines);
823 if (!a.value("fonthint").isEmpty())
824 vymtext.setFontHint(a.value("fonthint"));
828 bool parseVYMHandler::readImageAttr(const QXmlAttributes &a)
835 if (!a.value("href").isEmpty()) {
837 if (!lastImage->load(parseHREF(a.value("href")))) {
838 QMessageBox::warning(0, "Warning: ",
839 "Couldn't load image\n" +
840 parseHREF(a.value("href")));
845 if (!a.value("zPlane").isEmpty())
846 lastImage->setZValue(a.value("zPlane").toInt());
849 if (!a.value("posX").isEmpty()) { // Introduced in 2.9.501, added here for file compatibility
850 if (!a.value("posY").isEmpty()) {
851 x = a.value("posX").toFloat(&okx);
852 y = a.value("posY").toFloat(&oky);
854 lastImage->setRelPos(QPointF(x, y));
856 return false; // Couldn't read relPos
859 if (!a.value("relPosX").isEmpty()) {
860 if (!a.value("relPosY").isEmpty()) {
862 x = a.value("relPosX").toFloat(&okx);
863 y = a.value("relPosY").toFloat(&oky);
865 lastImage->setRelPos(QPointF(x, y));
867 // Couldn't read relPos
873 // scaleX and scaleY are no longer used since 2.7.509 and replaced by
876 if (!a.value("scaleX").isEmpty()) {
877 x = a.value("scaleX").toFloat(&okx);
882 if (!a.value("scaleY").isEmpty()) {
883 x = a.value("scaleY").toFloat(&oky);
888 if (!a.value("scaleFactor").isEmpty()) {
889 x = a.value("scaleFactor").toFloat(&okx);
895 lastImage->setScaleFactor(x);
900 if (!a.value("originalName").isEmpty())
902 lastImage->setOriginalFilename(a.value("originalName"));
907 bool parseVYMHandler::readXLinkAttr(const QXmlAttributes &a)
909 // Obsolete, see also readLinkAttr
911 if (!a.value("beginID").isEmpty()) {
912 if (!a.value("endID").isEmpty()) {
913 TreeItem *beginBI = model->findBySelectString(a.value("beginID"));
914 TreeItem *endBI = model->findBySelectString(a.value("endID"));
915 if (beginBI && endBI && beginBI->isBranchLikeType() &&
916 endBI->isBranchLikeType()) {
917 Link *li = new Link(model);
918 li->setBeginBranch((BranchItem *)beginBI);
919 li->setEndBranch((BranchItem *)endBI);
920 QPen pen = li->getPen();
922 if (!a.value("color").isEmpty()) {
924 col.setNamedColor(a.value("color"));
928 if (!a.value("width").isEmpty()) {
930 pen.setWidth(a.value("width").toInt(&okx, 10));
933 model->createLink(li);
940 bool parseVYMHandler::readLinkNewAttr(const QXmlAttributes &a)
942 // object ID is used starting in version 1.8.76
943 // (before there was beginBranch and endBranch)
945 // Starting in 1.13.2 xlinks are no longer subitems of branches,
946 // but listed at the end of the data in a map. This makes handling
947 // of links much safer and easier
949 if (!a.value("beginID").isEmpty()) {
950 if (!a.value("endID").isEmpty()) {
951 TreeItem *beginBI = model->findBySelectString(a.value("beginID"));
952 TreeItem *endBI = model->findBySelectString(a.value("endID"));
953 if (beginBI && endBI && beginBI->isBranchLikeType() &&
954 endBI->isBranchLikeType()) {
955 Link *li = new Link(model);
956 li->setBeginBranch((BranchItem *)beginBI);
957 li->setEndBranch((BranchItem *)endBI);
959 model->createLink(li);
962 QPen pen = li->getPen();
963 if (!a.value("type").isEmpty()) {
964 li->setLinkType(a.value("type"));
966 if (!a.value("color").isEmpty()) {
968 col.setNamedColor(a.value("color"));
971 if (!a.value("width").isEmpty()) {
972 pen.setWidth(a.value("width").toInt(&okx, 10));
974 if (!a.value("penstyle").isEmpty()) {
975 pen.setStyle(penStyle(a.value("penstyle"), okx));
979 if (!a.value("styleBegin").isEmpty())
980 li->setStyleBegin(a.value("styleBegin"));
981 if (!a.value("styleEnd").isEmpty())
982 li->setStyleEnd(a.value("styleEnd"));
984 XLinkObj *xlo = (XLinkObj *)(li->getMO());
985 if (xlo && !a.value("c0").isEmpty()) {
986 QPointF p = point(a.value("c0"), okx);
990 if (xlo && !a.value("c1").isEmpty()) {
991 QPointF p = point(a.value("c1"), okx);
1001 bool parseVYMHandler::readSettingAttr(const QXmlAttributes &a)
1003 if (!a.value("key").isEmpty()) {
1004 lastSetting = a.value("key");
1005 if (!a.value("value").isEmpty())
1006 settings.setLocalValue(
1007 model->getDestPath(), a.value("key"),
1018 bool parseVYMHandler::readSlideAttr(const QXmlAttributes &a)
1020 QStringList scriptlines; // FIXME-3 needed for switching to inScript
1021 // Most attributes are obsolete with inScript
1025 if (!a.value("name").isEmpty())
1026 lastSlide->setName(a.value("name"));
1027 if (!a.value("zoom").isEmpty()) {
1029 qreal z = a.value("zoom").toDouble(&ok);
1032 scriptlines.append(QString("setMapZoom(%1)").arg(z));
1034 if (!a.value("rotation").isEmpty()) {
1036 qreal z = a.value("rotation").toDouble(&ok);
1039 scriptlines.append(QString("setMapRotation(%1)").arg(z));
1041 if (!a.value("duration").isEmpty()) {
1043 int d = a.value("duration").toInt(&ok);
1046 scriptlines.append(QString("setMapAnimDuration(%1)").arg(d));
1048 if (!a.value("curve").isEmpty()) {
1050 int i = a.value("curve").toInt(&ok);
1053 if (i < 0 || i > QEasingCurve::OutInBounce)
1055 scriptlines.append(QString("setMapAnimCurve(%1)").arg(i));
1057 if (!a.value("mapitem").isEmpty()) {
1058 TreeItem *ti = model->findBySelectString(a.value("mapitem"));
1062 QString("centerOnID(\"%1\")").arg(ti->getUuid().toString()));
1064 if (!a.value("inScript").isEmpty()) {
1065 lastSlide->setInScript(unquoteMeta(a.value("inScript")));
1068 lastSlide->setInScript(unquoteMeta(scriptlines.join(";\n")));
1070 if (!a.value("outScript").isEmpty()) {
1071 lastSlide->setOutScript(unquoteMeta(a.value("outScript")));
1077 bool parseVYMHandler::readTaskAttr(const QXmlAttributes &a)
1082 if (!a.value("status").isEmpty())
1083 lastTask->setStatus(a.value("status"));
1084 if (!a.value("awake").isEmpty())
1085 lastTask->setAwake(a.value("awake"));
1086 if (!a.value("date_creation").isEmpty())
1087 lastTask->setDateCreation(a.value("date_creation"));
1088 if (!a.value("date_modification").isEmpty())
1089 lastTask->setDateModification(a.value("date_modification"));
1090 if (!a.value("date_sleep").isEmpty()) {
1091 if (!lastTask->setDateSleep(a.value("date_sleep")))
1094 if (!a.value("prio_delta").isEmpty()) {
1095 lastTask->setPriorityDelta(a.value("prio_delta").toInt());
1101 bool parseVYMHandler::readUserFlagDefAttr(const QXmlAttributes &a)
1108 if (!a.value("name").isEmpty())
1109 name = a.value("name");
1110 if (!a.value("tooltip").isEmpty())
1111 tooltip = a.value("tooltip");
1112 if (!a.value("uuid").isEmpty())
1113 uid = QUuid(a.value("uuid"));
1117 if (!a.value("href").isEmpty()) {
1118 // Setup flag with image
1119 flag = mainWindow->setupFlag(parseHREF(a.value("href")), Flag::UserFlag,
1120 name, tooltip, uid);
1123 qWarning() << "readUserFlagDefAttr: Couldn't read href of flag "
1128 if (!a.value("group").isEmpty())
1129 flag->setGroup(a.value("group"));
1134 bool parseVYMHandler::readUserFlagAttr(const QXmlAttributes &a)
1139 if (!a.value("name").isEmpty())
1140 name = a.value("name");
1141 if (!a.value("uuid").isEmpty())
1142 uuid = a.value("uuid");
1144 lastBranch->toggleFlagByUid(QUuid(uuid));