1 #include "xml-freemind.h"
6 #include "branchitem.h"
10 extern Settings settings;
11 extern QString vymVersion;
13 bool parseFreemindHandler::nodeLikeState()
15 if (state == StateCenter || state == StateMainNode || state == StateNode)
21 bool parseFreemindHandler::startDocument() // FIXME-3 import not complete yet
26 stateStack.append(StateInit);
31 QString parseFreemindHandler::parseHREF(QString href)
33 QString type = href.section(":", 0, 0);
34 QString path = href.section(":", 1, 1);
35 if (!tmpDir.endsWith("/"))
36 return tmpDir + "/" + path;
41 bool parseFreemindHandler::startElement(const QString &, const QString &,
43 const QXmlAttributes &atts)
47 if (eName.contains("node"))
48 qDebug() << "startElement: <" << eName
49 << "> state=" << state
50 << " laststate=" << stateStack.last();
51 //<< " loadMode=" << loadMode
52 //<<" line=" << QXmlDefaultHandler::lineNumber();
55 stateStack.append(state);
56 if (state == StateInit && (eName == "map")) {
58 if (!atts.value("version").isEmpty()) {
60 if (!versionLowerOrEqual(atts.value("version"), v))
62 0, "Warning: Version Problem",
63 "<h3>Freemind map is newer than version " + v +
65 "<p>The map you are just trying to load was "
66 "saved using freemind " +
67 atts.value("version") +
69 "Your version of vym can parse freemind " +
74 mapCenter = model->createMapCenter();
75 lastBranch = mapCenter;
77 // Create two hidden branches, because Freemind has no relative
78 // positioning for mainbranches
79 mainBranchLeft = model->createBranch(lastBranch);
80 mainBranchRight = model->createBranch(lastBranch);
82 mainBranchLeft->setRelPos(QPointF(-200, 0));
83 mainBranchLeft->setHeadingPlainText(" ");
84 model->emitDataChanged(mainBranchLeft);
86 mainBranchRight->setRelPos(QPointF(200, 0));
87 mainBranchRight->setHeadingPlainText(" ");
88 model->emitDataChanged(mainBranchRight);
90 else if (eName == "attribute_registry" && state == StateMap) {
91 state = StateAttributeRegistry;
93 else if (eName == "attribute_name" && state == StateAttributeRegistry) {
94 state = StateAttributeName;
96 else if (eName == "attribute_value" && state == StateAttributeName) {
97 state = StateAttributeValue;
99 else if (eName == "node" && state == StateMap) {
101 lastBranch = mapCenter;
104 else if (eName == "node" && state == StateCenter) {
105 state = StateMainNode;
106 lastBranch = model->createBranch(lastBranch);
109 else if (eName == "node" && (state == StateNode || state == StateMainNode)) {
111 lastBranch = model->createBranch(lastBranch);
114 else if (eName == "properties") {
116 else if (eName == "map_styles") {
118 else if (eName == "font" && nodeLikeState())
120 // FIXME-3 not implemented
123 else if (eName == "edge" && nodeLikeState())
125 // FIXME-3 xlink not implemented
128 else if (eName == "hook" && nodeLikeState()) {
131 else if (eName == "icon" && nodeLikeState()) {
133 if (!atts.value("BUILTIN").isEmpty()) {
134 QString f = atts.value("BUILTIN");
138 else if (f == "messagebox_warning")
139 v = "freemind-warning";
140 else if (f == "idea")
142 else if (f == "button_ok")
144 else if (f == "button_cancel")
146 else if (f.contains("full-"))
147 v = f.replace("full-", "freemind-priority-");
148 else if (f == "back")
150 else if (f == "forward")
151 v = "freemind-forward";
152 else if (f == "attach")
153 v = "freemind-attach";
154 else if (f == "ksmiletris")
155 v = "smiley-good"; //
156 else if (f == "clanbomber")
157 v = "freemind-clanbomber";
158 else if (f == "desktop_new")
159 v = "freemind-desktopnew";
160 else if (f == "flag")
162 else if (f == "gohome")
163 v = "freemind-gohome";
164 else if (f == "kaddressbook")
165 v = "freemind-kaddressbook";
166 else if (f == "knotify")
167 v = "freemind-knotify";
168 else if (f == "korn")
170 else if (f == "Mail")
172 else if (f == "password")
173 v = "freemind-password";
174 else if (f == "pencil")
175 v = "freemind-pencil";
176 else if (f == "stop")
178 else if (f == "wizard")
179 v = "freemind-wizard";
180 else if (f == "xmag")
182 else if (f == "bell")
184 else if (f == "bookmark")
185 v = "freemind-bookmark";
186 else if (f == "penguin")
187 v = "freemind-penguin";
188 else if (f == "licq")
191 qWarning() << "parseFreemindHandler: Unknown icon found: " << f;
193 lastBranch->activateStandardFlagByName(v);
196 else if (eName == "arrowlink" && nodeLikeState()) {
197 state = StateArrowLink;
199 else if (eName == "cloud" && nodeLikeState()) {
202 else if (eName == "richcontent" && nodeLikeState()) {
203 state = StateRichContent;
204 return readRichContentAttr(atts);
206 else if (eName == "html" && state == StateRichContent) {
208 htmldata = "<" + eName;
212 else if (eName == "text" && state == StateHook) {
215 else if (state == StateHtml) {
216 // accept all while in html mode,
217 htmldata += "<" + eName;
222 // Usually we would return an error here
223 // In order to not break with every new element in FreeMind or
224 // FreePlane, better ignore the new element for now
225 state = StateUnknown;
227 << "parseFreemindHandler: Unknown element found and ignoring:: "
233 bool parseFreemindHandler::endElement(const QString &, const QString &,
234 const QString &eName)
238 lastBranch ? h = lastBranch->getHeadingPlain() : h = "";
239 if (eName.contains("node"))
240 qDebug() << "endElement </" << eName << "> state=" << state << " lastBranch=" << h;
245 // Freemind does not have the two "extra" mainbranches used here,
246 // so we have to update mapcenter
247 model->emitDataChanged(mapCenter);
249 // Remove helper branches, if not needed
250 if (mainBranchLeft->childCount() == 0)
251 model->deleteItem(mainBranchLeft);
252 if (mainBranchRight->childCount() == 0)
253 model->deleteItem(mainBranchRight);
258 model->emitDataChanged(lastBranch);
259 lastBranch = (BranchItem *)lastBranch->parent();
261 lastBranch->setLastSelectedBranch(0);
263 qWarning() << "xml-vym: lastBranch == nullptr";
265 case StateRichContent:
266 if (!htmldata.isEmpty()) {
267 vymtext.setAutoText(htmldata);
268 if (htmlPurpose == Node)
269 lastBranch->setHeading(vymtext);
270 else if (htmlPurpose == Note)
271 lastBranch->setNote(vymtext);
275 htmldata += "</" + eName + ">";
276 if (eName == "html") {
277 htmldata = htmldata.replace("<br></br>", "<br />");
278 htmldata = htmldata.replace("\\n</p>", "</p>");
284 state = stateStack.takeLast();
288 bool parseFreemindHandler::characters(const QString &ch)
290 //qDebug() << "characters \"" << qPrintable(ch) << "\" state=" << state;
292 QString ch_org = quoteMeta(ch);
293 QString ch_simplified = ch.simplified();
294 if (ch_simplified.isEmpty())
317 lastBranch->setNote(ch_simplified);
330 QString parseFreemindHandler::errorString()
332 return "the document is not in the Freemind file format";
335 bool parseFreemindHandler::readNodeAttr(const QXmlAttributes &a)
337 if (state == StateMainNode)
339 // Freemind has a different concept for mainbranches
340 // Move either to left or right side of mapcenter
341 if (!a.value("POSITION").isEmpty()) {
342 if (a.value("POSITION") == "left")
343 model->relinkBranch(lastBranch, mainBranchLeft);
344 else if (a.value("POSITION") == "right")
345 model->relinkBranch(lastBranch, mainBranchRight);
349 if (a.value("FOLDED") == "true")
350 lastBranch->toggleScroll();
352 if (!a.value("TEXT").isEmpty()) {
353 lastBranch->setHeadingPlainText(
354 a.value("TEXT")); // FIXME-3 what about RT?
355 // model->setHeading (a.value ("TEXT"), lastBranch);
358 if (!a.value("COLOR").isEmpty())
359 lastBranch->setHeadingColor(QColor(a.value("COLOR")));
361 if (!a.value("LINK").isEmpty())
362 lastBranch->setURL(a.value("LINK"));
366 bool parseFreemindHandler::readRichContentAttr(const QXmlAttributes &a)
368 if (a.value("TYPE") == "NODE")
370 else if (a.value("TYPE") == "NOTE")
373 htmlPurpose = Unknown;
375 << "parseFreemindHandler: Unknown purpose of richContent found: "
378 // FIXME-3 Usually we would stop here, ignore for now