375 lines
13 KiB
C++
Executable File
375 lines
13 KiB
C++
Executable File
/**
|
|
**
|
|
** @RDE_HEADER@
|
|
** GeometryModel implementation to write and read PlanEditor plans from/to XML and manipulate DOM-tree.
|
|
** $Id$
|
|
** $HeadURL$
|
|
** $Author$
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Hardware-Environment: Intel-PC
|
|
** Software-Environment: Windows 7, Qt 5.4. ArcGIS 10.2.5
|
|
**
|
|
** Language ........: C++ 11
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Author ...........: Stephan Kuhagen <kuhagen@rheinmetall-de.com>
|
|
** Jörg Turla, SPD G, Tel. 3132
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
**
|
|
** Notes .........:
|
|
**
|
|
** ??.??.200?, SK : First edition for use with Qt4
|
|
** 11.11.2015, JT : Splitting interface and implementation
|
|
**
|
|
** -----------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
// clazy:excludeall=const-signal-or-slot
|
|
|
|
#pragma once
|
|
|
|
#include <QtGui/QColor>
|
|
#include <QtXml/QDomDocument>
|
|
#include <QtCore/QMultiMap>
|
|
#include <QtCore/QObject>
|
|
#include <QtCore/QPair>
|
|
#include <QtCore/QPointF>
|
|
#include <QtCore/QRectF>
|
|
#include <QtCore/QStack>
|
|
#include <QtCore/QString>
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QVariant>
|
|
|
|
#include "geometry_model.h"
|
|
class QTransform;
|
|
|
|
namespace SituationMap
|
|
{
|
|
|
|
// exported for unit test only
|
|
class GEOMETRYMODEL_EXPORT GeometryModelQDom : public GeometryModel, public QDomDocument
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
public:
|
|
|
|
explicit GeometryModelQDom(QObject *parent = nullptr);
|
|
|
|
//! Copy-Constructor
|
|
GeometryModelQDom(const GeometryModelQDom &other);
|
|
|
|
~GeometryModelQDom();
|
|
|
|
GeometryModelQDom & operator = (const GeometryModelQDom &other);
|
|
|
|
QByteArray toByteArray() const override;
|
|
QByteArray toByteArrayDebug() const override;
|
|
|
|
bool fromByteArray(const QByteArray &content) override;
|
|
bool fromDevice(QIODevice *device) override;
|
|
bool fromByteArrayDebug(const QByteArray &content) override;
|
|
|
|
bool isEmpty() const override;
|
|
|
|
Node getRootNode() const override;
|
|
|
|
Node getMapDefaultSettingsNode() const override;
|
|
|
|
void setModelAttribute(GeometryModel::Attribute attribute, const QVariant &value) override;
|
|
|
|
void setModelEditorAttribute(GeometryModel::Attribute attribute, const QVariant &value) override;
|
|
|
|
void setPrimitiveAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute, const QVariant &value) override;
|
|
|
|
void movePrimitiveIntoGroup(const GeometryModel::Node &primitive, const GeometryModel::Node &target) override;
|
|
|
|
void releaseGroup(const GeometryModel::Node &group) override;
|
|
|
|
void deleteGroup(const GeometryModel::Node &group) override;
|
|
|
|
void removePrimitive(const GeometryModel::Node &primitive) override;
|
|
|
|
void removePrimitivesByUserData(const QList<int> &userDataList) override;
|
|
|
|
void removeText(GeometryModel::Node &parent) override;
|
|
|
|
void setTextData(const GeometryModel::Node &textNode, const QString &data, GeometryModel::HorizontalAlign textAlign) override;
|
|
|
|
void clearModel() override;
|
|
|
|
void translateNode(const GeometryModel::Node &node, double x, double y) override;
|
|
|
|
void moveNode(const GeometryModel::Node &node, double x, double y) override;
|
|
|
|
void scaleNode(const GeometryModel::Node &node, double scaleX, double scaleY) override;
|
|
|
|
|
|
void rotateNode(const GeometryModel::Node &node, double angle) override;
|
|
|
|
void reorderPrimitives(const QList<GeometryModel::Node> &nodes, GeometryModel::PrimitivOrder order) override;
|
|
|
|
void merge(const GeometryModel::Node &other, bool skipUndo = false, bool intoNewGroup = false) override;
|
|
|
|
void merge(GeometryModel *other, bool skipUndo = false, bool intoNewGroup = false) override;
|
|
|
|
unsigned int modificationCounter() const override;
|
|
|
|
void resetModificationCounter() override;
|
|
|
|
void undo(unsigned int steps = 1) override;
|
|
|
|
void redo(unsigned int steps = 1) override;
|
|
|
|
void enableUndo(bool enable) override;
|
|
|
|
void startUndoBlock() override;
|
|
|
|
void endUndoBlock(const QString &eventDescription = QString()) override;
|
|
|
|
void abortUndoBlock() override;
|
|
|
|
void setMaxUndoSteps(unsigned int max) override;
|
|
|
|
unsigned int maxUndoSteps() const override;
|
|
|
|
void cleanModel() override;
|
|
|
|
|
|
GeometryModel::Node addPrimitive(GeometryModel::PrimitiveType type
|
|
, const QList<QPointF> &points
|
|
, const QList<QPair<GeometryModel::Attribute, QVariant> > &attributes
|
|
, int userData = -1
|
|
, const QString &textData = QString()
|
|
, GeometryModel::HorizontalAlign textAlign = HorizontalAlign::Left) override;
|
|
|
|
|
|
bool setPrimitivePoints(const GeometryModel::Node &node, const QList<QPointF> &points) override;
|
|
|
|
GeometryModel::Node addText(const GeometryModel::Node &parent
|
|
, const QString &textData
|
|
, GeometryModel::HorizontalAlign textAlign
|
|
, const QList<QPair<GeometryModel::Attribute, QVariant> > &attributes
|
|
, int userData) override;
|
|
|
|
GeometryModel::Node getText(const GeometryModel::Node &parent) const override;
|
|
|
|
QString getTextData(const GeometryModel::Node &textNode) const override;
|
|
|
|
QList<QPointF> getPrimitivePoints(const GeometryModel::Node &node) const override;
|
|
|
|
QRectF getBoundingBox(const GeometryModel::Node &node) const override;
|
|
|
|
void setNodeDisplayName(const Node &node, const QString &name) override;
|
|
|
|
QString getNodeDisplayName(const Node &node) const override;
|
|
|
|
QVariant getModelAttribute(Attribute attribute) const override;
|
|
|
|
QVariant getAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute) const override;
|
|
|
|
template <class T> T getAttribute(const Node &node, Attribute attribute) const;
|
|
|
|
bool hasAttribute(const GeometryModel::Node &node, GeometryModel::Attribute attribute) const override;
|
|
|
|
QVariant::Type attributeType(const GeometryModel::Attribute &attribute) const override;
|
|
|
|
QList<GeometryModel::Attribute> supportedAttributes(GeometryModel::PrimitiveType type) const override;
|
|
|
|
GeometryModel::Node createGroup(const QList<GeometryModel::Node> &primitives) override;
|
|
|
|
GeometryModel::Node isInGroup(const GeometryModel::Node &primitive) const override;
|
|
|
|
GeometryModel::NodeList getGroupPrimitives(const GeometryModel::Node &node) override;
|
|
|
|
GeometryModel::Node findPrimitive(int userData) const override;
|
|
|
|
bool hasUserData(const Node &node) const override;
|
|
|
|
int getUserData(const GeometryModel::Node &node, bool *ok = nullptr) const override;
|
|
|
|
void setUserData(const GeometryModel::Node &node, int userData) override;
|
|
|
|
QMultiMap<int, GeometryModel::Node> userDataMap(const GeometryModel::Node &node = GeometryModel::Node()) override;
|
|
|
|
GeometryModel::Node copy(const GeometryModel::Node &node, int userData = 0) override;
|
|
|
|
GeometryModel::PrimitiveType getType(const GeometryModel::Node &node) const override;
|
|
|
|
unsigned int undoSteps() const override;
|
|
|
|
unsigned int redoSteps() const override;
|
|
|
|
QStringList undoHistory() const override { return _undoHistory.toList(); }
|
|
|
|
QStringList redoHistory() const override { return _redoHistory.toList(); }
|
|
|
|
void clearUndoStack() override
|
|
{
|
|
_undoStack.clear();
|
|
_undoHistory.clear();
|
|
} // clearUndoStack
|
|
|
|
void clearRedoStack() override
|
|
{
|
|
_redoStack.clear();
|
|
_redoHistory.clear();
|
|
} // clearRedoStack
|
|
|
|
QString attributeToString(const GeometryModel::Attribute &attribute) const override;
|
|
|
|
bool parseSymbolAttributeString(const QString &sidcAttributes, QMap<QString, QVariant> &attrMap) const override;
|
|
|
|
QString buildSymbolAttributeString(const QMap<QString, QVariant> &attrMap) const override;
|
|
|
|
static void cleanupStaticMember();
|
|
|
|
private:
|
|
|
|
static void valueFromVariant(const QVariant &v, QPointF &result);
|
|
static void valueFromVariant(const QVariant &v, QColor &result);
|
|
|
|
/**
|
|
convert to QString (with non locale-aware conversions)
|
|
*/
|
|
static QString variant2XmlString(const QVariant &v);
|
|
|
|
/**
|
|
Create a QColor from an attribute-value with alpha-channel (QVariant
|
|
ignores Alpha)
|
|
\param attColor: The QString-QVariant from an attribute of Type QColor
|
|
\return QColor with alpha-channel or invalid QColor, if the value could be parsed.
|
|
*/
|
|
static QColor colorFromString(const QString &attColor);
|
|
|
|
/**
|
|
Create a QPoint from an attribute-value
|
|
\param attPoint: The QString-QVariant from an attribute of Type QPointF
|
|
\return QPointF
|
|
*/
|
|
static QPointF pointFromString(const QString &attPoint);
|
|
|
|
//! A mapping between all primitives and the attributes they support
|
|
static QMultiMap<GeometryModel::PrimitiveType, GeometryModel::Attribute> _primitiveSupportedAttributes;
|
|
//! Mappings between all primitive-types and their string/tag-name
|
|
static QMap<QString, GeometryModel::PrimitiveType> _primitiveTagsTypes;
|
|
static QMap<GeometryModel::PrimitiveType, QString> _primitiveTagsStrings;
|
|
|
|
//! Default-Values for all supported attributes
|
|
static QMap<QPair<GeometryModel::PrimitiveType, GeometryModel::Attribute>, QString> _attributeDefaults;
|
|
|
|
//! Mapping between Attributes and their QVariant-Type.
|
|
static QMap<GeometryModel::Attribute, QVariant::Type> _attributeTypes;
|
|
|
|
//! Bool to check, if static class variables have been initialized
|
|
static bool _staticInitDone;
|
|
|
|
/**
|
|
Init data of the object
|
|
*/
|
|
void init();
|
|
|
|
|
|
/**
|
|
Transform the points of a primitive.
|
|
\sa {translateNode(), moveNode(), rotateNode(), scaleNode()}
|
|
\param node: The primitive to transform.
|
|
\param t: The transformation-matrix.
|
|
*/
|
|
void transformNode(const QDomNode &node, const QTransform &t);
|
|
|
|
|
|
GeometryModel::PrimitiveType getType(const QDomNode &node) const;
|
|
|
|
bool hasUserData(const QDomNode &node) const;
|
|
|
|
int getUserData(const QDomNode &node, bool *okPtr) const;
|
|
|
|
QRectF getBoundingBox(const QDomNode &node) const;
|
|
|
|
QList<QPointF> getPrimitivePoints(const QDomNode &node) const;
|
|
|
|
bool hasAttribute(const QDomNode &node, GeometryModel::Attribute attribute) const;
|
|
|
|
QVariant getAttribute(const QDomNode &node, GeometryModel::Attribute attribute) const;
|
|
|
|
void removePrimitive(const QDomNode &primitive);
|
|
|
|
void translateNode(const QDomNode &node, double x, double y);
|
|
|
|
void moveNode(const QDomNode &node, double x, double y);
|
|
|
|
void scaleNode(const QDomNode &node, double scaleX, double scaleY);
|
|
|
|
void rotateNode(const QDomNode &node, double angle);
|
|
|
|
void merge(const QDomNode &other, bool skipUndo = false, bool intoNewGroup = false);
|
|
|
|
QDomNode createGroup(const QList<QDomNode> &primitives);
|
|
|
|
QMultiMap<int, QDomNode> userDataMap(const QDomNode &node) const;
|
|
|
|
|
|
/**
|
|
Wrapper for signal changed(), checks _skipChangedSignal
|
|
|
|
!!! ATTENTION: Do not use the signal changed directly.
|
|
Use emitChangedSignal() instead !!!
|
|
|
|
\param what: Short description of the change for logging
|
|
\param node: the changed node (if this is a Null-Node, the Root-Node of
|
|
the plan has changed)
|
|
\param att: The attribute, that changed. If att==MaxAttributes, then
|
|
multiple attributes are changed
|
|
\param coordsChanged: if true, the coordinated of the primitive are changed
|
|
*/
|
|
void emitChangedSignal(const Node &node, Attribute att, bool coordsChanged);
|
|
|
|
|
|
//! Lock for temporarily blocking changed()-Signals
|
|
bool _skipChangedSignal;
|
|
|
|
//! Undo-Stack
|
|
bool _undoEnabled;
|
|
unsigned int _maxUndoSteps;
|
|
QStack<QDomNode> _undoStack;
|
|
QStack<QString> _undoHistory;
|
|
QStack<QDomNode> _redoStack;
|
|
QStack<QString> _redoHistory;
|
|
|
|
//! Undo-blocks
|
|
QDomNode _undoBlock;
|
|
QString _undoHistoryBlock;
|
|
bool _insideUndoBlock;
|
|
unsigned int _modificationCounter;
|
|
|
|
//! Push/pop current state to undo-stack, if not locked
|
|
void pushUndo(const QString &eventDescription = QString());
|
|
GeometryModel::Node popUndo();
|
|
}; // GeometryModelQDom
|
|
|
|
|
|
template <class T> T GeometryModelQDom::getAttribute(const Node &node, Attribute attribute) const
|
|
{
|
|
const QVariant &v = getAttribute(node, attribute);
|
|
|
|
switch (qMetaTypeId<T>())
|
|
{
|
|
case QMetaType::QPointF:
|
|
case QMetaType::QColor:
|
|
{
|
|
T result; valueFromVariant(v, result); return result;
|
|
} break;
|
|
|
|
default: break;
|
|
}
|
|
return v.value<T>();
|
|
} // template <class T> T GeometryModelQDom::getAttribute( const Node & node, Attribute attribute ) const
|
|
|
|
|
|
} // namespace SituationMap
|