/** ** ** @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 ** 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 #include #include #include #include #include #include #include #include #include template 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, 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(); 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(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(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 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("\n\n")); } else xmlContent( localCopy, xmlContentMem ); qDebug() << " xmlContentMem " << xmlContentMem; return xmlContentMem; } // template MemoryClass xmlString(GeometryModelQDom localCopy) QByteArray GeometryModelQDom::toByteArray() const { return xmlContent(*this); } //QString GeometryModelQDom::toString() const //{ // return xmlContent(*this); //} /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ QByteArray GeometryModelQDom::toByteArrayDebug() const { return QDomDocument::toByteArray(3); } // complete XML content for debug purposes /* ~~~~~~~~~~~~~~~~ restore GeometryModel from XML representation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ template 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 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(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 &points , const QList > &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(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; QList 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 > &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 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(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 GeometryModelQDom::getPrimitivePoints(const Node &node) const { return getPrimitivePoints(node.get().node()); } QList 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 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(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(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(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(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(this)->attributeError(tr("Wrong number of points for new primitive %1").arg(_primitiveTagsStrings[type])); return result; } // QList 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 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 &userDataList) { _skipChangedSignal = true; int removed = 0; // First delete userData, then make the undo-backup QList 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 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 &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 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 &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(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 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::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; QVariant result(_attributeTypes[attribute]); result.setValue(_attributeDefaults[index(PrimitiveType::Unknown, attribute)]); return result; } else { emit const_cast(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::supportedAttributes(PrimitiveType type) const { if (_primitiveSupportedAttributes.contains(type)) return _primitiveSupportedAttributes.values(type); else return QList(); } // QList 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 primitives) QDomNode GeometryModelQDom::createGroup(const QList &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 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::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(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(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 GeometryModelQDom::userDataMap(const Node &node) { QMultiMap domResult = userDataMap(node.get().node()); QMultiMap result; QMultiMap::const_iterator iter = domResult.constBegin(); for (; iter != domResult.constEnd(); ++iter) result.insert(iter.key(), Node(Node::Implementation(iter.value()))); return result; } // QMultiMap GeometryModelQDom::userDataMap(const Node & node) QMultiMap GeometryModelQDom::userDataMap(const QDomNode &node) const { QMultiMap 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 deepResult = userDataMap(curNode); QMap::const_iterator it = deepResult.constBegin(); while (it != deepResult.constEnd()) { int key = it.key(); QList 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 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; // 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(this); // cast const away mapSettings = THIS->createElement(mapSettingsName); THIS->appendChild(mapSettings); using index = QPair; _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 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 &attrMap) const { attrMap.clear(); if (sidcAttributes.isEmpty()) return true; bool ok = true; const QVector sidcAttrList = sidcAttributes.splitRef(QLatin1Char(';')); for (const QStringRef &attr : sidcAttrList) { const QVector &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(this)->attributeError(errorString); continue; } attrMap[attrPair.first().toString()] = attrPair.last().toString(); } return ok; } // bool GeometryModelQDom::parseSymbolAttributeString( const QString & sidcAttributes, QMap & attrMap ) const QString GeometryModelQDom::buildSymbolAttributeString(const QMap &attrMap) const { QString attributeString; QMap::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(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(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 & attrMap) const } // namespace SituationMap