#include "xml-freeplane.h"
#define qdbg() qDebug().nospace().noquote()
#include "branchitem.h"
#include "vymmodel.h"
FreeplaneReader::FreeplaneReader(VymModel* m)
: BaseReader(m)
{
qDebug() << "Constr. FreeplaneReader";
mainBranchRight = nullptr;
mainBranchLeft = nullptr;
}
void FreeplaneReader::foundElement(const QString &e)
{
// remember we found this element
if (!foundElements.contains(e))
foundElements << e;
Q_ASSERT(xml.isStartElement() && xml.name() == e);
// remember its attributes
QStringList sl = elementAttributes[e];
for (int i = 0; i < xml.attributes().count(); i++) {
QString n = xml.attributes()[i].name().toString();
if (!sl.contains(n))
sl << n;
}
qdbg() << "regElement=" << e << " sl=" << sl.join(",");
elementAttributes[e] = sl;
}
QString FreeplaneReader::attrString()
{
QStringList sl;
for (int i = 0; i < xml.attributes().count(); i++) {
sl << xml.attributes()[i].name().toString();
}
return sl.join(",");
}
void FreeplaneReader::readToEnd()
{
QString endName = xml.name().toString();
while (!xml.isEndElement() || xml.name() != endName) {
xml.readNext();
if (xml.isStartElement() && !ignoredElements.contains(xml.name()))
ignoredElements << xml.name().toString();
}
}
bool FreeplaneReader::read(QIODevice *device)
{
Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("map"));
xml.setDevice(device);
if (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("map")) {
readMap();
} else {
xml.raiseError("No vymmap or heading as next element.");
}
}
// Report what we have found so far
qdbg() << "Found elements: " << foundElements.join(",");
foreach (QString e, foundElements) {
qdbg() << " Attributes of " << e << " " << elementAttributes[e];
}
qdbg() << "Ignored elements from readToEnd(): " << ignoredElements.join(",");
// FIXME-5 FreeplaneReader implementation uncomplete: ICON, NOTE, ...
return !xml.error();
}
void FreeplaneReader::readArrowLink()
{
QString elementName = "arrowlink";
foundElement(elementName);
readToEnd();
}
void FreeplaneReader::readAttribute()
{
QString elementName = "attribute";
foundElement(elementName);
Q_ASSERT(xml.isStartElement() && xml.name() == elementName);
readToEnd();
}
void FreeplaneReader::readCloud()
{
QString elementName = "cloud";
foundElement(elementName);
readToEnd();
}
void FreeplaneReader::readEdge()
{
QString elementName = "edge";
foundElement(elementName);
readToEnd();
}
void FreeplaneReader::readFont()
{
QString elementName = "font";
foundElement(elementName);
readToEnd();
}
void FreeplaneReader::readIcon()
{
QString elementName = "icon";
foundElement(elementName);
QString a = "BUILTIN";
QString s = xml.attributes().value(a).toString();
if (!s.isEmpty())
qDebug() << "FR:: Found builtin icon=" << s;
if (xml.tokenType() == QXmlStreamReader::StartElement)
qdbg() << "name: " << xml.name() << " " << xml.tokenString();
xml.readNext();
qdbg() << "name: " << xml.name() << " " << xml.tokenString();
}
void FreeplaneReader::readHook()
{
QString elementName = "hook";
foundElement(elementName);
QString a = "NAME";
QString s = xml.attributes().value(a).toString();
if(s == "MapStyle") {
a = "background";
s = xml.attributes().value(a).toString();
if (!s.isEmpty()) {
QColor col(s);
model->setBackgroundColor(col);
qdbg() << "FR::setBackground col = " << s;
}
}
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("properties")){
readProperties();
} else if (xml.name() == QLatin1String("map_styles")){
readMapStyles();
} else if (xml.name() == QLatin1String("Parameters")){
qdbg () << "FR::readHook ignoring <Parameters> element...";
readToEnd();
} else {
raiseUnknownElementError();
return;
}
}
}
void FreeplaneReader::readMap()
{
QString elementName = "map";
foundElement(elementName);
// Check version// FIXME-5 How to deal with Freeplane versions???
QString a = "version";
QString s = xml.attributes().value(a).toString();
if (s.isEmpty()) {
xml.raiseError("No version found for Freeplane map.");
return;
} else {
qDebug() << "FR: found version " << s;
}
// Start with clean map
model->clear();
lastBranch = model->getRootItem();
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("node")){
readNode();
} else {
raiseUnknownElementError();
return;
}
}
}
void FreeplaneReader::readMapStyles()
{
QString elementName = "map_styles";
foundElement(elementName);
qdbg() << QString("FP <%1> attributes: %2").arg(elementName).arg(attrString());
readToEnd();
}
void FreeplaneReader::readNode()
{
QString elementName = "node";
foundElement(elementName);
lastBranch = model->createBranchWhileLoading(lastBranch);
if (lastBranch->depth() == 0) {
// I am a mapcenter:
// Create two "helper" branches, because Freeplane seems to haves no
// relative positioning for mainbranches
mainBranchLeft = model->createBranchWhileLoading(lastBranch);
mainBranchRight = model->createBranchWhileLoading(lastBranch);
mainBranchLeft->setPos(QPointF(-200, 0));
mainBranchLeft->setHeadingPlainText(" ");
mainBranchRight->setPos(QPointF(200, 0));
mainBranchRight->setHeadingPlainText(" ");
}
htmldata.clear();
VymText heading;
QString a = "TEXT";
QString s = xml.attributes().value(a).toString();
if (!s.isEmpty())
heading.setPlainText(s);
a = "POSITION";
s = xml.attributes().value(a).toString();
if (lastBranch->depth() == 1 && !s.isEmpty()) {
// Freeplane has a different concept for mainbranches
// Move either to left or right side of mapcenter
if (s == "left")
model->relinkBranch(lastBranch, mainBranchLeft);
else if (s == "right")
model->relinkBranch(lastBranch, mainBranchRight);
}
a = "FOLDED";
s = xml.attributes().value(a).toString();
if (s == "true")
lastBranch->toggleScroll();
a = "COLOR";
s = xml.attributes().value(a).toString();
if (!s.isEmpty())
lastBranch->setHeadingColor(QColor(s));
a = "LINK";
s = xml.attributes().value(a).toString();
if (!s.isEmpty())
lastBranch->setUrl(s);
while (xml.readNextStartElement()) {
qdbg() << "FP::readNode startElement=" << xml.name();
if (xml.name() == QLatin1String("icon"))
readIcon();
else if (xml.name() == QLatin1String("arrowlink"))
readArrowLink();
else if (xml.name() == QLatin1String("attribute"))
readAttribute();
else if (xml.name() == QLatin1String("cloud"))
readCloud();
else if (xml.name() == QLatin1String("edge"))
readEdge();
else if (xml.name() == QLatin1String("font"))
readFont();
else if (xml.name() == QLatin1String("hook"))
readHook();
else if (xml.name() == QLatin1String("richcontent"))
readRichContent();
else if (xml.name() == QLatin1String("node")) {
readNode();
} else {
raiseUnknownElementError();
return;
}
}
if (!htmldata.isEmpty()) {
heading.setRichText(htmldata);
// qdbg() << "htmldata in node: '" <<htmldata << "'";
}
lastBranch->setHeading(heading);
lastBranch->updateVisuals();
if(lastBranch->depth() == 2) {
// Hop over helper "mainBranches" back to mapCenter
lastBranch = lastBranch->parentBranch()->parentBranch();
} else
lastBranch = lastBranch->parentBranch();
}
void FreeplaneReader::readProperties()
{
// Seems to be sub element of <hook NAME="MAPSTYLE" ...>
QString elementName = "properties";
foundElement(elementName);
QString a = "backgroundImageURI";
QString s = xml.attributes().value(a).toString();
if (!s.isEmpty()) {
model->loadBackgroundImage(s);
}
readToEnd();
}
void FreeplaneReader::readRichContent()
{
QString elementName = "richcontent";
foundElement(elementName);
while (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("html"))
readHtml();
else {
raiseUnknownElementError();
return;
}
}
//readToEnd();
}