initial work to move everything into the propertiesinterface which is related to it

This commit is contained in:
Martin Marmsoler
2020-08-13 23:27:11 +02:00
parent 70ef559874
commit 385d0ffd69
18 changed files with 555 additions and 226 deletions

View File

@@ -144,7 +144,7 @@ void CustomElementGraphicPart::setAntialiased(const bool b)
* Each style separate by ; and name-style/value are separate by :
* @param qde : QDOmElement used to write the style.
*/
void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const
void CustomElementGraphicPart::stylesToXml(QDomDocument &xml_document, QDomElement &qde) const
{
QString css_like_styles;
@@ -479,9 +479,8 @@ void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const
else if (_color == HTMLGrayBlackColor) css_like_styles += "HTMLGrayBlack";
else if (_color == NoneColor) css_like_styles += "none";
qde.setAttribute("style", css_like_styles);
qde.setAttribute("antialias", _antialiased ? "true" : "false");
qde.appendChild(createXmlProperty(xml_document, "style", css_like_styles));
qde.appendChild(createXmlProperty(xml_document, "antialias", _antialiased ? "true" : "false"));
}
@@ -493,13 +492,18 @@ void CustomElementGraphicPart::stylesToXml(QDomElement &qde) const
void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde)
{
resetStyles();
QString style_string;
propertyString(qde, "style", &style_string);
//Get the list of pair style/value
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // ### Qt 6: remove
QStringList styles = qde.attribute("style").split(";", QString::SkipEmptyParts);
QStringList styles = style_string.split(";", QString::SkipEmptyParts);
#else
QStringList styles = qde.attribute("style").split(";", Qt::SkipEmptyParts);
QStringList styles = style_string.split(";", Qt::SkipEmptyParts);
#endif
//Check each pair of style
QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-zA-Z-]+)\\s*$");
@@ -843,7 +847,9 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde)
}
}
//Get antialiasing
_antialiased = qde.attribute("antialias") == "true";
QString a;
propertyString(qde, "antialias", &a);
_antialiased = a == "true";
}

View File

@@ -95,7 +95,7 @@ class CustomElementGraphicPart : public QGraphicsObject, public CustomElementPar
virtual void resetAllHandlerColor() {}
protected:
void stylesToXml (QDomElement &) const;
void stylesToXml (QDomDocument &xml_document, QDomElement &) const;
void stylesFromXml(const QDomElement &);
void resetStyles ();
void applyStylesToQPainter(QPainter &) const;

View File

@@ -19,6 +19,7 @@
#define CUSTOM_ELEMENT_PART_H
#include "qet.h"
#include "propertiesinterface.h"
class CustomElement;
class ElementPrimitiveDecorator;
@@ -35,7 +36,7 @@ class QGraphicsSceneMouseEvent;
is no point for those classes to store their visual representation with
anything more complex than a QImage.
*/
class CustomElementPart {
class CustomElementPart: public PropertiesInterface {
// constructors, destructor
public:
/**
@@ -55,14 +56,6 @@ class CustomElementPart {
// methods
public:
/**
Load the primitive from an XML element that describes it
*/
virtual void fromXml(const QDomElement &) = 0;
/**
Export the primitive as an XML element
*/
virtual const QDomElement toXml(QDomDocument &) const = 0;
/**
Set a specific property of the primitive
*/

View File

@@ -98,14 +98,18 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options,
const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("arc");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
xml_element.setAttribute("width", QString("%1").arg(rect().width()));
xml_element.setAttribute("height", QString("%1").arg(rect().height()));
//to maintain compatibility with the previous version, we write the angle in degrees.
xml_element.setAttribute("start", QString("%1").arg(m_start_angle / 16));
xml_element.setAttribute("angle", QString("%1").arg(m_span_angle / 16));
stylesToXml(xml_element);
xml_element.appendChild(createXmlProperty(xml_document, "x", top_left.x()));
xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y()));
xml_element.appendChild(createXmlProperty(xml_document, "width", rect().width()));
xml_element.appendChild(createXmlProperty(xml_document, "height", rect().height()));
//to maintain compatibility with the previous version, we write the angle in degrees.
xml_element.appendChild(createXmlProperty(xml_document, "start", m_start_angle / 16));
xml_element.appendChild(createXmlProperty(xml_document, "angle", m_span_angle / 16));
stylesToXml(xml_document, xml_element);
return(xml_element);
}
@@ -115,14 +119,23 @@ const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
* @param qde : Xml document to use.
*/
void PartArc::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
m_rect = QRectF(mapFromScene(qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()),
QSizeF(qde.attribute("width", "0").toDouble(),
qde.attribute("height", "0").toDouble()) );
stylesFromXml(qde);
m_start_angle = qde.attribute("start", "0").toDouble() * 16;
m_span_angle = qde.attribute("angle", "-1440").toDouble() * 16;
double x = 0, y = 0, w = 0, h = 0; // default values
propertyDouble(qde, "x", &x);
propertyDouble(qde, "y", &y);
propertyDouble(qde, "width", &w);
propertyDouble(qde, "height", &h);
m_rect = QRectF(mapFromScene(x, y), QSizeF(w, h) );
m_start_angle = 0;
propertyDouble(qde, "start", &m_start_angle);
m_start_angle *= 16;
m_span_angle = -1440;
propertyDouble(qde, "angle", &m_span_angle);
m_span_angle *= 16;
}
/**

View File

@@ -82,20 +82,20 @@ const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const
if (qFuzzyCompare(rect().width(), rect().height()))
{
xml_element = xml_document.createElement("circle");
xml_element.setAttribute("diameter", QString("%1").arg(rect().width()));
xml_element.appendChild(createXmlProperty(xml_document, "diameter", rect().width()));
}
else
{
xml_element = xml_document.createElement("ellipse");
xml_element.setAttribute("width", QString("%1").arg(rect().width()));
xml_element.setAttribute("height", QString("%1").arg(rect().height()));
xml_element.appendChild(createXmlProperty(xml_document, "width", rect().width()));
xml_element.appendChild(createXmlProperty(xml_document, "height", rect().height()));
}
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
xml_element.appendChild(createXmlProperty(xml_document, "x", top_left.x()));
xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y()));
stylesToXml(xml_element);
stylesToXml(xml_document, xml_element);
return(xml_element);
}
@@ -108,19 +108,23 @@ const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const
void PartEllipse::fromXml(const QDomElement &qde)
{
stylesFromXml(qde);
qreal width, height;
double x = 0, y = 0, width = 0, height = 0;
if (qde.tagName() == "ellipse")
{
width = qde.attribute("width", "0").toDouble();
height = qde.attribute("height", "0").toDouble();
propertyDouble(qde, "width", &width);
propertyDouble(qde, "height", &height);
}
else
width = height = qde.attribute("diameter", "0").toDouble();
else {
propertyDouble(qde, "diameter", &width);
height = width;
}
m_rect = QRectF(mapFromScene(qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()),
QSizeF(width, height));
propertyDouble(qde, "x", &x);
propertyDouble(qde, "y", &y);
m_rect = QRectF(mapFromScene(x, y), QSizeF(width, height));
}
/**

View File

@@ -108,16 +108,18 @@ const QDomElement PartLine::toXml(QDomDocument &xml_document) const
QPointF p2(sceneP2());
QDomElement xml_element = xml_document.createElement("line");
xml_element.setAttribute("x1", QString("%1").arg(p1.x()));
xml_element.setAttribute("y1", QString("%1").arg(p1.y()));
xml_element.setAttribute("x2", QString("%1").arg(p2.x()));
xml_element.setAttribute("y2", QString("%1").arg(p2.y()));
xml_element.setAttribute("end1", Qet::endTypeToString(first_end));
xml_element.setAttribute("length1", QString("%1").arg(first_length));
xml_element.setAttribute("end2", Qet::endTypeToString(second_end));
xml_element.setAttribute("length2", QString("%1").arg(second_length));
xml_element.appendChild(createXmlProperty(xml_document, "x1", p1.x()));
xml_element.appendChild(createXmlProperty(xml_document, "y1", p1.y()));
xml_element.appendChild(createXmlProperty(xml_document, "x2", p2.x()));
xml_element.appendChild(createXmlProperty(xml_document, "y2", p2.y()));
xml_element.appendChild(createXmlProperty(xml_document, "end1", Qet::endTypeToString(first_end)));
xml_element.appendChild(createXmlProperty(xml_document, "length1", first_length));
xml_element.appendChild(createXmlProperty(xml_document, "end2", Qet::endTypeToString(second_end)));
xml_element.appendChild(createXmlProperty(xml_document, "length2", second_length));
stylesToXml(xml_element);
stylesToXml(xml_document, xml_element);
return(xml_element);
}
@@ -128,15 +130,28 @@ const QDomElement PartLine::toXml(QDomDocument &xml_document) const
*/
void PartLine::fromXml(const QDomElement &qde) {
stylesFromXml(qde);
m_line = QLineF(mapFromScene(qde.attribute("x1", "0").toDouble(),
qde.attribute("y1", "0").toDouble()),
mapFromScene(qde.attribute("x2", "0").toDouble(),
qde.attribute("y2", "0").toDouble()));
first_end = Qet::endTypeFromString(qde.attribute("end1"));
first_length = qde.attribute("length1", "1.5").toDouble();
second_end = Qet::endTypeFromString(qde.attribute("end2"));
second_length = qde.attribute("length2", "1.5").toDouble();
double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
propertyDouble(qde, "x1", &x1);
propertyDouble(qde, "y1", &y1);
propertyDouble(qde, "x2", &x2);
propertyDouble(qde, "y2", &y2);
m_line = QLineF(mapFromScene(x1, y1),
mapFromScene(x2, y2));
QString s;
propertyString(qde, "end1", &s);
first_end = Qet::endTypeFromString(s);
propertyString(qde, "end2", &s);
first_end = Qet::endTypeFromString(s);
first_length = 1.5;
second_length = 1.5;
propertyDouble(qde, "length1", &first_length);
propertyDouble(qde, "length2", &second_length);
}
/**

View File

@@ -89,22 +89,24 @@ void PartPolygon::fromXml(const QDomElement &qde)
int i = 1;
while(true)
{
if (QET::attributeIsAReal(qde, QString("x%1").arg(i)) &&\
QET::attributeIsAReal(qde, QString("y%1").arg(i)))
++ i;
if (propertyDouble(qde, QString("x%1").arg(i)) &&
propertyDouble(qde, QString("y%1").arg(i)))
i++;
else break;
}
QPolygonF temp_polygon;
double x, y;
for (int j = 1 ; j < i ; ++ j)
{
temp_polygon << QPointF(qde.attribute(QString("x%1").arg(j)).toDouble(),
qde.attribute(QString("y%1").arg(j)).toDouble());
propertyDouble(qde, QString("x%1").arg(j), &x);
propertyDouble(qde, QString("y%1").arg(j), &y);
temp_polygon << QPointF(x, y);
}
m_polygon = temp_polygon;
m_closed = qde.attribute("closed") != "false";
propertyBool(qde, "closed", &m_closed);
}
/**
@@ -119,12 +121,14 @@ const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const
int i = 1;
foreach(QPointF point, m_polygon) {
point = mapToScene(point);
xml_element.setAttribute(QString("x%1").arg(i), QString("%1").arg(point.x()));
xml_element.setAttribute(QString("y%1").arg(i), QString("%1").arg(point.y()));
xml_element.appendChild(createXmlProperty(xml_document, QString("x%1").arg(i), point.x()));
xml_element.appendChild(createXmlProperty(xml_document, QString("y%1").arg(i), point.y()));
++ i;
}
if (!m_closed) xml_element.setAttribute("closed", "false");
stylesToXml(xml_element);
xml_element.appendChild(createXmlProperty(xml_document, "closed", m_closed));
stylesToXml(xml_document, xml_element);
return(xml_element);
}

View File

@@ -81,10 +81,11 @@ const QDomElement PartRectangle::toXml(QDomDocument &xml_document) const
{
QDomElement xml_element = xml_document.createElement("rect");
QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y()));
xml_element.setAttribute("width", QString("%1").arg(m_rect.width()));
xml_element.setAttribute("height", QString("%1").arg(m_rect.height()));
xml_element.appendChild(createXmlProperty(xml_document, "x", top_left.x()));
xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y()));
xml_element.appendChild(createXmlProperty(xml_document, "width", m_rect.width()));
xml_element.appendChild(createXmlProperty(xml_document, "height", m_rect.height()));
QRectF rect = m_rect.normalized();
qreal x = m_xRadius;
@@ -98,8 +99,11 @@ const QDomElement PartRectangle::toXml(QDomDocument &xml_document) const
xml_element.setAttribute("rx", QString::number(m_xRadius));
xml_element.setAttribute("ry", QString::number(m_yRadius));
xml_element.appendChild(createXmlProperty(xml_document, "rx", m_xRadius));
xml_element.appendChild(createXmlProperty(xml_document, "ry", m_yRadius));
stylesToXml(xml_element);
stylesToXml(xml_document, xml_element);
return(xml_element);
}

View File

@@ -59,28 +59,41 @@ void PartText::fromXml(const QDomElement &xml_element)
{
bool ok;
if (xml_element.hasAttribute("size"))
int size;
QString font;
if (propertyInteger(xml_element, "size", &size) != PropertyFlags::NotFound)
{
int font_size = xml_element.attribute("size").toInt(&ok);
if (!ok || font_size < 1) {
font_size = 20;
if (size < 1) {
size = 20;
}
QFont font_ = this->font();
font_.setPointSize(font_size);
font_.setPointSize(size);
setFont(font_);
}
else if (xml_element.hasAttribute("font"))
else if (propertyString(xml_element, "font", &font) != PropertyFlags::NotFound)
{
QFont font_;
font_.fromString(xml_element.attribute("font"));
font_.fromString(font);
setFont(font_);
}
}
setDefaultTextColor(QColor(xml_element.attribute("color", "#000000")));
setPlainText(xml_element.attribute("text"));
setPos(xml_element.attribute("x").toDouble(),
xml_element.attribute("y").toDouble());
setRotation(xml_element.attribute("rotation", QString::number(0)).toDouble());
QString color;
QString text;
propertyString(xml_element, "color", &color, "#000000");
setDefaultTextColor(QColor(color));
propertyString(xml_element, "text", &text);
setPlainText(text);
double x, y, rot;
propertyDouble(xml_element, "x", &x, 0);
propertyDouble(xml_element, "y", &y, 0);
setPos(x, y);
propertyDouble(xml_element, "rotation", &rot, 0);
setRotation(rot);
}
/**
@@ -92,12 +105,12 @@ const QDomElement PartText::toXml(QDomDocument &xml_document) const
{
QDomElement xml_element = xml_document.createElement(xmlName());
xml_element.setAttribute("x", QString::number(pos().x()));
xml_element.setAttribute("y", QString::number(pos().y()));
xml_element.setAttribute("text", toPlainText());
xml_element.setAttribute("font", font().toString());
xml_element.setAttribute("rotation", QString::number(rotation()));
xml_element.setAttribute("color", defaultTextColor().name());
xml_element.appendChild(createXmlProperty(xml_document, "x", pos().x()));
xml_element.appendChild(createXmlProperty(xml_document, "y", pos().y()));
xml_element.appendChild(createXmlProperty(xml_document, "text", toPlainText()));
xml_element.appendChild(createXmlProperty(xml_document, "font", font().toString()));
xml_element.appendChild(createXmlProperty(xml_document, "rotation", rotation()));
xml_element.appendChild(createXmlProperty(xml_document, "color", defaultTextColor().name()));
return(xml_element);
}

View File

@@ -17,6 +17,224 @@
*/
#include "propertiesinterface.h"
/*!
* Available property types
*/
namespace {
const QString integerS = "int";
const QString doubleS = "double";
const QString boolS = "bool";
const QString stringS = "string";
}
PropertiesInterface::PropertiesInterface()
{
}
QDomElement PropertiesInterface::createXmlProperty(QDomDocument &doc, const QString& name, const QString value) const {
QDomElement p = doc.createElement("property");
p.setAttribute("name", name);
p.setAttribute("type", stringS);
p.setAttribute("value", value);
return p;
}
QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const int value) const {
QDomElement p = doc.createElement("property");
p.setAttribute("name", name);
p.setAttribute("type", integerS);
p.setAttribute("value", value);
return p;
}
QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const double value) const {
QDomElement p = doc.createElement("property");
p.setAttribute("name", name);
p.setAttribute("type", doubleS);
p.setAttribute("value", value);
return p;
}
QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const bool value) const {
QDomElement p = doc.createElement("property");
p.setAttribute("name", name);
p.setAttribute("type", boolS);
p.setAttribute("value", value);
return p;
}
QDomElement PropertiesInterface::property(const QDomElement& e, const QString& name) {
for (int i=0; i < e.childNodes().count(); i++) {
QDomElement child = e.childNodes().at(i).toElement();
if (!validXmlProperty(child))
return QDomElement();
if (child.attribute("name") == name)
return child;
}
return QDomElement();
}
/*!
* \brief PropertiesInterface::attribute
* Returns the property with the name \p attribute_name
* \param e Xml element which contains the property
* \param attribute_name
* \param type Type of the property
* \param attr
* \return
*/
bool PropertiesInterface::attribute(const QDomElement& e, const QString& attribute_name, const QString& type, QString* attr) {
QDomElement p = property(e, attribute_name);
if (p.isNull()) {
// check if legacy property is available,
// where the property is inside the element as attribute
if (!e.hasAttribute(attribute_name))
return false;
*attr = e.attribute(attribute_name);
} else {
if (p.attribute("type") != type)
return false;
*attr = p.attribute("value");
}
return true;
}
/*!
* \brief PropertiesInterface::propertyInteger
* Reads an interger from the XML element.
* \param e DomElement which contains the property attribute
* \param attribute_name Name of the attribute
* \param entier Return value if success
* \return True if reading an integer was successful, else False. If the attribute was not found,
* \p entier is not valid and the return value is False
*/
PropertiesInterface::PropertyFlags PropertiesInterface::propertyInteger(const QDomElement &e, const QString& attribute_name, int* entier, int defaultValue) {
QString attr;
if (!attribute(e, attribute_name, integerS, &attr)) {
*entier = defaultValue;
return PropertyFlags::NotFound;
}
// verifie la validite de l'attribut
bool ok;
int tmp = attr.toInt(&ok);
if (!ok)
return PropertyFlags::NoValidConversion;
if (entier != nullptr)
*entier = tmp;
return PropertyFlags::Success;
}
PropertiesInterface::PropertyFlags PropertiesInterface::propertyDouble(const QDomElement &e, const QString& attribute_name, double* reel, double defaultValue) {
QString attr;
if (!attribute(e, attribute_name, doubleS, &attr)) {
*reel = defaultValue;
return PropertyFlags::NotFound;
}
// verifie la validite de l'attribut
bool ok;
double tmp = attr.toDouble(&ok);
if (!ok)
return PropertyFlags::NoValidConversion;
if (reel != nullptr)
*reel = tmp;
return PropertyFlags::Success;
}
PropertiesInterface::PropertyFlags PropertiesInterface::propertyBool(const QDomElement &e, const QString& attribute_name, bool* boolean, bool defaulValue) {
QString attr;
if (!attribute(e, attribute_name, integerS, &attr)) {
*boolean = defaulValue;
return PropertyFlags::NotFound;
}
// verifie la validite de l'attribut
bool ok;
bool tmp = attr.toInt(&ok);
if (!ok)
return PropertyFlags::NoValidConversion;
if (boolean != nullptr)
*boolean = tmp;
return PropertyFlags::Success;
}
PropertiesInterface::PropertyFlags PropertiesInterface::propertyString(const QDomElement& e, const QString& attribute_name, QString* string, QString defaultValue) {
QString attr;
if (!attribute(e, attribute_name, stringS, &attr)) {
*string = defaultValue;
return PropertyFlags::NotFound;
}
// verifie la validite de l'attribut
if (string != nullptr)
*string = attr;
return PropertyFlags::Success;
}
/*!
* \brief PropertiesInterface::validXmlProperty
* Check if the Xml element contains the needed fields
* \param e Xml Property
* \return True if name, type, value attribute are available, else false
*/
bool PropertiesInterface::validXmlProperty(const QDomElement& e) {
if (!e.hasAttribute("name"))
return false;
if (!e.hasAttribute("type"))
return false;
if (!e.hasAttribute("value"))
return false;
}
/**
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
en orientation. Si la chaine fait plusieurs caracteres, seul le
premier est pris en compte. En cas d'incoherence, Qet::North est
retourne.
@param s Chaine de caractere cense representer une orientation
@return l'orientation designee par la chaine de caractere
*/
Qet::Orientation PropertiesInterface::orientationFromString(const QString &s) {
QChar c = s[0];
if (c == 'e') return(Qet::East);
else if (c == 's') return(Qet::South);
else if (c == 'w') return (Qet::West);
else return(Qet::North);
}
/**
@param o une orientation
@return une chaine de caractere representant l'orientation
*/
QString PropertiesInterface::orientationToString(Qet::Orientation o) {
QString ret;
switch(o) {
case Qet::North: ret = "n"; break;
case Qet::East : ret = "e"; break;
case Qet::South: ret = "s"; break;
case Qet::West : ret = "w"; break;
}
return(ret);
}

View File

@@ -21,6 +21,8 @@
#include <QString>
#include <QSettings>
#include <QDomElement>
#include <limits>
#include "qet.h"
/**
* @brief The PropertiesInterface class
@@ -36,6 +38,49 @@ class PropertiesInterface
// Save/load properties to xml element
virtual QDomElement toXml (QDomDocument &xml_document) const =0;
virtual bool fromXml (const QDomElement &xml_element) =0;
virtual bool valideXml(QDomElement& element) const = 0;
/*!
* Use this functions to add properties to the xml document
*/
QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const QString value) const;
QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const int value) const;
QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const double value) const;
QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const bool value) const;
static QDomElement property(const QDomElement& e, const QString& name);
static bool attribute(const QDomElement& e, const QString& attribute_name, const QString& type, QString* attr);
typedef enum PropertyFlags {
Success,
NotFound,
NoValidConversion,
};
static PropertyFlags propertyInteger(const QDomElement &e, const QString& attribute_name, int *entier = nullptr, int defaultValue = std::numeric_limits<int>::quiet_NaN());
static PropertyFlags propertyDouble(const QDomElement &e, const QString& attribute_name, double *reel = nullptr, double defaultValue = std::numeric_limits<double>::quiet_NaN());
static PropertyFlags propertyString(const QDomElement& e, const QString& attribute_name, QString* string = nullptr, QString defaultValue = QString());
static PropertyFlags propertyBool(const QDomElement &e, const QString& attribute_name, bool* boolean = nullptr, bool defaulValue = false);
static bool validXmlProperty(const QDomElement& e);
QVariant XmlProperty(const QDomElement& element);
/**
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
en orientation. Si la chaine fait plusieurs caracteres, seul le
premier est pris en compte. En cas d'incoherence, Qet::North est
retourne.
@param s Chaine de caractere cense representer une orientation
@return l'orientation designee par la chaine de caractere
*/
static Qet::Orientation orientationFromString(const QString &s);
/**
@param o une orientation
@return une chaine de caractere representant l'orientation
*/
static QString orientationToString(Qet::Orientation o);
};
#endif // PROPERTIESINTERFACE_H

View File

@@ -43,17 +43,11 @@ QDomElement TerminalData::toXml(QDomDocument &xml_document) const
{
QDomElement xml_element = xml_document.createElement("terminal");
// ecrit la position de la borne
xml_element.setAttribute("x", QString("%1").arg(q->scenePos().x()));
xml_element.setAttribute("y", QString("%1").arg(q->scenePos().y()));
xml_element.setAttribute("uuid", m_uuid.toString());
xml_element.setAttribute("name", m_name);
// ecrit l'orientation de la borne
xml_element.setAttribute("orientation", Qet::orientationToString(m_orientation));
// Write name and number to XML
xml_element.appendChild(createXmlProperty(xml_document, "x", q->scenePos().x()));
xml_element.appendChild(createXmlProperty(xml_document, "y", q->scenePos().y()));
xml_element.appendChild(createXmlProperty(xml_document, "uuid", m_uuid.toString()));
xml_element.appendChild(createXmlProperty(xml_document, "name", m_name));
xml_element.appendChild(createXmlProperty(xml_document, "orientation", orientationToString(m_orientation)));
return(xml_element);
}
@@ -61,27 +55,40 @@ bool TerminalData::fromXml (const QDomElement &xml_element)
{
// lit la position de la borne
qreal term_x = 0.0, term_y = 0.0;
if (!QET::attributeIsAReal(xml_element, "x", &term_x))
if (!propertyDouble(xml_element, "x", &term_x))
return false;
if (!QET::attributeIsAReal(xml_element, "y", &term_y))
if (!propertyDouble(xml_element, "y", &term_y))
return false;
m_pos = QPointF(term_x, term_y);
//emit posFromXML(QPointF(term_x, term_y));
QString uuid = xml_element.attribute("uuid");
QString uuid;
if (!propertyString(xml_element, "uuid", &uuid))
return false;
// update part and add uuid, which is used in the new version to connect terminals together
// if the attribute not exists, means, the element is created with an older version of qet. So use the legacy approach
// to identify terminals
if (!uuid.isEmpty())
m_uuid = QUuid(uuid);
m_name = xml_element.attribute("name");
if (!propertyString(xml_element, "name", &m_name))
return false;
QString o;
if (!propertyString(xml_element, "orientation", &o))
return false;
// lit l'orientation de la borne
m_orientation = Qet::orientationFromString(xml_element.attribute("orientation"));
m_orientation = orientationFromString(o);
return true;
}
bool TerminalData::valideXml(QDomElement& element) const {
return true;
}

View File

@@ -35,6 +35,24 @@ public:
QDomElement toXml(QDomDocument &xml_element) const override;
bool fromXml(const QDomElement &xml_element) override;
bool valideXml(QDomElement &element) const override;
/**
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
en orientation. Si la chaine fait plusieurs caracteres, seul le
premier est pris en compte. En cas d'incoherence, Qet::North est
retourne.
@param s Chaine de caractere cense representer une orientation
@return l'orientation designee par la chaine de caractere
*/
static Qet::Orientation orientationFromString(const QString &s);
/**
@param o une orientation
@return une chaine de caractere representant l'orientation
*/
static QString orientationToString(Qet::Orientation o);
// must be public, because this class is a private member of PartTerminal/Terminal and they must
// access this data
public:

View File

@@ -96,27 +96,21 @@ void XRefProperties::fromSettings(const QSettings &settings, const QString prefi
QDomElement XRefProperties::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("xref");
xml_element.setAttribute("type", m_key);
xml_element.setAttribute("showpowerctc", m_show_power_ctc? "true" : "false");
QString display = m_display == Cross? "cross" : "contacts";
xml_element.setAttribute("displayhas", display);
QString snap = m_snap_to == Bottom? "bottom" : "label";
xml_element.setAttribute("snapto", snap);
xml_element.appendChild(createXmlProperty(xml_document, "type", m_key));
xml_element.appendChild(createXmlProperty(xml_document, "showpowerctc", m_show_power_ctc));
xml_element.appendChild(createXmlProperty(xml_document, "displayhas", m_display == Cross? "cross" : "contacts"));
xml_element.appendChild(createXmlProperty(xml_document, "snapto", m_snap_to == Bottom? "bottom" : "label"));
QString xrefpos;
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
xml_element.setAttribute("xrefpos", var.valueToKey(m_xref_pos));
int offset = m_offset;
xml_element.setAttribute("offset", QString::number(offset));
QString master_label = m_master_label;
xml_element.setAttribute("master_label", master_label);
QString slave_label = m_slave_label;
xml_element.setAttribute("slave_label", slave_label);
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
xml_element.appendChild(createXmlProperty(xml_document, "xrefpos", var.valueToKey(m_xref_pos)));
xml_element.appendChild(createXmlProperty(xml_document, "offset", m_offset));
xml_element.appendChild(createXmlProperty(xml_document, "master_label", m_master_label));
xml_element.appendChild(createXmlProperty(xml_document, "slave_label", m_slave_label));
foreach (QString key, m_prefix.keys()) {
xml_element.setAttribute(key + "prefix", m_prefix.value(key));
xml_element.appendChild(createXmlProperty(xml_document, key + "prefix", m_prefix.value(key)));
}
return xml_element;
@@ -128,30 +122,42 @@ QDomElement XRefProperties::toXml(QDomDocument &xml_document) const {
* @param xml_element: QDomElement to use for load
*/
bool XRefProperties::fromXml(const QDomElement &xml_element) {
m_show_power_ctc = xml_element.attribute("showpowerctc") == "true";
QString display = xml_element.attribute("displayhas", "cross");
if (!propertyBool(xml_element, "showpowerctc", &m_show_power_ctc))
return false;
QString display;
propertyString(xml_element, "displayhas", &display, "cross");
display == "cross"? m_display = Cross : m_display = Contacts;
QString snap = xml_element.attribute("snapto", "label");
QString snap;
propertyString(xml_element, "snapto", &snap, "label");
snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label;
QString xrefpos = xml_element.attribute("xrefpos","Left");
QString xrefpos;
if (propertyString(xml_element, "xrefpos", &xrefpos, "Left") == PropertyFlags::NotFound) {
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
m_xref_pos = Qt::AlignmentFlag(var.keyToValue(xrefpos.toStdString().data()));
} else
m_xref_pos = Qt::AlignBottom;
QMetaEnum var = QMetaEnum::fromType<Qt::Alignment>();
if(xml_element.hasAttribute("xrefpos"))
m_xref_pos = Qt::AlignmentFlag(var.keyToValue(xml_element.attribute("xrefpos").toStdString().data()));
else
m_xref_pos = Qt::AlignBottom;
m_offset = xml_element.attribute("offset", "0").toInt();
m_master_label = xml_element.attribute("master_label", "%f-%l%c");
m_slave_label = xml_element.attribute("slave_label","(%f-%l%c)");
propertyInteger(xml_element, "offset", &m_offset, 0);
propertyString(xml_element, "master_label", &m_master_label, "%f-%l%c");
propertyString(xml_element, "slave_label", &m_slave_label, "(%f-%l%c)");
QString value;
foreach (QString key, m_prefix_keys) {
m_prefix.insert(key, xml_element.attribute(key + "prefix"));
propertyString(xml_element, key + "prefix", &value);
m_prefix.insert(key, value);
}
return true;
}
bool XRefProperties::valideXml(QDomElement& element) const {
// TODO: implement
return true;
}
/**
* @brief XRefProperties::defaultProperties
* @return the default properties stored in the setting file

View File

@@ -44,6 +44,7 @@ class XRefProperties : public PropertiesInterface
void fromSettings (const QSettings &settings, const QString = QString()) override;
QDomElement toXml (QDomDocument &xml_document) const override;
bool fromXml(const QDomElement &xml_element) override;
bool valideXml(QDomElement& element) const override;
static QHash<QString, XRefProperties> defaultProperties();

View File

@@ -25,37 +25,6 @@
#include <QSaveFile>
#include <QTextStream>
/**
Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w")
en orientation. Si la chaine fait plusieurs caracteres, seul le
premier est pris en compte. En cas d'incoherence, Qet::North est
retourne.
@param s Chaine de caractere cense representer une orientation
@return l'orientation designee par la chaine de caractere
*/
Qet::Orientation Qet::orientationFromString(const QString &s) {
QChar c = s[0];
if (c == 'e') return(Qet::East);
else if (c == 's') return(Qet::South);
else if (c == 'w') return (Qet::West);
else return(Qet::North);
}
/**
@param o une orientation
@return une chaine de caractere representant l'orientation
*/
QString Qet::orientationToString(Qet::Orientation o) {
QString ret;
switch(o) {
case Qet::North: ret = "n"; break;
case Qet::East : ret = "e"; break;
case Qet::South: ret = "s"; break;
case Qet::West : ret = "w"; break;
}
return(ret);
}
/**
Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal).
@param a La premiere orientation de Borne

View File

@@ -719,15 +719,13 @@ QList<Conductor *> Terminal::conductors() const {
QDomElement Terminal::toXml(QDomDocument &doc) const {
QDomElement qdo = doc.createElement("terminal");
// for backward compatibility
qdo.setAttribute("x", QString("%1").arg(dock_elmt_.x()));
qdo.setAttribute("y", QString("%1").arg(dock_elmt_.y()));
// end for backward compatibility
qdo.appendChild(createXmlProperty(doc, "x", dock_elmt_.x()));
qdo.appendChild(createXmlProperty(doc, "y", dock_elmt_.y()));
qdo.appendChild(createXmlProperty(doc, "orientation", orientationToString(d->m_orientation)));
qdo.appendChild(createXmlProperty(doc, "number", number_terminal_));
qdo.appendChild(createXmlProperty(doc, "name", name_terminal_));
qdo.appendChild(createXmlProperty(doc, "nameHidden", name_terminal_hidden));
qdo.setAttribute("orientation", d->m_orientation);
qdo.setAttribute("number", number_terminal_);
qdo.setAttribute("name", name_terminal_);
qdo.setAttribute("nameHidden", name_terminal_hidden);
return(qdo);
}
@@ -737,38 +735,36 @@ QDomElement Terminal::toXml(QDomDocument &doc) const {
@param terminal Le QDomElement a analyser
@return true si le QDomElement passe en parametre est une borne, false sinon
*/
bool Terminal::valideXml(QDomElement &terminal) {
// verifie le nom du tag
bool Terminal::valideXml(QDomElement &terminal) const {
if (terminal.tagName() != "terminal") return(false);
if (!propertyString(terminal, "number", nullptr))
return false;
if (!propertyString(terminal, "name", nullptr))
return false;
if (!propertyBool(terminal, "nameHidden", nullptr))
return false;
if (!propertyDouble(terminal, "x", nullptr))
return false;
if (!propertyDouble(terminal, "y", nullptr))
return false;
QString o;
if (!propertyString(terminal, "orientation", &o))
return false;
Qet::Orientation terminal_or = orientationFromString(o);
if (terminal_or != Qet::North
&& terminal_or != Qet::South
&& terminal_or != Qet::East
&& terminal_or != Qet::West)
return false;
// verifie la presence des attributs minimaux
if (!terminal.hasAttribute("x")) return(false);
if (!terminal.hasAttribute("y")) return(false);
if (!terminal.hasAttribute("orientation")) return(false);
bool conv_ok;
// parse l'abscisse
terminal.attribute("x").toDouble(&conv_ok);
if (!conv_ok) return(false);
// parse l'ordonnee
terminal.attribute("y").toDouble(&conv_ok);
if (!conv_ok) return(false);
// parse l'id
terminal.attribute("id").toInt(&conv_ok);
if (!conv_ok) return(false);
// parse l'orientation
int terminal_or = terminal.attribute("orientation").toInt(&conv_ok);
if (!conv_ok) return(false);
if (terminal_or != Qet::North
&& terminal_or != Qet::South
&& terminal_or != Qet::East
&& terminal_or != Qet::West) return(false);
// a ce stade, la borne est syntaxiquement correcte
return(true);
// a ce stade, la borne est syntaxiquement correcte
return true;
}
/**
@@ -779,15 +775,30 @@ bool Terminal::valideXml(QDomElement &terminal) {
@return true si la borne "se reconnait"
(memes coordonnes, meme orientation), false sinon
*/
bool Terminal::fromXml(QDomElement &terminal) {
number_terminal_ = terminal.attribute("number");
name_terminal_ = terminal.attribute("name");
name_terminal_hidden = terminal.attribute("nameHidden").toInt();
bool Terminal::fromXml(const QDomElement &terminal) {
if (!propertyString(terminal, "number", &number_terminal_))
return false;
return (
qFuzzyCompare(terminal.attribute("x").toDouble(), dock_elmt_.x()) &&
qFuzzyCompare(terminal.attribute("y").toDouble(), dock_elmt_.y()) &&
(terminal.attribute("orientation").toInt() == d->m_orientation)
if (!propertyString(terminal, "name", &name_terminal_))
return false;
if (!propertyBool(terminal, "nameHidden", &name_terminal_hidden))
return false;
double x, y;
if (!propertyDouble(terminal, "x", &x))
return false;
if (!propertyDouble(terminal, "y", &y))
return false;
QString o;
if (!propertyString(terminal, "orientation", &o))
return false;
return (
qFuzzyCompare(x, dock_elmt_.x()) &&
qFuzzyCompare(y, dock_elmt_.y()) &&
(orientationFromString(o) == d->m_orientation)
);
}

View File

@@ -20,6 +20,8 @@
#include <QtWidgets>
#include <QtXml>
#include "qet.h"
#include "propertiesinterface.h"
class Conductor;
class Diagram;
class Element;
@@ -31,7 +33,7 @@ class TerminalData;
plug point for conductors.
This class handles all mouse events for connecting conductors
*/
class Terminal : public QGraphicsObject
class Terminal : public QGraphicsObject, public PropertiesInterface
{
Q_OBJECT
@@ -88,9 +90,9 @@ class Terminal : public QGraphicsObject
bool canBeLinkedTo(Terminal *);
// methods related to XML import/export
static bool valideXml(QDomElement &);
bool fromXml (QDomElement &);
QDomElement toXml (QDomDocument &) const;
bool valideXml(QDomElement &) const override;
bool fromXml (const QDomElement &) override;
QDomElement toXml (QDomDocument &) const override;
protected:
// methods related to events management