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

View File

@@ -19,6 +19,7 @@
#define CUSTOM_ELEMENT_PART_H #define CUSTOM_ELEMENT_PART_H
#include "qet.h" #include "qet.h"
#include "propertiesinterface.h"
class CustomElement; class CustomElement;
class ElementPrimitiveDecorator; class ElementPrimitiveDecorator;
@@ -35,7 +36,7 @@ class QGraphicsSceneMouseEvent;
is no point for those classes to store their visual representation with is no point for those classes to store their visual representation with
anything more complex than a QImage. anything more complex than a QImage.
*/ */
class CustomElementPart { class CustomElementPart: public PropertiesInterface {
// constructors, destructor // constructors, destructor
public: public:
/** /**
@@ -55,14 +56,6 @@ class CustomElementPart {
// methods // methods
public: 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 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 { const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
QDomElement xml_element = xml_document.createElement("arc"); QDomElement xml_element = xml_document.createElement("arc");
QPointF top_left(sceneTopLeft()); 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.setAttribute("width", QString("%1").arg(rect().width())); xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y()));
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()));
//to maintain compatibility with the previous version, we write the angle in degrees. //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.appendChild(createXmlProperty(xml_document, "start", m_start_angle / 16));
xml_element.setAttribute("angle", QString("%1").arg(m_span_angle / 16)); xml_element.appendChild(createXmlProperty(xml_document, "angle", m_span_angle / 16));
stylesToXml(xml_element);
stylesToXml(xml_document, xml_element);
return(xml_element); return(xml_element);
} }
@@ -116,13 +120,22 @@ const QDomElement PartArc::toXml(QDomDocument &xml_document) const {
*/ */
void PartArc::fromXml(const QDomElement &qde) { void PartArc::fromXml(const QDomElement &qde) {
stylesFromXml(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()) );
m_start_angle = qde.attribute("start", "0").toDouble() * 16; double x = 0, y = 0, w = 0, h = 0; // default values
m_span_angle = qde.attribute("angle", "-1440").toDouble() * 16; 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())) if (qFuzzyCompare(rect().width(), rect().height()))
{ {
xml_element = xml_document.createElement("circle"); 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 else
{ {
xml_element = xml_document.createElement("ellipse"); xml_element = xml_document.createElement("ellipse");
xml_element.setAttribute("width", QString("%1").arg(rect().width())); xml_element.appendChild(createXmlProperty(xml_document, "width", rect().width()));
xml_element.setAttribute("height", QString("%1").arg(rect().height())); xml_element.appendChild(createXmlProperty(xml_document, "height", rect().height()));
} }
QPointF top_left(sceneTopLeft()); QPointF top_left(sceneTopLeft());
xml_element.setAttribute("x", QString("%1").arg(top_left.x())); xml_element.appendChild(createXmlProperty(xml_document, "x", top_left.x()));
xml_element.setAttribute("y", QString("%1").arg(top_left.y())); xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y()));
stylesToXml(xml_element); stylesToXml(xml_document, xml_element);
return(xml_element); return(xml_element);
} }
@@ -108,19 +108,23 @@ const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const
void PartEllipse::fromXml(const QDomElement &qde) void PartEllipse::fromXml(const QDomElement &qde)
{ {
stylesFromXml(qde); stylesFromXml(qde);
qreal width, height; double x = 0, y = 0, width = 0, height = 0;
if (qde.tagName() == "ellipse") if (qde.tagName() == "ellipse")
{ {
width = qde.attribute("width", "0").toDouble(); propertyDouble(qde, "width", &width);
height = qde.attribute("height", "0").toDouble(); propertyDouble(qde, "height", &height);
}
else {
propertyDouble(qde, "diameter", &width);
height = width;
} }
else
width = height = qde.attribute("diameter", "0").toDouble();
m_rect = QRectF(mapFromScene(qde.attribute("x", "0").toDouble(),
qde.attribute("y", "0").toDouble()), propertyDouble(qde, "x", &x);
QSizeF(width, height)); 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()); QPointF p2(sceneP2());
QDomElement xml_element = xml_document.createElement("line"); 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));
stylesToXml(xml_element); 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_document, xml_element);
return(xml_element); return(xml_element);
} }
@@ -128,15 +130,28 @@ const QDomElement PartLine::toXml(QDomDocument &xml_document) const
*/ */
void PartLine::fromXml(const QDomElement &qde) { void PartLine::fromXml(const QDomElement &qde) {
stylesFromXml(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")); double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
first_length = qde.attribute("length1", "1.5").toDouble(); propertyDouble(qde, "x1", &x1);
second_end = Qet::endTypeFromString(qde.attribute("end2")); propertyDouble(qde, "y1", &y1);
second_length = qde.attribute("length2", "1.5").toDouble(); 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; int i = 1;
while(true) while(true)
{ {
if (QET::attributeIsAReal(qde, QString("x%1").arg(i)) &&\ if (propertyDouble(qde, QString("x%1").arg(i)) &&
QET::attributeIsAReal(qde, QString("y%1").arg(i))) propertyDouble(qde, QString("y%1").arg(i)))
++ i; i++;
else break; else break;
} }
QPolygonF temp_polygon; QPolygonF temp_polygon;
double x, y;
for (int j = 1 ; j < i ; ++ j) for (int j = 1 ; j < i ; ++ j)
{ {
temp_polygon << QPointF(qde.attribute(QString("x%1").arg(j)).toDouble(), propertyDouble(qde, QString("x%1").arg(j), &x);
qde.attribute(QString("y%1").arg(j)).toDouble()); propertyDouble(qde, QString("y%1").arg(j), &y);
temp_polygon << QPointF(x, y);
} }
m_polygon = temp_polygon; 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; int i = 1;
foreach(QPointF point, m_polygon) { foreach(QPointF point, m_polygon) {
point = mapToScene(point); point = mapToScene(point);
xml_element.setAttribute(QString("x%1").arg(i), QString("%1").arg(point.x())); xml_element.appendChild(createXmlProperty(xml_document, QString("x%1").arg(i), point.x()));
xml_element.setAttribute(QString("y%1").arg(i), QString("%1").arg(point.y())); xml_element.appendChild(createXmlProperty(xml_document, QString("y%1").arg(i), point.y()));
++ i; ++ 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); return(xml_element);
} }

View File

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

View File

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

View File

@@ -17,6 +17,224 @@
*/ */
#include "propertiesinterface.h" #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() 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 <QString>
#include <QSettings> #include <QSettings>
#include <QDomElement> #include <QDomElement>
#include <limits>
#include "qet.h"
/** /**
* @brief The PropertiesInterface class * @brief The PropertiesInterface class
@@ -36,6 +38,49 @@ class PropertiesInterface
// Save/load properties to xml element // Save/load properties to xml element
virtual QDomElement toXml (QDomDocument &xml_document) const =0; virtual QDomElement toXml (QDomDocument &xml_document) const =0;
virtual bool fromXml (const QDomElement &xml_element) =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 #endif // PROPERTIESINTERFACE_H

View File

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

View File

@@ -35,6 +35,24 @@ public:
QDomElement toXml(QDomDocument &xml_element) const override; QDomElement toXml(QDomDocument &xml_element) const override;
bool fromXml(const QDomElement &xml_element) 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 // must be public, because this class is a private member of PartTerminal/Terminal and they must
// access this data // access this data
public: public:

View File

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

View File

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

View File

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