5 // #include <q3stylesheet.h>
11 #include "linkablemapobj.h"
14 static BranchObj *lastBranch;
15 static FloatObj *lastFloat;
16 static OrnamentedObj *lastOO;
18 extern Settings settings;
19 extern QString vymVersion;
21 mapBuilderHandler::mapBuilderHandler() {}
23 mapBuilderHandler::~mapBuilderHandler() {}
25 QString mapBuilderHandler::errorProtocol() { return errorProt; }
27 bool mapBuilderHandler::startDocument()
31 laststate = StateInit;
39 QString mapBuilderHandler::parseHREF(QString href)
41 QString type=href.section(":",0,0);
42 QString path=href.section(":",1,1);
43 if (!tmpDir.endsWith("/"))
44 return tmpDir + "/" + path;
49 bool mapBuilderHandler::startElement ( const QString&, const QString&,
50 const QString& eName, const QXmlAttributes& atts )
54 cout << "startElement <"<< eName.ascii()<<
56 " laststate="<<laststate<<
57 " loadMode="<<loadMode<<endl;
59 if ( state == StateInit && (eName == "vymmap") )
62 if (!atts.value( "version").isEmpty() )
64 if (!checkVersion(atts.value("version")))
65 QMessageBox::warning( 0, "Warning: Version Problem" ,
66 "<h3>Map is newer than VYM</h3>"
67 "<p>The map you are just trying to load was "
68 "saved using vym " +atts.value("version")+". "
69 "The version of this vym is " + vymVersion +
70 ". If you run into problems after pressing "
71 "the ok-button below, updating vym should help.");
73 mc->setVersion(atts.value( "version" ));
76 if (loadMode==NewMap ||
77 (loadMode==ImportReplace && me->getSelection()==mc))
79 if (!atts.value( "author").isEmpty() )
81 mc->setAuthor(atts.value( "author" ) );
83 if (!atts.value( "comment").isEmpty() )
85 mc->setComment (atts.value( "comment" ) );
87 if (!atts.value( "backgroundColor").isEmpty() )
89 col.setNamedColor(atts.value("backgroundColor"));
90 mc->getScene()->setBackgroundBrush(col);
92 if (!atts.value( "linkColorHint").isEmpty() )
94 if (atts.value("linkColorHint")=="HeadingColor")
95 me->setMapLinkColorHint(HeadingColor);
97 me->setMapLinkColorHint(DefaultColor);
99 if (!atts.value( "linkStyle").isEmpty() )
101 me->setMapLinkStyle(atts.value("linkStyle"));
103 if (!atts.value( "linkColor").isEmpty() )
105 col.setNamedColor(atts.value("linkColor"));
106 me->setMapDefLinkColor(col);
108 if (!atts.value( "defXLinkColor").isEmpty() )
110 col.setNamedColor(atts.value("defXLinkColor"));
111 me->setMapDefXLinkColor(col);
113 if (!atts.value( "defXLinkWidth").isEmpty() )
115 me->setMapDefXLinkWidth(atts.value("defXLinkWidth").toInt ());
118 } else if ( eName == "select" && state == StateMap )
120 state=StateMapSelect;
121 } else if ( eName == "setting" && state == StateMap )
123 state=StateMapSetting;
124 if (loadMode==NewMap)
125 readSettingAttr (atts);
126 } else if ( eName == "mapcenter" && state == StateMap )
128 state=StateMapCenter;
129 if (loadMode==NewMap)
131 // Really use the found mapcenter as MCO in a new map
132 lastBranch=mc; // avoid empty pointer
135 // Treat the found mapcenter as a branch
136 // in an existing map
137 LinkableMapObj* lmo=me->getSelection();
138 if (lmo && (typeid(*lmo) == typeid(BranchObj) )
139 || (typeid(*lmo) == typeid(MapCenterObj) ) )
141 lastBranch=(BranchObj*)lmo;
142 if (loadMode==ImportAdd)
144 lastBranch->addBranch();
145 lastBranch=lastBranch->getLastBranch();
151 readBranchAttr (atts);
152 } else if ( (eName == "standardflag" ||eName == "standardFlag") && state == StateMapCenter)
154 state=StateMapCenterStandardFlag;
155 } else if ( eName == "heading" && state == StateMapCenter)
157 state=StateMapCenterHeading;
158 if (!atts.value( "textColor").isEmpty() )
160 col.setNamedColor(atts.value("textColor"));
161 lastBranch->setColor(col );
163 } else if ( eName == "note" && state == StateMapCenter)
164 { // only for backward compatibility (<1.4.6). Use htmlnote now.
165 state=StateMapCenterNote;
166 if (!readNoteAttr (atts) ) return false;
167 } else if ( eName == "htmlnote" && state == StateMapCenter)
171 } else if ( eName == "floatimage" && state == StateMapCenter )
173 state=StateMapCenterFloatImage;
174 lastBranch->addFloatImage();
175 lastFloat=lastBranch->getLastFloatImage();
176 if (!readFloatImageAttr(atts)) return false;
177 } else if ( (eName == "branch"||eName=="floatimage") && state == StateMap)
179 // This is used in vymparts, which have no mapcenter!
181 LinkableMapObj* lmo=me->getSelection();
184 // If a vym part is _loaded_ (not imported),
185 // selection==lmo==NULL
186 // Treat it like ImportAdd then...
190 if (lmo && (typeid(*lmo) == typeid(BranchObj) )
191 || (typeid(*lmo) == typeid(MapCenterObj) ) )
193 lastBranch=(BranchObj*)(lmo);
197 if (loadMode==ImportAdd)
199 lastBranch->addBranch();
200 lastBranch=lastBranch->getLastBranch();
205 readBranchAttr (atts);
206 } else if (eName=="floatimage")
208 state=StateFloatImage;
209 lastBranch->addFloatImage();
210 lastFloat=lastBranch->getLastFloatImage();
211 if (!readFloatImageAttr(atts)) return false;
214 } else if ( eName == "branch" && state == StateMapCenter)
218 lastBranch->addBranch();
219 lastBranch=lastBranch->getLastBranch();
220 readBranchAttr (atts);
221 } else if ( (eName=="standardflag" ||eName == "standardFlag") && state == StateBranch)
223 state=StateBranchStandardFlag;
224 } else if ( eName == "heading" && state == StateBranch)
226 state=StateBranchHeading;
227 if (!atts.value( "textColor").isEmpty() )
229 col.setNamedColor(atts.value("textColor"));
230 lastBranch->setColor(col );
232 } else if ( eName == "note" && state == StateBranch)
234 state=StateBranchNote;
235 if (!readNoteAttr (atts) ) return false;
236 } else if ( eName == "htmlnote" && state == StateBranch)
241 if (!atts.value( "fonthint").isEmpty() )
242 no.setFontHint(atts.value ("fonthint") );
243 } else if ( eName == "floatimage" && state == StateBranch )
245 state=StateBranchFloatImage;
246 lastBranch->addFloatImage();
247 lastFloat=lastBranch->getLastFloatImage();
248 if (!readFloatImageAttr(atts)) return false;
249 } else if ( eName == "xlink" && state == StateBranch )
251 state=StateBranchXLink;
252 if (!readXLinkAttr (atts)) return false;
253 } else if ( eName == "branch" && state == StateBranch )
255 lastBranch->addBranch();
256 lastBranch=lastBranch->getLastBranch();
258 readBranchAttr (atts);
259 } else if ( eName == "html" && state == StateHtmlNote )
265 } else if ( state == StateHtml )
267 // accept all while in html mode,
272 return false; // Error
276 bool mapBuilderHandler::endElement ( const QString&, const QString&, const QString &eName)
278 // cout << "endElement </"<<eName<<"> state="<<state <<" laststate="<<laststate<<endl;
281 case StateMapSelect: state=StateMap; return true;
282 case StateMapSetting: state=StateMap; return true;
283 case StateMapCenter: state=StateMap; return true;
284 case StateMapCenterStandardFlag: state=StateMapCenter; return true;
285 case StateMapCenterHeading: state=StateMapCenter; return true;
286 case StateMapCenterNote: state=StateMapCenter; return true;
287 case StateMapCenterFloatImage: state=StateMapCenter; return true;
288 case StateFloatImage: state=StateMap; return true;
300 state=StateMapCenter;
302 lastBranch=(BranchObj*)(lastBranch->getParObj());
304 case StateBranchStandardFlag: state=StateBranch; return true;
305 case StateBranchHeading: state=StateBranch; return true;
306 case StateBranchNote: state=StateBranch; return true;
307 case StateBranchFloatImage: state=StateBranch; return true;
308 case StateBranchXLink: state=StateBranch; return true;
309 case StateHtmlNote: state=laststate; return true;
311 htmldata+="</"+eName+">";
315 htmldata.replace ("<br></br>","<br />");
316 no.setNote (htmldata);
317 lastBranch->setNote (no);
323 case StateMap: state=StateInit; return true;
325 // even for HTML includes, this should never be reached
330 bool mapBuilderHandler::characters ( const QString& ch)
332 //cout << "characters \""<<ch<<"\" state="<<state <<" laststate="<<laststate<<endl;
334 QString ch_org=quotemeta (ch);
335 QString ch_simplified=ch.simplifyWhiteSpace();
336 if ( ch_simplified.isEmpty() ) return true;
340 case StateInit: break;
341 case StateMap: break;
343 me->select(ch_simplified);
345 case StateMapSetting:break;
346 case StateMapCenter: break;
347 case StateMapCenterStandardFlag:
348 lastBranch->activateStandardFlag(ch_simplified);
350 case StateMapCenterHeading:
351 lastBranch->setHeading(ch_simplified);
353 case StateMapCenterNote:
354 lastBranch->setNote(ch_simplified);
356 case StateBranch: break;
357 case StateBranchStandardFlag:
358 lastBranch->activateStandardFlag(ch_simplified);
360 case StateBranchHeading:
361 lastBranch->setHeading(ch_simplified);
363 case StateBranchNote:
364 lastBranch->setNote(ch_simplified);
366 case StateBranchFloatImage: break;
367 case StateHtmlNote: break;
377 QString mapBuilderHandler::errorString()
379 return "the document is not in the VYM file format";
382 bool mapBuilderHandler::fatalError( const QXmlParseException& exception )
384 errorProt += QString( "Fatal parsing error: %1 in line %2, column %3\n")
385 .arg( exception.message() )
386 .arg( exception.lineNumber() )
387 .arg( exception.columnNumber() );
388 // Try to read the bogus line
389 errorProt+=QString("File is: %1\n").arg(inputFile);
391 if (loadStringFromDisk (inputFile,s))
393 QStringList sl=QStringList::split ("\n",s);
395 QStringList::Iterator it = sl.begin();
396 while (i<exception.lineNumber()-1)
402 s.insert (exception.columnNumber()-1,"<ERROR>");
405 return QXmlDefaultHandler::fatalError( exception );
408 void mapBuilderHandler::setMapEditor (MapEditor* e)
411 mc=me->getMapCenter();
414 void mapBuilderHandler::setTmpDir (QString tp)
419 void mapBuilderHandler::setInputFile (QString f)
424 void mapBuilderHandler::setLoadMode (const LoadMode &lm)
429 bool mapBuilderHandler::readBranchAttr (const QXmlAttributes& a)
432 if (!readOOAttr(a)) return false;
434 if (!a.value( "scrolled").isEmpty() )
435 lastBranch->toggleScroll();
436 if (!a.value( "frameType").isEmpty() )
437 lastBranch->setFrameType (a.value("frameType"));
439 if (!a.value( "incImgV").isEmpty() )
441 if (a.value("incImgV")=="true")
442 lastBranch->setIncludeImagesVer(true);
444 lastBranch->setIncludeImagesVer(false);
446 if (!a.value( "incImgH").isEmpty() )
448 if (a.value("incImgH")=="true")
449 lastBranch->setIncludeImagesHor(true);
451 lastBranch->setIncludeImagesHor(false);
456 bool mapBuilderHandler::readOOAttr (const QXmlAttributes& a)
462 if (!a.value( "relPosX").isEmpty() )
464 if (!a.value( "relPosY").isEmpty() )
466 x=a.value("relPosX").toInt (&okx, 10);
467 y=a.value("relPosY").toInt (&oky, 10);
470 lastOO->setUseRelPos (true);
471 lastOO->move2RelPos (x,y);
474 return false; // Couldn't read relPos
477 if (!a.value( "absPosX").isEmpty() && loadMode==NewMap && branchDepth<2)
479 if (!a.value( "absPosY").isEmpty() )
481 x=a.value("absPosX").toInt (&okx, 10);
482 y=a.value("absPosY").toInt (&oky, 10);
486 return false; // Couldn't read absPos
489 if (!a.value( "url").isEmpty() )
490 lastOO->setURL (a.value ("url"));
491 if (!a.value( "vymLink").isEmpty() )
492 lastOO->setVymLink (a.value ("vymLink"));
493 if (!a.value( "hideInExport").isEmpty() )
494 if (a.value("hideInExport")=="true")
495 lastOO->setHideInExport(true);
497 if (!a.value( "hideLink").isEmpty())
499 if (a.value ("hideLink") =="true")
500 lastOO->setHideLinkUnselected(true);
502 lastOO->setHideLinkUnselected(false);
508 bool mapBuilderHandler::readNoteAttr (const QXmlAttributes& a)
509 { // only for backward compatibility (<1.4.6). Use htmlnote now.
512 if (!a.value( "href").isEmpty() )
515 fn=parseHREF(a.value ("href") );
517 QString s; // Reading a note
519 if ( !file.open( QIODevice::ReadOnly) )
521 qWarning ("mapBuilderHandler::readNoteAttr: Couldn't load "+fn);
524 QTextStream stream( &file );
526 while ( !stream.atEnd() ) {
527 lines += stream.readLine()+"\n";
531 /* TODO very likely not needed any longer
532 // Convert to richtext
533 if ( !Q3StyleSheet::mightBeRichText( lines ) )
535 // Here we are workarounding the QT conversion method:
536 // convertFromPlainText does not generate valid xml, needed
537 // for the parser, but just <p> and <br> without closing tags.
538 // So we have to add those by ourselves
539 //lines=quotemeta (lines);
540 qWarning ("xml.cpp: Still using Q3StyleSheet::mightBeRichText");
541 lines = Q3StyleSheet::convertFromPlainText( lines, Q3StyleSheetItem::WhiteSpaceNormal );
542 lines.replace ("<br>","<br />");
546 lines ="<html><head><meta name=\"qrichtext\" content=\"1\" /></head><body>"+lines + "</p></body></html>";
549 if (!a.value( "fonthint").isEmpty() )
550 no.setFontHint(a.value ("fonthint") );
551 if (state == StateMapCenterNote)
554 lastBranch->setNote(no);
558 bool mapBuilderHandler::readFloatImageAttr (const QXmlAttributes& a)
562 //if (!readOOAttr(a)) return false;
564 if (!a.value( "useOrientation").isEmpty() )
566 if (a.value ("useOrientation") =="true")
567 lastFloat->setUseOrientation (true);
569 lastFloat->setUseOrientation (false);
571 if (!a.value( "href").isEmpty() )
574 if (!lastFloat->load (parseHREF(a.value ("href") ) ))
576 QMessageBox::warning( 0, "Warning: " ,
577 "Couldn't load float image\n"+parseHREF(a.value ("href") ));
578 lastBranch->removeFloatImage(((FloatImageObj*)(lastFloat)));
584 if (!a.value( "floatExport").isEmpty() )
586 // Only for compatibility. THis is not used since 1.7.11
587 if (a.value ("floatExport") =="true")
588 lastFloat->setFloatExport(true);
590 lastFloat->setFloatExport (false);
592 if (!a.value( "zPlane").isEmpty() )
593 lastFloat->setZValue (a.value("zPlane").toInt ());
596 if (!a.value( "relPosX").isEmpty() )
598 if (!a.value( "relPosY").isEmpty() )
601 x=a.value("relPosX").toInt (&okx, 10);
602 y=a.value("relPosY").toInt (&oky, 10);
606 lastFloat->setRelPos (QPoint (x,y) );
607 // make sure floats in mapcenter are repositioned to relative pos
608 if (mc==lastBranch) mc->positionContents();
611 // Couldn't read relPos
616 if (!readOOAttr(a)) return false;
618 if (!a.value ("orgName").isEmpty() )
620 ((FloatImageObj*)(lastFloat))->setOriginalFilename (a.value("orgName"));
625 bool mapBuilderHandler::readXLinkAttr (const QXmlAttributes& a)
630 XLinkObj *xlo=new XLinkObj (mc->getScene());
631 if (!a.value( "color").isEmpty() )
633 col.setNamedColor(a.value("color"));
637 if (!a.value( "width").isEmpty() )
639 xlo->setWidth(a.value ("width").toInt (&okx, 10));
642 if (!a.value( "beginBranch").isEmpty() )
644 if (!a.value( "endBranch").isEmpty() )
646 LinkableMapObj *lmo=mc->findObjBySelect (a.value( "beginBranch"));
647 if (lmo && typeid (*lmo)==typeid (BranchObj))
649 xlo->setBegin ((BranchObj*)lmo);
650 lmo=mc->findObjBySelect (a.value( "endBranch"));
651 if (lmo && typeid (*lmo)==typeid (BranchObj))
653 xlo->setEnd ((BranchObj*)(lmo));
657 success=true; // Not all branches there yet, no error
660 if (!success) delete (xlo);
664 bool mapBuilderHandler::readHtmlAttr (const QXmlAttributes& a)
666 for (int i=1; i<=a.count(); i++)
667 htmldata+=" "+a.localName(i-1)+"=\""+a.value(i-1)+"\"";
671 bool mapBuilderHandler::readSettingAttr (const QXmlAttributes& a)
673 if (!a.value( "key").isEmpty() )
675 if (!a.value( "value").isEmpty() )
676 settings.setLocalEntry (me->getDestPath(), a.value ("key"), a.value ("value"));