2712 lines
108 KiB
C++
Executable File
2712 lines
108 KiB
C++
Executable File
/**
|
||
**
|
||
** @RDE_HEADER@
|
||
** GeometryModel implementation to write and read PlanEditor plans from/to XML and manipulate DOM-tree.
|
||
** $Id$
|
||
** $HeadURL$
|
||
** $Author$
|
||
**
|
||
** -----------------------------------------------------------------------------------------------
|
||
**
|
||
** Hardware-Environment: Intel-PC
|
||
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
||
**
|
||
** Language ........: C++ 11
|
||
**
|
||
** -----------------------------------------------------------------------------------------------
|
||
**
|
||
** Author ...........: Stephan Kuhagen <kuhagen@rheinmetall-de.com>
|
||
** Jörg Turla, SPD G, Tel. 3132
|
||
**
|
||
** -----------------------------------------------------------------------------------------------
|
||
**
|
||
** Notes .........:
|
||
**
|
||
** ??.??.200?, SK : First edition for use with Qt4
|
||
** 11.11.2015, JT : Splitting interface and implementation
|
||
**
|
||
** -----------------------------------------------------------------------------------------------
|
||
*/
|
||
|
||
#include "geometry_model_q_dom.h"
|
||
|
||
#include <Common/id_handler.h>
|
||
|
||
#include <QtGui/QFont>
|
||
#include <QtGui/QFontMetrics>
|
||
#include <QtGui/QTransform>
|
||
|
||
#include <QtXml/QDomNode>
|
||
#include <QtXml/QDomElement>
|
||
|
||
#include <QCoreApplication>
|
||
#include <QDebug>
|
||
|
||
#include <limits.h>
|
||
#include <assert.h>
|
||
|
||
|
||
template<class _Ty, class _Other = _Ty> inline _Ty doExchange(_Ty &_Val, _Other && _New_val)
|
||
{
|
||
// assign _New_val to _Val, return previous _Val
|
||
_Ty _Old_val = std::move(_Val);
|
||
_Val = std::forward<_Other>(_New_val);
|
||
return (_Old_val);
|
||
}
|
||
|
||
namespace SituationMap
|
||
{
|
||
|
||
const int CoordinateDoublePrecision = 20;
|
||
|
||
bool GeometryModelQDom::_staticInitDone = false;
|
||
|
||
QMultiMap< GeometryModel::PrimitiveType , GeometryModel::Attribute > GeometryModelQDom::_primitiveSupportedAttributes;
|
||
QMap < QString , GeometryModel::PrimitiveType> GeometryModelQDom::_primitiveTagsTypes;
|
||
QMap < GeometryModel::PrimitiveType , QString > GeometryModelQDom::_primitiveTagsStrings;
|
||
QMap < QPair<GeometryModel::PrimitiveType, GeometryModel::Attribute>, QString > GeometryModelQDom::_attributeDefaults;
|
||
QMap < GeometryModel::Attribute , QVariant::Type > GeometryModelQDom::_attributeTypes;
|
||
|
||
|
||
static const QLatin1String mapSettingsName("MapSettings");
|
||
static const QLatin1String rootNodeName("GeometryModel");
|
||
static const QLatin1String connectionIdName("connectionId");
|
||
static const QLatin1String userDataName("userData");
|
||
|
||
|
||
// convert to QString (with non locale-aware conversions)
|
||
QString GeometryModelQDom::variant2XmlString(const QVariant &v)
|
||
{
|
||
switch (v.type())
|
||
{
|
||
case QVariant::Int : return QString::fromLatin1(QByteArray::number(v.toInt())); break;
|
||
case QVariant::UInt : return QString::fromLatin1(QByteArray::number(v.toUInt())); break;
|
||
case QVariant::LongLong : return QString::fromLatin1(QByteArray::number(v.toLongLong())); break;
|
||
case QVariant::ULongLong : return QString::fromLatin1(QByteArray::number(v.toULongLong())); break;
|
||
case QVariant::Double : return QString::fromLatin1(QByteArray::number(v.toDouble(), 'f', -1)); break;
|
||
case QVariant::PointF :
|
||
{
|
||
const QPointF &point = v.toPointF();
|
||
return QString::number(point.x(), 'f', CoordinateDoublePrecision) + QLatin1Char(' ') + QString::number(point.y(), 'f', CoordinateDoublePrecision);
|
||
} break;
|
||
|
||
case QVariant::Color :
|
||
{
|
||
const QColor &color = v.value<QColor>();
|
||
|
||
return QStringLiteral("#%1%2%3%4")
|
||
.arg(color.red() , 2, 16, QLatin1Char('0'))
|
||
.arg(color.green(), 2, 16, QLatin1Char('0'))
|
||
.arg(color.blue() , 2, 16, QLatin1Char('0'))
|
||
.arg(color.alpha(), 2, 16, QLatin1Char('0'));
|
||
} break;
|
||
|
||
default: break;
|
||
}
|
||
|
||
return v.toString();
|
||
} // QString GeometryModelQDom::variant2XmlString( const QVariant & v )
|
||
|
||
|
||
|
||
QColor GeometryModelQDom::colorFromString(const QString &attColor)
|
||
{
|
||
QColor result = Qt::black; // in case of wrong attColor the default is black.
|
||
|
||
if (attColor.startsWith(QLatin1Char('#')) && attColor.length() == 9)
|
||
{
|
||
result.setNamedColor(attColor.left(7));
|
||
// Get Alpha-Channel
|
||
bool ok;
|
||
int alpha = attColor.rightRef(2).toInt(&ok, 16);
|
||
if (ok) result.setAlpha(alpha);
|
||
}
|
||
else result.setNamedColor(attColor);
|
||
|
||
return result;
|
||
} // QColor GeometryModelQDom::colorFromString( const QString & attColor )
|
||
|
||
|
||
void GeometryModelQDom::valueFromVariant(const QVariant &v, QPointF &result) { result = GeometryModelQDom::pointFromString(v.toString()); }
|
||
void GeometryModelQDom::valueFromVariant(const QVariant &v, QColor &result) { result = GeometryModelQDom::colorFromString(v.toString()); }
|
||
|
||
|
||
QPointF GeometryModelQDom::pointFromString(const QString &attPoint)
|
||
{
|
||
QPointF result;
|
||
const auto xyStrList = attPoint.splitRef(QLatin1Char(' '));
|
||
|
||
if (xyStrList.size() == 2)
|
||
{
|
||
bool okX = false;
|
||
bool okY = false;
|
||
|
||
const double &x = xyStrList[0].toDouble(&okX);
|
||
const double &y = xyStrList[1].toDouble(&okY);
|
||
|
||
if (okX && okY)
|
||
{
|
||
result.setX(x);
|
||
result.setY(y);
|
||
}
|
||
}
|
||
return result;
|
||
} // QPointF GeometryModelQDom::pointFromString( const QString & attPoint )
|
||
|
||
|
||
#ifdef _WINDOWS
|
||
#pragma warning ( disable : 4172 )
|
||
#endif
|
||
|
||
class GeometryModel::Node::Implementation
|
||
{
|
||
mutable QDomNode _domNode;
|
||
|
||
static SituationMap::IdHandler *_idHandler;
|
||
|
||
static SituationMap::IdHandler &idHandler()
|
||
{
|
||
if (!_idHandler)
|
||
_idHandler = new SituationMap::IdHandler();
|
||
return *_idHandler;
|
||
} // idHandler()
|
||
|
||
|
||
public:
|
||
|
||
Implementation() : _domNode() {;}
|
||
|
||
Implementation(const QDomNode &domNode) : _domNode(domNode)
|
||
{
|
||
// The QDomNode is simply a smart pointer to internal QDom objects. For this the
|
||
// QDomNode handles the derived classes itself, so we don't habe to distinguish
|
||
// the different QDomNode classes, like QDomElement, QDomAttr ... Just use the copy
|
||
// ctor of QDomNode.
|
||
} // Implementation(const QDomNode & domNode)
|
||
|
||
Implementation(const QDomElement &domElement) : _domNode(domElement) {;}
|
||
|
||
Implementation(const Implementation &other) : Implementation(other._domNode) {;}
|
||
|
||
~Implementation() = default;
|
||
|
||
Implementation &operator = (const QDomNode &domNode)
|
||
{
|
||
_domNode = domNode;
|
||
return *this;
|
||
} // operator =
|
||
|
||
Implementation &operator = (const Implementation &other)
|
||
{
|
||
if (this != &other) _domNode = other._domNode;
|
||
return *this;
|
||
} // operator =
|
||
|
||
|
||
QDomNode *operator ->() const { return &_domNode; }
|
||
|
||
const QDomNode &node() const { return _domNode; }
|
||
QDomNode &node() { return _domNode; }
|
||
|
||
bool isValid() const { return !_domNode.isNull(); }
|
||
bool isRootNode() const { return (_domNode.nodeName() == rootNodeName); }
|
||
bool hasChildNodes() const { return _domNode.hasChildNodes(); }
|
||
|
||
Node parentNode() const { return Node(Implementation(_domNode.parentNode())); }
|
||
Node next() const { return Node(Implementation(_domNode.nextSiblingElement())); }
|
||
Node firstChildNode() const { return Node(Implementation(_domNode.firstChildElement())); }
|
||
Node firstChildNode(const QString &nodeName) const { return Node(Implementation(_domNode.firstChildElement(nodeName))); }
|
||
|
||
bool operator == (const Implementation &other) const { return (_domNode == other._domNode); }
|
||
bool operator != (const Implementation &other) const { return (_domNode != other._domNode); }
|
||
|
||
|
||
Referenced *connected() const
|
||
{
|
||
uint id = connectedId();
|
||
if (id != SituationMap::IdHandler::BadId)
|
||
return static_cast<Referenced *>(idHandler().accessId(id));
|
||
return nullptr;
|
||
} // connected() const
|
||
|
||
|
||
uint connectedId() const
|
||
{
|
||
if (isValid())
|
||
{
|
||
QDomElement e = _domNode.toElement();
|
||
if (e.hasAttribute(connectionIdName))
|
||
{
|
||
QString value = e.attribute(connectionIdName);
|
||
bool ok = false;
|
||
uint id = value.toUInt(&ok, 10);
|
||
|
||
if ((ok) && (idHandler().isIdInUse(id)))
|
||
return id;
|
||
e.removeAttribute(connectionIdName);
|
||
}
|
||
}
|
||
return SituationMap::IdHandler::BadId;
|
||
} // connectedId() const
|
||
|
||
|
||
uint makeConnection(Referenced *objPtr)
|
||
{
|
||
if (objPtr != nullptr)
|
||
{
|
||
uint id = idHandler().createId(static_cast<IdHandler::AccessableId*>(objPtr));
|
||
if (id != SituationMap::IdHandler::BadId)
|
||
{
|
||
QDomElement e = _domNode.toElement();
|
||
e.setAttribute(connectionIdName, id);
|
||
return id;
|
||
}
|
||
}
|
||
return SituationMap::IdHandler::BadId;
|
||
} // makeConnection(SituationMap::IdHandler::AccessableId * objPtr)
|
||
|
||
|
||
bool unlinkConnection() const
|
||
{
|
||
uint id = connectedId();
|
||
if (id != SituationMap::IdHandler::BadId)
|
||
{
|
||
idHandler().freeId(id);
|
||
QDomElement e = _domNode.toElement();
|
||
e.removeAttribute(connectionIdName);
|
||
return true;
|
||
}
|
||
return false;
|
||
} // unlinkConnection()
|
||
|
||
}; // GeometryModel::Node::Implementation
|
||
|
||
|
||
SituationMap::IdHandler *GeometryModel::Node::Implementation::_idHandler = nullptr;
|
||
|
||
|
||
#ifdef _WINDOWS
|
||
#pragma warning ( default : 4172 )
|
||
#endif
|
||
|
||
|
||
GeometryModel::Node::Node() : _d(new Implementation()) {;}
|
||
GeometryModel::Node::Node(const Node &other) : _d(new Implementation(*(other._d))) {;}
|
||
GeometryModel::Node::Node(const Implementation &other) : _d(new Implementation(other)) {;}
|
||
|
||
GeometryModel::Node::~Node() { delete _d; }
|
||
|
||
GeometryModel::Node &GeometryModel::Node::operator= (const Node &other)
|
||
{
|
||
if (this != &other) // self-assignment check
|
||
{
|
||
delete _d;
|
||
_d = new Implementation(*(other._d));
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
GeometryModel::Node &GeometryModel::Node::operator = (Node &&other)
|
||
{
|
||
if (this != &other) // self-assignment check
|
||
{
|
||
delete _d;
|
||
_d = doExchange(other._d, nullptr);
|
||
}
|
||
return *this;
|
||
}
|
||
|
||
|
||
const GeometryModel::Node::Implementation &GeometryModel::Node::get() const { return *_d; }
|
||
GeometryModel::Node::Implementation &GeometryModel::Node::get() { return *_d; }
|
||
bool GeometryModel::Node::isValid() const { return _d->isValid(); }
|
||
bool GeometryModel::Node::isRootNode() const { return _d->isRootNode(); }
|
||
GeometryModel::Node GeometryModel::Node::parentNode() const { return _d->parentNode(); }
|
||
bool GeometryModel::Node::hasChildNodes() const { return _d->hasChildNodes(); }
|
||
GeometryModel::Node GeometryModel::Node::next() const { return _d->next(); }
|
||
GeometryModel::Node GeometryModel::Node::firstChildNode() const { return _d->firstChildNode(); }
|
||
GeometryModel::Node GeometryModel::Node::firstChildNode(const QString &nodeName) const { return _d->firstChildNode(nodeName); }
|
||
bool GeometryModel::Node::operator ==(const Node &other) const { return ((*_d) == (*(other._d))); }
|
||
bool GeometryModel::Node::operator !=(const Node &other) const { return ((*_d) != (*(other._d))); }
|
||
|
||
uint GeometryModel::Node::makeConnection(Referenced *objPtr) const { return _d->makeConnection(objPtr); }
|
||
bool GeometryModel::Node::unlinkConnection() const { return _d->unlinkConnection(); }
|
||
uint GeometryModel::Node::connectedId() const { return _d->connectedId(); }
|
||
Referenced *GeometryModel::Node::connected() const { return _d->connected(); }
|
||
|
||
|
||
GeometryModelQDom::GeometryModelQDom(QObject *parent)
|
||
: GeometryModel(parent)
|
||
, QDomDocument(QLatin1String(rootNodeName) + QLatin1String("Document"))
|
||
, _skipChangedSignal(false)
|
||
, _undoEnabled(true)
|
||
, _maxUndoSteps(100)
|
||
, _undoStack()
|
||
, _undoHistory()
|
||
, _redoStack()
|
||
, _redoHistory()
|
||
, _undoBlock()
|
||
, _undoHistoryBlock()
|
||
, _insideUndoBlock(false)
|
||
, _modificationCounter(0)
|
||
{
|
||
init();
|
||
|
||
// OpenSuse13.2:
|
||
// Don´t really know why, but ModuleTest::checkOverlayHandler2/3 (dealing with GeometryModel)
|
||
// lead to SegFault at end of program, if 'cleanupStaticMember' is not added:
|
||
qAddPostRoutine(&GeometryModelQDom::cleanupStaticMember);
|
||
|
||
} // GeometryModelQDom::GeometryModelQDom(QObject *parent)
|
||
|
||
|
||
GeometryModelQDom::GeometryModelQDom(const GeometryModelQDom &other)
|
||
: GeometryModel(other)
|
||
, QDomDocument(other.cloneNode().toDocument())
|
||
, _skipChangedSignal(false)
|
||
, _undoEnabled(other._undoEnabled)
|
||
, _maxUndoSteps(other._maxUndoSteps)
|
||
, _undoStack()
|
||
, _undoHistory()
|
||
, _redoStack()
|
||
, _redoHistory()
|
||
, _undoBlock()
|
||
, _undoHistoryBlock()
|
||
, _insideUndoBlock(false)
|
||
, _modificationCounter(0)
|
||
{
|
||
} // GeometryModelQDom::GeometryModelQDom(const GeometryModelQDom &other)
|
||
|
||
|
||
GeometryModelQDom::~GeometryModelQDom()
|
||
{
|
||
cleanModel();
|
||
}
|
||
|
||
|
||
|
||
GeometryModelQDom & GeometryModelQDom::operator = (const GeometryModelQDom &other)
|
||
{
|
||
fromByteArray(other.toByteArray());
|
||
_undoEnabled = other._undoEnabled;
|
||
_maxUndoSteps = other._maxUndoSteps;
|
||
return *this;
|
||
} // GeometryModelQDom & GeometryModelQDom::operator = (const GeometryModelQDom &other)
|
||
|
||
|
||
/* ~~~~~~~~~~~~~~~~ create XML representation of GeometryModel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
static void xmlContent( const QDomDocument & domDocument, QByteArray & xmlContent )
|
||
{
|
||
xmlContent = domDocument.toByteArray(3);
|
||
}
|
||
|
||
template<class MemoryClass> MemoryClass xmlContent(GeometryModelQDom localCopy)
|
||
{
|
||
MemoryClass xmlContentMem;
|
||
|
||
// 'clean' just localCopy, not the original
|
||
// cleanModel removes userData; in other words: unlink; remove uniqueMapIds
|
||
localCopy.cleanModel();
|
||
|
||
QDomElement rootNode = localCopy.firstChildElement(rootNodeName);
|
||
|
||
qDebug() << " xmlContent rootNode.isNull " << rootNode.isNull()
|
||
<< ", rootNode.hasChildNodes " << rootNode.hasChildNodes()
|
||
<< ", rootNode.hasAttributes " << rootNode.hasAttributes();
|
||
|
||
// rootNode may have ChildNodes and/or Attribute (like metaData)
|
||
// pay attention also to attributes
|
||
if ((rootNode.isNull()) || !(rootNode.hasChildNodes() || rootNode.hasAttributes()) )
|
||
{
|
||
qDebug() << " empty -> use constant default string";
|
||
// Don't return an empty string because file mamagement service will get an error when loading
|
||
// the empty file content.
|
||
xmlContentMem = MemoryClass::fromStdString(std::string("<!DOCTYPE GeometryModelDocument>\n<GeometryModel>\n</GeometryModel>"));
|
||
}
|
||
else
|
||
xmlContent( localCopy, xmlContentMem );
|
||
|
||
qDebug() << " xmlContentMem " << xmlContentMem;
|
||
return xmlContentMem;
|
||
} // template<class MemoryClass> MemoryClass xmlString(GeometryModelQDom localCopy)
|
||
|
||
|
||
QByteArray GeometryModelQDom::toByteArray() const
|
||
{
|
||
return xmlContent<QByteArray>(*this);
|
||
}
|
||
|
||
//QString GeometryModelQDom::toString() const
|
||
//{
|
||
// return xmlContent<QString>(*this);
|
||
//}
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
|
||
QByteArray GeometryModelQDom::toByteArrayDebug() const { return QDomDocument::toByteArray(3); } // complete XML content for debug purposes
|
||
|
||
|
||
/* ~~~~~~~~~~~~~~~~ restore GeometryModel from XML representation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
template<class ContentClass> bool parseXmlString(ContentClass content, GeometryModelQDom &geoModel)
|
||
{
|
||
qDebug() << " parseXmlString 1";
|
||
geoModel.clearUndoStack();
|
||
geoModel.clearRedoStack();
|
||
geoModel.cleanModel();
|
||
bool ok = geoModel.QDomDocument::setContent(content);
|
||
|
||
qDebug() << " parseXmlString geoModel.cleanModel() " << geoModel.toString();
|
||
|
||
geoModel.blockSignals(true);
|
||
{
|
||
geoModel.cleanModel();
|
||
|
||
qDebug() << " parseXmlString geoModel.cleanModel() " << geoModel.toString();;
|
||
|
||
QDomElement rootNode = geoModel.firstChildElement(rootNodeName);
|
||
if (rootNode.isNull())
|
||
{
|
||
QDomElement root = geoModel.createElement(rootNodeName);
|
||
geoModel.appendChild(root);
|
||
}
|
||
|
||
}
|
||
geoModel.blockSignals(false);
|
||
qDebug() << " parseXmlString ok = " << ok;
|
||
return ok;
|
||
} // template<class MemoryClass> bool parseXmlString(MemoryClass memory, GeometryModelQDom &geoModel)
|
||
|
||
|
||
bool GeometryModelQDom::fromByteArray(const QByteArray &content)
|
||
{
|
||
if (content.isEmpty()) // allow empty content
|
||
{
|
||
blockSignals(true);
|
||
clearModel();
|
||
blockSignals(false);
|
||
clearUndoStack();
|
||
clearRedoStack();
|
||
return true;
|
||
}
|
||
return parseXmlString(content,*this);
|
||
} // bool GeometryModelQDom::fromByteArray(const QByteArray &content)
|
||
|
||
|
||
bool GeometryModelQDom::fromDevice(QIODevice *device)
|
||
{
|
||
if (device->size() < 1) // allow empty content
|
||
{
|
||
blockSignals(true);
|
||
clearModel();
|
||
blockSignals(false);
|
||
clearUndoStack();
|
||
clearRedoStack();
|
||
return true;
|
||
}
|
||
return parseXmlString(device,*this);
|
||
} // bool GeometryModelQDom::fromDevice (QIODevice *device)
|
||
|
||
|
||
bool GeometryModelQDom::fromByteArrayDebug(const QByteArray &content)
|
||
{
|
||
clearUndoStack();
|
||
clearRedoStack();
|
||
cleanModel();
|
||
return QDomDocument::setContent(content);
|
||
} // bool GeometryModelQDom::fromStringDebug(const QByteArray &content)
|
||
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||
|
||
|
||
void GeometryModelQDom::setModelAttribute(Attribute attribute, const QVariant &value)
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
qDebug() << "GeometryModelQDom isNull = " << root.isNull();
|
||
|
||
//const bool bEnableUndoRedo = true; //attribute != Attribute::MetaPixelBasedTextBoxes;
|
||
|
||
pushUndo(QLatin1String("setModelAttribute"));
|
||
|
||
if (supportedAttributes(PrimitiveType::RootNode).contains(attribute))
|
||
root.setAttribute(attributeToString(attribute), variant2XmlString(value));
|
||
else
|
||
{
|
||
emit attributeError(tr("Unknown or unsupported attribute for model root node: %1").arg(attributeToString(attribute)));
|
||
popUndo();
|
||
return;
|
||
}
|
||
emitChangedSignal(Node(), attribute, false);
|
||
} // void GeometryModelQDom::setModelAttribute(Attribute attribute, const QVariant &value)
|
||
|
||
|
||
QVariant GeometryModelQDom::getModelAttribute(Attribute attribute) const
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
|
||
if (supportedAttributes(PrimitiveType::RootNode).contains(attribute))
|
||
return getAttribute(root, attribute);
|
||
else
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(tr("Unknown or unsupported attribute for model root node: %1").arg(attributeToString(attribute)));
|
||
return QVariant();
|
||
} // QVariant GeometryModelQDom::getModelAttribute(Attribute attribute) const
|
||
|
||
|
||
void GeometryModelQDom::setModelEditorAttribute(Attribute attribute, const QVariant &value)
|
||
{
|
||
QDomElement root = firstChildElement(mapSettingsName);
|
||
|
||
switch (attribute)
|
||
{
|
||
case Attribute::PeMapBrightness:
|
||
case Attribute::PeMapCenterX:
|
||
case Attribute::PeMapCenterY:
|
||
case Attribute::PeMapSaturation:
|
||
case Attribute::PeMapZoom:
|
||
case Attribute::PeShowUtm:
|
||
case Attribute::PeSymbolOpacity:
|
||
case Attribute::PeSymbolFillType:
|
||
case Attribute::PeSymbolScale:
|
||
case Attribute::PeMapRotation:
|
||
case Attribute::PeMapType:
|
||
root.setAttribute(attributeToString(attribute), variant2XmlString(value));
|
||
break;
|
||
|
||
default:
|
||
emit attributeError(tr("Unknown or unsupported attribute for model-editor: %1").arg(attributeToString(attribute)));
|
||
return;
|
||
}
|
||
emitChangedSignal(Node(), attribute, false);
|
||
} // void GeometryModelQDom::setModelEditorAttribute(Attribute attribute, const QVariant &value)
|
||
|
||
|
||
void GeometryModelQDom::setPrimitiveAttribute(const Node &node, Attribute attribute, const QVariant &value)
|
||
{
|
||
pushUndo(QLatin1String("setPrimitiveAttribute"));
|
||
// Check, if Attribute is supported by Primitive; if so, set it
|
||
if (hasAttribute(node, attribute))
|
||
node.get()->toElement().setAttribute(attributeToString(attribute), variant2XmlString(value));
|
||
else
|
||
{
|
||
emit attributeError(tr("Unknown or unsupported attribute for primitive: %1, Attribute: %2").arg(node.get()->nodeName(), attributeToString(attribute)));
|
||
|
||
popUndo();
|
||
return;
|
||
}
|
||
emitChangedSignal(node, attribute, false);
|
||
} // void GeometryModelQDom::setPrimitiveAttribute(QDomNode node...)
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::addPrimitive( PrimitiveType type
|
||
, const QList<QPointF> &points
|
||
, const QList<QPair<Attribute, QVariant> > &attributes
|
||
, int userData
|
||
, const QString &textData
|
||
, HorizontalAlign textAlign)
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
bool undoEnabledRestore = _undoEnabled;
|
||
pushUndo(QLatin1String("addPrimitive"));
|
||
_undoEnabled = false;
|
||
// Create new node and set required attributes
|
||
|
||
QDomElement primitiveDom;
|
||
|
||
if (_primitiveTagsStrings.contains(type))
|
||
primitiveDom = createElement(_primitiveTagsStrings[type]);
|
||
else
|
||
{
|
||
emit typeError(tr("Unknown Primitive-Type %1").arg(static_cast<int>(type)));
|
||
_undoEnabled = undoEnabledRestore;
|
||
popUndo();
|
||
return Node();
|
||
}
|
||
|
||
Node primitiveNode(primitiveDom);
|
||
|
||
// No changed() inside this block
|
||
_skipChangedSignal = true;
|
||
|
||
if (setPrimitivePoints(Node(primitiveDom), points))
|
||
{
|
||
// Init Primitive with default-Values
|
||
using index = QPair<GeometryModelQDom::PrimitiveType, GeometryModelQDom::Attribute>;
|
||
QList<Attribute> primAttributes = supportedAttributes(type);
|
||
for (int i = 0; i < primAttributes.size(); ++i)
|
||
{
|
||
Attribute ap = primAttributes.at(i);
|
||
setPrimitiveAttribute(primitiveNode, ap, _attributeDefaults[index(type, ap)]);
|
||
}
|
||
|
||
// Set Attributes given as parameter
|
||
for (int i = 0; i < attributes.size(); ++i)
|
||
setPrimitiveAttribute(primitiveNode, (attributes.at(i)).first, (attributes.at(i)).second);
|
||
|
||
// Add textData, if any
|
||
if (! textData.isNull())
|
||
setTextData(primitiveNode, textData, textAlign);
|
||
|
||
// Insert userData as Attribute
|
||
if ((type != PrimitiveType::Node) && (type != PrimitiveType::RootNode))
|
||
{
|
||
if (SituationMap::IdHandler::isIdValid(userData))
|
||
{
|
||
QString userDataStr = QString::number(userData, 10);
|
||
primitiveDom.setAttribute(userDataName, userDataStr);
|
||
}
|
||
}
|
||
|
||
Node result(root.appendChild(primitiveDom));
|
||
_skipChangedSignal = false;
|
||
|
||
emitChangedSignal(result, Attribute::MaxAttributes, true);
|
||
|
||
_undoEnabled = undoEnabledRestore;
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
_undoEnabled = undoEnabledRestore;
|
||
popUndo();
|
||
return Node();
|
||
}
|
||
} // QDomNode GeometryModelQDom::addPrimitive(PrimitiveType type, ...)
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::addText(const Node &parent
|
||
, const QString &textData
|
||
, HorizontalAlign textAlign
|
||
, const QList<QPair<Attribute, QVariant> > &attributes
|
||
, int userData)
|
||
{
|
||
pushUndo(QLatin1String("addText"));
|
||
|
||
// Check, if parent is of correct type
|
||
QString tag = parent.get()->nodeName();
|
||
PrimitiveType type = getType(parent);
|
||
|
||
// Get Position (center of bounding box)
|
||
// TODO: Position of text depends on Parent-Type
|
||
// TODO: on moveNode, translateNode,... transform text also
|
||
QRectF parentBox = getBoundingBox(parent);
|
||
QList<QPointF> pointList;
|
||
|
||
switch (type)
|
||
{
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Line:
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Rectangle:
|
||
case PrimitiveType::Spline:
|
||
pointList.append(parentBox.topLeft());
|
||
break;
|
||
|
||
default:
|
||
emit typeError(tr("Can not add text to type %1").arg(tag));
|
||
popUndo();
|
||
return Node();
|
||
}
|
||
|
||
// Create Text-Node and reparent to parent
|
||
Node textNode(addPrimitive(PrimitiveType::Text, pointList, attributes, userData));
|
||
parent.get()->appendChild(textNode.get().node());
|
||
|
||
// Set textData and alignment
|
||
QDomElement textDataNode = (textNode.get()->appendChild(createElement(QLatin1String("text_data")))).toElement();
|
||
textDataNode.setAttribute(QLatin1String("alignment"), QString::number((int)textAlign, 10));
|
||
QDomCDATASection cdata = createCDATASection(textData);
|
||
emitChangedSignal(parent, Attribute::MaxAttributes, false);
|
||
return Node(Node::Implementation(textDataNode.appendChild(cdata)));
|
||
} // QDomNode GeometryModelQDom::addText(QDomNode parent, const QString &textData,...
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::getRootNode() const { return Node(Node::Implementation(firstChildElement(rootNodeName))); }
|
||
|
||
|
||
bool GeometryModelQDom::isEmpty() const
|
||
{
|
||
QDomElement rootNode = firstChildElement(rootNodeName);
|
||
return (!rootNode.hasChildNodes());
|
||
} // bool GeometryModelQDom::isEmpty() const
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::getText(const Node &parent) const
|
||
{
|
||
// Check, if parent is of correct type
|
||
PrimitiveType type = getType(parent);
|
||
|
||
switch (type)
|
||
{
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Line:
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Rectangle:
|
||
case PrimitiveType::Spline:
|
||
return Node(Node::Implementation(parent.get()->firstChildElement(QLatin1String("text"))));
|
||
|
||
default:
|
||
return Node();
|
||
}
|
||
} // QDomNode GeometryModelQDom::getText(QDomNode parent)
|
||
|
||
|
||
QString GeometryModelQDom::getTextData(const Node &node) const
|
||
{
|
||
QString result;
|
||
// Check, if parent is of correct type
|
||
QString tag = node.get()->nodeName();
|
||
if (tag != QLatin1String("text"))
|
||
emit const_cast<GeometryModelQDom*>(this)->typeError(tr("Can not get text-data from %1").arg(tag));
|
||
else
|
||
{
|
||
QDomNode textData = node.get()->firstChildElement(QLatin1String("text_data"));
|
||
QDomNode data = textData.firstChild();
|
||
if (! data.isNull())
|
||
result = data.nodeValue();
|
||
}
|
||
return result;
|
||
} // QString GeometryModelQDom::getTextData(QDomNode textNode)
|
||
|
||
|
||
QList<QPointF> GeometryModelQDom::getPrimitivePoints(const Node &node) const { return getPrimitivePoints(node.get().node()); }
|
||
|
||
|
||
QList<QPointF> GeometryModelQDom::getPrimitivePoints(const QDomNode &node) const
|
||
{
|
||
const QString &tag = node.nodeName();
|
||
PrimitiveType type = getType(node);
|
||
|
||
// set the number of required points for this primitive...
|
||
QList<QPointF> result;
|
||
int minPoints = 0;
|
||
int maxPoints = 0;
|
||
|
||
switch (type)
|
||
{
|
||
|
||
case PrimitiveType::DictionarySymbol:
|
||
{
|
||
minPoints = 1;
|
||
maxPoints = INT_MAX;
|
||
} break;
|
||
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Rectangle:
|
||
{
|
||
minPoints = 4;
|
||
maxPoints = 4;
|
||
} break;
|
||
|
||
case PrimitiveType::ParticipantSymbol:
|
||
case PrimitiveType::Symbol:
|
||
case PrimitiveType::Text:
|
||
{
|
||
minPoints = 1;
|
||
maxPoints = 1;
|
||
} break;
|
||
|
||
case PrimitiveType::Line:
|
||
{
|
||
minPoints = 2;
|
||
maxPoints = 2;
|
||
} break;
|
||
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Spline:
|
||
{
|
||
minPoints = 3;
|
||
maxPoints = INT_MAX;
|
||
} break;
|
||
|
||
default:
|
||
{
|
||
emit const_cast<GeometryModelQDom*>(this)->modelError(tr("No points in primitive of type %1").arg(tag));
|
||
return result;
|
||
}
|
||
} // switch
|
||
|
||
// ... and get the points
|
||
QDomNodeList nodes = node.childNodes();
|
||
if (nodes.isEmpty())
|
||
emit const_cast<GeometryModelQDom*>(this)->modelError(tr("No points found in primitive of type %1").arg(tag));
|
||
else
|
||
{
|
||
for (int i = 0; i < nodes.size(); ++i)
|
||
{
|
||
QDomElement p = nodes.at(i).toElement();
|
||
if (p.nodeName() != QLatin1String("point")) continue;
|
||
if (!p.hasAttribute(QLatin1String("x")) || !p.hasAttribute(QLatin1String("y")))
|
||
emit const_cast<GeometryModelQDom*>(this)->modelError(tr("Invalid point in primitive of type %1").arg(tag));
|
||
else
|
||
{
|
||
bool okx, oky;
|
||
double x = p.toElement().attribute(QLatin1String("x")).toDouble(&okx);
|
||
double y = p.toElement().attribute(QLatin1String("y")).toDouble(&oky);
|
||
if (!(okx && oky))
|
||
emit const_cast<GeometryModelQDom*>(this)->modelError(tr("Invalid point in primitive of type %1").arg(tag));
|
||
else
|
||
result.append(QPointF(x, y));
|
||
}
|
||
}
|
||
}
|
||
|
||
// Check points
|
||
if ((result.size() < minPoints) || (result.size() > maxPoints))
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(tr("Wrong number of points for new primitive %1").arg(_primitiveTagsStrings[type]));
|
||
|
||
return result;
|
||
} // QList<QPointF> GeometryModelQDom::getPrimitivePoints(QDomNode node) const
|
||
|
||
|
||
QRectF GeometryModelQDom::getBoundingBox(const Node &node) const { return getBoundingBox(node.get().node()); }
|
||
|
||
|
||
QRectF GeometryModelQDom::getBoundingBox(const QDomNode &node) const
|
||
{
|
||
PrimitiveType type = getType(node);
|
||
|
||
QRectF result;
|
||
if ((type == PrimitiveType::Node) || (type == PrimitiveType::RootNode) || (node == *this))
|
||
{
|
||
// Recursive over all children
|
||
QRectF merge;
|
||
QDomNodeList children;
|
||
if ((type == PrimitiveType::Node) || (type == PrimitiveType::RootNode))
|
||
{
|
||
// Children of other Node
|
||
children = node.childNodes();
|
||
}
|
||
else
|
||
children = node.firstChildElement(rootNodeName).childNodes();
|
||
for (int i = 0; i < children.size(); ++i)
|
||
{
|
||
merge = getBoundingBox(children.at(i));
|
||
if (! merge.isNull())
|
||
result = result.isNull() ? merge : result.united(merge);
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
// TODO Add calculation for rotated Primitives
|
||
|
||
bool ok;
|
||
QList<QPointF> points = getPrimitivePoints(node);
|
||
double width, height;
|
||
|
||
switch (type)
|
||
{
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Rectangle:
|
||
width = getAttribute(node, Attribute::Width).toDouble(&ok);
|
||
height = getAttribute(node, Attribute::Height).toDouble(&ok);
|
||
if (ok && (points.size() == 1))
|
||
{
|
||
result.setRect(points[0].x(), points[0].y(), width, height);
|
||
result.moveCenter(points[0]);
|
||
}
|
||
break;
|
||
|
||
case PrimitiveType::Line:
|
||
if (points.size() == 2)
|
||
result = QRectF(points[0], points[1]).normalized();
|
||
break;
|
||
|
||
case PrimitiveType::DictionarySymbol:
|
||
if (points.size() > 2)
|
||
{
|
||
result = QRectF(points.at(0), points.at(1));
|
||
for (int i = 2; i < points.count(); ++i)
|
||
result = result.united(QRectF(points.at(0), points.at(i)));
|
||
}
|
||
else
|
||
{
|
||
result = QRectF(points[0].x(), points[0].y(), 1.0, 1.0);
|
||
result.moveCenter(points[0]);
|
||
}
|
||
break;
|
||
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Spline:
|
||
if (points.size() > 2)
|
||
{
|
||
result = QRectF(points.at(0), points.at(1));
|
||
for (int i = 2; i < points.count(); ++i)
|
||
result = result.united(QRectF(points.at(0), points.at(i)));
|
||
}
|
||
break;
|
||
|
||
case PrimitiveType::ParticipantSymbol:
|
||
case PrimitiveType::Symbol:
|
||
case PrimitiveType::Text:
|
||
if (points.size() == 1)
|
||
{
|
||
// TODO Calculate real dimensions of Textbox and Symbol?
|
||
// Only possible with more information from GDW implementation, Map Scale etc.
|
||
result = QRectF(0, 0, 0, 0);
|
||
result.moveCenter(points[0]);
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
} // if ( type == Node ) {...} else...
|
||
|
||
return result;
|
||
} // QRectF GeometryModelQDom::getBoundingBox(QDomNode node)
|
||
|
||
|
||
|
||
void GeometryModelQDom::movePrimitiveIntoGroup(const Node &primitive, const Node &target)
|
||
{
|
||
pushUndo(QLatin1String("movePrimitiveIntoGroup"));
|
||
|
||
QString tag = primitive.get()->nodeName();
|
||
if (target.get()->nodeName() != QLatin1String("node"))
|
||
{
|
||
emit typeError(tr("Can not move primitive into %1").arg(target.get()->nodeName()));
|
||
popUndo();
|
||
return;
|
||
}
|
||
if (_primitiveTagsTypes.contains(tag))
|
||
{
|
||
target.get()->appendChild(primitive.get().node());
|
||
emitChangedSignal(primitive, Attribute::MaxAttributes, false);
|
||
}
|
||
} // void GeometryModelQDom::movePrimitiveIntoGroup(QDomNode primitive, QDomNode target)
|
||
|
||
|
||
void GeometryModelQDom::releaseGroup(const Node &group)
|
||
{
|
||
pushUndo(QLatin1String("releaseGroup"));
|
||
|
||
if (group.get()->nodeName() != QLatin1String("node"))
|
||
{
|
||
emit typeError(tr("Given node is not a group: %1").arg(group.get()->nodeName()));
|
||
popUndo();
|
||
return;
|
||
}
|
||
|
||
QDomNode parent = group.get()->parentNode();
|
||
while (group.get()->hasChildNodes())
|
||
parent.appendChild(group.get()->firstChild());
|
||
parent.removeChild(group.get().node());
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
|
||
} // void GeometryModelQDom::releaseGroup(QDomNode group)
|
||
|
||
|
||
void GeometryModelQDom::deleteGroup(const Node &group)
|
||
{
|
||
if (!group.isValid()) return;
|
||
|
||
pushUndo(QLatin1String("deleteGroup"));
|
||
|
||
if (group.get()->nodeName() != QLatin1String("node"))
|
||
{
|
||
emit typeError(tr("Given node is not a group: %1").arg(group.get()->nodeName()));
|
||
popUndo();
|
||
return;
|
||
}
|
||
|
||
QDomNode parent = group.get()->parentNode();
|
||
parent.removeChild(group.get().node());
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
} // void GeometryModelQDom::deleteGroup(QDomNode group)
|
||
|
||
|
||
void GeometryModelQDom::removePrimitive(const Node &primitive)
|
||
{
|
||
_skipChangedSignal = true;
|
||
removePrimitive(primitive.get().node());
|
||
_skipChangedSignal = false;
|
||
}
|
||
|
||
|
||
void GeometryModelQDom::removePrimitive(const QDomNode &primitive)
|
||
{
|
||
// could be a group node
|
||
while (primitive.hasChildNodes())
|
||
{
|
||
removePrimitive(primitive.firstChild());
|
||
}
|
||
|
||
// Remove userData
|
||
bool ok;
|
||
int userData = getUserData(primitive, &ok);
|
||
if (ok)
|
||
{
|
||
primitive.toElement().removeAttribute(userDataName);
|
||
emit userDataCleanup(userData);
|
||
}
|
||
|
||
// pushUndo() here, because we must not save the primitive with userData, since
|
||
// the GeISiR2-Primitive is removed from the Map
|
||
pushUndo(QLatin1String("removePrimitive"));
|
||
QDomNode parent = primitive.parentNode();
|
||
QDomNode oldChild = parent.removeChild(primitive);
|
||
|
||
if (! oldChild.isNull())
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
else popUndo();
|
||
} // void GeometryModelQDom::removePrimitive(QDomNode primitive)
|
||
|
||
|
||
void GeometryModelQDom::removePrimitivesByUserData(const QList<int> &userDataList)
|
||
{
|
||
_skipChangedSignal = true;
|
||
int removed = 0;
|
||
// First delete userData, then make the undo-backup
|
||
QList<QDomNode> nodeList;
|
||
|
||
nodeList.reserve(userDataList.size());
|
||
for (int i = 0; i < userDataList.size(); ++i)
|
||
{
|
||
Node node = findPrimitive(userDataList.at(i));
|
||
node.get()->toElement().removeAttribute(userDataName);
|
||
nodeList.append(node.get().node());
|
||
}
|
||
startUndoBlock();
|
||
for (int i = 0; i < nodeList.size(); ++i)
|
||
{
|
||
removePrimitive(nodeList.at(i));
|
||
++removed;
|
||
}
|
||
endUndoBlock(QLatin1String("removePrimitivesByUserData"));
|
||
_skipChangedSignal = false;
|
||
|
||
if (removed > 0)
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
} // void GeometryModelQDom::removePrimitivesByUserData(QList<int> userDataList)
|
||
|
||
|
||
void GeometryModelQDom::removeText(Node &parent)
|
||
{
|
||
pushUndo(QLatin1String("removeText"));
|
||
|
||
// Check, if parent is of correct type
|
||
PrimitiveType type = getType(parent);
|
||
|
||
switch (type)
|
||
{
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Line:
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Rectangle:
|
||
case PrimitiveType::Spline:
|
||
parent.get()->removeChild(parent.get()->firstChildElement(QLatin1String("text")));
|
||
emitChangedSignal(parent, Attribute::MaxAttributes, false);
|
||
break;
|
||
|
||
default:
|
||
popUndo();
|
||
return;
|
||
}
|
||
} // void GeometryModelQDom::removeText(QDomNode parent)
|
||
|
||
|
||
void GeometryModelQDom::setTextData(const Node &textNode, const QString &data, HorizontalAlign textAlign)
|
||
{
|
||
pushUndo(QLatin1String("setTextData"));
|
||
|
||
// Check, if parent is of correct type
|
||
const QString &tag = textNode.get()->nodeName();
|
||
if (tag != QLatin1String("text"))
|
||
{
|
||
emit typeError(tr("Can not set text-data for %1").arg(tag));
|
||
popUndo();
|
||
}
|
||
else
|
||
{
|
||
QDomNode textData = textNode.get()->firstChildElement(QLatin1String("text_data"));
|
||
if (textData.isNull())
|
||
textData = (textNode.get()->appendChild(createElement(QLatin1String("text_data")))).toElement();
|
||
textData.toElement().setAttribute(QLatin1String("alignment"), QString::number((int)textAlign, 10));
|
||
textData.removeChild(textData.firstChild());
|
||
textData.appendChild(createCDATASection(data));
|
||
|
||
emitChangedSignal(textNode, Attribute::MaxAttributes, false);
|
||
}
|
||
} // void GeometryModelQDom::setTextData(QDomNode textNode, const QString &data, HorizontalAlign textAlign)
|
||
|
||
|
||
void GeometryModelQDom::clearModel()
|
||
{
|
||
qDebug() << " GeometryModelQDom::clearModel()";
|
||
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
pushUndo(QLatin1String("clearPlan"));
|
||
|
||
bool oldSCS = _skipChangedSignal;
|
||
bool oldUE = _undoEnabled;
|
||
_skipChangedSignal = true;
|
||
_undoEnabled = false;
|
||
while (root.hasChildNodes())
|
||
removePrimitive(root.firstChild());
|
||
_skipChangedSignal = oldSCS;
|
||
_undoEnabled = oldUE;
|
||
|
||
const auto supportedAttribs = supportedAttributes(GeometryModel::PrimitiveType::RootNode);
|
||
for (const GeometryModel::Attribute &attr : supportedAttribs)
|
||
{
|
||
const QString & attrName = attributeToString(attr);
|
||
if (root.hasAttribute(attrName))
|
||
{
|
||
root.removeAttribute(attrName);
|
||
}
|
||
}
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
} // void GeometryModelQDom::clearModel()
|
||
|
||
|
||
bool GeometryModelQDom::setPrimitivePoints(const Node &node, const QList<QPointF> &points)
|
||
{
|
||
PrimitiveType type = getType(node);
|
||
|
||
// Check number of points and insert them
|
||
int minPoints = 0;
|
||
int maxPoints = 0;
|
||
switch (type)
|
||
{
|
||
case PrimitiveType::DictionarySymbol:
|
||
{
|
||
minPoints = 1;
|
||
maxPoints = INT_MAX;
|
||
} break;
|
||
|
||
case PrimitiveType::Ellipse:
|
||
case PrimitiveType::Rectangle:
|
||
{
|
||
minPoints = 4;
|
||
maxPoints = 4;
|
||
} break;
|
||
|
||
case PrimitiveType::ParticipantSymbol:
|
||
case PrimitiveType::Symbol:
|
||
case PrimitiveType::Text:
|
||
{
|
||
minPoints = 1;
|
||
maxPoints = 1;
|
||
} break;
|
||
|
||
case PrimitiveType::Line:
|
||
{
|
||
minPoints = 2;
|
||
maxPoints = 2;
|
||
} break;
|
||
|
||
case PrimitiveType::Polyline:
|
||
case PrimitiveType::Spline:
|
||
{
|
||
minPoints = 3;
|
||
maxPoints = INT_MAX;
|
||
} break;
|
||
|
||
case PrimitiveType::RootNode:
|
||
case PrimitiveType::Node:
|
||
{
|
||
if (points.isEmpty()) return true;
|
||
} break;
|
||
|
||
default: break;
|
||
}
|
||
|
||
if ((points.size() < minPoints) || (points.size() > maxPoints))
|
||
{
|
||
emit attributeError(tr("Wrong number of points for primitive %1").arg(_primitiveTagsStrings[type]));
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
|
||
pushUndo(QLatin1String("setPrimitivePoints"));
|
||
|
||
// Remove old Points before Adding
|
||
QDomElement p = node.get()->firstChildElement(QLatin1String("point"));
|
||
while (! p.isNull())
|
||
{
|
||
node.get()->removeChild(p);
|
||
p = node.get()->firstChildElement(QLatin1String("point"));
|
||
}
|
||
|
||
for (int i = 0; i < points.size(); ++i)
|
||
{
|
||
QDomElement point = (node.get()->appendChild(createElement(QLatin1String("point")))).toElement();
|
||
// QString::number() does NOT honor locale settings:
|
||
point.setAttribute(QLatin1String("x"), QString::number(points.at(i).x(), 'f', CoordinateDoublePrecision)); // to enforce "1.23" instead of "1,23"
|
||
point.setAttribute(QLatin1String("y"), QString::number(points.at(i).y(), 'f', CoordinateDoublePrecision));
|
||
}
|
||
emitChangedSignal(node, Attribute::None, true);
|
||
}
|
||
return true;
|
||
} // bool GeometryModelQDom::setPrimitivePoints(QDomNode node, QList<QPointF> points)
|
||
|
||
|
||
void GeometryModelQDom::translateNode(const Node &node, double x, double y) { translateNode(node.get().node(), x, y); }
|
||
|
||
void GeometryModelQDom::translateNode(const QDomNode &node, double x, double y)
|
||
{
|
||
pushUndo(QLatin1String("translateNode"));
|
||
|
||
QTransform t;
|
||
t = t.translate(x, y);
|
||
|
||
if (node == *this)
|
||
{
|
||
// translate complete plan
|
||
QDomElement root = node.firstChildElement(rootNodeName);
|
||
QDomNodeList children = root.childNodes();
|
||
// No changed() inside this block
|
||
_skipChangedSignal = true;
|
||
for (int i = 0; i < children.size(); ++i)
|
||
translateNode(children.at(i), x, y);
|
||
_skipChangedSignal = false;
|
||
}
|
||
else
|
||
{
|
||
QString tag = node.nodeName();
|
||
if (tag == QLatin1String("node"))
|
||
{
|
||
QDomNodeList children = node.childNodes();
|
||
for (int i = 0; i < children.size(); ++i)
|
||
translateNode(children.at(i), x, y);
|
||
}
|
||
else
|
||
transformNode(node, t);
|
||
}
|
||
|
||
emitChangedSignal(Node(Node::Implementation(node)), Attribute::None, true);
|
||
} // void GeometryModelQDom::translateNode(QDomNode node, double x, double y)
|
||
|
||
|
||
void GeometryModelQDom::moveNode(const Node &node, double x, double y) { moveNode(node.get().node(), x, y); }
|
||
|
||
|
||
void GeometryModelQDom::moveNode(const QDomNode &node, double x, double y)
|
||
{
|
||
pushUndo(QLatin1String("moveNode"));
|
||
|
||
// Move to (x,y)
|
||
QRectF bb = getBoundingBox(node);
|
||
QPointF center = bb.center();
|
||
|
||
translateNode(node, -center.x() + x, -center.y() + y);
|
||
|
||
emitChangedSignal(Node(Node::Implementation(node)), Attribute::None, true);
|
||
} // void GeometryModelQDom::moveNode(QDomNode node, double x, double y)
|
||
|
||
|
||
void GeometryModelQDom::scaleNode(const Node &node, double scaleX, double scaleY) { scaleNode(node.get().node(), scaleX, scaleY); }
|
||
|
||
|
||
void GeometryModelQDom::scaleNode(const QDomNode &node, double scaleX, double scaleY)
|
||
{
|
||
pushUndo(QLatin1String("scaleNode"));
|
||
|
||
// Translate to (0.0, 0.0)
|
||
QRectF bb = getBoundingBox(node);
|
||
QPointF center = bb.center();
|
||
translateNode(node, -center.x(), -center.y());
|
||
|
||
// Scale
|
||
QTransform t;
|
||
t = t.scale(scaleX, scaleY);
|
||
QString tag = node.nodeName();
|
||
if (tag == QLatin1String("node"))
|
||
{
|
||
QDomNodeList children = node.childNodes();
|
||
for (int i = 0; i < children.size(); ++i)
|
||
transformNode(children.at(i), t);
|
||
}
|
||
else transformNode(node, t);
|
||
|
||
|
||
// Translate back
|
||
translateNode(node, center.x(), center.y());
|
||
|
||
emitChangedSignal(Node(Node::Implementation(node)), Attribute::None, true);
|
||
} // void GeometryModelQDom::scaleNode(QDomNode node, double scaleX, double scaleY)
|
||
|
||
|
||
void GeometryModelQDom::rotateNode(const Node &node, double angle) { rotateNode(node.get().node(), angle); }
|
||
|
||
void GeometryModelQDom::rotateNode(const QDomNode &node, double angle)
|
||
{
|
||
pushUndo(QLatin1String("rotateNode"));
|
||
|
||
// Translate to (0.0, 0.0)
|
||
QRectF bb = getBoundingBox(node);
|
||
QPointF center = bb.center();
|
||
translateNode(node, -center.x(), -center.y());
|
||
|
||
// Rotate
|
||
QTransform t;
|
||
t = t.rotate(angle);
|
||
QString tag = node.nodeName();
|
||
if (tag == QLatin1String("node"))
|
||
{
|
||
QDomNodeList children = node.childNodes();
|
||
for (int i = 0; i < children.size(); ++i)
|
||
transformNode(children.at(i), t);
|
||
}
|
||
else transformNode(node, t);
|
||
|
||
|
||
// Translate back
|
||
translateNode(node, center.x(), center.y());
|
||
|
||
emitChangedSignal(Node(Node::Implementation(node)), Attribute::Rotate, true);
|
||
|
||
} // void GeometryModelQDom::rotateNode(QDomNode node, double angle)
|
||
|
||
|
||
void GeometryModelQDom::reorderPrimitives(const NodeList &nodes, PrimitivOrder order)
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
if (nodes.length() > 0)
|
||
{
|
||
pushUndo(QLatin1String("reorderPrimitives"));
|
||
|
||
if (order == GeometryModelQDom::PrimitivOrder::Lower)
|
||
{
|
||
QDomNode before;
|
||
for (int i = nodes.length() - 1; i >= 0; --i)
|
||
before = root.insertBefore(nodes.at(i).get().node(), before);
|
||
}
|
||
else if (order == GeometryModelQDom::PrimitivOrder::Raise)
|
||
{
|
||
for (int i = 0; i < nodes.length(); ++i)
|
||
root.insertAfter(nodes.at(i).get().node(), QDomNode());
|
||
}
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
}
|
||
} // void GeometryModelQDom::reorderPrimitives(const QList<QDomNode> &nodes, t_PrimOrder order)
|
||
|
||
|
||
void GeometryModelQDom::merge(const Node &other, bool skipUndo, bool intoNewGroup) { merge(other.get().node(), skipUndo, intoNewGroup); }
|
||
|
||
|
||
void GeometryModelQDom::merge(GeometryModel *other, bool skipUndo, bool intoNewGroup)
|
||
{
|
||
const GeometryModelQDom *otherQDom = dynamic_cast<GeometryModelQDom *>(other);
|
||
merge(*otherQDom, skipUndo, intoNewGroup);
|
||
|
||
} // void GeometryModelQDom::merge( GeometryModel * other, bool skipUndo, bool intoNewGroup )
|
||
|
||
|
||
void GeometryModelQDom::merge(const QDomNode &other, bool skipUndo, bool intoNewGroup)
|
||
{
|
||
if ((other == *this) || (other.ownerDocument() == *this))
|
||
{
|
||
// Do not merge with itself or own child
|
||
return;
|
||
}
|
||
|
||
if (! skipUndo)
|
||
pushUndo(QLatin1String("merge"));
|
||
|
||
QString tag = other.nodeName();
|
||
if (other.nodeType() == QDomNode::DocumentNode)
|
||
{
|
||
// Its a complete plan, add recursive
|
||
QDomElement root = other.firstChildElement(rootNodeName);
|
||
// No changed() inside this block
|
||
_skipChangedSignal = true;
|
||
if (intoNewGroup)
|
||
{
|
||
QList<QDomNode> nodeList;
|
||
QDomNodeList domNodeList = root.childNodes();
|
||
nodeList.reserve(domNodeList.size());
|
||
for (int i = 0; i < domNodeList.size(); ++i)
|
||
nodeList.append(domNodeList.at(i));
|
||
const QDomNode &group = createGroup(nodeList);
|
||
setNodeDisplayName(Node(group), tr("Imported Group"));
|
||
}
|
||
else
|
||
{
|
||
while (root.hasChildNodes())
|
||
merge(root.firstChild(), true);
|
||
}
|
||
_skipChangedSignal = false;
|
||
}
|
||
else if ((getType(other) == PrimitiveType::Unknown) || (getType(other) == PrimitiveType::MapDefaults))
|
||
{
|
||
// Unknown type error
|
||
emit typeError(tr("Can not merge with %1").arg(tag));
|
||
if (! skipUndo)
|
||
popUndo();
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
// Insert
|
||
QDomElement docRoot = firstChildElement(rootNodeName);
|
||
docRoot.appendChild(other);
|
||
}
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
} // void PlanModel::merge(QDomNode other, bool skipUndo, bool intoNewGroup)
|
||
|
||
|
||
unsigned int GeometryModelQDom::modificationCounter() const { return _modificationCounter; }
|
||
|
||
|
||
void GeometryModelQDom::resetModificationCounter()
|
||
{
|
||
_modificationCounter = 0;
|
||
emit modificationCount(_modificationCounter);
|
||
} // void GeometryModelQDom::resetModificationCounter()
|
||
|
||
|
||
void GeometryModelQDom::undo(unsigned int steps)
|
||
{
|
||
if (undoSteps() < 1) return;
|
||
if (steps < 1) return;
|
||
|
||
if (_insideUndoBlock)
|
||
endUndoBlock();
|
||
|
||
emit nodeCleanup(Node(firstChildElement(rootNodeName)));
|
||
while ((steps > 0) && (undoSteps() > 0))
|
||
{
|
||
QDomNode root = firstChildElement(rootNodeName);
|
||
QDomNode undoNode = _undoStack.pop();
|
||
|
||
_redoStack.push(root.cloneNode());
|
||
_redoHistory.push(_undoHistory.pop());
|
||
|
||
root = replaceChild(undoNode, root);
|
||
|
||
if (root.isNull()) // was replaceChild successful?
|
||
{
|
||
emit criticalError(tr("Undo function failed."));
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
--steps;
|
||
}
|
||
--_modificationCounter;
|
||
emit modificationCount(_modificationCounter);
|
||
}
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, true);
|
||
|
||
} // void GeometryModelQDom::undo(unsigned int steps)
|
||
|
||
|
||
void GeometryModelQDom::redo(unsigned int steps)
|
||
{
|
||
if (redoSteps() < 1) return;
|
||
if (steps < 1) return;
|
||
|
||
emit nodeCleanup(Node(firstChildElement(rootNodeName)));
|
||
|
||
while ((steps > 0) && (redoSteps() > 0))
|
||
{
|
||
QDomNode root = firstChildElement(rootNodeName);
|
||
QDomNode redoNode = _redoStack.pop();
|
||
|
||
_undoStack.push(root.cloneNode());
|
||
_undoHistory.push(_redoHistory.pop());
|
||
|
||
root = replaceChild(redoNode, root);
|
||
|
||
if (root.isNull()) // was replaceChild successful?
|
||
{
|
||
emit criticalError(tr("Redo function failed."));
|
||
break;
|
||
}
|
||
--steps;
|
||
++_modificationCounter;
|
||
emit modificationCount(_modificationCounter);
|
||
}
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, true);
|
||
|
||
} // void GeometryModelQDom::redo(unsigned int steps)
|
||
|
||
|
||
void GeometryModelQDom::enableUndo(bool enable)
|
||
{
|
||
_undoEnabled = enable;
|
||
} // void GeometryModelQDom::enableUndo(bool enable)
|
||
|
||
|
||
void GeometryModelQDom::startUndoBlock()
|
||
{
|
||
if (! _insideUndoBlock)
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
_undoBlock = root.cloneNode();
|
||
}
|
||
_insideUndoBlock = true;
|
||
} // void GeometryModelQDom::startUndoBlock()
|
||
|
||
|
||
void GeometryModelQDom::abortUndoBlock()
|
||
{
|
||
if (_insideUndoBlock)
|
||
_undoBlock.clear();
|
||
} // void GeometryModelQDom::abortUndoBlock()
|
||
|
||
|
||
void GeometryModelQDom::endUndoBlock(const QString &eventDescription)
|
||
{
|
||
if (_insideUndoBlock)
|
||
{
|
||
if (_undoEnabled && (! _undoBlock.isNull()))
|
||
{
|
||
while (undoSteps() >= _maxUndoSteps)
|
||
{
|
||
// Size-limit reached, remove first element
|
||
_undoStack.erase(_undoStack.begin());
|
||
_undoHistory.erase(_undoHistory.begin());
|
||
}
|
||
_undoStack.push(_undoBlock);
|
||
_undoHistory.push((eventDescription.isEmpty() ? _undoHistoryBlock : eventDescription));
|
||
clearRedoStack();
|
||
++_modificationCounter;
|
||
emit modificationCount(_modificationCounter);
|
||
}
|
||
}
|
||
_insideUndoBlock = false;
|
||
} // void GeometryModelQDom::endUndoBlock(const QString &eventDescription)
|
||
|
||
|
||
void GeometryModelQDom::setMaxUndoSteps(unsigned int max)
|
||
{
|
||
_maxUndoSteps = (max < 1) ? 1 : max;
|
||
|
||
while (undoSteps() > _maxUndoSteps)
|
||
{
|
||
// shrink to max size, if needed.
|
||
_undoStack.erase(_undoStack.begin());
|
||
_undoHistory.erase(_undoHistory.begin());
|
||
}
|
||
} // void GeometryModelQDom::setMaxUndoSteps(int max)
|
||
|
||
|
||
unsigned int GeometryModelQDom::maxUndoSteps() const
|
||
{
|
||
return _maxUndoSteps;
|
||
}
|
||
|
||
|
||
void GeometryModelQDom::cleanModel()
|
||
{
|
||
qDebug() << " GeometryModelQDom::cleanModel()";
|
||
|
||
QMap<QString, GeometryModelQDom::PrimitiveType>::iterator it = _primitiveTagsTypes.begin();
|
||
while (it != _primitiveTagsTypes.end())
|
||
{
|
||
QDomNodeList nodes = elementsByTagName(it.key());
|
||
for (int i = 0; i < nodes.size(); ++i)
|
||
{
|
||
if ((_primitiveTagsTypes[it.key()] == PrimitiveType::Node) || (_primitiveTagsTypes[it.key()] == PrimitiveType::RootNode))
|
||
{
|
||
// Remove empty groups
|
||
QDomNode group = nodes.at(i);
|
||
|
||
if ( ! (group.hasChildNodes() || group.hasAttributes()) )
|
||
{
|
||
group.parentNode().removeChild(group);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Remove userData
|
||
const QDomNode &node = nodes.at(i);
|
||
if (hasUserData(node))
|
||
{
|
||
bool ok;
|
||
int userData = getUserData(node, &ok);
|
||
if (ok)
|
||
{
|
||
nodes.at(i).toElement().removeAttribute(userDataName);
|
||
emit userDataCleanup(userData);
|
||
}
|
||
}
|
||
}
|
||
|
||
GeometryModel::Node::Implementation nodeImpl(nodes.at(i));
|
||
emit connectionCleanup(nodeImpl.connected());
|
||
nodeImpl.unlinkConnection();
|
||
}
|
||
++it;
|
||
}
|
||
|
||
resetModificationCounter();
|
||
} // void GeometryModelQDom::cleanModel()
|
||
|
||
|
||
void GeometryModelQDom::setNodeDisplayName(const Node &node, const QString &name)
|
||
{
|
||
const QString attName = QLatin1String("GuiDisplayName");
|
||
QDomElement e = node.get().node().toElement();
|
||
|
||
if (e.isNull())
|
||
{
|
||
qCritical() << " node not found";
|
||
return;
|
||
}
|
||
|
||
e.setAttribute(attName, name);
|
||
|
||
emitChangedSignal(node, Attribute::MaxAttributes, false);
|
||
|
||
} // void GeometryModelQDom::setNodeDisplayName(const Node & node, const QString & name)
|
||
|
||
|
||
QString GeometryModelQDom::getNodeDisplayName(const Node &node) const
|
||
{
|
||
const QString attName = QLatin1String("GuiDisplayName");
|
||
QDomElement e = node.get().node().toElement();
|
||
|
||
return (e.hasAttribute(attName)) ? e.attribute(attName) : QString();
|
||
|
||
} // QString GeometryModelQDom::getNodeDisplayName(const Node & node) const
|
||
|
||
|
||
QVariant GeometryModelQDom::getAttribute(const Node &node, Attribute attribute) const { return getAttribute(node.get().node(), attribute); }
|
||
|
||
QVariant GeometryModelQDom::getAttribute(const QDomNode &node, Attribute attribute) const
|
||
{
|
||
QString att = attributeToString(attribute);
|
||
QDomElement e = node.toElement();
|
||
|
||
if (e.hasAttribute(att))
|
||
{
|
||
QString value = e.attribute(att);
|
||
|
||
if (_attributeTypes[attribute] == QVariant::Color)
|
||
{
|
||
// Return Colors as QString and let the user convert it with static method
|
||
// PlanModel::colorFromString() - QVariant ignores alpha in Colors
|
||
return QVariant(colorFromString(value));
|
||
}
|
||
else if (_attributeTypes[attribute] == QVariant::PointF)
|
||
return QVariant(pointFromString(value));
|
||
else
|
||
{
|
||
if (_attributeTypes[attribute] == QVariant::UserType)
|
||
{
|
||
// Return PlanModel-Enums as String-Value
|
||
// TODO: Implement UserTypes?
|
||
return QVariant(value);
|
||
}
|
||
else
|
||
{
|
||
// Convert other values to their native type
|
||
QVariant result(_attributeTypes[attribute]);
|
||
result.setValue(value);
|
||
return result;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// Check for default
|
||
if (hasAttribute(node, attribute))
|
||
{
|
||
using index = QPair<GeometryModelQDom::PrimitiveType, GeometryModelQDom::Attribute>;
|
||
QVariant result(_attributeTypes[attribute]);
|
||
result.setValue(_attributeDefaults[index(PrimitiveType::Unknown, attribute)]);
|
||
return result;
|
||
}
|
||
else
|
||
{
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(att + tr(": Attribute unknown in primitive %1").arg(node.nodeName()));
|
||
return QVariant(QVariant::Invalid);
|
||
}
|
||
}
|
||
|
||
return QVariant(QVariant::Invalid);
|
||
} // QVariant GeometryModelQDom::getAttribute(QDomNode node, Attribute attribute)
|
||
|
||
|
||
bool GeometryModelQDom::hasAttribute(const Node &node, Attribute attribute) const { return hasAttribute(node.get().node(), attribute); }
|
||
|
||
|
||
bool GeometryModelQDom::hasAttribute(const QDomNode &node, Attribute attribute) const
|
||
{
|
||
QString tag = node.nodeName();
|
||
if (_primitiveTagsTypes.contains(tag))
|
||
{
|
||
PrimitiveType t = _primitiveTagsTypes[tag];
|
||
if (_primitiveSupportedAttributes.contains(t))
|
||
return supportedAttributes(t).contains(attribute);
|
||
}
|
||
return false;
|
||
} // bool GeometryModelQDom::hasAttribute(QDomNode node, Attribute attribute) const
|
||
|
||
|
||
QVariant::Type GeometryModelQDom::attributeType(const Attribute &attribute) const
|
||
{
|
||
if (_attributeTypes.contains(attribute)) return _attributeTypes[attribute];
|
||
else return QVariant::Invalid;
|
||
} // QVariant::Type GeometryModelQDom::attributeType(Attribute attribute) const
|
||
|
||
|
||
QList<GeometryModelQDom::Attribute> GeometryModelQDom::supportedAttributes(PrimitiveType type) const
|
||
{
|
||
if (_primitiveSupportedAttributes.contains(type)) return _primitiveSupportedAttributes.values(type);
|
||
else return QList<GeometryModelQDom::Attribute>();
|
||
} // QList<GeometryModelQDom::Attribute> GeometryModelQDom::supportedAttributes(PrimitiveType type) const
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::createGroup(const NodeList &primitives)
|
||
{
|
||
pushUndo(QLatin1String("createGroup"));
|
||
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
QDomElement node = createElement(_primitiveTagsStrings[PrimitiveType::Node]);
|
||
QDomNode group = root.appendChild(node);
|
||
if (! group.isNull())
|
||
{
|
||
for (int i = 0; i < primitives.size(); ++i)
|
||
{
|
||
// For performance-reasons we use direct appendChild(), but
|
||
// normally you should use movePrimitiveIntoGroup(primitives.at(i), group);
|
||
group.appendChild(primitives.at(i).get().node());
|
||
}
|
||
}
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
|
||
return Node(Node::Implementation(group));
|
||
} // QDomNode PlanModel::createGroup(QList<QDomNode> primitives)
|
||
|
||
|
||
QDomNode GeometryModelQDom::createGroup(const QList<QDomNode> &primitives)
|
||
{
|
||
pushUndo(QLatin1String("createGroup"));
|
||
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
QDomElement node = createElement(_primitiveTagsStrings[PrimitiveType::Node]);
|
||
QDomNode group = root.appendChild(node);
|
||
if (! group.isNull())
|
||
{
|
||
for (int i = 0; i < primitives.size(); ++i)
|
||
{
|
||
// For performance-reasons we use direct appendChild(), but
|
||
// normally you should use movePrimitiveIntoGroup(primitives.at(i), group);
|
||
group.appendChild(primitives.at(i));
|
||
}
|
||
}
|
||
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
|
||
return group;
|
||
} // QDomNode PlanModel::createGroup(QList<QDomNode> primitives)
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::isInGroup(const Node &node) const
|
||
{
|
||
QDomNode parent = node.get()->parentNode();
|
||
return Node(Node::Implementation((getType(parent) == PrimitiveType::Node) ? parent : QDomNode()));
|
||
} // QDomNode GeometryModelQDom::isInGroup(QDomNode primitive) const
|
||
|
||
|
||
GeometryModel::NodeList GeometryModelQDom::getGroupPrimitives(const Node &node)
|
||
{
|
||
PrimitiveType myNodeType = getType(node);
|
||
if ((myNodeType != PrimitiveType::Node) && (myNodeType != PrimitiveType::RootNode))
|
||
{
|
||
emit typeError(tr("Given node is not a group: %1").arg(node.get()->nodeName()));
|
||
return NodeList();
|
||
}
|
||
|
||
const QDomNodeList &domPrimitiveList = node.get()->childNodes();
|
||
GeometryModel::NodeList primitiveList;
|
||
|
||
primitiveList.reserve(domPrimitiveList.size());
|
||
for (int i = 0; i < domPrimitiveList.size(); ++i)
|
||
primitiveList += Node(Node::Implementation(domPrimitiveList.at(i)));
|
||
|
||
return primitiveList;
|
||
|
||
} // QDomNodeList GeometryModelQDom::getGroupPrimitives(QDomNode node) const
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::findPrimitive(int userData) const
|
||
{
|
||
// TODO: This is inefficient!!! Search only for Att userData!
|
||
QString userDataString = QString::number(userData, 10);
|
||
QMap<QString, GeometryModelQDom::PrimitiveType>::iterator it = _primitiveTagsTypes.begin();
|
||
while (it != _primitiveTagsTypes.end())
|
||
{
|
||
QDomNodeList nodes = elementsByTagName(it.key());
|
||
for (int i = 0; i < nodes.size(); ++i)
|
||
{
|
||
QDomElement e = nodes.at(i).toElement();
|
||
if (e.hasAttribute(userDataName) && (e.attribute(userDataName) == userDataString))
|
||
return Node(Node::Implementation(nodes.at(i)));
|
||
}
|
||
++it;
|
||
}
|
||
|
||
return Node();
|
||
} // QDomNode GeometryModelQDom::findPrimitive(int userData) const
|
||
|
||
|
||
bool GeometryModelQDom::hasUserData(const Node &node) const { return hasUserData(node.get().node()); }
|
||
int GeometryModelQDom::getUserData(const Node &node, bool *ok) const { return getUserData(node.get().node(), ok); }
|
||
|
||
|
||
bool GeometryModelQDom::hasUserData(const QDomNode &node) const { return node.toElement().hasAttribute(userDataName); }
|
||
|
||
|
||
int GeometryModelQDom::getUserData(const QDomNode &node, bool *okPtr) const
|
||
{
|
||
if (okPtr) *okPtr = false; // if provided, initialize
|
||
|
||
int result = 0;
|
||
bool ok = false;
|
||
|
||
QDomElement e = node.toElement();
|
||
if (e.hasAttribute(userDataName))
|
||
{
|
||
QString value = e.attribute(userDataName);
|
||
result = value.toInt(&ok, 10);
|
||
if (!(ok))
|
||
emit const_cast<GeometryModelQDom*>(this)->modelError(tr("Can not convert value to int: %1").arg(value));
|
||
}
|
||
else
|
||
{
|
||
PrimitiveType type = getType(node);
|
||
|
||
if ((type != PrimitiveType::Node) && (type != PrimitiveType::RootNode) && (type != PrimitiveType::Unknown))
|
||
{
|
||
qWarning() << "Missing user data at node " << node.nodeName() << " connectedId=" << Node::Implementation(node).connectedId()
|
||
<< " [maybe m_internal->m_modelClipboard->clearModel()]";
|
||
// #ifdef LTS_DEBUG
|
||
// // *** To locate a bug stop program here and start debugger, should be removed for final release
|
||
// assert(false);
|
||
// // ***
|
||
// #endif
|
||
emit const_cast<GeometryModelQDom*>(this)->typeError(tr("No UserData in %1").arg(node.nodeName()));
|
||
}
|
||
return SituationMap::IdHandler::BadId;
|
||
}
|
||
if (okPtr) *okPtr = ok;
|
||
return result;
|
||
} // void* GeometryModelQDom::getUserData(QDomNode node, bool *ok)
|
||
|
||
|
||
void GeometryModelQDom::setUserData(const Node &node, int userData)
|
||
{
|
||
PrimitiveType type = getType(node);
|
||
|
||
if ((type == PrimitiveType::Node) || (type == PrimitiveType::RootNode) || (type == PrimitiveType::Unknown))
|
||
emit typeError(tr("Can not set UserData in %1").arg(node.get()->nodeName()));
|
||
else
|
||
{
|
||
if (!SituationMap::IdHandler::isIdValid(userData))
|
||
{
|
||
QDomElement e = node.get()->toElement();
|
||
e.removeAttribute(userDataName);
|
||
}
|
||
else
|
||
{
|
||
QString userDataString = QString::number(userData, 10);
|
||
QDomElement e = node.get()->toElement();
|
||
e.setAttribute(userDataName, userDataString);
|
||
}
|
||
emitChangedSignal(node, Attribute::MaxAttributes, false);
|
||
}
|
||
} // void GeometryModelQDom::setUserData(QDomNode node, int userData)
|
||
|
||
|
||
QMultiMap<int, GeometryModel::Node> GeometryModelQDom::userDataMap(const Node &node)
|
||
{
|
||
QMultiMap<int, QDomNode> domResult = userDataMap(node.get().node());
|
||
QMultiMap<int, GeometryModel::Node> result;
|
||
|
||
QMultiMap<int, QDomNode>::const_iterator iter = domResult.constBegin();
|
||
|
||
for (; iter != domResult.constEnd(); ++iter)
|
||
result.insert(iter.key(), Node(Node::Implementation(iter.value())));
|
||
|
||
return result;
|
||
} // QMultiMap<int, GeometryModel::Node> GeometryModelQDom::userDataMap(const Node & node)
|
||
|
||
|
||
QMultiMap<int, QDomNode> GeometryModelQDom::userDataMap(const QDomNode &node) const
|
||
{
|
||
QMultiMap<int, QDomNode> result;
|
||
if ((node.ownerDocument() != *this) && (! node.isNull()))
|
||
{
|
||
// Not a Node of this Document, ignore
|
||
return result;
|
||
}
|
||
|
||
QDomNodeList children;
|
||
if ((node == *this) || node.isNull())
|
||
children = firstChildElement(rootNodeName).childNodes();
|
||
else if ((getType(node) == PrimitiveType::Node) || (getType(node) == PrimitiveType::RootNode))
|
||
children = node.childNodes();
|
||
|
||
for (int i = 0; i < children.size(); ++i)
|
||
{
|
||
QDomNode curNode = children.at(i);
|
||
if (getType(curNode) == PrimitiveType::Node)
|
||
{
|
||
// If its a node, search deep and merge results...
|
||
QMultiMap<int, QDomNode> deepResult = userDataMap(curNode);
|
||
QMap<int, QDomNode>::const_iterator it = deepResult.constBegin();
|
||
while (it != deepResult.constEnd())
|
||
{
|
||
int key = it.key();
|
||
QList<QDomNode> values = deepResult.values(key);
|
||
for (int k = 0; k < values.size(); ++k)
|
||
result.insert(key, values.at(k));
|
||
++it;
|
||
}
|
||
|
||
}
|
||
else
|
||
{
|
||
// ...get UserData and append to result
|
||
bool ok;
|
||
int userData = getUserData(curNode, &ok);
|
||
if (ok)
|
||
result.insert(userData, curNode);
|
||
}
|
||
}
|
||
return result;
|
||
} // QMultiMap<int, QDomNode> GeometryModelQDom::userDataMap(QDomNode node)
|
||
|
||
|
||
static void resetUserData(const QDomNode &node)
|
||
{
|
||
const QDomNodeList &childNodes = node.childNodes();
|
||
for (int i = 0; i < childNodes.size(); ++i)
|
||
resetUserData(childNodes.at(i));
|
||
node.toElement().removeAttribute(userDataName);
|
||
node.toElement().removeAttribute(connectionIdName);
|
||
|
||
} // resetUserData (QDomNode & node)
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::copy(const Node &node, int)
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
pushUndo(QLatin1String("copy"));
|
||
|
||
QDomNode clone = node.get()->cloneNode(true);
|
||
|
||
resetUserData(clone);
|
||
|
||
QDomNode result = root.appendChild(clone);
|
||
emitChangedSignal(Node(), Attribute::MaxAttributes, false);
|
||
return Node(Node::Implementation(result));
|
||
} // GeometryModel::Node GeometryModelQDom::copy(Node node, int userData)
|
||
|
||
|
||
GeometryModelQDom::PrimitiveType GeometryModelQDom::getType(const Node &node) const { return getType(node.get().node()); }
|
||
|
||
|
||
GeometryModelQDom::PrimitiveType GeometryModelQDom::getType(const QDomNode &node) const
|
||
{
|
||
QString tag = node.nodeName();
|
||
if (_primitiveTagsTypes.contains(tag)) return _primitiveTagsTypes[tag];
|
||
else return PrimitiveType::Unknown;
|
||
} // PrimitiveType GeometryModelQDom::getType(QDomNode node) const
|
||
|
||
|
||
unsigned int GeometryModelQDom::redoSteps() const { return _redoStack.size(); }
|
||
unsigned int GeometryModelQDom::undoSteps() const { return _undoStack.size(); }
|
||
|
||
|
||
QString GeometryModelQDom::attributeToString(const Attribute &attribute) const
|
||
{
|
||
switch (attribute)
|
||
{
|
||
case Attribute::AbcProtection: return QLatin1String("abc_protection");
|
||
case Attribute::Affiliation: return QLatin1String("affil");
|
||
case Attribute::Alignment: return QLatin1String("alignment");
|
||
case Attribute::AnchorHorizontal: return QLatin1String("anchor_horizontal");
|
||
case Attribute::AnchorVertical: return QLatin1String("anchor_vertical");
|
||
case Attribute::ArrowClampHeight: return QLatin1String("arrow_clamp_height");
|
||
case Attribute::ArrowHeight: return QLatin1String("arrow_height");
|
||
case Attribute::ArrowLineWidth: return QLatin1String("arrow_line_width");
|
||
case Attribute::Arrows: return QLatin1String("arrows");
|
||
case Attribute::ArrowWidth: return QLatin1String("arrow_width");
|
||
case Attribute::Box: return QLatin1String("box");
|
||
case Attribute::Center: return QLatin1String("center_point");
|
||
case Attribute::Close: return QLatin1String("close");
|
||
case Attribute::Color: return QLatin1String("color");
|
||
case Attribute::Extent: return QLatin1String("extent");
|
||
case Attribute::Fill: return QLatin1String("fill");
|
||
case Attribute::FillColor: return QLatin1String("FillColor");
|
||
case Attribute::FillPattern: return QLatin1String("FillPattern");
|
||
case Attribute::FillStyle: return QLatin1String("FillStyle");
|
||
case Attribute::Font: return QLatin1String("font");
|
||
case Attribute::FontBold: return QLatin1String("FontBold");
|
||
case Attribute::FontItalic: return QLatin1String("FontItalic");
|
||
case Attribute::FontSize: return QLatin1String("FontSize");
|
||
case Attribute::Height: return QLatin1String("height");
|
||
case Attribute::LineColor: return QLatin1String("linecolor");
|
||
case Attribute::LineStyle: return QLatin1String("linestyle");
|
||
case Attribute::LineWidth: return QLatin1String("linewidth");
|
||
case Attribute::MarginHorizontal: return QLatin1String("margin_horizontal");
|
||
case Attribute::MarginVertical: return QLatin1String("margin_vertical");
|
||
case Attribute::Mobility: return QLatin1String("mobility");
|
||
case Attribute::SIDC: return QLatin1String("sidc");
|
||
case Attribute::SIDC_Color: return QLatin1String("sidc_color");
|
||
case Attribute::SIDC_Attributes: return QLatin1String("sidc_attributes");
|
||
case Attribute::SymbolId: return QLatin1String("symbol_id");
|
||
case Attribute::SymbolOffsetX: return QLatin1String("symbol_offsetX");
|
||
case Attribute::SymbolOffsetY: return QLatin1String("symbol_offsetY");
|
||
case Attribute::SymbolDirection: return QLatin1String("symbol_direction");
|
||
case Attribute::ForceId: return QLatin1String("force_id");
|
||
case Attribute::SymbolState: return QLatin1String("symbolState");
|
||
case Attribute::SymbolUncertainty: return QLatin1String("symbolUncertainty");
|
||
case Attribute::SymbolExplicitScale: return QLatin1String("explicitScale");
|
||
case Attribute::DamageForceId: return QLatin1String("damage_force_id");
|
||
case Attribute::Injury: return QLatin1String("injury");
|
||
case Attribute::PeMapBrightness: return QLatin1String("pe_map_brightness");
|
||
case Attribute::PeMapCenterX: return QLatin1String("pe_map_centerx");
|
||
case Attribute::PeMapCenterY: return QLatin1String("pe_map_centery");
|
||
case Attribute::PeMapSaturation: return QLatin1String("pe_map_saturation");
|
||
case Attribute::PeMapZoom: return QLatin1String("pe_map_zoom");
|
||
case Attribute::PeMapRotation: return QLatin1String("pe_map_rotation");
|
||
case Attribute::PeMapType: return QLatin1String("pe_map_type");
|
||
case Attribute::PeShowUtm: return QLatin1String("pe_show_utm");
|
||
|
||
case Attribute::PeSymbolOpacity: return QLatin1String("symbol_opacity");
|
||
case Attribute::PeSymbolFillType: return QLatin1String("pe_symbol_fill_type");
|
||
case Attribute::PeSymbolScale: return QLatin1String("pe_symbol_scale");
|
||
|
||
case Attribute::MetaDataTitle: return QLatin1String("meta_data_title");
|
||
case Attribute::MetaDataAuthor: return QLatin1String("meta_data_author");
|
||
case Attribute::MetaDataDate: return QLatin1String("meta_data_date");
|
||
case Attribute::MetaDataDesciption: return QLatin1String("meta_data_description");
|
||
case Attribute::MetaDataMinScale: return QLatin1String("meta_data_min_scale");
|
||
case Attribute::MetaDataMaxScale: return QLatin1String("meta_data_max_scale");
|
||
case Attribute::MetaPixelBasedTextBoxes: return QLatin1String("meta_pixel_based_text_boxes");
|
||
|
||
case Attribute::Rotate: return QLatin1String("rotate");
|
||
case Attribute::Rounding: return QLatin1String("rounding");
|
||
case Attribute::Start: return QLatin1String("start");
|
||
case Attribute::Text_EF: return QLatin1String("text_ef");
|
||
case Attribute::Text_G: return QLatin1String("text_g");
|
||
case Attribute::Text_H: return QLatin1String("text_h");
|
||
case Attribute::Text_KLNPJ: return QLatin1String("text_jklnp");
|
||
case Attribute::Text_M: return QLatin1String("text_m");
|
||
case Attribute::Text_T: return QLatin1String("text_t");
|
||
case Attribute::Text_V: return QLatin1String("text_v");
|
||
case Attribute::Text_W: return QLatin1String("text_w");
|
||
case Attribute::Text_XY: return QLatin1String("text_xy");
|
||
case Attribute::Text_Z: return QLatin1String("text_z");
|
||
case Attribute::UtmEast: return QLatin1String("utm_east");
|
||
case Attribute::UtmGrid: return QLatin1String("utm_grid");
|
||
case Attribute::UtmNorth: return QLatin1String("utm_north");
|
||
case Attribute::UtmZone: return QLatin1String("utm_zone");
|
||
case Attribute::Width: return QLatin1String("width");
|
||
case Attribute::att_vbg_et: return QLatin1String("w_vbg_et");
|
||
default: return QLatin1String("Unknown Attribute");
|
||
}
|
||
} // QString GeometryModelQDom::attributeToString(Attribute attribute) const
|
||
|
||
|
||
|
||
void GeometryModelQDom::init()
|
||
{
|
||
using index = QPair<GeometryModelQDom::PrimitiveType, GeometryModelQDom::Attribute>;
|
||
|
||
// Only once
|
||
if (! _staticInitDone)
|
||
{
|
||
// Create mapping between primitive-types and their string/tag-name
|
||
|
||
_primitiveTagsTypes[QLatin1String("participantSymbol")] = PrimitiveType::ParticipantSymbol;
|
||
_primitiveTagsTypes[QLatin1String("dictionarySymbol")] = PrimitiveType::DictionarySymbol;
|
||
_primitiveTagsTypes[QLatin1String("ellipse")] = PrimitiveType::Ellipse;
|
||
_primitiveTagsTypes[QLatin1String("line")] = PrimitiveType::Line;
|
||
_primitiveTagsTypes[QLatin1String("polyline")] = PrimitiveType::Polyline;
|
||
_primitiveTagsTypes[QLatin1String("rectangle")] = PrimitiveType::Rectangle;
|
||
_primitiveTagsTypes[QLatin1String("spline")] = PrimitiveType::Spline;
|
||
_primitiveTagsTypes[QLatin1String("symbol")] = PrimitiveType::Symbol;
|
||
_primitiveTagsTypes[QLatin1String("text")] = PrimitiveType::Text;
|
||
_primitiveTagsTypes[QLatin1String("node")] = PrimitiveType::Node;
|
||
_primitiveTagsTypes[rootNodeName] = PrimitiveType::RootNode;
|
||
|
||
_primitiveTagsStrings[PrimitiveType::ParticipantSymbol] = QLatin1String("participantSymbol");
|
||
_primitiveTagsStrings[PrimitiveType::DictionarySymbol] = QLatin1String("dictionarySymbol");
|
||
_primitiveTagsStrings[PrimitiveType::Ellipse] = QLatin1String("ellipse");
|
||
_primitiveTagsStrings[PrimitiveType::Line] = QLatin1String("line");
|
||
_primitiveTagsStrings[PrimitiveType::Polyline] = QLatin1String("polyline");
|
||
_primitiveTagsStrings[PrimitiveType::Rectangle] = QLatin1String("rectangle");
|
||
_primitiveTagsStrings[PrimitiveType::Spline] = QLatin1String("spline");
|
||
_primitiveTagsStrings[PrimitiveType::Symbol] = QLatin1String("symbol");
|
||
_primitiveTagsStrings[PrimitiveType::Text] = QLatin1String("text");
|
||
_primitiveTagsStrings[PrimitiveType::Node] = QLatin1String("node");
|
||
|
||
|
||
// Don't set
|
||
// _primitiveTagsStrings[PrimitiveType::RootNode] = rootNodeName;
|
||
// because the root node can not be created from interface.
|
||
|
||
// Create mapping between node-types and supported attributes
|
||
// "Unknown" is used for plan-attributes
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataTitle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataAuthor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataDate);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataDesciption);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataMinScale);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaDataMaxScale);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::RootNode, Attribute::MetaPixelBasedTextBoxes);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapBrightness);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapCenterX);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapCenterY);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapSaturation);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapZoom);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapRotation);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeMapType);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeShowUtm);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeSymbolOpacity);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeSymbolFillType);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::PeSymbolScale);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::UtmEast);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::UtmGrid);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::UtmNorth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::MapDefaults, Attribute::UtmZone);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::DictionarySymbol, Attribute::SIDC);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::DictionarySymbol, Attribute::SIDC_Attributes);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::SIDC);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::SIDC_Attributes);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::ForceId);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::SymbolState);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::DamageForceId);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Injury);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_EF);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_G);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_H);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_KLNPJ);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_M);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_T);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_V);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_W);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_XY);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::ParticipantSymbol, Attribute::Text_Z);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Center);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Height);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Width);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Extent);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Fill);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::FillColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::FillPattern);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::FillStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::LineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Rotate);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Ellipse, Attribute::Start);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::ArrowClampHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::ArrowHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::ArrowLineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::Arrows);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::ArrowWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Line, Attribute::LineWidth);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::ArrowClampHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::ArrowHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::ArrowLineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::Arrows);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::ArrowWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::Close);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::Fill);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::FillColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::FillPattern);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Polyline, Attribute::LineWidth);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Center);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Height);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Width);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Fill);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::FillColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::FillPattern);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::LineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Rotate);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Rectangle, Attribute::Rounding);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::ArrowClampHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::ArrowHeight);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::ArrowLineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::Arrows);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::ArrowWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::Close);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::Fill);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::FillColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::FillPattern);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Spline, Attribute::LineWidth);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::AbcProtection);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Affiliation);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Mobility);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolId);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolOffsetX);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolOffsetY);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolDirection);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::ForceId);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolState);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolUncertainty);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::SymbolExplicitScale);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::DamageForceId);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_EF);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_G);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_H);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_KLNPJ);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_M);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_T);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_V);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_W);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_XY);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::Text_Z);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Symbol, Attribute::att_vbg_et);
|
||
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::AnchorHorizontal);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::AnchorVertical);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::Box);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::Color);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::Fill);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::FillColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::FillPattern);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::Font);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::FontBold);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::FontItalic);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::FontSize);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::LineColor);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::LineStyle);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::LineWidth);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::MarginHorizontal);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::MarginVertical);
|
||
_primitiveSupportedAttributes.insert(PrimitiveType::Text, Attribute::Rotate);
|
||
|
||
// Init all default-values for all required attributes
|
||
QFont defaultFont;
|
||
int fontSize = defaultFont.pixelSize();
|
||
|
||
// TODO: Find better defaults
|
||
|
||
// "Unknown" is used for plan-attributes
|
||
_attributeDefaults.insert(index(PrimitiveType::DictionarySymbol, Attribute::SIDC), QLatin1String("------------"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::ParticipantSymbol, Attribute::SIDC), QLatin1String("------------"));
|
||
_attributeDefaults.insert(index(PrimitiveType::ParticipantSymbol, Attribute::SIDC_Color), variant2XmlString(QColor(0, 0, 0, 0)));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataTitle), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataAuthor), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataDate), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataDesciption), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataMinScale), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::RootNode, Attribute::MetaDataMaxScale), QString());
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Center), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Height), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Width), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Extent), QLatin1String("360"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Fill), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::FillColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::FillPattern), QLatin1String("none"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::FillStyle), QLatin1String("pieslice"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::LineWidth), QLatin1String("0.1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Rotate), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Ellipse, Attribute::Start), QLatin1String("0"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::ArrowClampHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::ArrowHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::ArrowLineWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::Arrows), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::ArrowWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Line, Attribute::LineWidth), QLatin1String("0.1"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::ArrowClampHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::ArrowHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::ArrowLineWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::Arrows), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::ArrowWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::Close), QLatin1String("1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::Fill), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::FillColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::FillPattern), QLatin1String("none"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Polyline, Attribute::LineWidth), QLatin1String("0.1"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Center), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Height), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Width), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Fill), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::FillColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::FillPattern), QLatin1String("none"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::LineWidth), QLatin1String("0.1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Rotate), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Rectangle, Attribute::Rounding), QLatin1String("0.0"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::ArrowClampHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::ArrowHeight), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::ArrowLineWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::Arrows), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::ArrowWidth), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::Close), QLatin1String("1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::Fill), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::FillColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::FillPattern), QLatin1String("none"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Spline, Attribute::LineWidth), QLatin1String("0.1"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::AbcProtection), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Affiliation), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Mobility), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolId), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolOffsetX), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolOffsetY), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolDirection), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::ForceId), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolState), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolUncertainty), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::SymbolExplicitScale), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::DamageForceId), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_EF), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_G), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_H), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_KLNPJ), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_M), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_T), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_V), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_W), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_XY), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::Text_Z), QString());
|
||
_attributeDefaults.insert(index(PrimitiveType::Symbol, Attribute::att_vbg_et), QString());
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::AnchorHorizontal), QLatin1String("center"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::AnchorVertical), QLatin1String("center"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::Box), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::Color), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::Fill), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::FillColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::FillPattern), QLatin1String("none"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::Font), defaultFont.key());
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::FontBold), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::FontItalic), QLatin1String("0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::FontSize), QString::number(fontSize));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::LineColor), QColor().name());
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::LineStyle), QLatin1String("solid"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::LineWidth), QLatin1String("0.1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::MarginHorizontal), QLatin1String("1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::MarginVertical), QLatin1String("1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::Text, Attribute::Rotate), QLatin1String("0"));
|
||
|
||
_attributeTypes[Attribute::AbcProtection] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::Affiliation] = QVariant::UserType; // Type: Symbol::t_affil
|
||
_attributeTypes[Attribute::Alignment] = QVariant::UserType; // Type: HorizontalAlign
|
||
_attributeTypes[Attribute::AnchorHorizontal] = QVariant::UserType; // Type: HorizontalAlign
|
||
_attributeTypes[Attribute::AnchorVertical] = QVariant::UserType; // Type: t_valign
|
||
_attributeTypes[Attribute::ArrowClampHeight] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::ArrowHeight] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::ArrowLineWidth] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Arrows] = QVariant::UserType; // Type: t_arrows
|
||
_attributeTypes[Attribute::ArrowWidth] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Box] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::Center] = QVariant::PointF; // Type: PointF
|
||
_attributeTypes[Attribute::Close] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::Color] = QVariant::Color; // Type: QColor
|
||
_attributeTypes[Attribute::Extent] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Fill] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::FillColor] = QVariant::Color; // Type: QColor
|
||
_attributeTypes[Attribute::FillPattern] = QVariant::UserType; // Type: t_fillPattern
|
||
_attributeTypes[Attribute::FillStyle] = QVariant::UserType; // Type: t_fillStyle
|
||
_attributeTypes[Attribute::Font] = QVariant::UserType; // Type: t_font
|
||
_attributeTypes[Attribute::FontBold] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::FontItalic] = QVariant::Bool; // Type: bool
|
||
_attributeTypes[Attribute::FontSize] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::LineColor] = QVariant::Color; // Type: QColor
|
||
_attributeTypes[Attribute::LineStyle] = QVariant::UserType; // Type: t_lineStyle
|
||
_attributeTypes[Attribute::LineWidth] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::MarginHorizontal] = QVariant::UserType; // Type: int
|
||
_attributeTypes[Attribute::MarginVertical] = QVariant::UserType; // Type: int
|
||
_attributeTypes[Attribute::Mobility] = QVariant::UserType; // Type: Symbol::t_mob
|
||
_attributeTypes[Attribute::SIDC] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::SIDC_Color] = QVariant::Color; // Type: QColor
|
||
_attributeTypes[Attribute::SIDC_Attributes] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::SymbolId] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::SymbolOffsetX] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::SymbolOffsetY] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::SymbolDirection] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::ForceId] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::SymbolState] = QVariant::UserType; // Type: SymbolTypes::t_state
|
||
_attributeTypes[Attribute::SymbolUncertainty] = QVariant::UserType; // Type: SymbolTypes::t_uncertainty
|
||
_attributeTypes[Attribute::SymbolExplicitScale] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::DamageForceId] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::Injury] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::PeMapBrightness] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::PeMapCenterX] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::PeMapCenterY] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::PeMapSaturation] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::PeMapZoom] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::PeMapRotation] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::PeMapType] = QVariant::UserType; // Type: t_mapType
|
||
_attributeTypes[Attribute::PeShowUtm] = QVariant::Bool; // Type: bool
|
||
|
||
_attributeTypes[Attribute::PeSymbolOpacity] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::PeSymbolFillType] = QVariant::UserType; // Type: SymbolTypes::t_filltype
|
||
_attributeTypes[Attribute::PeSymbolScale] = QVariant::Bool; // Type: bool
|
||
|
||
_attributeTypes[Attribute::MetaDataTitle] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::MetaDataAuthor] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::MetaDataDate] = QVariant::DateTime;
|
||
_attributeTypes[Attribute::MetaDataDesciption] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::MetaDataMinScale] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::MetaDataMaxScale] = QVariant::Double; // Type: double
|
||
|
||
_attributeTypes[Attribute::Rotate] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Rounding] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Start] = QVariant::Double; // Type: double
|
||
_attributeTypes[Attribute::Text_EF] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_G] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_H] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_KLNPJ] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_M] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_T] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_V] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_W] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_XY] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::Text_Z] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::UtmEast] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::UtmGrid] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::UtmNorth] = QVariant::Int; // Type: int
|
||
_attributeTypes[Attribute::UtmZone] = QVariant::String; // Type: QString
|
||
_attributeTypes[Attribute::att_vbg_et] = QVariant::UserType; // Type: t_w_vbg_et
|
||
|
||
_staticInitDone = true;
|
||
}
|
||
|
||
QDomElement root = createElement(rootNodeName);
|
||
appendChild(root);
|
||
|
||
clearUndoStack();
|
||
} // void GeometryModelQDom::init()
|
||
|
||
void GeometryModelQDom::cleanupStaticMember()
|
||
{
|
||
_primitiveTagsTypes.clear();
|
||
_primitiveTagsStrings.clear();
|
||
_primitiveSupportedAttributes.clear();
|
||
_attributeDefaults.clear();
|
||
_attributeTypes.clear();
|
||
}
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::getMapDefaultSettingsNode() const
|
||
{
|
||
QDomElement mapSettings = firstChildElement(mapSettingsName);
|
||
|
||
if (mapSettings.isNull())
|
||
{
|
||
GeometryModelQDom *THIS = const_cast<GeometryModelQDom *>(this); // cast const away
|
||
|
||
mapSettings = THIS->createElement(mapSettingsName);
|
||
|
||
THIS->appendChild(mapSettings);
|
||
|
||
using index = QPair<GeometryModelQDom::PrimitiveType, GeometryModelQDom::Attribute>;
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapBrightness), QLatin1String("100"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapCenterX), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapCenterY), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapSaturation), QLatin1String("100"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapZoom), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapRotation), QLatin1String("0.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeMapType), QLatin1String("MapPrimitiveType::Unknown"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeShowUtm), QLatin1String("1"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::UtmEast), QLatin1String("10000"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::UtmGrid), QLatin1String("XY"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::UtmNorth), QLatin1String("10000"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::UtmZone), QLatin1String("00Z"));
|
||
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeSymbolOpacity), QLatin1String("1.0"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeSymbolFillType), QLatin1String("filled"));
|
||
_attributeDefaults.insert(index(PrimitiveType::MapDefaults, Attribute::PeSymbolScale), QLatin1String("1.0"));
|
||
|
||
// Create root-node and set required attributes
|
||
|
||
|
||
QList<Attribute> modelAttributes = supportedAttributes(PrimitiveType::MapDefaults);
|
||
for (int i = 0; i < modelAttributes.size(); ++i)
|
||
{
|
||
Attribute at = modelAttributes.at(i);
|
||
THIS->setModelEditorAttribute(at, _attributeDefaults[index(PrimitiveType::MapDefaults, at)]);
|
||
}
|
||
}
|
||
|
||
return Node(Node::Implementation(mapSettings));
|
||
|
||
} // GeometryModelQDom::getMapDefaultSettingsNode
|
||
|
||
|
||
void GeometryModelQDom::transformNode(const QDomNode &node, const QTransform &t)
|
||
{
|
||
QString tag = node.nodeName();
|
||
if (!_primitiveTagsTypes.contains(tag))
|
||
{
|
||
emit modelError(tr("Can not translate node of type %1").arg(tag));
|
||
return;
|
||
}
|
||
|
||
QDomNodeList nodes = node.childNodes();
|
||
for (int i = 0; i < nodes.size(); ++i)
|
||
{
|
||
QDomElement p = nodes.at(i).toElement();
|
||
if (p.nodeName() != QLatin1String("point"))
|
||
continue;
|
||
if (!p.hasAttribute(QLatin1String("x")) || !p.hasAttribute(QLatin1String("y")))
|
||
emit modelError(tr("Invalid point in primitive of type %1").arg(tag));
|
||
else
|
||
{
|
||
bool okx, oky;
|
||
double oldx = p.toElement().attribute(QLatin1String("x")).toDouble(&okx);
|
||
double oldy = p.toElement().attribute(QLatin1String("y")).toDouble(&oky);
|
||
if (!(okx && oky))
|
||
emit modelError(tr("Invalid point in primitive of type %1").arg(tag));
|
||
else
|
||
{
|
||
QPointF point = t.map(QPointF(oldx, oldy));
|
||
p.setAttribute(QLatin1String("x"), QString::number(point.x(), 'f', CoordinateDoublePrecision));
|
||
p.setAttribute(QLatin1String("y"), QString::number(point.y(), 'f', CoordinateDoublePrecision));
|
||
}
|
||
}
|
||
}
|
||
} // void GeometryModelQDom::transformNode(QDomNode node, QTransform t)
|
||
|
||
|
||
void GeometryModelQDom::emitChangedSignal(const Node &node, Attribute att, bool coordsChanged)
|
||
{
|
||
if (!_skipChangedSignal)
|
||
emit changed(node, att, coordsChanged);
|
||
} // void GeometryModelQDom::emitChangedSignal(QDomNode node, Attribute att, bool coordsChanged)
|
||
|
||
|
||
void GeometryModelQDom::pushUndo(const QString &eventDescription)
|
||
{
|
||
if (_undoEnabled && (! _insideUndoBlock))
|
||
{
|
||
QDomElement root = firstChildElement(rootNodeName);
|
||
while (undoSteps() >= _maxUndoSteps)
|
||
{
|
||
// Size-limit reached, remove first element
|
||
_undoStack.erase(_undoStack.begin());
|
||
_undoHistory.erase(_undoHistory.begin());
|
||
}
|
||
_undoStack.push(root.cloneNode());
|
||
_undoHistory.push(eventDescription);
|
||
}
|
||
if (_insideUndoBlock)
|
||
_undoHistoryBlock = eventDescription;
|
||
} // void GeometryModelQDom::pushUndo(const QString &eventDescription)
|
||
|
||
|
||
GeometryModel::Node GeometryModelQDom::popUndo()
|
||
{
|
||
if (_undoEnabled && (! _insideUndoBlock))
|
||
{
|
||
_undoHistory.pop();
|
||
return Node(Node::Implementation(_undoStack.pop()));
|
||
}
|
||
return Node();
|
||
} // void GeometryModelQDom::pushUndo()
|
||
|
||
|
||
|
||
bool GeometryModelQDom::parseSymbolAttributeString(const QString &sidcAttributes, QMap<QString, QVariant> &attrMap) const
|
||
{
|
||
attrMap.clear();
|
||
|
||
if (sidcAttributes.isEmpty()) return true;
|
||
|
||
bool ok = true;
|
||
const QVector<QStringRef> sidcAttrList = sidcAttributes.splitRef(QLatin1Char(';'));
|
||
|
||
for (const QStringRef &attr : sidcAttrList)
|
||
{
|
||
const QVector<QStringRef> &attrPair = attr.split(QLatin1Char('='));
|
||
if (attrPair.size() != 2)
|
||
{
|
||
ok = false;
|
||
QString errorString = tr("%1 Parsing symbol attribute list failed. %2").arg(QString::fromStdString(LOGFUNCTION), attr.toString());
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(errorString);
|
||
continue;
|
||
}
|
||
attrMap[attrPair.first().toString()] = attrPair.last().toString();
|
||
}
|
||
return ok;
|
||
} // bool GeometryModelQDom::parseSymbolAttributeString( const QString & sidcAttributes, QMap<QString,QVariant> & attrMap ) const
|
||
|
||
|
||
QString GeometryModelQDom::buildSymbolAttributeString(const QMap<QString, QVariant> &attrMap) const
|
||
{
|
||
QString attributeString;
|
||
|
||
QMap<QString, QVariant>::const_iterator iter = attrMap.cbegin();
|
||
while (attrMap.cend() != iter)
|
||
{
|
||
const QString &key = iter.key();
|
||
const QString &val = iter.value().toString();
|
||
|
||
if (!val.isEmpty())
|
||
{
|
||
if (key.isEmpty())
|
||
{
|
||
QString errorString = tr("%1 Empty key found").arg(QString::fromStdString(LOGFUNCTION));
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(errorString);
|
||
++iter;
|
||
continue;
|
||
}
|
||
|
||
if (val.contains(QLatin1Char('=')) || val.contains(QLatin1Char(';')))
|
||
{
|
||
QString errorString = tr("%1 Attribute value has illegal characters <;=> : %2").arg(QString::fromStdString(LOGFUNCTION), val);
|
||
emit const_cast<GeometryModelQDom*>(this)->attributeError(errorString);
|
||
++iter;
|
||
continue;
|
||
}
|
||
|
||
if (!attributeString.isEmpty()) attributeString += QLatin1Char(';');
|
||
attributeString += QStringLiteral("%1=%2").arg(key, val);
|
||
}
|
||
++iter;
|
||
}
|
||
return attributeString;
|
||
} // QString GeometryModelQDom::buildSymbolAttributeString(const QMap<QString, QVariant> & attrMap) const
|
||
|
||
|
||
} // namespace SituationMap
|