]> git.sven.stormbind.net Git - sven/vym.git/blob - xml-freemind.cpp
Import Upstream version 2.6.11
[sven/vym.git] / xml-freemind.cpp
1 #include "xml-freemind.h"
2
3 #include <QDebug>
4 #include <QMessageBox>
5
6 #include "branchitem.h"
7 #include "version.h"
8 #include "vymmodel.h"
9
10 extern Settings settings;
11 extern QString vymVersion;
12
13 bool parseFreemindHandler::startDocument()  //FIXME-3 import not complete yet
14 {
15     errorProt = "";
16     state = StateInit;
17     stateStack.clear();
18     stateStack.append(StateInit);
19     isVymPart=false;
20     return true;
21 }
22
23
24 QString parseFreemindHandler::parseHREF(QString href)
25 {
26     QString type=href.section(":",0,0);
27     QString path=href.section(":",1,1);
28     if (!tmpDir.endsWith("/"))
29         return tmpDir + "/" + path;
30     else    
31         return tmpDir + path;
32 }
33
34 bool parseFreemindHandler::startElement  ( const QString&, const QString&,
35                     const QString& eName, const QXmlAttributes& atts ) 
36 {
37     QColor col;
38     /* Testing
39     qDebug() << "startElement <"<< qPrintable(eName)
40         <<">  state="<<state 
41         <<"  stateLast="<<stateStack.last()
42         <<"   loadMode="<<loadMode
43     //  <<"       line="<<qPrintable (QXmlDefaultHandler::lineNumber())
44         ;
45     */  
46     stateStack.append (state);  
47     if ( state == StateInit && (eName == "map")  ) 
48     {
49         state = StateMap;
50         if (!atts.value( "version").isEmpty() ) 
51         {
52             QString v="0.9.0";
53             if (! versionLowerOrEqual( atts.value("version"),v ) )
54                 QMessageBox::warning( 0, "Warning: Version Problem" ,
55                    "<h3>Freemind map is newer than version " +v +" </h3>"
56                    "<p>The map you are just trying to load was "
57                    "saved using freemind " +atts.value("version")+". "
58                    "Your version of vym can parse freemind " + v +"."); 
59         }
60         // Create mapcenter
61         model->clear();
62         mapCenter=model->createMapCenter();
63         lastBranch=mapCenter;
64
65         // Create two hidden branches, because Freemind has no relative 
66         // positioning for mainbranches
67         mainBranchLeft  = model->createBranch (lastBranch);
68         mainBranchRight = model->createBranch (lastBranch);
69
70         mainBranchLeft->setRelPos ( QPointF(-200,0));
71     mainBranchLeft->setHeadingPlainText ("  ");
72         mainBranchRight->setRelPos ( QPointF(200,0));
73     mainBranchRight->setHeadingPlainText ("  ");
74     } else if ( eName == "attribute_registry" &&  state == StateMap ) 
75     {
76         state = StateAttributeRegistry;
77     } else if ( eName == "attribute_name" &&  state == StateAttributeRegistry) 
78     {
79         state = StateAttributeName;
80     } else if ( eName == "attribute_value" &&  state == StateAttributeName) 
81     {
82         state = StateAttributeValue;
83     } else if ( eName == "node" &&  state == StateMap ) 
84     {
85         state=StateNode;
86         readNodeAttr (atts);
87     } else if ( eName == "node" &&  state == StateNode ) 
88     {
89         lastBranch=model->createBranch(lastBranch);
90         state=StateNode;
91         readNodeAttr (atts);
92     } else if ( eName == "properties" )
93     {
94     } else if ( eName == "map_styles" )
95     {
96     } else if ( eName == "font" && state == StateNode) //FIXME-3 not implemented
97     {
98         state=StateFont;
99     } else if ( eName == "edge" && state == StateNode) //FIXME-3 xlink not implemented
100     {
101         state=StateEdge;
102     } else if ( eName == "hook" && state == StateNode) 
103     {
104         state=StateHook;
105     } else if ( eName == "icon" && state == StateNode) 
106     {
107         state=StateIcon;
108         if (!atts.value("BUILTIN").isEmpty() )
109         {
110             QString f=atts.value("BUILTIN");
111             QString v;
112             if (f=="help")
113                 v="questionmark";
114             else if (f=="messagebox_warning")
115                 v="freemind-warning"; 
116             else if (f=="idea")
117                 v="lamp"; 
118             else if (f=="button_ok")
119                 v="hook-green"; 
120             else if (f=="button_cancel")
121                 v="cross-red"; 
122             else if (f.contains("full-"))
123                 v=f.replace("full-","freemind-priority-"); 
124             else if (f=="back")
125                 v="freemind-back"; 
126             else if (f=="forward")
127                 v="freemind-forward"; 
128             else if (f=="attach")
129                 v="freemind-attach"; 
130             else if (f=="ksmiletris")
131                 v="smiley-good"; // 
132             else if (f=="clanbomber")
133                 v="freemind-clanbomber"; 
134             else if (f=="desktop_new")
135                 v="freemind-desktopnew"; 
136             else if (f=="flag")
137                 v="freemind-flag"; 
138             else if (f=="gohome")
139                 v="freemind-gohome"; 
140             else if (f=="kaddressbook")
141                 v="freemind-kaddressbook"; 
142             else if (f=="knotify")
143                 v="freemind-knotify"; 
144             else if (f=="korn")
145                 v="freemind-korn";
146             else if (f=="Mail")
147                 v="freemind-mail"; 
148             else if (f=="password")
149                 v="freemind-password"; 
150             else if (f=="pencil")
151                 v="freemind-pencil";
152             else if (f=="stop")
153                 v="freemind-stop"; 
154             else if (f=="wizard")
155                 v="freemind-wizard";
156             else if (f=="xmag")
157                 v="freemind-xmag";
158             else if (f=="bell")
159                 v="freemind-bell";
160             else if (f=="bookmark")
161                 v="freemind-bookmark"; 
162             else if (f=="penguin")
163                 v="freemind-penguin"; 
164             else if (f=="licq")
165                 v="freemind-licq"; 
166             else 
167                 qWarning()<<"parseFreemindHandler: Unknown icon found: "<<f;
168
169             lastBranch->activateStandardFlag (v);
170         }
171     } else if ( eName == "arrowlink" && state == StateNode) 
172     {
173         state=StateArrowLink;
174     } else if ( eName == "cloud" && state == StateNode) 
175     {
176         state=StateCloud;
177     } else if ( eName == "richcontent" && state == StateNode) 
178     {
179         state=StateRichContent;
180         return readRichContentAttr (atts);
181     } else if ( eName == "html" && state == StateRichContent) 
182     {
183         state=StateHtml;
184         htmldata="<"+eName;
185         readHtmlAttr(atts);
186         htmldata+=">";
187     } else if ( eName == "text" && state == StateHook) 
188     {
189         state=StateText;
190     } else if ( state == StateHtml ) 
191     {
192         // accept all while in html mode,
193         htmldata+="<"+eName;
194         readHtmlAttr(atts);
195         htmldata+=">";
196     } else 
197     {
198         // Usually we would return an error here
199         // In order to not break with every new element in FreeMind or FreePlane,
200         // better ignore the new element for now
201         state=StateUnknown;
202         qWarning()<<"parseFreemindHandler: Unknown element found and ignoring:: "<<eName;
203     }
204     return true;
205 }
206
207 bool parseFreemindHandler::endElement  ( const QString &, const QString&, const QString &eName)
208 {
209     /* Testing
210     qDebug() << "endElement </" <<qPrintable(eName)
211         <<">  state=" <<state 
212         <<"  stateStack="<<stateStack.last() 
213         ;
214     */
215     switch ( state ) 
216     {
217         case StateMap:
218             // Freemind does not have the two "extra" mainbranches used here,
219             // so we have to update mapcenter
220             model->emitDataChanged (mapCenter);
221
222             // Remove helper branches, if not needed
223             if (mainBranchLeft->childCount()==0) model->deleteItem (mainBranchLeft);
224             if (mainBranchRight->childCount()==0) model->deleteItem (mainBranchRight);
225             break;
226         case StateNode: 
227             model->emitDataChanged (lastBranch);
228             lastBranch=(BranchItem*)lastBranch->parent();
229             lastBranch->setLastSelectedBranch (0);  
230             break;
231         case StateRichContent:
232             if (!htmldata.isEmpty()) 
233             {
234                 if (htmlPurpose==Node)
235             lastBranch->setHeadingPlainText (htmldata);  // FIXME-3 probably wrong for RT heading
236                 else if (htmlPurpose==Note)
237                     lastBranch->setNote (htmldata);
238             }   
239             break;
240         case StateHtml: 
241             htmldata+="</"+eName+">";
242             if (eName=="html")
243             {
244                 //state=StateHtmlNote;  
245                 htmldata.replace ("<br></br>","<br />");
246             }   
247             break;
248         default: 
249             break;
250     }  
251     state=stateStack.takeLast();    
252     return true;
253 }
254
255 bool parseFreemindHandler::characters   ( const QString& ch)
256 {
257     //qDebug() << "characters \""<<qPrintable(ch)<<"\"  state="<<state;
258
259     QString ch_org=quotemeta (ch);
260     QString ch_simplified=ch.simplified();
261     if ( ch_simplified.isEmpty() ) return true;
262
263     switch ( state ) 
264     {
265         case StateInit: break;
266         case StateMap: break; 
267         case StateNode: break; 
268         case StateCloud: break; 
269         case StateEdge: break; 
270         case StateIcon: break; 
271         case StateArrowLink: break; 
272         case StateFont: break; 
273         case StateHook: break; 
274         case StateText: 
275             lastBranch->setNote (ch_simplified);
276             break; 
277         case StateHtml:
278             htmldata+=ch_org;
279             break;
280         default: 
281             return false;
282     }
283     return true;
284 }
285
286 QString parseFreemindHandler::errorString() 
287 {
288     return "the document is not in the Freemind file format";
289 }
290
291 bool parseFreemindHandler::readNodeAttr (const QXmlAttributes& a)  
292 {
293     // Freemind has a different concept for mainbranches
294     if (!a.value( "POSITION").isEmpty() )
295     {
296         if (a.value ("POSITION")=="left")
297             model->relinkBranch (lastBranch, mainBranchLeft);
298         else if (a.value ("POSITION")=="right")
299             model->relinkBranch (lastBranch, mainBranchRight);
300     } 
301
302     if (a.value( "FOLDED")=="true" )
303         lastBranch->toggleScroll();
304
305     if (!a.value( "TEXT").isEmpty() )
306     {
307     lastBranch->setHeadingPlainText (a.value ("TEXT"));  // FIXME-3 what about RT?
308         //model->setHeading (a.value ("TEXT"), lastBranch);
309     }
310
311     if (!a.value( "COLOR").isEmpty() )
312         lastBranch->setHeadingColor (QColor (a.value ("COLOR")));
313
314     if (!a.value( "LINK").isEmpty() )   
315         lastBranch->setURL (a.value ("LINK"));
316     return true;    
317 }
318
319
320 bool parseFreemindHandler::readRichContentAttr (const QXmlAttributes& a)  
321 {
322     if (a.value ("TYPE")=="NODE" )
323         htmlPurpose=Node;
324     else if (a.value ("TYPE")=="NOTE" )
325         htmlPurpose=Note;
326     else
327     {
328         htmlPurpose=Unknown;
329         qWarning()<<"parseFreemindHandler: Unknown purpose of richContent found: "<<a.value("TYPE");;
330         // FIXME-3 Usually we would stop here, ignore for now
331         //return false;
332     }   
333     return true;
334 }
335