Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/SymbologyXML/symbol_writer.cpp
T
2026-08-13 18:33:10 +02:00

317 lines
11 KiB
C++
Executable File

/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
*/
#include "symbol_writer.h"
#include "primitive.h"
#include "attribute_data.h"
#include <QFile>
#include <QXmlStreamWriter>
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace SymbologyXML
{
SymbolWriter::SymbolWriter()
: logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("AdvSymbologyXML.SymbolWriter"))
{
DEBUG_LOG(logger) << LOGFUNCTION ;
DEBUG_LOG(logger) << "END " << LOGFUNCTION ;
} // SymbolWriter::SymbolWriter()
bool SymbolWriter::toFile(const Symbol &symbol, QFile *file, t_attFilterPrimitive attributeFilter) const
{
DEBUG_LOG(logger) << LOGFUNCTION ;
if (!file->isOpen() && !file->open(QIODevice::WriteOnly))
{
DEBUG_LOG(logger) << "END " << LOGFUNCTION ;
return false;
}
file->write(toString(symbol, attributeFilter));
file->close();
DEBUG_LOG(logger) << "END " << LOGFUNCTION ;
return true;
} // bool SymbolWriter::toFile(const Symbol& symbol, QFile* file, t_attFilterPrimitive attributeFilter)
QByteArray SymbolWriter::toString(const Symbol& symbol, t_attFilterPrimitive attributeFilter) const
{
DEBUG_LOG(logger) << LOGFUNCTION ;
QByteArray xml;
QXmlStreamWriter sw(&xml);
sw.setAutoFormatting(true);
sw.setAutoFormattingIndent(2);
sw.setCodec("UTF-8");
sw.writeStartDocument(QStringLiteral("1.0"), true);
sw.writeDTD(QStringLiteral("<!DOCTYPE symboltable SYSTEM \"symbole.dtd\">"));
sw.writeStartElement(QStringLiteral("symbol"));
sw.writeAttribute(QStringLiteral("version"), QString::fromLatin1(Symbol::SymbolVersion));
// Tag symbol, attribute id
sw.writeAttribute(QStringLiteral("id"), QString::number(symbol.id()));
// Tag symbol, attribute dimen
sw.writeAttribute(QStringLiteral("dimen"), SymbolTypes::instance()->getDimen()->convert_enum2str(symbol.getDimen()));
// Tag symbol, attribute affil
sw.writeAttribute(QStringLiteral("affil"), SymbolTypes::instance()->getAffil()->convert_enum2str(symbol.getAffil()));
// Tag symbol, attribute transformed
sw.writeAttribute(QStringLiteral("transformed"), symbol.transformed() ? QStringLiteral("1") : QStringLiteral("0"));
// Tag symbol, attribute bcdab
sw.writeAttribute(QStringLiteral("bcdab"), SymbolTypes::instance()->getBcdab()->convert_enum2str(symbol.getBcdab()));
// Tag symbol, attribute command_level
sw.writeAttribute(QStringLiteral("command_level"), SymbolTypes::instance()->getCommandLevel()->convert_enum2str(symbol.getCommandLevel()));
// Tag symbol, attribute headquarter
sw.writeAttribute(QStringLiteral("headquarter"), symbol.getHeadquarter() ? QStringLiteral("true") : QStringLiteral("false"));
// Tag symbol, attribute mob
sw.writeAttribute(QStringLiteral("mob"), SymbolTypes::instance()->getMob()->convert_enum2str(symbol.getMob()));
// Tag symbol, attribute vehicle
sw.writeAttribute(QStringLiteral("vehicle"), SymbolTypes::instance()->getVehicle()->convert_enum2str(symbol.getVehicle()));
// Tag symbol, attribute intrinsicmob
sw.writeAttribute(QStringLiteral("intrinsicmob"), SymbolTypes::instance()->getIntrinsicMob()->convert_enum2str(symbol.getIntrinsicMob()));
// Tag symbol, attribute arming
sw.writeAttribute(QStringLiteral("arming"), SymbolTypes::instance()->getArming()->convert_enum2str(symbol.getArming()));
// Tag name
sw.writeTextElement(QStringLiteral("name"), symbol.getName());
// Tag APP6 class
{
sw.writeStartElement(QStringLiteral("app6class"));
sw.writeAttribute(QStringLiteral("classname"), symbol.getClassName());
sw.writeAttribute(QStringLiteral("classhierarchy"), symbol.getClassHierarchy());
sw.writeAttribute(QStringLiteral("classcodeid"), symbol.getClassCodeId());
sw.writeEndElement();
}
// Tag(s) misc with attribute class
{
NGL::BitSet<qint64> misc = symbol.getMiscTags();
QVectorIterator<SymbolTypes::t_misc> it = SymbolTypes::instance()->getMisc()->getIterator();
SymbolTypes::t_misc val;
while (it.hasNext())
{
val = it.next();
if (misc[val])
{
sw.writeStartElement(QStringLiteral("misc"));
sw.writeAttribute(QStringLiteral("class"), SymbolTypes::instance()->getMisc()->convert_enum2str(val));
sw.writeEndElement();
}
}
}
{
// Tag(s) branch with attribute class
NGL::BitSet<qint64> branches = symbol.getBranchTags();
QVectorIterator<SymbolTypes::t_branch> it = SymbolTypes::instance()->getBranch()->getIterator();
SymbolTypes::t_branch val;
while (it.hasNext())
{
val = it.next();
if (branches[val])
{
sw.writeStartElement(QStringLiteral("branch"));
sw.writeAttribute(QStringLiteral("class"), SymbolTypes::instance()->getBranch()->convert_enum2str(val));
sw.writeEndElement();
}
}
}
// Tag text with attribute maxdatalength
Symbol::t_text textType = symbol.getTextType();
if (textType != Symbol::TEXT_UNDEFINED)
{
sw.writeStartElement(QStringLiteral("text%1").arg(textType));
sw.writeAttribute(QStringLiteral("maxdatalength"), QString::number(symbol.maxStringLength()));
// Add tag data with attribute align to text
for (int i = Symbol::TEXT1; i <= symbol.getTextType(); ++i)
{
sw.writeStartElement(QStringLiteral("data"));
switch (symbol.getTextAlign(i))
{
case Symbol::LEFT:
sw.writeAttribute(QStringLiteral("align"), QStringLiteral("left"));
break;
case Symbol::ALIGNMENT_UNDEFINED:
case Symbol::CENTER:
sw.writeAttribute(QStringLiteral("align"), QStringLiteral("center"));
break;
case Symbol::RIGHT:
sw.writeAttribute(QStringLiteral("align"), QStringLiteral("right"));
break;
}
sw.writeCharacters(symbol.getText(i));
sw.writeEndElement(); // data
}
sw.writeEndElement(); // text%1
}
// Tag graphic with attribute scale
{
sw.writeStartElement(QStringLiteral("graphic"));
sw.writeAttribute(QStringLiteral("scale"), QString::number(symbol.getScale()));
QLinkedListIterator<Primitive*> pi(symbol.getPrimitives());
// Add all primitive-tags to graphic
while (pi.hasNext())
primitiveToString(sw, pi.next(), attributeFilter);
sw.writeEndElement();
}
sw.writeEndElement(); // symbol
DEBUG_LOG(logger) << "END " << LOGFUNCTION ;
return xml;
} // QString SymbolWriter::toString(const Symbol& symbol, t_attFilterPrimitive attributeFilter)
static inline QString lineStyle2String(const Primitive *p)
{
switch (p->getLineStyle())
{
case Primitive::DASHED_DOTTED:
return QStringLiteral("dashed_dotted");
case Primitive::DOTTED:
return QStringLiteral("dotted");
case Primitive::DASHED:
return QStringLiteral("dashed");
case Primitive::SOLID:
return QStringLiteral("solid");
}
return QStringLiteral("solid");
}
static inline QString color2Name(const Primitive *p)
{
const QColor pColor = p->getColor();
// why not pColor.name(QColor::HexArgb) ?
return pColor.name() + QString::number(pColor.alpha(), 16);
}
static inline bool isNotFiltered(SymbolWriter::t_attFilterPrimitive attributeFilter,
SymbolWriter::t_attFilterPrimitive attr)
{
return (attributeFilter & attr) == 0;
}
void SymbolWriter::writePrimitiveAttributes(QXmlStreamWriter &sw, const Primitive *p, t_attFilterPrimitive attributeFilter)
{
if (isNotFiltered(attributeFilter, AFP_TRANSFORM))
sw.writeAttribute(QStringLiteral("transform"), p->getTransform() ? QStringLiteral("true") : QStringLiteral("false"));
if (isNotFiltered(attributeFilter, AFP_ROTATE))
sw.writeAttribute(QStringLiteral("rotate"), QString::number(p->getRotation()));
if (isNotFiltered(attributeFilter, AFP_COLOR))
sw.writeAttribute(QStringLiteral("color"), color2Name(p));
if (isNotFiltered(attributeFilter, AFP_LINEWIDTH))
sw.writeAttribute(QStringLiteral("linewidth"), QString::number(p->getLineWidth()));
if (isNotFiltered(attributeFilter, AFP_LINESTYLE))
sw.writeAttribute(QStringLiteral("linestyle"), lineStyle2String(p));
if (p->type() == Primitive::ELLIPSE ||
p->type() == Primitive::POLYGON ||
p->type() == Primitive::RECT)
{
if (isNotFiltered(attributeFilter, AFP_CLOSED))
sw.writeAttribute(QStringLiteral("closed"), QString::number(p->closed()));
if (isNotFiltered(attributeFilter, AFP_FILL))
sw.writeAttribute(QStringLiteral("fill"), QString::number(p->fill()));
}
if (p->type() == Primitive::ELLIPSE)
{
if (isNotFiltered(attributeFilter, AFP_START))
sw.writeAttribute(QStringLiteral("start"), QString::number(p->getStartAngle()));
if (isNotFiltered(attributeFilter, AFP_EXTENT))
sw.writeAttribute(QStringLiteral("extent"), QString::number(p->getExtent()));
}
if (p->type() == Primitive::ICON)
{
sw.writeAttribute(QStringLiteral("id"), QString::number(p->icon()));
sw.writeAttribute(QStringLiteral("icon_type"), SymbolTypes::instance()->getIconType()->convert_enum2str(p->iconType()));
sw.writeAttribute(QStringLiteral("position"), SymbolTypes::instance()->getSectorPosition()->convert_enum2str(p->position()));
if((p->rectpos() != SymbolTypes::SECTOR_RECTPOS_UNDEFINED) &&
(p->rectpos() != SymbolTypes::SECTOR_RECTPOS_DEFAULT))
sw.writeAttribute(QStringLiteral("rectpos"), SymbolTypes::instance()->getSectorRectpos()->convert_enum2str(p->rectpos()));
if (p->scalemode() == Primitive::Scalemode_Unproport)
sw.writeAttribute(QStringLiteral("scalemode"), Primitive::scalemode(p->scalemode()));
}
if (p->type() == Primitive::TEXT)
{
// split p->text() in two strings:
const auto strL = p->text().split(QLatin1Char('\n'));
if (strL.size() > 0)
sw.writeAttribute(QStringLiteral("sval1"), strL.at(0));
if (strL.size() > 1)
sw.writeAttribute(QStringLiteral("sval2"), strL.at(1));
}
}
void SymbolWriter::primitiveToString(QXmlStreamWriter &sw, const Primitive *p, t_attFilterPrimitive attributeFilter)
{
// Fill in data from primitive into templates
switch (p->type())
{
case Primitive::LINE:
sw.writeStartElement(QStringLiteral("line"));
break;
case Primitive::ELLIPSE:
sw.writeStartElement(QStringLiteral("ellipse"));
break;
case Primitive::POLYGON:
sw.writeStartElement(QStringLiteral("polygon"));
break;
case Primitive::RECT:
sw.writeStartElement(QStringLiteral("rect"));
break;
case Primitive::ICON:
sw.writeStartElement(QStringLiteral("icon"));
break;
case Primitive::TEXT:
sw.writeStartElement(QStringLiteral("text"));
break;
default:
Q_ASSERT(false);
return;
}
writePrimitiveAttributes(sw, p, attributeFilter);
// Create point-tags and insert into primitive-tag
const QPolygonF pointList = p->getPoints();
// specials for Primitive::ICON
bool ignorePoints = false;
if (p->type() == Primitive::ICON && pointList.size() == 2)
{
const QRectF rect = QRectF(pointList.at(0), pointList.at(1));
if (rect == SymbolTypes::getDefaultRect(p->position(), p->rectpos()))
ignorePoints = true;
}
if (!ignorePoints)
{
for (const QPointF &pLocal : pointList)
{
sw.writeStartElement(QStringLiteral("point"));
sw.writeAttribute(QStringLiteral("x"), QString::number(pLocal.x()));
sw.writeAttribute(QStringLiteral("y"), QString::number(pLocal.y()));
sw.writeEndElement();
}
}
sw.writeEndElement();
} // QString SymbolWriter::primitiveToString (Primitive* p, t_attFilterPrimitive attributeFilter)
} // namespace SymbologyXML