diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h index 51b7b00fc..6d19c5ac3 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h +++ b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h @@ -53,7 +53,7 @@ class QetGraphicsHandlerItem : public QGraphicsItem QRectF m_handler_rect, m_br; qreal m_size; - QColor m_color; + QColor m_color{Qt::black}; QPen m_pen; public: diff --git a/sources/borderproperties.cpp b/sources/borderproperties.cpp index c16186504..d123e5a73 100644 --- a/sources/borderproperties.cpp +++ b/sources/borderproperties.cpp @@ -32,15 +32,7 @@ - 17 colonnes affichees de 60.0 px de large pour 20.0px de haut - 8 lignes affichees de 80.0 px de haut pour 20.0px de large */ -BorderProperties::BorderProperties() : - columns_count(17), - columns_width(60.0), - columns_header_height(20.0), - display_columns(true), - rows_count(8), - rows_height(80.0), - rows_header_width(20.0), - display_rows(true) +BorderProperties::BorderProperties() { } @@ -96,17 +88,21 @@ bool BorderProperties::operator!=(const BorderProperties &bp) { XML element to which attributes will be added \~French Element XML auquel seront ajoutes des attributs */ -void BorderProperties::toXml(QDomElement &e) const -{ - e.setAttribute("cols", columns_count); - e.setAttribute("colsize", QString("%1").arg(columns_width)); - e.setAttribute("rows", rows_count); - e.setAttribute("rowsize", QString("%1").arg(rows_height)); - e.setAttribute("displaycols", display_columns ? "true" : "false"); - e.setAttribute("displayrows", display_rows ? "true" : "false"); +QDomElement BorderProperties::toXml(QDomDocument &dom_doc) const { + + QDomElement e = dom_doc.createElement("border"); + + e.appendChild(createXmlProperty(dom_doc, "cols", columns_count)); + e.appendChild(createXmlProperty(dom_doc, "colsize", columns_width)); + e.appendChild(createXmlProperty(dom_doc, "rows", rows_count)); + e.appendChild(createXmlProperty(dom_doc, "rowsize", rows_height)); + e.appendChild(createXmlProperty(dom_doc, "displayrows", display_rows)); + e.appendChild(createXmlProperty(dom_doc, "displaycols", display_columns)); + + return e; } -/** +/**RETURNS True @brief BorderProperties::fromXml Import dimensions from XML attributes of element e \~French Importe les dimensions a partir des attributs XML de l'element e @@ -115,13 +111,29 @@ void BorderProperties::toXml(QDomElement &e) const XML element whose attributes will be read \~French Element XML dont les attributs seront lus */ -void BorderProperties::fromXml(QDomElement &e) { - if (e.hasAttribute("cols")) columns_count = e.attribute("cols").toInt(); - if (e.hasAttribute("colsize")) columns_width = e.attribute("colsize").toInt(); - if (e.hasAttribute("rows")) rows_count = e.attribute("rows").toInt(); - if (e.hasAttribute("rowsize")) rows_height = e.attribute("rowsize").toInt(); - if (e.hasAttribute("displaycols")) display_columns = e.attribute("displaycols") == "true"; - if (e.hasAttribute("displayrows")) display_rows = e.attribute("displayrows") == "true"; +bool BorderProperties::fromXml(const QDomElement &e) { + + if (propertyInteger(e, "cols", &columns_count) == PropertyFlags::NoValidConversion || + propertyDouble(e, "colsize", &columns_width) == PropertyFlags::NoValidConversion || + propertyInteger(e, "rows", &rows_count) == PropertyFlags::NoValidConversion || + propertyDouble(e, "rowsize", &rows_height) == PropertyFlags::NoValidConversion || + propertyBool(e, "displaycols", &display_columns) == PropertyFlags::NoValidConversion || + propertyBool(e, "displayrows", &display_rows) == PropertyFlags::NoValidConversion) + return false; + + return true; +} + +bool BorderProperties::valideXml(QDomElement& e) { + + if (propertyInteger(e, "cols") == PropertyFlags::Success || + propertyDouble(e, "colsize") == PropertyFlags::Success || + propertyInteger(e, "rows") == PropertyFlags::Success || + propertyDouble(e, "rowsize") == PropertyFlags::Success || + propertyBool(e, "displaycols") == PropertyFlags::Success || + propertyBool(e, "displayrows") == PropertyFlags::Success) + return true; + return false; } /** @@ -155,7 +167,7 @@ void BorderProperties::toSettings(QSettings &settings, const QString &prefix) co \~ @param prefix : prefix to be added before the names of the parameters \~French prefixe a ajouter devant les noms des parametres */ -void BorderProperties::fromSettings(QSettings &settings, const QString &prefix) { +void BorderProperties::fromSettings(const QSettings &settings, const QString &prefix) { columns_count = settings.value(prefix + "cols", columns_count).toInt(); columns_width = qRound(settings.value(prefix + "colsize", columns_width).toDouble()); display_columns = settings.value(prefix + "displaycols", display_columns).toBool(); diff --git a/sources/borderproperties.h b/sources/borderproperties.h index a8429a332..91ec3781e 100644 --- a/sources/borderproperties.h +++ b/sources/borderproperties.h @@ -20,13 +20,15 @@ #include #include +#include "propertiesinterface.h" + /** @brief The BorderProperties class This class is a container for dimensions and display properties of a diagram. @remark Attributes are public */ -class BorderProperties { +class BorderProperties : public PropertiesInterface { public: // constructor, destructor, operators BorderProperties(); @@ -35,22 +37,23 @@ class BorderProperties { bool operator==(const BorderProperties &); bool operator!=(const BorderProperties &); - void toXml(QDomElement &) const; - void fromXml(QDomElement &); + QDomElement toXml(QDomDocument &dom_doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& e); void toSettings(QSettings &, const QString & = QString()) const; void fromSettings(QSettings &, const QString & = QString()); static BorderProperties defaultProperties(); // attributes - int columns_count; ///< Columns count - qreal columns_width; ///< Columns width - qreal columns_header_height; ///< Column headers height - bool display_columns; ///< Whether to display column headers + int columns_count{17}; ///< Columns count + qreal columns_width{60.0}; ///< Columns width + qreal columns_header_height{20.0}; ///< Column headers height + bool display_columns{true}; ///< Whether to display column headers - int rows_count; ///< Rows count - qreal rows_height; ///< Rows height - qreal rows_header_width; ///< Row headers width - bool display_rows; ///< Whether to display row headers + int rows_count{8}; ///< Rows count + qreal rows_height{80.0}; ///< Rows height + qreal rows_header_width{20.0}; ///< Row headers width + bool display_rows{true}; ///< Whether to display row headers }; #endif diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp index 9f509f044..60f49f662 100644 --- a/sources/bordertitleblock.cpp +++ b/sources/bordertitleblock.cpp @@ -206,8 +206,8 @@ QRectF BorderTitleBlock::insideBorderRect() const Exports the title block current values to XML. @param xml_elmt the XML element attributes will be added to */ -void BorderTitleBlock::titleBlockToXml(QDomElement &xml_elmt) { - exportTitleBlock().toXml(xml_elmt); +void BorderTitleBlock::titleBlockToXml(QDomElement& doc) { + exportTitleBlock().toXml(doc); } /** diff --git a/sources/bordertitleblock.h b/sources/bordertitleblock.h index 779b2f005..61a2ed715 100644 --- a/sources/bordertitleblock.h +++ b/sources/bordertitleblock.h @@ -173,7 +173,7 @@ class BorderTitleBlock : public QObject void setPreviousFolioNum(const QString &previous); void setNextFolioNum(const QString &next); - void titleBlockToXml(QDomElement &); + void titleBlockToXml(QDomElement &doc); void titleBlockFromXml(const QDomElement &); void borderToXml(QDomElement &); void borderFromXml(const QDomElement &); diff --git a/sources/conductorproperties.cpp b/sources/conductorproperties.cpp index bd1b3f999..baa821d00 100644 --- a/sources/conductorproperties.cpp +++ b/sources/conductorproperties.cpp @@ -23,11 +23,7 @@ /** Constructeur par defaut */ -SingleLineProperties::SingleLineProperties() : - hasGround(true), - hasNeutral(true), - is_pen(false), - phases(1) +SingleLineProperties::SingleLineProperties() { } @@ -215,12 +211,17 @@ void SingleLineProperties::drawPen(QPainter *painter, ajoutes a l'element e. @param e Element XML auquel seront ajoutes des attributs */ -void SingleLineProperties::toXml(QDomElement &e) const -{ - e.setAttribute("ground", hasGround ? "true" : "false"); - e.setAttribute("neutral", hasNeutral ? "true" : "false"); - e.setAttribute("phase", phases); - if (isPen()) e.setAttribute("pen", "true"); +QDomElement SingleLineProperties::toXml(QDomDocument &doc) const { + + QDomElement e = doc.createElement("SingleLine"); + e.appendChild(createXmlProperty(doc, "ground", hasGround)); + e.appendChild(createXmlProperty(doc, "neutral", hasNeutral)); + e.appendChild(createXmlProperty(doc, "phase", phases)); + + if (isPen()) + e.appendChild(createXmlProperty(doc, "pen", true)); + + return e; } /** @@ -228,11 +229,36 @@ void SingleLineProperties::toXml(QDomElement &e) const de l'element e @param e Element XML dont les attributs seront lus */ -void SingleLineProperties::fromXml(QDomElement &e) { - hasGround = e.attribute("ground") == "true"; - hasNeutral = e.attribute("neutral") == "true"; - setPhasesCount(e.attribute("phase").toInt()); - is_pen = (hasGround && hasNeutral && e.attribute("pen", "false") == "true"); +bool SingleLineProperties::fromXml(const QDomElement &e) { + if (propertyBool(e, "ground", &hasGround) != PropertyFlags::Success || + propertyBool(e, "neutral", &hasNeutral) != PropertyFlags::Success) + return false; + + int phase; + if (propertyInteger(e, "phase", &phase) != PropertyFlags::Success) + return false; + setPhasesCount(phase); + + bool pen; + if (propertyBool(e, "pen", &pen) != PropertyFlags::Success) + return false; + is_pen = (hasGround && hasNeutral && pen); + + return true; +} + +bool SingleLineProperties::valideXml(QDomElement& e) { + if (propertyBool(e, "ground") != PropertyFlags::Success || + propertyBool(e, "neutral") != PropertyFlags::Success) + return false; + + if (propertyInteger(e, "phase") != PropertyFlags::Success) + return false; + + if (propertyBool(e, "pen") != PropertyFlags::Success) + return false; + + return true; } /** @@ -266,98 +292,105 @@ ConductorProperties::~ConductorProperties() Export conductor propertie, in the XML element 'e' @param e the xml element */ -void ConductorProperties::toXml(QDomElement &e) const +QDomElement ConductorProperties::toXml(QDomDocument& doc) const { - e.setAttribute("type", typeToString(type)); - if (color != QColor(Qt::black)) - e.setAttribute("color", color.name()); + QDomElement e = doc.createElement("defaultconductor"); - e.setAttribute("bicolor", m_bicolor? "true" : "false"); - e.setAttribute("color2", m_color_2.name()); - e.setAttribute("dash-size", QString::number(m_dash_size)); + e.appendChild(createXmlProperty(doc, "type", typeToString(type))); + e.appendChild(createXmlProperty(doc, "color", color)); + + e.appendChild(createXmlProperty(doc, "bicolor", m_bicolor)); + e.appendChild(createXmlProperty(doc, "color2", m_color_2)); + e.appendChild(createXmlProperty(doc, "dash-size", m_dash_size)); if (type == Single) - singleLineProperties.toXml(e); - - e.setAttribute("num", text); - e.setAttribute("text_color", text_color.name()); - e.setAttribute("formula", m_formula); - e.setAttribute("cable", m_cable); - e.setAttribute("bus", m_bus); - e.setAttribute("function", m_function); - e.setAttribute("tension_protocol", m_tension_protocol); - e.setAttribute("conductor_color", m_wire_color); - e.setAttribute("conductor_section", m_wire_section); - e.setAttribute("numsize", QString::number(text_size)); - e.setAttribute("condsize", QString::number(cond_size)); - e.setAttribute("displaytext", m_show_text); - e.setAttribute("onetextperfolio", m_one_text_per_folio); - e.setAttribute("vertirotatetext", QString::number(verti_rotate_text)); - e.setAttribute("horizrotatetext", QString::number(horiz_rotate_text)); + e.appendChild(singleLineProperties.toXml(doc)); + e.appendChild(createXmlProperty(doc, "num", text)); + e.appendChild(createXmlProperty(doc, "text_color", text_color)); + e.appendChild(createXmlProperty(doc, "formula", m_formula)); + e.appendChild(createXmlProperty(doc, "function", m_function)); + e.appendChild(createXmlProperty(doc, "tension_protocol", m_tension_protocol)); + e.appendChild(createXmlProperty(doc, "conductor_color", m_wire_color)); + e.appendChild(createXmlProperty(doc, "conductor_section", m_wire_section)); + e.appendChild(createXmlProperty(doc, "numsize", text_size)); + e.appendChild(createXmlProperty(doc, "condsize", cond_size)); + e.appendChild(createXmlProperty(doc, "displaytext", m_show_text)); + e.appendChild(createXmlProperty(doc, "onetextperfolio", m_one_text_per_folio)); + e.appendChild(createXmlProperty(doc, "onetextperfolio", verti_rotate_text)); + e.appendChild(createXmlProperty(doc, "horizrotatetext", horiz_rotate_text)); +// TODO: implement +//e.setAttribute("cable", m_cable); +// e.setAttribute("bus", m_bus); QMetaEnum me = QMetaEnum::fromType(); - e.setAttribute("horizontal-alignment", me.valueToKey(m_horizontal_alignment)); - e.setAttribute("vertical-alignment", me.valueToKey(m_vertical_alignment)); + e.appendChild(createXmlProperty(doc, "horizontal-alignment", me.valueToKey(m_horizontal_alignment))); + e.appendChild(createXmlProperty(doc, "vertical-alignment", me.valueToKey(m_vertical_alignment))); QString conductor_style = writeStyle(); if (!conductor_style.isEmpty()) - e.setAttribute("style", conductor_style); + e.appendChild(createXmlProperty(doc, "style", conductor_style)); + + return e; } -/** +/** RETURNS True @brief ConductorProperties::fromXml Import conductor propertie, from the attribute of the xml element 'e' @param e the xml document */ -void ConductorProperties::fromXml(QDomElement &e) +bool ConductorProperties::fromXml(const QDomElement &e) { // get conductor color - QColor xml_color= QColor(e.attribute("color")); - color = (xml_color.isValid()? xml_color : QColor(Qt::black)); - - QString bicolor_str = e.attribute("bicolor", "false"); - m_bicolor = bicolor_str == "true"? true : false; - - QColor xml_color_2 = QColor(e.attribute("color2")); - m_color_2 = xml_color_2.isValid()? xml_color_2 : QColor(Qt::black); - - m_dash_size = e.attribute("dash-size", QString::number(1)).toInt(); + propertyColor(e, "color", &color); + propertyBool(e, "bicolor", &m_bicolor); + propertyColor(e, "color2", &m_color_2); + propertyInteger(e, "dash-size", &m_dash_size); // read style of conductor - readStyle(e.attribute("style")); + QString style_string; + propertyString(e, "style", &style_string); + readStyle(style_string); - if (e.attribute("type") == typeToString(Single)) + QString type_t; + if (propertyString(e, "type", &type_t) == PropertyFlags::Success) { + if (type_t == typeToString(Single)) { // get specific properties for single conductor singleLineProperties.fromXml(e); type = Single; } - else + else if (type_t == typeToString(Multi)) type = Multi; + else { + //Keep retrocompatible with version older than 0,4 + //If the propertie @type is simple (removed since QET 0,4), we set text no visible. + //@TODO remove this code for qet 0.6 or later - text = e.attribute("num"); + if (type_t == "simple") m_show_text = false; + } + } + + propertyString(e, "num", &text); + // TODO: implement: + //m_cable = e.attribute("cable"); + //m_bus = e.attribute("bus"); // get text color - QColor xml_text_color= QColor(e.attribute("text_color")); - text_color = (xml_text_color.isValid()? xml_text_color : QColor(Qt::black)); - m_formula = e.attribute("formula"); - m_cable = e.attribute("cable"); - m_bus = e.attribute("bus"); - m_function = e.attribute("function"); - m_tension_protocol = e.attribute("tension_protocol"); - m_wire_color = e.attribute("conductor_color"); - m_wire_section = e.attribute("conductor_section"); - text_size = e.attribute("numsize", QString::number(9)).toInt(); - cond_size = e.attribute("condsize", QString::number(1)).toDouble(); - m_show_text = e.attribute("displaytext", QString::number(1)).toInt(); - m_one_text_per_folio = e.attribute("onetextperfolio", QString::number(0)).toInt(); - verti_rotate_text = e.attribute("vertirotatetext").toDouble(); - horiz_rotate_text = e.attribute("horizrotatetext").toDouble(); + propertyColor(e, "text_color", &text_color); + propertyString(e, "formula", &m_formula); + propertyString(e, "function", &m_function); + propertyString(e, "tension_protocol", &m_tension_protocol); + propertyString(e, "conductor_color", &m_wire_color); + propertyString(e, "conductor_section", &m_wire_section); + propertyInteger(e, "numsize", &text_size); + propertyDouble(e, "condsize", &cond_size); + propertyBool(e, "displaytext", &m_show_text); + propertyBool(e, "onetextperfolio", &m_one_text_per_folio); + propertyDouble(e, "vertirotatetext", &verti_rotate_text); + propertyDouble(e, "horizrotatetext", &horiz_rotate_text); QMetaEnum me = QMetaEnum::fromType(); - m_horizontal_alignment = Qt::Alignment( - me.keyToValue( e.attribute( "horizontal-alignment", "AlignBottom" @@ -369,13 +402,38 @@ void ConductorProperties::fromXml(QDomElement &e) "AlignRight" ).toStdString().data())); - //Keep retrocompatible with version older than 0,4 - //If the propertie @type is simple (removed since QET 0,4), we set text no visible. - //@TODO remove this code for qet 0.6 or later -#if TODO_LIST -#pragma message("@TODO remove this code for qet 0.6 or later") -#endif - if (e.attribute("type") == "simple") m_show_text = false; + QString alinment_temp; + if (propertyString(e, "horizontal-alignment", &alinment_temp) == PropertyFlags::Success) + m_horizontal_alignment = Qt::Alignment(me.keyToValue(alinment_temp.toStdString().data())); + if (propertyString(e, "vertical-alignment", &alinment_temp) == PropertyFlags::Success) + m_vertical_alignment = Qt::Alignment(me.keyToValue(alinment_temp.toStdString().data())); + + return true; +} + +bool ConductorProperties::valideXml(QDomElement& e) { + if (propertyColor(e, "color") || + propertyBool(e, "bicolor") || + propertyColor(e, "color2") || + propertyInteger(e, "dash-size") || + propertyString(e, "type") || + propertyString(e, "num") || + propertyColor(e, "text_color") || + propertyString(e, "formula") || + propertyString(e, "function") || + propertyString(e, "tension_protocol") || + propertyString(e, "conductor_color") || + propertyString(e, "conductor_section") || + propertyInteger(e, "numsize") || + propertyDouble(e, "condsize") || + propertyBool(e, "displaytext") || + propertyBool(e, "onetextperfolio") || + propertyDouble(e, "vertirotatetext") || + propertyDouble(e, "horizrotatetext") || + propertyString(e, "horizontal-alignment") || + propertyString(e, "vertical-alignment")) + return false; + return true; } /** @@ -417,7 +475,7 @@ void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) @param settings Parametres a lire @param prefix prefixe a ajouter devant les noms des parametres */ -void ConductorProperties::fromSettings(QSettings &settings, const QString &prefix) +void ConductorProperties::fromSettings(const QSettings &settings, const QString &prefix) { QColor settings_color = QColor(settings.value(prefix + "color").toString()); color = (settings_color.isValid()? settings_color : QColor(Qt::black)); diff --git a/sources/conductorproperties.h b/sources/conductorproperties.h index e07471ff6..1127e3a9a 100644 --- a/sources/conductorproperties.h +++ b/sources/conductorproperties.h @@ -22,13 +22,15 @@ #include #include +#include "propertiesinterface.h" + class QPainter; /** @brief The SingleLineProperties class This class represents the properties of a singleline conductor. */ -class SingleLineProperties { +class SingleLineProperties: public PropertiesInterface { public: SingleLineProperties(); virtual ~SingleLineProperties(); @@ -37,23 +39,24 @@ class SingleLineProperties { unsigned short int phasesCount(); bool isPen() const; void draw(QPainter *, QET::ConductorSegmentType, const QRectF &); - void toXml(QDomElement &) const; - void fromXml(QDomElement &); + QDomElement toXml(QDomDocument& doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& element); void toSettings(QSettings &, const QString & = QString()) const; void fromSettings(QSettings &, const QString & = QString()); /// Whether the singleline conductor should display the ground symbol - bool hasGround; + bool hasGround{true}; /// Whether the singleline conductor should display the neutral symbol - bool hasNeutral; + bool hasNeutral{true}; /// Protective Earth Neutral: visually merge neutral and ground - bool is_pen; + bool is_pen{false}; int operator==(const SingleLineProperties &) const; int operator!=(const SingleLineProperties &) const; private: - unsigned short int phases; + unsigned short int phases{1}; void drawGround (QPainter *, QET::ConductorSegmentType, QPointF, qreal); void drawNeutral(QPainter *, QPointF, qreal); void drawPen(QPainter *, QET::ConductorSegmentType, QPointF, qreal); @@ -64,7 +67,7 @@ class SingleLineProperties { This class represents the functional properties of a particular conductor, i.e. properties other than path and terminals. */ -class ConductorProperties +class ConductorProperties: public PropertiesInterface { public: ConductorProperties(); @@ -80,12 +83,12 @@ class ConductorProperties //Attributes - ConductorType type; + ConductorType type{ConductorType::Single}; - QColor - color, - m_color_2, - text_color; + // TODO: set default values! + QColor color{QColor(Qt::black)}, + m_color_2{QColor(Qt::black)}, + text_color{QColor(Qt::black)}; QString text, @@ -97,31 +100,32 @@ class ConductorProperties m_bus, m_cable; - int + int text_size{9}, text_size, m_dash_size = 1; - double + double cond_size{1}, cond_size, verti_rotate_text, horiz_rotate_text; - bool - m_show_text, - m_one_text_per_folio, + bool m_show_text{true}, + m_one_text_per_folio{true}, m_bicolor = false; - Qt::Alignment + Qt::Alignment + m_horizontal_alignment = Qt::AlignBottom, m_horizontal_alignment = Qt::AlignBottom, m_vertical_alignment = Qt::AlignRight; - Qt::PenStyle style; + Qt::PenStyle style{Qt::PenStyle::SolidLine}; SingleLineProperties singleLineProperties; // methods - void toXml(QDomElement &) const; - void fromXml(QDomElement &); + QDomElement toXml(QDomDocument &doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& element); void toSettings(QSettings &, const QString & = QString()) const; void fromSettings(QSettings &, const QString & = QString()); static QString typeToString(ConductorType); diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 9b3e981ac..7db108d74 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -735,14 +735,13 @@ QDomDocument Diagram::toXml(bool whole_content) { // schema properties // proprietes du schema if (whole_content) { + // TODO: compare with old version border_and_titleblock.titleBlockToXml(dom_root); border_and_titleblock.borderToXml(dom_root); // Default conductor properties - QDomElement default_conductor = + dom_root.appendChild(defaultConductorProperties.toXml(document)); document.createElement("defaultconductor"); - defaultConductorProperties.toXml(default_conductor); - dom_root.appendChild(default_conductor); // Conductor autonum if (!m_conductors_autonum_name.isEmpty()) { @@ -916,13 +915,11 @@ QDomDocument Diagram::toXml(bool whole_content) { // correspondence table between the addresses of the terminals and their ids // table de correspondance entre les adresses des bornes et leurs ids - QHash table_adr_id; if (!list_elements.isEmpty()) { auto dom_elements = document.createElement("elements"); for (auto elmt : list_elements) { - dom_elements.appendChild(elmt->toXml(document, - table_adr_id)); + dom_elements.appendChild(elmt->toXml(document)); } dom_root.appendChild(dom_elements); } @@ -930,8 +927,7 @@ QDomDocument Diagram::toXml(bool whole_content) { if (!list_conductors.isEmpty()) { auto dom_conductors = document.createElement("conductors"); for (auto cond : list_conductors) { - dom_conductors.appendChild(cond->toXml(document, - table_adr_id)); + dom_conductors.appendChild(cond->toXml(document)); } dom_root.appendChild(dom_conductors); } @@ -991,7 +987,7 @@ void Diagram::folioSequentialsToXml(QHashcreateElement(type); folioseq.setAttribute("title", i.key()); for (int j = 0; j < i.value().size(); j++) { - folioseq.setAttribute(seq_type + QString::number(j+1), + folioseq.setAttribute(seq_type + QString::number(j+1), i.value().at(j)); i.value().at(j)); } domElement->appendChild(folioseq); @@ -1103,8 +1099,8 @@ Terminal* findTerminal(int conductor_index, QString element_index = "element" + QString::number(conductor_index); QString terminal_index = "terminal" + QString::number(conductor_index); - if (f.hasAttribute(element_index)) { - QUuid element_uuid = QUuid(f.attribute(element_index)); + QUuid element_uuid; + if (PropertiesInterface::propertyUuid(conductor, element_index, &element_uuid) == PropertiesInterface::PropertyFlags::Success) { // element1 did not exist in the conductor part of the xml until prior 0.7 // It is used as an indicator that uuid's are used to identify terminals bool element_found = false; @@ -1112,7 +1108,8 @@ Terminal* findTerminal(int conductor_index, if (element->uuid() != element_uuid) continue; element_found = true; - QUuid terminal_uuid = QUuid(f.attribute(terminal_index)); + QUuid terminal_uuid; + PropertiesInterface::propertyUuid(conductor, terminal_index, &terminal_uuid); for (auto terminal: element->terminals()) { if (terminal->uuid() != terminal_uuid) continue; @@ -1136,9 +1133,11 @@ Terminal* findTerminal(int conductor_index, << element_uuid << "not found"; } else { - // Backward compatibility. - // Until version 0.7 a generated id is used to link the terminal. - int id_p1 = f.attribute(terminal_index).toInt(); + // Backward compatibility. Until version 0.7 a generated id is used to link the terminal. + int id_p1 = -1; + if (PropertiesInterface::propertyInteger(conductor, terminal_index, &id_p1) != PropertiesInterface::PropertyFlags::Success) { + qDebug() << "diagramm.cpp:findTerminal(): Reading Id was not successfull"; + } if (!table_adr_id.contains(id_p1)) { qDebug() << "Diagram::fromXml() : terminal id " << id_p1 @@ -1146,6 +1145,7 @@ Terminal* findTerminal(int conductor_index, } else return table_adr_id.value(id_p1); } + qDebug() << "Diagram::findTerminal(): No terminal found."; return nullptr; } @@ -1188,6 +1188,8 @@ bool Diagram::fromXml(QDomElement &document, // The first element must be a diagram if (root.tagName() != "diagram") return(false); + qDebug() << "Diagram::fromXml; Diagram: " << root.attribute("title"); + // Read attributes of this diagram if (consider_informations) { @@ -1203,6 +1205,7 @@ bool Diagram::fromXml(QDomElement &document, defaultConductorProperties.fromXml(default_conductor_elmt); } + // Load the autonum m_conductors_autonum_name = root.attribute("conductorAutonum"); @@ -1377,7 +1380,7 @@ bool Diagram::fromXml(QDomElement &document, Terminal* p1 = findTerminal(1, f, table_adr_id, added_elements); Terminal* p2 = findTerminal(2, f, table_adr_id, added_elements); - if (p1 && p2 && p1 != p2) + if (p1 && p2 && p1 != p2)// TODO: why the condition for unequal is required? { Conductor *c = new Conductor(p1, p2); if (c->isValid()) @@ -1388,6 +1391,8 @@ bool Diagram::fromXml(QDomElement &document, } else delete c; + } else { + qDebug() << "Diagramm::fromXML(): No matching terminals found."; } } diff --git a/sources/diagram.h b/sources/diagram.h index 553335b8b..3bc5f8367 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -96,7 +96,7 @@ class Diagram : public QGraphicsScene /// margin around the diagram static const qreal margin; /// background color of diagram - static QColor background_color; + static QColor background_color; // default value set in cpp file /// Hash containing max values for folio sequential autonums in this diagram QHash m_elmt_unitfolio_max; QHash m_elmt_tenfolio_max; @@ -282,6 +282,8 @@ class Diagram : public QGraphicsScene /// from the diagram within elements collection void findElementRequired(const ElementsLocation &); + /// Signal emitted when users wish to edit an element from the diagram + void editElementRequired(const ElementsLocation &); void diagramActivated(); }; Q_DECLARE_METATYPE(Diagram *) diff --git a/sources/diagramcontext.cpp b/sources/diagramcontext.cpp index 9df38993c..36d6c52aa 100644 --- a/sources/diagramcontext.cpp +++ b/sources/diagramcontext.cpp @@ -209,8 +209,10 @@ void DiagramContext::toSettings(QSettings &settings, const QString &array_name) Read this context properties from \a settings by running through the array named \a array_name. */ -void DiagramContext::fromSettings(QSettings &settings, const QString &array_name) { +void DiagramContext::fromSettings(const QSettings &settings, const QString &array_name) { int size = settings.beginReadArray(array_name); + QSettings& s = const_cast(settings); + int size = s.beginReadArray(array_name); for (int i = 0 ; i < size; ++ i) { settings.setArrayIndex(i); QString key = settings.value("name").toString(); diff --git a/sources/editor/graphicspart/customelementgraphicpart.cpp b/sources/editor/graphicspart/customelementgraphicpart.cpp index 53d0990c3..7b918f3d6 100644 --- a/sources/editor/graphicspart/customelementgraphicpart.cpp +++ b/sources/editor/graphicspart/customelementgraphicpart.cpp @@ -161,7 +161,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; @@ -496,9 +496,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")); } @@ -511,6 +510,9 @@ 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); diff --git a/sources/editor/graphicspart/customelementgraphicpart.h b/sources/editor/graphicspart/customelementgraphicpart.h index 4138d21e0..6807705fe 100644 --- a/sources/editor/graphicspart/customelementgraphicpart.h +++ b/sources/editor/graphicspart/customelementgraphicpart.h @@ -303,7 +303,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; diff --git a/sources/editor/graphicspart/customelementpart.h b/sources/editor/graphicspart/customelementpart.h index a4e88ad96..d5d7262de 100644 --- a/sources/editor/graphicspart/customelementpart.h +++ b/sources/editor/graphicspart/customelementpart.h @@ -19,6 +19,7 @@ #define CUSTOM_ELEMENT_PART_H #include "qet.h" +#include "propertiesinterface.h" class CustomElement; class ElementPrimitiveDecorator; @@ -37,7 +38,7 @@ class QGraphicsSceneMouseEvent; there 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: /** @@ -61,14 +62,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 */ diff --git a/sources/editor/graphicspart/partarc.cpp b/sources/editor/graphicspart/partarc.cpp index 6c33a5b98..c325b7f93 100644 --- a/sources/editor/graphicspart/partarc.cpp +++ b/sources/editor/graphicspart/partarc.cpp @@ -102,18 +102,22 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, @param xml_document : Xml document to use for create the xml element. @return : an xml element that describe this arc */ -const QDomElement PartArc::toXml(QDomDocument &xml_document) 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())); + + 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.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, "start", m_start_angle / 16)); + xml_element.appendChild(createXmlProperty(xml_document, "angle", m_span_angle / 16)); + + + stylesToXml(xml_document, xml_element); return(xml_element); } @@ -122,15 +126,41 @@ const QDomElement PartArc::toXml(QDomDocument &xml_document) const Import the properties of this arc from a xml element. @param qde : Xml document to use. */ -void PartArc::fromXml(const QDomElement &qde) { +bool 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()) ); - 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; + if (propertyDouble(qde, "x", &x) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "y", &y) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "width", &w) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "height", &h) == PropertyFlags::NoValidConversion) + return false; + + m_rect = QRectF(mapFromScene(x, y), QSizeF(w, h) ); + + m_start_angle = 0; + if (propertyDouble(qde, "start", &m_start_angle) == PropertyFlags::NoValidConversion) + return false; + m_start_angle *= 16; + + m_span_angle = -1440; + if (propertyDouble(qde, "angle", &m_span_angle) == PropertyFlags::NoValidConversion) + return false; + m_span_angle *= 16; + + return true; +} + +bool PartArc::valideXml(QDomElement& element) { + + if (propertyDouble(element, "x") == PropertyFlags::NoValidConversion || + propertyDouble(element, "y") == PropertyFlags::NoValidConversion || + propertyDouble(element, "width") == PropertyFlags::NoValidConversion || + propertyDouble(element, "height") == PropertyFlags::NoValidConversion || + propertyDouble(element, "start") == PropertyFlags::NoValidConversion || + propertyDouble(element, "angle") == PropertyFlags::NoValidConversion) + return false; + return true; } /** diff --git a/sources/editor/graphicspart/partarc.h b/sources/editor/graphicspart/partarc.h index 2cb00a545..a37dc7b9c 100644 --- a/sources/editor/graphicspart/partarc.h +++ b/sources/editor/graphicspart/partarc.h @@ -51,8 +51,9 @@ class PartArc : public AbstractPartEllipse //Name and XML QString name() const override { return(QObject::tr("arc", "element part name")); } QString xmlName() const override { return(QString("arc")); } - const QDomElement toXml (QDomDocument &) const override; - void fromXml (const QDomElement &) override; + QDomElement toXml (QDomDocument &) const override; + bool fromXml (const QDomElement &) override; + static bool valideXml(QDomElement& element); QPainterPath shape() const override; QPainterPath shadowShape() const override; diff --git a/sources/editor/graphicspart/partdynamictextfield.cpp b/sources/editor/graphicspart/partdynamictextfield.cpp index e40a80f70..0fe577cdd 100644 --- a/sources/editor/graphicspart/partdynamictextfield.cpp +++ b/sources/editor/graphicspart/partdynamictextfield.cpp @@ -92,36 +92,37 @@ void PartDynamicTextField::handleUserTransformation( @param dom_doc @return */ -const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const +QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const { QDomElement root_element = dom_doc.createElement(xmlName()); - root_element.setAttribute("x", QString::number(pos().x())); - root_element.setAttribute("y", QString::number(pos().y())); - root_element.setAttribute("z", QString::number(zValue())); - root_element.setAttribute("rotation", QString::number(QET::correctAngle(rotation()))); - root_element.setAttribute("font", font().toString()); - root_element.setAttribute("uuid", m_uuid.toString()); - root_element.setAttribute("frame", m_frame? "true" : "false"); - root_element.setAttribute("text_width", QString::number(m_text_width)); + root_element.appendChild(createXmlProperty(dom_doc, "x", pos().x())); + root_element.appendChild(createXmlProperty(dom_doc, "y", pos().y())); + root_element.appendChild(createXmlProperty(dom_doc, "z", zValue())); + root_element.appendChild(createXmlProperty(dom_doc, "rotation", QET::correctAngle(rotation()))); + + root_element.appendChild(createXmlProperty(dom_doc, "font", font().toString())); + root_element.appendChild(createXmlProperty(dom_doc, "uuid", m_uuid)); + root_element.appendChild(createXmlProperty(dom_doc, "frame", m_frame)); + root_element.appendChild(createXmlProperty(dom_doc, "text_width", m_text_width)); QMetaEnum me = DynamicElementTextItem::textFromMetaEnum(); - root_element.setAttribute("text_from", me.valueToKey(m_text_from)); + root_element.appendChild(createXmlProperty(dom_doc, "text_from", me.valueToKey(m_text_from))); me = QMetaEnum::fromType(); if(this -> alignment() &Qt::AlignRight) - root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignRight)); + root_element.appendChild(createXmlProperty(dom_doc, "Halignment", me.valueToKey(Qt::AlignRight))); else if(this -> alignment() &Qt::AlignLeft) - root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignLeft)); + root_element.appendChild(createXmlProperty(dom_doc, "Halignment", me.valueToKey(Qt::AlignLeft))); else if(this -> alignment() &Qt::AlignHCenter) - root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignHCenter)); + root_element.appendChild(createXmlProperty(dom_doc, "Halignment", me.valueToKey(Qt::AlignHCenter))); if(this -> alignment() &Qt::AlignBottom) - root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignBottom)); + root_element.appendChild(createXmlProperty(dom_doc, "Valignment", me.valueToKey(Qt::AlignBottom))); else if(this -> alignment() & Qt::AlignTop) - root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignTop)); + root_element.appendChild(createXmlProperty(dom_doc, "Valignment", me.valueToKey(Qt::AlignTop))); else if(this -> alignment() &Qt::AlignVCenter) - root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignVCenter)); + root_element.appendChild(createXmlProperty(dom_doc, "Valignment", me.valueToKey(Qt::AlignVCenter))); QDomElement dom_text = dom_doc.createElement("text"); dom_text.appendChild(dom_doc.createTextNode(toPlainText())); @@ -155,24 +156,33 @@ const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const @brief PartDynamicTextField::fromXml @param dom_elmt */ -void PartDynamicTextField::fromXml(const QDomElement &dom_elmt) { +bool PartDynamicTextField::fromXml(const QDomElement &dom_elmt) if (dom_elmt.tagName() != xmlName()) { qDebug() << "PartDynamicTextField::fromXml : Wrong tagg name"; - return; + return false; } - QGraphicsTextItem::setPos( - dom_elmt.attribute("x", QString::number(0)).toDouble(), + double x=0, y=0, z=0, rot=0; dom_elmt.attribute("y", QString::number(0)).toDouble() ); - setZValue(dom_elmt.attribute("z", QString::number(zValue())).toDouble()); - QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble()); - if (dom_elmt.hasAttribute("font")) { + if (propertyDouble(dom_elmt, "x", &x) == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "y", &y) == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "z", &z) == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "rotation", &rot) == PropertyFlags::NoValidConversion) + return false; + + QGraphicsTextItem::setPos(x, y); + setZValue(z); + QGraphicsTextItem::setRotation(rot); + + QString font; + if (propertyString(dom_elmt, "font", &font) == PropertyFlags::Success) + { QFont font_; - font_.fromString(dom_elmt.attribute("font")); + font_.fromString(font); setFont(font_); - } + } else { //Keep compatibility TODO remove in futur else { #if TODO_LIST #pragma message("@TODO remove in futur") @@ -181,19 +191,24 @@ void PartDynamicTextField::fromXml(const QDomElement &dom_elmt) { setFont(QETApp::dynamicTextsItemFont(9)); } - m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString())); - setFrame(dom_elmt.attribute("frame", "false") == "true"? true : false); - setTextWidth(dom_elmt.attribute("text_width", QString::number(-1)).toDouble()); + propertyUuid(dom_elmt, "uuid", &m_uuid); + bool frame; + propertyBool(dom_elmt, "frame", &frame); + + double text_width=-1; + propertyDouble(dom_elmt, "text_width", &text_width); + setTextWidth(text_width); QMetaEnum me = DynamicElementTextItem::textFromMetaEnum(); - m_text_from = DynamicElementTextItem::TextFrom( - me.keyToValue(dom_elmt.attribute("text_from").toStdString().data())); + QString text_from; + propertyString(dom_elmt, "text_from", &text_from); + m_text_from = DynamicElementTextItem::TextFrom(me.keyToValue(text_from.toStdString().data())); me = QMetaEnum::fromType(); - if(dom_elmt.hasAttribute("Halignment")) - setAlignment(Qt::Alignment( - me.keyToValue(dom_elmt.attribute("Halignment").toStdString().data()))); - if(dom_elmt.hasAttribute(("Valignment"))) + QString alignment; + if(propertyString(dom_elmt, "Halignment", &alignment) != PropertyFlags::NotFound) + setAlignment(Qt::Alignment(me.keyToValue(alignment.toStdString().data()))); + if(propertyString(dom_elmt, "Valignment", &alignment) != PropertyFlags::NotFound) setAlignment(Qt::Alignment( me.keyToValue(dom_elmt.attribute("Valignment").toStdString().data())) | this -> alignment()); @@ -220,6 +235,29 @@ void PartDynamicTextField::fromXml(const QDomElement &dom_elmt) { QDomElement dom_color = dom_elmt.firstChildElement("color"); if(!dom_color.isNull()) setColor(QColor(dom_color.text())); + + return true; +} + +bool PartDynamicTextField::valideXml(QDomElement& dom_elmt) { + if (propertyDouble(dom_elmt, "x") == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "y") == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "z") == PropertyFlags::NoValidConversion || + propertyDouble(dom_elmt, "rotation") == PropertyFlags::NoValidConversion) + return false; + + if (propertyUuid(dom_elmt, "uuid") == PropertyFlags::NoValidConversion) + return false; + + if (propertyString(dom_elmt, "text_from")) + return false; + + if(propertyString(dom_elmt, "Halignment") == PropertyFlags::NotFound) + return false; + if(propertyString(dom_elmt, "Valignment") == PropertyFlags::NotFound) + return false; + + return true; } /** diff --git a/sources/editor/graphicspart/partdynamictextfield.h b/sources/editor/graphicspart/partdynamictextfield.h index 39eecdfd2..77f42272c 100644 --- a/sources/editor/graphicspart/partdynamictextfield.h +++ b/sources/editor/graphicspart/partdynamictextfield.h @@ -75,9 +75,10 @@ class PartDynamicTextField : public QGraphicsTextItem, public CustomElementPart void startUserTransformation(const QRectF &initial_selection_rect) override; void handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) override; - const QDomElement toXml(QDomDocument &dom_doc) const override; - void fromXml(const QDomElement &dom_elmt) override; + QDomElement toXml(QDomDocument &dom_doc) const override; + bool fromXml(const QDomElement &dom_elmt) override; void fromTextFieldXml(const QDomElement &dom_element); + static bool valideXml(QDomElement& dom_elmt); DynamicElementTextItem::TextFrom textFrom() const; void setTextFrom (DynamicElementTextItem::TextFrom text_from); @@ -116,7 +117,7 @@ class PartDynamicTextField : public QGraphicsTextItem, public CustomElementPart m_info_name, m_composite_text; DynamicElementTextItem::TextFrom m_text_from = DynamicElementTextItem::UserText; - QUuid m_uuid; + QUuid m_uuid{QUuid::createUuid()}; bool m_frame = false, m_first_add = true, m_block_alignment = false; diff --git a/sources/editor/graphicspart/partellipse.cpp b/sources/editor/graphicspart/partellipse.cpp index b7f7a2c1a..709b1fb5c 100644 --- a/sources/editor/graphicspart/partellipse.cpp +++ b/sources/editor/graphicspart/partellipse.cpp @@ -83,26 +83,26 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio @param xml_document : Xml document to use for create the xml element. @return : an xml element that describe this ellipse */ -const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const +QDomElement PartEllipse::toXml(QDomDocument &xml_document) const { QDomElement xml_element; 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); } @@ -112,22 +112,51 @@ const QDomElement PartEllipse::toXml(QDomDocument &xml_document) const Import the properties of this ellipse from a xml element. @param qde : Xml document to use. */ -void PartEllipse::fromXml(const QDomElement &qde) +bool 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(); + if (propertyDouble(qde, "width", &width) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "height", &height) == PropertyFlags::NoValidConversion) + return false; + } + else { + if (propertyDouble(qde, "diameter", &width) == PropertyFlags::NoValidConversion) + return false; + height = width; } - else - width = height = qde.attribute("diameter", "0").toDouble(); - m_rect = QRectF(mapFromScene(qde.attribute("x", "0").toDouble(), - qde.attribute("y", "0").toDouble()), - QSizeF(width, height)); + + if (propertyDouble(qde, "x", &x) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "y", &y) == PropertyFlags::NoValidConversion) + return false; + + m_rect = QRectF(mapFromScene(x, y), QSizeF(width, height)); + + return true; +} + +bool PartEllipse::valideXml(QDomElement& element) { + if (element.tagName() == "ellipse") + { + if (propertyDouble(element, "width") & PropertyFlags::NoValidConversion || + propertyDouble(element, "height") & PropertyFlags::NoValidConversion) + return false; + } + else { + if (propertyDouble(element, "diameter") & PropertyFlags::NoValidConversion) + return false; + } + + + if ((propertyDouble(element, "x") & PropertyFlags::NoValidConversion) || + (propertyDouble(element, "y") & PropertyFlags::NoValidConversion)) + return false; + + return true; } /** diff --git a/sources/editor/graphicspart/partellipse.h b/sources/editor/graphicspart/partellipse.h index 472b1abc3..d92dea2a9 100644 --- a/sources/editor/graphicspart/partellipse.h +++ b/sources/editor/graphicspart/partellipse.h @@ -52,8 +52,9 @@ class PartEllipse : public AbstractPartEllipse //Name and XML QString name() const override { return(QObject::tr("ellipse", "element part name")); } QString xmlName() const override { return(QString("ellipse")); } - const QDomElement toXml (QDomDocument &) const override; - void fromXml (const QDomElement &) override; + QDomElement toXml (QDomDocument &) const override; + bool fromXml (const QDomElement &) override; + static bool valideXml(QDomElement& element); QPainterPath shape() const override; QPainterPath shadowShape() const override; void setRect(const QRectF &rect) override {AbstractPartEllipse::setRect(rect); adjusteHandlerPos();} diff --git a/sources/editor/graphicspart/partline.cpp b/sources/editor/graphicspart/partline.cpp index d65935a2d..2d4c75f61 100644 --- a/sources/editor/graphicspart/partline.cpp +++ b/sources/editor/graphicspart/partline.cpp @@ -109,22 +109,24 @@ void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, @param xml_document : Xml document to use for create the xml element. @return an xml element that describe this line */ -const QDomElement PartLine::toXml(QDomDocument &xml_document) const +QDomElement PartLine::toXml(QDomDocument &xml_document) const { QPointF p1(sceneP1()); 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)); - 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); } @@ -133,17 +135,48 @@ const QDomElement PartLine::toXml(QDomDocument &xml_document) const Import the properties of this line from a xml element. @param qde : Xml document to use */ -void PartLine::fromXml(const QDomElement &qde) { +bool 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; + if (propertyDouble(qde, "x1", &x1) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "y1", &y1) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "x2", &x2) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "y2", &y2) == PropertyFlags::NoValidConversion) + return false; + + m_line = QLineF(mapFromScene(x1, y1), + mapFromScene(x2, y2)); + + QString s; + if (propertyString(qde, "end1", &s) != PropertyFlags::Success) + return false; + first_end = Qet::endTypeFromString(s); + + if (propertyString(qde, "end2", &s) != PropertyFlags::Success) + return false; + + first_end = Qet::endTypeFromString(s); + + if (propertyDouble(qde, "length1", &first_length) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "length2", &second_length) == PropertyFlags::NoValidConversion) + return false; + + return true; +} + +bool PartLine::valideXml(QDomElement& element) const { + if (propertyDouble(element, "x1") || + propertyDouble(element, "y1") || + propertyDouble(element, "x2") || + propertyDouble(element, "y2") || + propertyString(element, "end1") || + propertyString(element, "end2") || + propertyDouble(element, "length1") || + propertyDouble(element, "length2") ) + return false; + + return true; } /** diff --git a/sources/editor/graphicspart/partline.h b/sources/editor/graphicspart/partline.h index 22635d2d1..ce534a6f5 100644 --- a/sources/editor/graphicspart/partline.h +++ b/sources/editor/graphicspart/partline.h @@ -70,8 +70,9 @@ class PartLine : public CustomElementGraphicPart void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = nullptr) override; QString name() const override { return(QObject::tr("ligne", "element part name")); } QString xmlName() const override { return(QString("line")); } - const QDomElement toXml(QDomDocument &) const override; - void fromXml(const QDomElement &) override; + QDomElement toXml(QDomDocument &) const override; + bool fromXml(const QDomElement &) override; + bool valideXml(QDomElement& element) const; virtual QPointF sceneP1() const; virtual QPointF sceneP2() const; QPainterPath shape() const override; @@ -115,10 +116,10 @@ class PartLine : public CustomElementGraphicPart /*****************/ Qet::EndType first_end; - qreal first_length; + qreal first_length{1.5}; Qet::EndType second_end; - qreal second_length; + qreal second_length{1.5}; QList saved_points_; QLineF m_line; int m_vector_index = -1; diff --git a/sources/editor/graphicspart/partpolygon.cpp b/sources/editor/graphicspart/partpolygon.cpp index 5b00d585f..e8edf714b 100644 --- a/sources/editor/graphicspart/partpolygon.cpp +++ b/sources/editor/graphicspart/partpolygon.cpp @@ -89,29 +89,37 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio Import the properties of this polygon from a xml element @param qde : Xml document to use */ -void PartPolygon::fromXml(const QDomElement &qde) +bool PartPolygon::fromXml(const QDomElement &qde) { stylesFromXml(qde); + int error_counter = 0; 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)) == PropertyFlags::Success && + propertyDouble(qde, QString("y%1").arg(i)) == PropertyFlags::Success) + 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()); + error_counter += propertyDouble(qde, QString("x%1").arg(j), &x); + error_counter += propertyDouble(qde, QString("y%1").arg(j), &y); + if (error_counter) + return false; + temp_polygon << QPointF(x, y); } m_polygon = temp_polygon; - m_closed = qde.attribute("closed") != "false"; + if (propertyBool(qde, "closed", &m_closed) != PropertyFlags::Success) + return false; + + return true; } /** @@ -120,21 +128,28 @@ void PartPolygon::fromXml(const QDomElement &qde) @param xml_document : Xml document to use for create the xml element @return an xml element that describe this polygon */ -const QDomElement PartPolygon::toXml(QDomDocument &xml_document) const +QDomElement PartPolygon::toXml(QDomDocument &xml_document) const { QDomElement xml_element = xml_document.createElement("polygon"); 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); } +bool PartPolygon::valideXml(QDomElement& element) { + // TODO: implement + return true; +} + /** @brief PartPolygon::isUseless @return true if this part is irrelevant and does not deserve to be Retained / registered. diff --git a/sources/editor/graphicspart/partpolygon.h b/sources/editor/graphicspart/partpolygon.h index 6217eaf91..9f838f8e8 100644 --- a/sources/editor/graphicspart/partpolygon.h +++ b/sources/editor/graphicspart/partpolygon.h @@ -61,8 +61,10 @@ class PartPolygon : public CustomElementGraphicPart QString name() const override { return(QObject::tr("polygone", "element part name")); } QString xmlName() const override { return(QString("polygon")); } - void fromXml(const QDomElement &) override; - const QDomElement toXml(QDomDocument &) const override; + bool fromXml(const QDomElement &) override; + QDomElement toXml(QDomDocument &) const override; + static bool valideXml(QDomElement& element); + QPainterPath shape () const override; QPainterPath shadowShape() const override; diff --git a/sources/editor/graphicspart/partrectangle.cpp b/sources/editor/graphicspart/partrectangle.cpp index 938685426..5940998bd 100644 --- a/sources/editor/graphicspart/partrectangle.cpp +++ b/sources/editor/graphicspart/partrectangle.cpp @@ -84,14 +84,15 @@ void PartRectangle::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt @param xml_document : Xml document to use for create the xml element. @return an xml element that describe this ellipse */ -const QDomElement PartRectangle::toXml(QDomDocument &xml_document) 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; @@ -106,7 +107,10 @@ const QDomElement PartRectangle::toXml(QDomDocument &xml_document) const xml_element.setAttribute("rx", QString::number(m_xRadius)); 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); } @@ -115,18 +119,45 @@ const QDomElement PartRectangle::toXml(QDomDocument &xml_document) const Import the properties of this rectangle from a xml element. @param qde : Xml document to use. */ -void PartRectangle::fromXml(const QDomElement &qde) +bool PartRectangle::fromXml(const QDomElement &qde) { stylesFromXml(qde); - setPos(mapFromScene(qde.attribute("x", "0").toDouble(), - qde.attribute("y", "0").toDouble())); - QRectF rect(QPointF(0,0), QSizeF(qde.attribute("width", "0").toDouble(), - qde.attribute("height", "0").toDouble())); + double x=0, y=0, w=0, h=0, rx=0, ry=0; + if (propertyDouble(qde, "x", &x) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "y", &y) == PropertyFlags::NoValidConversion) + return false; + + setPos(mapFromScene(x, y)); + + if (propertyDouble(qde, "width", &w) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "width", &h) == PropertyFlags::NoValidConversion) + return false; + + QRectF rect(QPointF(x,y), QSizeF(w, h)); setRect(rect.normalized()); - setXRadius(qde.attribute("rx", "0").toDouble()); - setYRadius(qde.attribute("ry", "0").toDouble()); + + if (propertyDouble(qde, "rx", &rx) == PropertyFlags::NoValidConversion || + propertyDouble(qde, "ry", &ry) == PropertyFlags::NoValidConversion) + return false; + + setXRadius(rx); + setYRadius(ry); + + return true; +} + +bool PartRectangle::valideXml(QDomElement& element) { + // parameters have default values so no value is not a non valid xml element + if ((propertyDouble(element, "x") & PropertyFlags::NoValidConversion) | + (propertyDouble(element, "y") & PropertyFlags::NoValidConversion) | + (propertyDouble(element, "width") & PropertyFlags::NoValidConversion) | + (propertyDouble(element, "width") & PropertyFlags::NoValidConversion) | + (propertyDouble(element, "rx") & PropertyFlags::NoValidConversion) | + (propertyDouble(element, "ry") & PropertyFlags::NoValidConversion)) + return false; + return true; } /** diff --git a/sources/editor/graphicspart/partrectangle.h b/sources/editor/graphicspart/partrectangle.h index 5fbdcbb3e..045b4096b 100644 --- a/sources/editor/graphicspart/partrectangle.h +++ b/sources/editor/graphicspart/partrectangle.h @@ -60,8 +60,9 @@ class PartRectangle : public CustomElementGraphicPart QString name () const override { return(QObject::tr("rectangle", "element part name")); } QString xmlName () const override { return(QString("rect")); } - const QDomElement toXml (QDomDocument &) const override; - void fromXml (const QDomElement &) override; + QDomElement toXml (QDomDocument &) const override; + bool fromXml (const QDomElement &) override; + static bool valideXml(QDomElement& element); QRectF rect() const; void setRect(const QRectF &rect); diff --git a/sources/editor/graphicspart/partterminal.cpp b/sources/editor/graphicspart/partterminal.cpp index 71dc90120..dcdb65ee0 100644 --- a/sources/editor/graphicspart/partterminal.cpp +++ b/sources/editor/graphicspart/partterminal.cpp @@ -29,6 +29,7 @@ PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent) : CustomElementGraphicPart(editor, parent) { d = new TerminalData(this); + d->m_name = tr("terminal"); d -> m_orientation = Qet::North; d -> m_uuid = QUuid::createUuid(); // if part is loaded this uuid will be overwritten, but being sure that terminal has a uuid updateSecondPoint(); @@ -44,10 +45,21 @@ PartTerminal::~PartTerminal() Importe les proprietes d'une borne depuis un element XML @param xml_elmt Element XML a lire */ -void PartTerminal::fromXml(const QDomElement &xml_elmt) { - d -> fromXml(xml_elmt); +bool PartTerminal::fromXml(const QDomElement &xml_elmt) { + + QUuid uuid; + // 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 + propertyUuid(xml_elmt, "uuid", &d->m_uuid); + + if (!d->fromXml(xml_elmt)) + return false; + setPos(d -> m_pos); updateSecondPoint(); + + return true; } /** @@ -55,9 +67,25 @@ void PartTerminal::fromXml(const QDomElement &xml_elmt) { @param xml_document Document XML a utiliser pour creer l'element XML @return un element XML decrivant la borne */ -const QDomElement PartTerminal::toXml(QDomDocument &xml_document) const -{ - return d -> toXml(xml_document); +QDomElement PartTerminal::toXml(QDomDocument &xml_document) const { + + QDomElement qdo = xml_document.createElement("terminal"); + + qdo.appendChild(createXmlProperty(xml_document, "uuid", d->m_uuid)); + + d->m_pos = pos(); + + // Do not store terminal data in its own child + QDomElement terminalDataElement = d->toXml(xml_document); + for (int i=0; i < terminalDataElement.childNodes().length(); i++) { + qdo.appendChild(terminalDataElement.childNodes().at(i).cloneNode()); // cloneNode() is important, otherwise no deep clone is made + } + + return qdo; +} + +bool PartTerminal::valideXml(QDomElement& element) { + return TerminalData::valideXml(element); } /** diff --git a/sources/editor/graphicspart/partterminal.h b/sources/editor/graphicspart/partterminal.h index a99f30536..c23aa6c4e 100644 --- a/sources/editor/graphicspart/partterminal.h +++ b/sources/editor/graphicspart/partterminal.h @@ -53,9 +53,10 @@ class PartTerminal : public CustomElementGraphicPart { int type() const override { return Type; } QString name() const override { return d -> m_name; } QString xmlName() const override { return(QString("terminal")); } - void fromXml(const QDomElement &) override; - const QDomElement toXml(QDomDocument &) const override; - void paint( + bool fromXml(const QDomElement &) override; + QDomElement toXml(QDomDocument &) const override; + static bool valideXml(QDomElement& element); + void paint( QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) override; diff --git a/sources/editor/graphicspart/parttext.cpp b/sources/editor/graphicspart/parttext.cpp index c255c9014..f84079ae0 100644 --- a/sources/editor/graphicspart/parttext.cpp +++ b/sources/editor/graphicspart/parttext.cpp @@ -66,29 +66,48 @@ PartText::~PartText() Importe les proprietes d'un texte statique depuis un element XML @param xml_element Element XML a lire */ -void PartText::fromXml(const QDomElement &xml_element) { - bool ok; +bool PartText::fromXml(const QDomElement &xml_element) + int size; + QString font; - if (xml_element.hasAttribute("size")) { - int font_size = xml_element.attribute("size").toInt(&ok); - if (!ok || font_size < 1) { - font_size = 20; + if (propertyInteger(xml_element, "size", &size) != PropertyFlags::NotFound) + { + 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_); + } else { + return false; } - 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()); + QColor color; + QString text; + propertyColor(xml_element, "color", &color); + setDefaultTextColor(color); + + + propertyString(xml_element, "text", &text); + setPlainText(text); + + double x=0, y=0, rot=0; + if (propertyDouble(xml_element, "x", &x) == PropertyFlags::NoValidConversion || + propertyDouble(xml_element, "y", &y) == PropertyFlags::NoValidConversion) + return false; + setPos(x, y); + + if (propertyDouble(xml_element, "rotation", &rot) == PropertyFlags::NoValidConversion) + return false; + setRotation(rot); + + return true; } /** @@ -96,20 +115,44 @@ void PartText::fromXml(const QDomElement &xml_element) { @param xml_document Document XML a utiliser pour creer l'element XML @return un element XML decrivant le texte statique */ -const QDomElement PartText::toXml(QDomDocument &xml_document) 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); } +bool PartText::valideXml(QDomElement& element) { + + if (propertyInteger(element, "size") == PropertyFlags::NotFound || + propertyString(element, "font") == PropertyFlags::NotFound) { + return false; + } + + if (propertyString(element, "color") == PropertyFlags::NoValidConversion) + return false; + + + if (propertyString(element, "text")) + return false; + + if (propertyDouble(element, "x") == PropertyFlags::NoValidConversion || + propertyDouble(element, "y") == PropertyFlags::NoValidConversion) + return false; + + if (propertyDouble(element, "rotation", 0) == PropertyFlags::NoValidConversion) + return false; + + return true; +} + /** @return Les coordonnees du point situe en bas a gauche du texte. */ diff --git a/sources/editor/graphicspart/parttext.h b/sources/editor/graphicspart/parttext.h index f48db3a30..63a830f0f 100644 --- a/sources/editor/graphicspart/parttext.h +++ b/sources/editor/graphicspart/parttext.h @@ -58,8 +58,9 @@ class PartText : public QGraphicsTextItem, public CustomElementPart { int type() const override { return Type; } QString name() const override { return(QObject::tr("texte", "element part name")); } QString xmlName() const override { return(QString("text")); } - void fromXml(const QDomElement &) override; - const QDomElement toXml(QDomDocument &) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& element); + QDomElement toXml(QDomDocument &) const override; void setRotation(qreal angle) {(QGraphicsObject::setRotation(QET::correctAngle(angle)));} bool isUseless() const override; QRectF sceneGeometricRect() const override; diff --git a/sources/elementtextpattern.cpp b/sources/elementtextpattern.cpp index 0de39099d..c942bbca2 100644 --- a/sources/elementtextpattern.cpp +++ b/sources/elementtextpattern.cpp @@ -108,8 +108,7 @@ QDomDocument ExportElementTextPattern::xmlConf() const root.setAttribute("name", m_name); doc.appendChild(root); - QHash H; - QDomElement elmt = m_element->toXml(doc, H); + QDomElement elmt = m_element->toXml(doc); QDomElement texts = elmt.firstChildElement("dynamic_texts"); QDomElement groups = elmt.firstChildElement("texts_groups"); diff --git a/sources/properties/propertiesinterface.cpp b/sources/properties/propertiesinterface.cpp index d72941027..90869280f 100644 --- a/sources/properties/propertiesinterface.cpp +++ b/sources/properties/propertiesinterface.cpp @@ -17,16 +17,321 @@ */ #include "propertiesinterface.h" + + * Available property types + */ +namespace { + const QString integerS = "int"; + const QString doubleS = "double"; + const QString boolS = "bool"; + const QString stringS = "string"; + const QString uuidS = "uuid"; + const QString colorS = "color"; +} + /** @brief PropertiesInterface::PropertiesInterface */ PropertiesInterface::PropertiesInterface() { } + /** @brief PropertiesInterface::~PropertiesInterface */ PropertiesInterface::~PropertiesInterface() { - +} + +bool PropertiesInterface::valideXml(QDomElement& element) { + qDebug(QString("ValideXml() is not implemented. File: %1, Line: %2").arg(__FILE__).arg(__LINE__).toStdString().data()); + return false; +} + +QDomElement PropertiesInterface::createXmlProperty(QDomDocument &doc, const QString& name, const QString value) { + 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 char* value) { + 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) { + QDomElement p = doc.createElement("property"); + p.setAttribute("name", name); + p.setAttribute("type", integerS); + p.setAttribute("value", QString::number(value)); + return p; +} + +QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const double value) { + QDomElement p = doc.createElement("property"); + p.setAttribute("name", name); + p.setAttribute("type", doubleS); + p.setAttribute("value", QString::number(value)); + return p; +} + +QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const bool value) { + QDomElement p = doc.createElement("property"); + p.setAttribute("name", name); + p.setAttribute("type", boolS); + p.setAttribute("value", QString::number(value)); + return p; +} + +QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const QUuid value) { + QDomElement p = doc.createElement("property"); + p.setAttribute("name", name); + p.setAttribute("type", uuidS); + p.setAttribute("value", value.toString()); + return p; +} + +QDomElement PropertiesInterface::createXmlProperty(QDomDocument& doc, const QString& name, const QColor value) { + QDomElement p = doc.createElement("property"); + p.setAttribute("name", name); + p.setAttribute("type", colorS); + p.setAttribute("value", value.name()); + 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)) + continue; // there might also non property childs + + if (child.attribute("name") == name) + return child; + } + return QDomElement(); +} + +/*! + * \brief PropertiesInterface::attribute + * Returns the property with the name \p attribute_name and type \p type + * \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)) { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "Property " << attribute_name << "is not available"; + return false; + } + + *attr = e.attribute(attribute_name); + + } else { + if (p.attribute("type") != type) { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ", Property: " << attribute_name << "(" << p.attribute("type") << ") has not 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) { + + QString attr; + + if (!attribute(e, attribute_name, integerS, &attr)) { + return PropertyFlags::NotFound; + } + + // verifie la validite de l'attribut + bool ok; + int tmp = attr.toInt(&ok); + if (!ok) { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "No valid Conversion: " << attribute_name << ". type: " << integerS << ". value: " << attr; + return PropertyFlags::NoValidConversion; + } + + if (entier != nullptr) + *entier = tmp; + + return PropertyFlags::Success; +} + +PropertiesInterface::PropertyFlags PropertiesInterface::propertyDouble(const QDomElement &e, const QString& attribute_name, double* reel) { + + QString attr; + + if (!attribute(e, attribute_name, doubleS, &attr)) { + return PropertyFlags::NotFound; + } + + // verifie la validite de l'attribut + bool ok; + double tmp = attr.toDouble(&ok); + if (!ok) { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "No valid Conversion: " << attribute_name << ". type: " << doubleS << ". value: " << attr; + return PropertyFlags::NoValidConversion; + } + + if (reel != nullptr) + *reel = tmp; + + return PropertyFlags::Success; +} + +PropertiesInterface::PropertyFlags PropertiesInterface::propertyBool(const QDomElement &e, const QString& attribute_name, bool* boolean) { + + QString attr; + + if (!attribute(e, attribute_name, boolS, &attr)) { + return PropertyFlags::NotFound; + } + + // verifie la validite de l'attribut + bool ok; + bool tmp = attr.toInt(&ok); + if (!ok) { + if (attr == "true" || attr == "1") + tmp = true; + else if (attr == "false" || attr == "0") + tmp = false; + else { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "No valid Conversion: " << attribute_name << ". type: " << integerS << ". value: " << attr; + return PropertyFlags::NoValidConversion; + } + } + + if (boolean != nullptr) + *boolean = tmp; + + return PropertyFlags::Success; +} + +PropertiesInterface::PropertyFlags PropertiesInterface::propertyColor(const QDomElement &e, const QString& attribute_name, QColor* color) { + + QString attr; + + if (!attribute(e, attribute_name, colorS, &attr)) { + return PropertyFlags::NotFound; + } + + // verifie la validite de l'attribut + QColor tmp = QColor(attr); + if (!tmp.isValid()) { + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "No valid Conversion: " << attribute_name << ". type: " << colorS << ". value: " << attr; + return PropertyFlags::NoValidConversion; + } + + if (color != nullptr) + *color = tmp; + + return PropertyFlags::Success; +} + +PropertiesInterface::PropertyFlags PropertiesInterface::propertyUuid(const QDomElement &e, const QString& attribute_name, QUuid* uuid) { + QString attr; + + if (!attribute(e, attribute_name, uuidS, &attr)) { + return PropertyFlags::NotFound; + } + + if (QUuid(attr).isNull()){ + qDebug() << "\t\t\t" << "Tagname: " << e.tagName() << ". " << "No valid Conversion: " << attribute_name << ". type: " << uuidS << ". value: " << attr; + return PropertyFlags::NoValidConversion; + } + + + if (uuid != nullptr) + *uuid = QUuid(attr); + + return PropertyFlags::Success; +} + +PropertiesInterface::PropertyFlags PropertiesInterface::propertyString(const QDomElement& e, const QString& attribute_name, QString* string) { + + QString attr; + if (!attribute(e, attribute_name, stringS, &attr)) { + 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; + + return true; +} + +/** + 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]; + // in some cases/ old projects? (affuteuse_250h.qet) numbers instead of characters are + // used for the orientation + if (c == 'e' || c == '1') return(Qet::East); + else if (c == 's' || c == '2') return(Qet::South); + else if (c == 'w' || c == '3') return (Qet::West); + else return(Qet::North); // c == '0' +} + +/** + @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); } diff --git a/sources/properties/propertiesinterface.h b/sources/properties/propertiesinterface.h index 645d7b11e..a9b02bd35 100644 --- a/sources/properties/propertiesinterface.h +++ b/sources/properties/propertiesinterface.h @@ -20,7 +20,11 @@ #include #include +#include #include +#include +#include "qet.h" +#include /** @brief The PropertiesInterface class @@ -64,6 +68,59 @@ class PropertiesInterface @return true / false */ virtual bool fromXml (const QDomElement &xml_element) =0; + static bool valideXml(QDomElement& element); + + /*! + * Use this functions to add properties to the xml document + */ + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const QString value); + static QDomElement createXmlProperty(QDomDocument &doc, const QString& name, const char* value); + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const int value); + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const double value); + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const bool value); + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const QUuid value); + static QDomElement createXmlProperty(QDomDocument& doc, const QString& name, const QColor value); + + static QDomElement property(const QDomElement& e, const QString& name); + static bool attribute(const QDomElement& e, const QString& attribute_name, const QString& type, QString* attr); + + enum PropertyFlags { + Success = 0, + NotFound = 1, + NoValidConversion = 2, + // = 4 + }; + + /*! + * Try not using the default Value feature. It is better to initialize the class members in the class definition! + */ + static PropertyFlags propertyInteger(const QDomElement &e, const QString& attribute_name, int *entier = nullptr); + static PropertyFlags propertyDouble(const QDomElement &e, const QString& attribute_name, double *reel = nullptr); + static PropertyFlags propertyString(const QDomElement& e, const QString& attribute_name, QString* string = nullptr); + static PropertyFlags propertyBool(const QDomElement &e, const QString& attribute_name, bool* boolean = nullptr); + static PropertyFlags propertyUuid(const QDomElement &e, const QString& attribute_name, QUuid* uuid = nullptr); + static PropertyFlags propertyColor(const QDomElement &e, const QString& attribute_name, QColor* color = nullptr); + + + 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 diff --git a/sources/properties/terminaldata.cpp b/sources/properties/terminaldata.cpp index 45859541d..222b8ffc2 100644 --- a/sources/properties/terminaldata.cpp +++ b/sources/properties/terminaldata.cpp @@ -76,26 +76,22 @@ void TerminalData::fromSettings(const QSettings &settings, const QString prefix) */ QDomElement TerminalData::toXml(QDomDocument &xml_document) const { - QDomElement xml_element = xml_document.createElement("terminal"); + QDomElement xml_element = xml_document.createElement("terminaldata"); // write the position of the 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())); - // Write name and number to XML - xml_element.setAttribute("uuid", m_uuid.toString()); - xml_element.setAttribute("name", m_name); - - // write the orientation of the terminal - // ecrit l'orientation de la borne - xml_element.setAttribute("orientation", - Qet::orientationToString(m_orientation)); + // m_pos cannot be stored, because in the partterminal it will not be updated. + // In PartTerminal m_pos is the position of the dock, in Terminal m_pos is the second side of the terminal + // This is hold for legacy compability reason + xml_element.appendChild(createXmlProperty(xml_document, "x", m_pos.x())); + xml_element.appendChild(createXmlProperty(xml_document, "y", m_pos.y())); + xml_element.appendChild(createXmlProperty(xml_document, "name", m_name)); + xml_element.appendChild(createXmlProperty(xml_document, "orientation", orientationToString(m_orientation))); return(xml_element); } -/** +/* @brief TerminalData::fromXml load properties to xml element @@ -104,38 +100,60 @@ QDomElement TerminalData::toXml(QDomDocument &xml_document) const @param xml_element @return true if succeeded / false if the attribute is not real */ -bool TerminalData::fromXml (const QDomElement &xml_element) +bool TerminalData::fromXml (const QDomElement &xml_element) // RETURNS True { qreal term_x = 0.0; qreal term_y = 0.0; // reads the position of the terminal // lit la position de la borne - 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)); +// emit posFromXML(QPointF(term_x, term_y)); - QString uuid = xml_element.attribute("uuid"); - // update part and add uuid, which is used in the new version - // to connect terminals together + // do not write uuid from this class, because only PartTerminal::fromXml need + // to write it to xml file. Terminal::fromXml does not need. // 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; + propertyString(xml_element, "name", &m_name); // some parts do not have a name. Example: affuteuse_250h.qet, Terminal at x="0" y="-20" + + QString o; + if (propertyString(xml_element, "orientation", &o)) + return false; // read the orientation of the terminal // lit l'orientation de la borne m_orientation = Qet::orientationFromString( xml_element.attribute("orientation")); - + return true; +} + +bool TerminalData::valideXml(const QDomElement& xml_element) { + if (propertyDouble(xml_element, "x")) + return false; + + if (propertyDouble(xml_element, "y")) + return false; + + // legacy elements do not have an uuid +// if (propertyUuid(xml_element, "uuid")) +// return false; + + //if (propertyString(xml_element, "name")) // some parts do not have a name. Example: affuteuse_250h.qet, Terminal at x="0" y="-20" + // return false; + + if (propertyString(xml_element, "orientation")) + return false; return true; } diff --git a/sources/properties/terminaldata.h b/sources/properties/terminaldata.h index 58d90f484..0506ebb24 100644 --- a/sources/properties/terminaldata.h +++ b/sources/properties/terminaldata.h @@ -28,25 +28,25 @@ class TerminalData : public PropertiesInterface void setParent(QGraphicsObject* parent); void toSettings(QSettings &settings, const QString prefix = QString()) const override; - void fromSettings(const QSettings &settings, - const QString prefix = QString()) override; + void toSettings(QSettings &settings, const QString& = QString()) const override; + void fromSettings(const QSettings &settings, const QString& = QString()) override; QDomElement toXml(QDomDocument &xml_element) const override; bool fromXml(const QDomElement &xml_element) override; - // must be public, because this class is a private member - // of PartTerminal/Terminal and they must access this data + static bool valideXml(const QDomElement &xml_element); + public: /** @brief m_orientation Orientation of the terminal */ - Qet::Orientation m_orientation; + Qet::Orientation m_orientation{Qet::Orientation::North}; /** @brief second_point Position of the second point of the terminal in scene coordinates */ - QPointF second_point; + QPointF second_point{0,0}; /** @brief m_uuid Uuid of the terminal. @@ -61,7 +61,7 @@ class TerminalData : public PropertiesInterface valid. So if in the loaded document a uuid exists, use this one and don't create a new one. */ - QUuid m_uuid; + QUuid m_uuid; // default is an invalid uuid. /** @brief m_name Name of the element. @@ -79,7 +79,7 @@ class TerminalData : public PropertiesInterface It is used to store the initial position so that PartTerminal and Terminal have access to it. */ - QPointF m_pos; + QPointF m_pos{0,0}; private: QGraphicsObject* q{nullptr}; }; diff --git a/sources/properties/xrefproperties.cpp b/sources/properties/xrefproperties.cpp index 9f5af155d..a8f776d17 100644 --- a/sources/properties/xrefproperties.cpp +++ b/sources/properties/xrefproperties.cpp @@ -27,14 +27,6 @@ */ XRefProperties::XRefProperties() { - m_show_power_ctc = true; - m_display = Cross; - m_snap_to = Bottom; - m_prefix_keys << "power" << "delay" << "switch"; - m_master_label = "%f-%l%c"; - m_slave_label = "(%f-%l%c)"; - m_offset = 0; - m_xref_pos = Qt::AlignBottom; } /** @@ -103,58 +95,60 @@ 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(); - 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()) { - xml_element.setAttribute(key + "prefix", m_prefix.value(key)); + xml_element.appendChild(createXmlProperty(xml_document, key + "prefix", m_prefix.value(key))); } return xml_element; } -/** +/** RETURNS True @brief XRefProperties::fromXml Load from xml @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"); - display == "cross"? m_display = Cross : m_display = Contacts; - QString snap = xml_element.attribute("snapto", "label"); - snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label; - QString xrefpos = xml_element.attribute("xrefpos","Left"); + if (propertyBool(xml_element, "showpowerctc", &m_show_power_ctc)) + return false; - QMetaEnum var = QMetaEnum::fromType(); + QString display; + if (propertyString(xml_element, "displayhas", &display) != PropertyFlags::NotFound) { + display == "cross"? m_display = Cross : m_display = Contacts; + } - 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)"); + QString snap; + if (propertyString(xml_element, "snapto", &snap) != PropertyFlags::NotFound) { + snap == "bottom"? m_snap_to = Bottom : m_snap_to = Label; + } + + QString xrefpos; + if (propertyString(xml_element, "xrefpos", &xrefpos) != PropertyFlags::NotFound) { + QMetaEnum var = QMetaEnum::fromType(); + m_xref_pos = Qt::AlignmentFlag(var.keyToValue(xrefpos.toStdString().data())); + } + // TODO: why it compiles without this true?? + propertyInteger(xml_element, "offset", &m_offset); + propertyString(xml_element, "master_label", &m_master_label); + propertyString(xml_element, "slave_label", &m_slave_label); + QString value; foreach (QString key, m_prefix_keys) { - m_prefix.insert(key, xml_element.attribute(key + "prefix")); + if (!propertyString(xml_element, key + "prefix", &value)); + m_prefix.insert(key, value); } return true; } diff --git a/sources/properties/xrefproperties.h b/sources/properties/xrefproperties.h index f32683246..8f7821f3b 100644 --- a/sources/properties/xrefproperties.h +++ b/sources/properties/xrefproperties.h @@ -42,8 +42,8 @@ class XRefProperties : public PropertiesInterface Label }; - void toSettings (QSettings &settings, - const QString = QString()) const override; + void toSettings (QSettings &settings, const QString& = QString()) const override; + 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; @@ -80,15 +80,15 @@ class XRefProperties : public PropertiesInterface void setKey(QString& key) {m_key = key;} private: - bool m_show_power_ctc; - DisplayHas m_display; - SnapTo m_snap_to; - Qt::AlignmentFlag m_xref_pos; + bool m_show_power_ctc{true}; + DisplayHas m_display{Cross}; + SnapTo m_snap_to{Bottom}; + Qt::AlignmentFlag m_xref_pos{Qt::AlignBottom}; QHash m_prefix; - QStringList m_prefix_keys; - QString m_master_label; - QString m_slave_label; - int m_offset; + QStringList m_prefix_keys{"power","delay","switch"}; + QString m_master_label{"%f-%l%c"}; + QString m_slave_label{"(%f-%l%c)"}; + int m_offset{0}; QString m_key; }; diff --git a/sources/qet.cpp b/sources/qet.cpp index 7d136cf48..f58142e0b 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -34,31 +34,6 @@ 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 @param b La seconde orientation de Borne diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index e79671d8e..e92a56830 100644 --- a/sources/qetgraphicsitem/conductor.cpp +++ b/sources/qetgraphicsitem/conductor.cpp @@ -76,14 +76,7 @@ class ConductorXmlRetroCompatibility */ Conductor::Conductor(Terminal *p1, Terminal* p2) : terminal1(p1), - terminal2(p2), - m_mouse_over(false), - m_text_item(nullptr), - segments(nullptr), - m_moving_segment(false), - modified_path(false), - has_to_save_profile(false), - must_highlight_(Conductor::None) + terminal2(p2) { //set Zvalue at 11 to be upper than the DiagramImageItem and element setZValue(11); @@ -585,36 +578,16 @@ ConductorTextItem *Conductor::textItem() const @return true si l'element XML represente bien un Conducteur ; false sinon */ bool Conductor::valideXml(QDomElement &e){ - // verifie le nom du tag - if (e.tagName() != "conductor") return(false); - // verifie la presence des attributs minimaux - if (!e.hasAttribute("terminal1")) return(false); - if (!e.hasAttribute("terminal2")) return(false); +// // TODO: seems to short! (see fromXML) +// if (propertyDouble(e, "x") || +// propertyDouble(e, "y")) +// return false; - bool conv_ok; - // parse l'abscisse - if (e.hasAttribute("element1")) { - if (QUuid(e.attribute("element1")).isNull()) - return false; - if (QUuid(e.attribute("terminal1")).isNull()) - return false; - } else { - e.attribute("terminal1").toInt(&conv_ok); - if (!conv_ok) return(false); - } +// if (propertyBool(e, "freezeLabel")) +// return false; - // parse l'ordonnee - if (e.hasAttribute("element2")) { - if (QUuid(e.attribute("element2")).isNull()) - return false; - if (QUuid(e.attribute("terminal2")).isNull()) - return false; - } else { - e.attribute("terminal2").toInt(&conv_ok); - if (!conv_ok) return(false); - } - return(true); + return true; } /** @@ -987,10 +960,13 @@ void Conductor::pointsToSegments(const QList& points_list) { @param dom_element @return true is loading success else return false */ -bool Conductor::fromXml(QDomElement &dom_element) +bool Conductor::fromXml(const QDomElement &dom_element) { - setPos(dom_element.attribute("x", nullptr).toDouble(), - dom_element.attribute("y", nullptr).toDouble()); + // TODO: seems to short! + double x=0, y=0; + propertyDouble(dom_element, "x", &x); + propertyDouble(dom_element, "y", &y); + setPos(x, y); bool return_ = pathFromXml(dom_element); @@ -1004,14 +980,13 @@ bool Conductor::fromXml(QDomElement &dom_element) else m_autoNum_seq.fromXml(dom_element.firstChildElement("sequentialNumbers")); - m_freeze_label = dom_element.attribute("freezeLabel") == "true"? true : false; - + propertyBool(dom_element, "freezeLabel", &m_freeze_label); setProperties(pr); return return_; } -/** +// does not support legacy method @brief Conductor::toXml Exporte les caracteristiques du conducteur sous forme d'une element XML. @param dom_document : @@ -1020,33 +995,39 @@ bool Conductor::fromXml(QDomElement &dom_element) Hash stockant les correspondances entre les ids des bornes dans le document XML et leur adresse en memoire @return Un element XML representant le conducteur -*/ -QDomElement Conductor::toXml(QDomDocument &dom_document, - QHash &table_adr_id) const -{ - QDomElement dom_element = dom_document.createElement("conductor"); +QDomElement Conductor::toXml(QDomDocument & doc) const { + QDomElement dom_element = doc.createElement("conductor"); - dom_element.setAttribute("x", QString::number(pos().x())); - dom_element.setAttribute("y", QString::number(pos().y())); + + dom_element.appendChild(createXmlProperty(doc, "x", pos().x())); + dom_element.appendChild(createXmlProperty(doc, "y", pos().y())); // Terminal is uniquely identified by the uuid of the terminal and the element - if (terminal1->uuid().isNull()) { - // legacy method to identify the terminal - dom_element.setAttribute("terminal1", table_adr_id.value(terminal1)); // for backward compability + QUuid terminal = terminal1->uuid(); + QUuid terminalParent = terminal1->parentElement()->uuid(); + if (terminalParent.isNull() || terminal.isNull()) { + // legacy when the terminal does not have a valid uuid + // do not store element1 information, because this is used to determine in the fromXml + // process that legacy file format + dom_element.appendChild(createXmlProperty(doc, "terminal1", terminal1->ID())); } else { - dom_element.setAttribute("element1", terminal1->parentElement()->uuid().toString()); - dom_element.setAttribute("terminal1", terminal1->uuid().toString()); + dom_element.appendChild(createXmlProperty(doc, "element1", terminalParent)); + dom_element.appendChild(createXmlProperty(doc, "terminal1", terminal)); } - if (terminal2->uuid().isNull()) { - // legacy method to identify the terminal - dom_element.setAttribute("terminal2", table_adr_id.value(terminal2)); // for backward compability + terminal = terminal2->uuid(); + terminalParent = terminal2->parentElement()->uuid(); + if (terminalParent.isNull() || terminal.isNull()) { + // legacy when the terminal does not have a valid uuid + // do not store element1 information, because this is used to determine in the fromXml + // process that legacy file format + dom_element.appendChild(createXmlProperty(doc, "terminal2", terminal2->ID())); } else { - dom_element.setAttribute("element2", terminal2->parentElement()->uuid().toString()); - dom_element.setAttribute("terminal2", terminal2->uuid().toString()); + dom_element.appendChild(createXmlProperty(doc, "element2", terminal2->parentElement()->uuid())); + dom_element.appendChild(createXmlProperty(doc, "terminal2", terminal2->uuid())); } - dom_element.setAttribute("freezeLabel", m_freeze_label? "true" : "false"); + + dom_element.appendChild(createXmlProperty(doc, "freezeLabel", m_freeze_label)); // on n'exporte les segments du conducteur que si ceux-ci ont // ete modifies par l'utilisateur @@ -1056,35 +1037,92 @@ QDomElement Conductor::toXml(QDomDocument &dom_document, QDomElement current_segment; foreach(ConductorSegment *segment, segmentsList()) { - current_segment = dom_document.createElement("segment"); - current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical"); - current_segment.setAttribute("length", QString("%1").arg(segment -> length())); + current_segment = doc.createElement("segment"); + current_segment.appendChild(createXmlProperty(doc, "orientation", segment->isHorizontal() ? "horizontal": "vertical")); + current_segment.appendChild(createXmlProperty(doc, "length", segment -> length())); dom_element.appendChild(current_segment); } } - QDomElement dom_seq = m_autoNum_seq.toXml(dom_document); + QDomElement dom_seq = m_autoNum_seq.toXml(doc); // swquentialNumbers tag dom_element.appendChild(dom_seq); // Export the properties and text - m_properties. toXml(dom_element); - if(m_text_item->wasMovedByUser()) - { - dom_element.setAttribute("userx", QString::number(m_text_item->pos().x())); - dom_element.setAttribute("usery", QString::number(m_text_item->pos().y())); + QDomElement conductorProperties = m_properties.toXml(doc); + for (int i=0; i < conductorProperties.childNodes().count(); i++) { + QDomNode node = conductorProperties.childNodes().at(i).cloneNode(); // cloneNode() is important! + dom_element.appendChild(node); } - if(m_text_item->wasRotateByUser()) - dom_element.setAttribute("rotation", QString::number(m_text_item->rotation())); + + m_text_item->toXml(doc, dom_element); return(dom_element); } /** - @brief Conductor::pathFromXml - Generate the path (of the line) from xml file by checking the segments in the xml - file - @param e - @return true if generate path success else return false + Exporte les caracteristiques du conducteur sous forme d'une element XML. + @param d Le document XML a utiliser pour creer l'element XML + @param table_adr_id Hash stockant les correspondances entre les ids des + bornes dans le document XML et leur adresse en memoire + @return Un element XML representant le conducteur +*/ +//QDomElement Conductor::toXml(QDomDocument &dom_document, QHash &table_adr_id) const +//{ +// QDomElement dom_element = dom_document.createElement("conductor"); + +// dom_element.setAttribute("x", QString::number(pos().x())); +// dom_element.setAttribute("y", QString::number(pos().y())); + +// // Terminal is uniquely identified by the uuid of the terminal and the element +// if (terminal1->uuid().isNull()) { +// // legacy method to identify the terminal +// dom_element.setAttribute("terminal1", table_adr_id.value(terminal1)); // for backward compability +// } else { +// dom_element.setAttribute("element1", terminal1->parentElement()->uuid().toString()); +// dom_element.setAttribute("terminal1", terminal1->uuid().toString()); +// } + +// if (terminal2->uuid().isNull()) { +// // legacy method to identify the terminal +// dom_element.setAttribute("terminal2", table_adr_id.value(terminal2)); // for backward compability +// } else { +// dom_element.setAttribute("element2", terminal2->parentElement()->uuid().toString()); +// dom_element.setAttribute("terminal2", terminal2->uuid().toString()); +// } +// dom_element.setAttribute("freezeLabel", m_freeze_label? "true" : "false"); + +// // on n'exporte les segments du conducteur que si ceux-ci ont +// // ete modifies par l'utilisateur +// if (modified_path) +// { +// // parcours et export des segments +// QDomElement current_segment; +// foreach(ConductorSegment *segment, segmentsList()) +// { +// current_segment = dom_document.createElement("segment"); +// current_segment.setAttribute("orientation", segment -> isHorizontal() ? "horizontal" : "vertical"); +// current_segment.setAttribute("length", QString("%1").arg(segment -> length())); +// dom_element.appendChild(current_segment); +// } +// } + +// QDomElement dom_seq = m_autoNum_seq.toXml(dom_document); +// dom_element.appendChild(dom_seq); + +// // Export the properties and text +// m_properties.toXml(dom_document); +// if(m_text_item->wasMovedByUser()) +// { +// dom_element.setAttribute("userx", QString::number(m_text_item->pos().x())); +// dom_element.setAttribute("usery", QString::number(m_text_item->pos().y())); +// } +// if(m_text_item->wasRotateByUser()) +// dom_element.setAttribute("rotation", QString::number(m_text_item->rotation())); + +// return(dom_element); +//} + +/** */ bool Conductor::pathFromXml(const QDomElement &e) { // parcourt les elements XML "segment" et en extrait deux listes de longueurs @@ -1096,14 +1134,21 @@ bool Conductor::pathFromXml(const QDomElement &e) { if (current_segment.isNull() || current_segment.tagName() != "segment") continue; // le segment doit avoir une longueur - if (!current_segment.hasAttribute("length")) continue; + qreal segment_length; + if (propertyDouble(current_segment, "length", & segment_length)) + continue; - // cette longueur doit etre un reel - bool ok; - qreal segment_length = current_segment.attribute("length").toDouble(&ok); - if (!ok) continue; + bool isHorizontal = false; + QString orientation; + if (propertyString(current_segment, "orientation", &orientation) == PropertyFlags::Success) { + if (orientation == "horizontal") + isHorizontal = true; + } else { + qDebug() << "PathFromXML failed"; + return false; + } - if (current_segment.attribute("orientation") == "horizontal") { + if (isHorizontal) { segments_x << segment_length; segments_y << 0.0; } else { diff --git a/sources/qetgraphicsitem/conductor.h b/sources/qetgraphicsitem/conductor.h index 8680343f6..8c537aa9e 100644 --- a/sources/qetgraphicsitem/conductor.h +++ b/sources/qetgraphicsitem/conductor.h @@ -19,6 +19,7 @@ #define CONDUCTOR_H #include "conductorproperties.h" +#include "propertiesinterface.h" #include #include "assignvariables.h" @@ -39,7 +40,7 @@ typedef QHash ConductorProfilesGroup; This class represents a conductor, i.e. a wire between two element terminals. */ -class Conductor : public QGraphicsObject +class Conductor : public QGraphicsObject, public PropertiesInterface { Q_OBJECT @@ -100,11 +101,9 @@ class Conductor : public QGraphicsObject public: static bool valideXml (QDomElement &); - bool fromXml (QDomElement &); - QDomElement toXml ( - QDomDocument &, - QHash &) const; + bool fromXml (const QDomElement &) override; + //QDomElement toXml (QDomDocument &, QHash &) const; + QDomElement toXml (QDomDocument &doc) const override; private: bool pathFromXml(const QDomElement &); @@ -181,28 +180,28 @@ class Conductor : public QGraphicsObject QVector m_handler_vector; int m_vector_index = -1; - bool m_mouse_over; + bool m_mouse_over{false}; /// Functional properties ConductorProperties m_properties; /// Text input for non simple, non-singleline conductors - ConductorTextItem *m_text_item; + ConductorTextItem *m_text_item{nullptr}; /// Segments composing the conductor - ConductorSegment *segments; + ConductorSegment *segments{nullptr}; /// Attributs related to mouse interaction - bool m_moving_segment; + bool m_moving_segment{false}; int moved_point; qreal m_previous_z_value; ConductorSegment *m_moved_segment; QPointF before_mov_text_pos_; /// Whether the conductor was manually modified by users - bool modified_path; + bool modified_path{false}; /// Whether the current profile should be saved as soon as possible - bool has_to_save_profile; + bool has_to_save_profile{false}; /// conductor profile: "photography" of what the conductor is supposed to look /// like - there is one profile per kind of traject ConductorProfilesGroup conductor_profiles; /// Define whether and how the conductor should be highlighted - Highlight must_highlight_; + Highlight must_highlight_{Conductor::None}; bool m_valid; bool m_freeze_label = false; diff --git a/sources/qetgraphicsitem/conductortextitem.cpp b/sources/qetgraphicsitem/conductortextitem.cpp index 66d05c69b..5593c8a9d 100644 --- a/sources/qetgraphicsitem/conductortextitem.cpp +++ b/sources/qetgraphicsitem/conductortextitem.cpp @@ -26,9 +26,7 @@ */ ConductorTextItem::ConductorTextItem(Conductor *parent_conductor) : DiagramTextItem(parent_conductor), - parent_conductor_(parent_conductor), - moved_by_user_(false), - rotate_by_user_(false) + parent_conductor_(parent_conductor) { setAcceptHoverEvents(true); } @@ -62,19 +60,34 @@ Conductor *ConductorTextItem::parentConductor() const return(parent_conductor_); } +void ConductorTextItem::toXml(QDomDocument& doc, QDomElement& e) { + if(moved_by_user_) + { + e.appendChild(PropertiesInterface::createXmlProperty(doc, "userx", pos().x())); + e.appendChild(PropertiesInterface::createXmlProperty(doc, "usery", pos().y())); + } + if(rotate_by_user_) + e.appendChild(PropertiesInterface::createXmlProperty(doc, "rotation", rotation())); +} + + /** @brief ConductorTextItem::fromXml Read the properties stored in the xml element given in parameter @param e */ void ConductorTextItem::fromXml(const QDomElement &e) { - if (e.hasAttribute("userx")) { - setPos(e.attribute("userx").toDouble(), - e.attribute("usery").toDouble()); + + double userx=0, usery=0; + if (PropertiesInterface::propertyDouble(e, "userx", &userx) == PropertiesInterface::PropertyFlags::Success && + PropertiesInterface::propertyDouble(e, "usery", &usery) == PropertiesInterface::PropertyFlags::Success) { + setPos(userx, usery); moved_by_user_ = true; } - if (e.hasAttribute("rotation")) { - setRotation(e.attribute("rotation").toDouble()); + + double rotation; + if (PropertiesInterface::propertyDouble(e, "rotation", &rotation) == PropertiesInterface::PropertyFlags::Success) { + setRotation(rotation); rotate_by_user_ = true; } } diff --git a/sources/qetgraphicsitem/conductortextitem.h b/sources/qetgraphicsitem/conductortextitem.h index 7d57d2d60..a3c43ae1e 100644 --- a/sources/qetgraphicsitem/conductortextitem.h +++ b/sources/qetgraphicsitem/conductortextitem.h @@ -42,6 +42,7 @@ class ConductorTextItem : public DiagramTextItem enum { Type = UserType + 1006 }; Conductor *parentConductor() const; void fromXml(const QDomElement &) override; + void toXml(QDomDocument& doc, QDomElement& e); int type() const override { return Type; } virtual bool wasMovedByUser() const; virtual bool wasRotateByUser() const; @@ -61,8 +62,8 @@ class ConductorTextItem : public DiagramTextItem // attributes private: Conductor *parent_conductor_; - bool moved_by_user_; - bool rotate_by_user_; + bool moved_by_user_{false}; + bool rotate_by_user_{false}; QPointF before_mov_pos_; }; #endif diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index 43901195b..e058e2e86 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -212,7 +212,7 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) setColor(QColor(dom_color.text())); //Force the update of the displayed text - setTextFrom(m_text_from); + setTextFrom(m_text_from); // TODO: does not update because there is a retrun inside if the textfrom argument is the same as m_text_from QGraphicsTextItem::setPos(dom_elmt.attribute("x", QString::number(0)).toDouble(), dom_elmt.attribute("y", QString::number(0)).toDouble()); diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index b7864af9a..a88476a75 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -152,7 +152,7 @@ class DynamicElementTextItem : public DiagramTextItem QList m_formula_connection, m_update_slave_Xref_connection; - QColor m_user_color; + QColor m_user_color{QColor()}; bool m_frame = false, m_first_scene_change = true; diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index c794258e3..b003fa0ee 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -96,7 +96,8 @@ Element::Element( } } int elmt_state; - buildFromXml(location.xml(), &elmt_state); + qDebug() << "\tCollection Path: " << location.collectionPath(); + buildFromXml(location.xml(), &elmt_state); // build from the collection definition if (state) { *state = elmt_state; } @@ -387,7 +388,7 @@ void Element::drawHighlight( /** @brief Element::buildFromXml - Build this element from an xml description + Build this element from an xml description (from the collection) @param xml_def_elmt @param state Optional pointer which define the status of build @@ -504,11 +505,15 @@ bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state) if (qde.isNull()) continue; - if (parseElement(qde)) { + qDebug() << "\t\tElement.cpp:buildFromXml;parseElement: " << qde.tagName(); + + if (parseElement(qde)) { // TODO: why lines are not parsed here? + qDebug() << "\t\t\tParsing Element success"; ++ parsed_elements_count; } else { + qDebug() << "\t\t\tParsing Element no success"; if (state) *state = 7; m_state = QET::GIOK; @@ -541,7 +546,6 @@ bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state) m_state = QET::GIOK; return(true); } -} /** @brief Element::parseElement @@ -644,13 +648,11 @@ DynamicElementTextItem *Element::parseDynamicText( */ Terminal *Element::parseTerminal(const QDomElement &dom_element) { - TerminalData* data = new TerminalData(); - if (!data->fromXml(dom_element)) { - delete data; + if (!Terminal::valideXml(dom_element)) return nullptr; - } - Terminal *new_terminal = new Terminal(data, this); + Terminal *new_terminal = new Terminal(0, 0, Qet::Orientation::North, this); // does not matter which values are typed in here, because they get overwritten by the fromXML() function + new_terminal->fromXml(dom_element); m_terminals << new_terminal; //Sort from top to bottom and left to rigth @@ -665,7 +667,7 @@ Terminal *Element::parseTerminal(const QDomElement &dom_element) return (a->dockConductor().y() < b->dockConductor().y()); }); - return(new_terminal); + return(new_terminal); // TODO: makes no sense } /** @@ -715,7 +717,7 @@ bool Element::fromXml( les bornes vont maintenant etre recensees pour associer leurs id a leur adresse reelle ce recensement servira lors de la mise en place des fils */ - QList liste_terminals; + QList liste_terminals; // terminals in the element in the diagram foreach(QDomElement qde, QET::findInDomElement(e, "terminals", "terminal")) { if (Terminal::valideXml(qde)) liste_terminals << qde; @@ -723,15 +725,29 @@ bool Element::fromXml( QHash priv_id_adr; int terminals_non_trouvees = 0; - foreach(QGraphicsItem *qgi, childItems()) { + // The added childs from the collection now must match with the terminals from the diagram. Iterate through + // all Terminals in the collection and in the diagram to link them together + for(QGraphicsItem *qgi: childItems()) { // TODO: Where the Terminals are added as childs? if (Terminal *p = qgraphicsitem_cast(qgi)) { bool terminal_trouvee = false; - foreach(QDomElement qde, liste_terminals) { - if (p -> fromXml(qde)) { - priv_id_adr.insert( - qde.attribute( - "id").toInt(), - p); + for(QDomElement qde: liste_terminals) { + // The position in the collection element definition is the origin position (originPos). + // The position in the diagram element definition is the position where the conductor is connected (dock position) + // Therefore a simple operator overloading is not possible. + Terminal diagramTerminal(0,0, Qet::Orientation::East); + diagramTerminal.fromXml(qde); + QPointF dockPos1 = diagramTerminal.originPos(); // position here is directly the dock_elmt_ position (stored in the diagram) + QPointF dockPos2 = p->dockPos(); + if (qFuzzyCompare(dockPos1.x(), dockPos2.x()) && + qFuzzyCompare(dockPos1.y(), dockPos2.y()) && + p->orientation() == diagramTerminal.orientation()) { // check if the part in the collection is the same as in the diagram stored + qDebug() << "Matching Terminal found."; + // store id for legacy purpose, because when opening a old project in the collection the terminal does not have an uuid. Therefore the id must be used + if (p->uuid().isNull()) { + p->setID(qde.attribute("id").toInt()); + } + + priv_id_adr.insert(qde.attribute("id").toInt(), p); terminal_trouvee = true; // We used to break here, because we did not expect // several terminals to share the same position. @@ -744,6 +760,7 @@ bool Element::fromXml( if (terminals_non_trouvees > 0) { + qDebug() << "element.cpp: Element::fromXML; Elements not found: " << terminals_non_trouvees; m_state = QET::GIOK; return(false); } @@ -761,15 +778,15 @@ bool Element::fromXml( } // copie des associations id / adr foreach(int id_trouve, priv_id_adr.keys()) { - table_id_adr.insert(id_trouve, + table_id_adr.insert(id_trouve, priv_id_adr.value(id_trouve)); priv_id_adr.value(id_trouve)); } } //load uuid of connected elements - QList uuid_list = QET::findInDomElement(e, - "links_uuids", - "link_uuid"); + QList uuid_list = QET::findInDomElement(e, "links_uuids", "link_uuid"); + foreach (QDomElement qdo, uuid_list) tmp_uuids_link << qdo.attribute("uuid"); + foreach (QDomElement qdo, uuid_list) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) // ### Qt 6: remove tmp_uuids_link << qdo.attribute("uuid"); @@ -823,7 +840,7 @@ bool Element::fromXml( //************************// //***Dynamic texts item***// - //************************// + //************************// read from the diagram section for (const QDomElement& qde : QET::findInDomElement( e, "dynamic_texts", @@ -837,7 +854,7 @@ bool Element::fromXml( //************************// //***Element texts item***// //************************// - QList inputs = QET::findInDomElement(e, "inputs", "input"); + QList inputs = QET::findInDomElement(e, "inputs", "input"); // inputs in diagram section //First case, we check for the text item converted to dynamic text item const QList conv_deti_list = @@ -1194,18 +1211,7 @@ QDomElement Element::toXml( element.setAttribute("z", QString::number(this->zValue())); element.setAttribute("orientation", QString::number(orientation())); - /* get the first id to use for the bounds of this element * recupere le premier id a utiliser pour les bornes de cet element */ - int id_terminal = 0; - if (!table_adr_id.isEmpty()) { - // trouve le plus grand id - int max_id_t = -1; - foreach (int id_t, table_adr_id.values()) { - if (id_t > max_id_t) max_id_t = id_t; - } - id_terminal = max_id_t + 1; - } - // registration of device terminals // enregistrement des bornes de l'appareil QDomElement xml_terminals = document.createElement("terminals"); @@ -1214,8 +1220,10 @@ QDomElement Element::toXml( foreach(Terminal *t, terminals()) { // alors on enregistre la borne QDomElement terminal = t -> toXml(document); - terminal.setAttribute("id", id_terminal); // for backward compatibility - table_adr_id.insert(t, id_terminal ++); + if (t->ID() > 0) { + // for backward compatibility + terminal.setAttribute("id", t->ID()); // for backward compatibility + } xml_terminals.appendChild(terminal); } element.appendChild(xml_terminals); diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index 3e59dacc3..c9e580597 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -38,7 +38,7 @@ class ElementTextItemGroup; /** This is the base class for electrical elements. */ -class Element : public QetGraphicsItem +class Element : public QetGraphicsItem // TODO: derive from propertiesInterface! { friend class DiagramEventAddElement; @@ -130,14 +130,8 @@ class Element : public QetGraphicsItem QPoint hotspot() const; void editProperty() override; static bool valideXml(QDomElement &); - virtual bool fromXml( - QDomElement &, - QHash &); - virtual QDomElement toXml( - QDomDocument &, - QHash &) const; + virtual bool fromXml(QDomElement &, QHash &, bool = false); + virtual QDomElement toXml(QDomDocument &) const; QUuid uuid() const; int orientation() const; diff --git a/sources/qetgraphicsitem/elementtextitemgroup.cpp b/sources/qetgraphicsitem/elementtextitemgroup.cpp index 36fcab736..debd0b548 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.cpp +++ b/sources/qetgraphicsitem/elementtextitemgroup.cpp @@ -437,6 +437,7 @@ QDomElement ElementTextItemGroup::toXml(QDomDocument &dom_document) const return dom_element; } +// TOOD: inherit from propertiesinterface /** @brief ElementTextItemGroup::fromXml Import data of this group from xml diff --git a/sources/qetgraphicsitem/elementtextitemgroup.h b/sources/qetgraphicsitem/elementtextitemgroup.h index ae01c165d..3cc0b0bbc 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.h +++ b/sources/qetgraphicsitem/elementtextitemgroup.h @@ -32,7 +32,7 @@ class CrossRefItem; This class represent a group of element text Texts in the group can be aligned left / center /right */ -class ElementTextItemGroup : public QObject, public QGraphicsItemGroup +class ElementTextItemGroup : public QObject, public QGraphicsItemGroup // TODO: derive from PropertiesInterface { Q_OBJECT @@ -112,7 +112,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup m_hold_to_bottom_of_page = false, m_block_alignment_update = false, m_frame = false; - QPointF m_initial_position; + QPointF m_initial_position{QPointF(0,0)}; int m_vertical_adjustment = 0; CrossRefItem *m_Xref_item = nullptr; Element *m_parent_element = nullptr; diff --git a/sources/qetgraphicsitem/independenttextitem.cpp b/sources/qetgraphicsitem/independenttextitem.cpp index 9f93a8166..2655c44ce 100644 --- a/sources/qetgraphicsitem/independenttextitem.cpp +++ b/sources/qetgraphicsitem/independenttextitem.cpp @@ -50,6 +50,7 @@ IndependentTextItem::~IndependentTextItem() { } +// TODO: inherit from PropertiesInterface /** Permet de lire le texte a mettre dans le champ a partir d'un element XML. Cette methode se base sur la position du champ pour assigner ou non la diff --git a/sources/qetgraphicsitem/qetgraphicsitem.cpp b/sources/qetgraphicsitem/qetgraphicsitem.cpp index 8c892d53c..7c0a20bb5 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.cpp +++ b/sources/qetgraphicsitem/qetgraphicsitem.cpp @@ -24,10 +24,7 @@ @param parent : Parent Item */ QetGraphicsItem::QetGraphicsItem(QGraphicsItem *parent): - QGraphicsObject(parent), - is_movable_(true), - m_first_move(true), - snap_to_grid_(true) + QGraphicsObject(parent) {} QetGraphicsItem::~QetGraphicsItem() diff --git a/sources/qetgraphicsitem/qetgraphicsitem.h b/sources/qetgraphicsitem/qetgraphicsitem.h index b77d795bf..336d89b85 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.h +++ b/sources/qetgraphicsitem/qetgraphicsitem.h @@ -55,10 +55,10 @@ class QetGraphicsItem : public QGraphicsObject void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; protected: - bool is_movable_; - bool m_first_move; - bool snap_to_grid_; - QPointF m_mouse_to_origin_movement; + bool is_movable_{true}; + bool m_first_move{true}; + bool snap_to_grid_{true}; + QPointF m_mouse_to_origin_movement{QPointF(0,0)}; QET::GraphicsItemState m_state = QET:: GIOK; }; diff --git a/sources/qetgraphicsitem/qetshapeitem.cpp b/sources/qetgraphicsitem/qetshapeitem.cpp index 2d727b10e..88e710e12 100644 --- a/sources/qetgraphicsitem/qetshapeitem.cpp +++ b/sources/qetgraphicsitem/qetshapeitem.cpp @@ -835,6 +835,7 @@ void QetShapeItem::handlerMouseReleaseEvent() } } +// TODO: inherit from Propertiesinterface! /** @brief QetShapeItem::fromXml Build this item from the xml description diff --git a/sources/qetgraphicsitem/slaveelement.h b/sources/qetgraphicsitem/slaveelement.h index a75e021ce..d7e108373 100644 --- a/sources/qetgraphicsitem/slaveelement.h +++ b/sources/qetgraphicsitem/slaveelement.h @@ -35,7 +35,7 @@ class SlaveElement : public Element void unlinkElement(Element *elmt) override; private: - QGraphicsTextItem *m_xref_item; + QGraphicsTextItem *m_xref_item{nullptr}; }; #endif // SLAVEELEMENT_H diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index d0d1e1f47..e14a09876 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -30,7 +30,7 @@ QColor Terminal::neutralColor = QColor(Qt::blue); QColor Terminal::allowedColor = QColor(Qt::darkGreen); QColor Terminal::warningColor = QColor("#ff8000"); QColor Terminal::forbiddenColor = QColor(Qt::red); -const qreal Terminal::terminalSize = 4.0; +const qreal Terminal::terminalSize = 4.0; // TODO: store terminalSize in terminaldata, because in PartTerminal there is the same parameter. So only one is needed const qreal Terminal::Z = 1000; /** @@ -43,8 +43,6 @@ const qreal Terminal::Z = 1000; void Terminal::init( QString number, QString name, bool hiddenName) { - hovered_color_ = Terminal::neutralColor; - // calcul de la position du point d'amarrage a l'element dock_elmt_ = d->m_pos; switch(d->m_orientation) { @@ -57,17 +55,15 @@ void Terminal::init( // Number of terminal number_terminal_ = std::move(number); // Name of terminal - name_terminal_ = std::move(name); + d->m_name = std::move(name); name_terminal_hidden = hiddenName; // par defaut : pas de conducteur // QRectF null br_ = new QRectF(); - previous_terminal_ = nullptr; // divers setAcceptHoverEvents(true); setAcceptedMouseButtons(Qt::LeftButton); - hovered_ = false; setToolTip(QObject::tr("Borne", "tooltip")); setZValue(Z); } @@ -213,11 +209,18 @@ void Terminal::setNumber(QString number) @param hiddenName : bool */ void Terminal::setName(QString name, bool hiddenName) -{ - name_terminal_ = std::move(name); + d->m_name = std::move(name); name_terminal_hidden = hiddenName; } +/** + @brief Terminal::name + @return the name of terminal. +*/ +inline QString Terminal::name() const { + return(d->m_name); +} + /** @brief Terminal::addConductor Add a conductor to this terminal @@ -745,6 +748,10 @@ bool Terminal::canBeLinkedTo(Terminal *other_terminal) return true; } +void Terminal::setID(int id) { + m_id = id; +} + /** @brief Terminal::conductors @return La liste des conducteurs lies a cette borne @@ -764,15 +771,24 @@ 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, "number", number_terminal_)); + qdo.appendChild(createXmlProperty(doc, "nameHidden", name_terminal_hidden)); + + // store terminal data too! + + // Do not store terminal data in its own child + // Bad hack. The problem is that in the diagrams the terminal is described by the position and in the Collection by the dock. + QPointF tempPos = d->m_pos; + d->m_pos = dock_elmt_; + QDomElement terminalDataElement = d->toXml(doc); + d->m_pos = tempPos; + + int childsCount = terminalDataElement.childNodes().count(); + for (int i=0; i < childsCount; i++) { + QDomNode node = terminalDataElement.childNodes().at(i).cloneNode(); // cloneNode() is important, otherwise no deep clone is made + qdo.appendChild(node); + } - qdo.setAttribute("orientation", d->m_orientation); - qdo.setAttribute("number", number_terminal_); - qdo.setAttribute("name", name_terminal_); - qdo.setAttribute("nameHidden", name_terminal_hidden); return(qdo); } @@ -782,42 +798,25 @@ 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) +bool Terminal::valideXml(const QDomElement &terminal) { { - // verifie le nom du tag if (terminal.tagName() != "terminal") 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); +// affuteuse_250h.qet contains in line 8398 terminals which do not have this +// if (propertyString(terminal, "number")) +// return false; +// affuteuse_250h.qet contains in line 8398 terminals which do not have this +// if (propertyBool(terminal, "nameHidden")) +// 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); + if (!TerminalData::valideXml(terminal)) + return false; // a ce stade, la borne est syntaxiquement correcte - return(true); + return true; } -/** +/** RETURNS True @brief Terminal::fromXml Permet de savoir si un element XML represente cette borne. Attention, l'element XML n'est pas verifie @@ -825,17 +824,17 @@ 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) { + propertyString(terminal, "number", &number_terminal_); - return ( - qFuzzyCompare(terminal.attribute("x").toDouble(), dock_elmt_.x()) && - qFuzzyCompare(terminal.attribute("y").toDouble(), dock_elmt_.y()) && - (terminal.attribute("orientation").toInt() == d->m_orientation) - ); + propertyBool(terminal, "nameHidden", &name_terminal_hidden); + + if(!d->fromXml(terminal)) + return false; + + + init(number_terminal_, d->m_name, name_terminal_hidden); // initialize dock_elmt_. This must be done after Terminal data is initialized + return true; } /** @@ -872,6 +871,18 @@ QUuid Terminal::uuid() const return d->m_uuid; } +int Terminal::ID() const { + return m_id; +} + +QPointF Terminal::dockPos() { + return dock_elmt_; +} + +QPointF Terminal::originPos() { + return d->m_pos; +} + /** @brief Conductor::relatedPotentialTerminal Return terminal at the same potential from the same diff --git a/sources/qetgraphicsitem/terminal.h b/sources/qetgraphicsitem/terminal.h index 43bf34762..040e839c1 100644 --- a/sources/qetgraphicsitem/terminal.h +++ b/sources/qetgraphicsitem/terminal.h @@ -20,6 +20,8 @@ #include #include #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 @@ -77,6 +79,9 @@ class Terminal : public QGraphicsObject Diagram *diagram () const; Element *parentElement () const; QUuid uuid () const; + int ID() const; + QPointF dockPos(); + QPointF originPos(); QList conductors() const; Qet::Orientation orientation() const; @@ -88,11 +93,12 @@ class Terminal : public QGraphicsObject void updateConductor(); bool isLinkedTo(Terminal *); bool canBeLinkedTo(Terminal *); + void setID(int id); // methods related to XML import/export - static bool valideXml(QDomElement &); - bool fromXml (QDomElement &); - QDomElement toXml (QDomDocument &) const; + static bool valideXml(const QDomElement &); + bool fromXml (const QDomElement &) override; + QDomElement toXml (QDomDocument &) const override; protected: // methods related to events management @@ -110,6 +116,7 @@ class Terminal : public QGraphicsObject static const qreal terminalSize; static const qreal Z; // Various static colors used for hover effects + // The assignement is in the cpp file /// default color static QColor neutralColor; /// color for legal actions @@ -142,16 +149,17 @@ class Terminal : public QGraphicsObject */ QRectF *br_{nullptr}; /// Last terminal seen through an attached conductor - Terminal *previous_terminal_; + Terminal *previous_terminal_{nullptr}; /// Whether the mouse pointer is hovering the terminal - bool hovered_; + bool hovered_{false}; /// Color used for the hover effect - QColor hovered_color_; + QColor hovered_color_{Terminal::hovered_color_}; /// Number of Terminal QString number_terminal_; - /// Name of Terminal - QString name_terminal_; - bool name_terminal_hidden; + bool name_terminal_hidden{true}; + + /// legacy id used by the conductor to find the terminal. From 0.8x on the uuid is used instead. + int m_id{-1}; private: void init(QString number, QString name, bool hiddenName); @@ -177,15 +185,7 @@ inline QString Terminal::number() const return(number_terminal_); } -/** - @brief Terminal::name - @return the name of terminal. -*/ -inline QString Terminal::name() const { - return(name_terminal_); -} - QList relatedPotentialTerminal (const Terminal *terminal, const bool all_diagram = true); diff --git a/sources/qetproject.cpp b/sources/qetproject.cpp index eae884a47..1a2ca56c5 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -1505,7 +1505,11 @@ void QETProject::readDefaultPropertiesXml(QDomDocument &xml_project) { XRefProperties xrp; xrp.fromXml(elmt); - m_default_xref_properties.insert(elmt.attribute("type"), xrp); + QString type; + if (PropertiesInterface::propertyString(elmt, "type", &type) == PropertiesInterface::PropertyFlags::Success) + m_default_xref_properties.insert(type, xrp); + else + qDebug() << "xref Property was not added to m_default_xref_properties."; } } if (!conds_autonums.isNull()) @@ -1563,19 +1567,13 @@ void QETProject::writeDefaultPropertiesXml(QDomElement &xml_element) QDomDocument xml_document = xml_element.ownerDocument(); // export size of border - QDomElement border_elmt = xml_document.createElement("border"); - default_border_properties_.toXml(border_elmt); - xml_element.appendChild(border_elmt); + xml_element.appendChild(default_border_properties_.toXml(xml_document)); // export content of titleblock - QDomElement titleblock_elmt = xml_document.createElement("inset"); - default_titleblock_properties_.toXml(titleblock_elmt); - xml_element.appendChild(titleblock_elmt); + xml_element.appendChild(default_titleblock_properties_.toXml(xml_document)); // exporte default conductor - QDomElement conductor_elmt = xml_document.createElement("conductors"); - default_conductor_properties_.toXml(conductor_elmt); - xml_element.appendChild(conductor_elmt); + xml_element.appendChild(default_conductor_properties_.toXml(xml_document)); // export default report properties QDomElement report_elmt = xml_document.createElement("report"); diff --git a/sources/titleblock/helpercell.h b/sources/titleblock/helpercell.h index 905d12136..f484f1caa 100644 --- a/sources/titleblock/helpercell.h +++ b/sources/titleblock/helpercell.h @@ -37,11 +37,11 @@ class HelperCell : public QGraphicsObject, public QGraphicsLayoutItem { // attributes public: - QColor background_color; ///< Background color when rendering this cell - QColor foreground_color; ///< Text color when rendering this cell + QColor background_color{Qt::white}; ///< Background color when rendering this cell + QColor foreground_color{Qt::black}; ///< Text color when rendering this cell QString label; ///< Label displayed in this cell - Qt::Orientation orientation; ///< Orientation of this cell - int index; ///< Index of this cell + Qt::Orientation orientation{Qt::Horizontal}; ///< Orientation of this cell + int index{-1}; ///< Index of this cell // methods public: diff --git a/sources/titleblock/splittedhelpercell.h b/sources/titleblock/splittedhelpercell.h index 29935b731..747124418 100644 --- a/sources/titleblock/splittedhelpercell.h +++ b/sources/titleblock/splittedhelpercell.h @@ -36,6 +36,7 @@ class SplittedHelperCell : public HelperCell { void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget * = nullptr) override; // attributes + // colors are set in the constructor QColor split_background_color; ///< Background color on the split side QColor split_foreground_color; ///< Text color on the split side QString split_label; ///< Text displayed on the split side diff --git a/sources/titleblockproperties.cpp b/sources/titleblockproperties.cpp index 04acd2de9..411988240 100644 --- a/sources/titleblockproperties.cpp +++ b/sources/titleblockproperties.cpp @@ -23,11 +23,7 @@ Constructeur. Initialise un objet TitleBlockProperties avec tous les champs vides (date vide + useDate a UseDateValue). */ -TitleBlockProperties::TitleBlockProperties() : - date(), - useDate(UseDateValue), - display_at(Qt::BottomEdge), - collection (QET::QetCollection::Common) +TitleBlockProperties::TitleBlockProperties() { } @@ -100,29 +96,42 @@ void TitleBlockProperties::toXml(QDomElement &e) const } } -/** +QDomElement TitleBlockProperties::toXml(QDomDocument &d) const { + Q_UNUSED(d) + qDebug() << "NOT IMPLEMENTED!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; + return QDomElement(); +} + +/** RETURNS True Importe le cartouche a partir des attributs XML de l'element e @param e Element XML dont les attributs seront lus */ -void TitleBlockProperties::fromXml(const QDomElement &e) { +bool TitleBlockProperties::fromXml(const QDomElement &e) { + + // reads the historical fields - if (e.hasAttribute("author")) author = e.attribute("author"); - if (e.hasAttribute("title")) title = e.attribute("title"); - if (e.hasAttribute("filename")) filename = e.attribute("filename"); - if (e.hasAttribute("plant")) plant = e.attribute("plant"); - if (e.hasAttribute("locmach")) locmach = e.attribute("locmach"); - if (e.hasAttribute("indexrev")) indexrev = e.attribute("indexrev"); - if (e.hasAttribute("version")) version = e.attribute("version"); - if (e.hasAttribute("folio")) folio = e.attribute("folio"); - if (e.hasAttribute("auto_page_num")) auto_page_num = e.attribute("auto_page_num"); - if (e.hasAttribute("date")) setDateFromString(e.attribute("date")); - if (e.hasAttribute("displayAt")) display_at = (e.attribute("displayAt") == "bottom" ? Qt::BottomEdge : Qt::RightEdge); + propertyString(e, "author", &author); + propertyString(e, "title", &title); + propertyString(e, "filename", &filename); + propertyString(e, "plant", &plant); + propertyString(e, "locmach", &locmach); + propertyString(e, "indexrev", &indexrev); + propertyString(e, "version", &version); + propertyString(e, "folio", &folio); + propertyString(e, "auto_page_num", &auto_page_num); + QString date; + propertyString(e, "date", &date); + setDateFromString(date); + + QString display_at_temp; + if (propertyString(e, "displayAt", &display_at_temp) == PropertyFlags::Success) + display_at = (display_at_temp == "bottom" ? Qt::BottomEdge : Qt::RightEdge); // otherwise it gets default in header file // reads the template used to render the title block - if (e.hasAttribute("titleblocktemplate")) - { - template_name = e.attribute("titleblocktemplate"); - collection = QET::qetCollectionFromString(e.attribute("titleblocktemplateCollection")); + if (propertyString(e, "titleblocktemplate", &template_name) == PropertyFlags::Success) { + QString tbc; + if (propertyString(e, "titleblocktemplateCollection", &tbc) == PropertyFlags::Success) + collection = QET::qetCollectionFromString(tbc); } // reads the additional fields used to fill the title block @@ -130,6 +139,7 @@ void TitleBlockProperties::fromXml(const QDomElement &e) { foreach (QDomElement e, QET::findInDomElement(e, "properties")) { context.fromXml(e); } + return true; } /** @@ -161,7 +171,7 @@ void TitleBlockProperties::toSettings(QSettings &settings, const QString &prefix @param settings Parametres a lire @param prefix prefixe a ajouter devant les noms des parametres */ -void TitleBlockProperties::fromSettings(QSettings &settings, const QString &prefix) { +void TitleBlockProperties::fromSettings(const QSettings &settings, const QString &prefix) { title = settings.value(prefix + "title").toString(); author = settings.value(prefix + "author").toString(); filename = settings.value(prefix + "filename").toString(); diff --git a/sources/titleblockproperties.h b/sources/titleblockproperties.h index fbe61ff60..1a1395d4e 100644 --- a/sources/titleblockproperties.h +++ b/sources/titleblockproperties.h @@ -21,12 +21,14 @@ #include "diagramcontext.h" #include "qet.h" +#include "propertiesinterface.h" + /** This class provides a container for the properties of a particular title block, i.e. title, author, date, filename, folio, template, custom properties, ... */ -class TitleBlockProperties { +class TitleBlockProperties: public PropertiesInterface { public: TitleBlockProperties(); virtual ~TitleBlockProperties(); @@ -39,10 +41,11 @@ class TitleBlockProperties { bool operator==(const TitleBlockProperties &); bool operator!=(const TitleBlockProperties &); - void toXml(QDomElement &) const; - void fromXml(const QDomElement &); - void toSettings(QSettings &, const QString & = QString()) const; - void fromSettings(QSettings &, const QString & = QString()); + QDomElement toXml(QDomDocument &e) const override; + void toXml(QDomElement &e) const; + bool fromXml(const QDomElement &) override; + void toSettings(QSettings &, const QString & = QString()) const override; + void fromSettings(const QSettings &, const QString & = QString()) override; void setAutoPageNum(QString autonum) {auto_page_num = autonum;} @@ -61,11 +64,11 @@ class TitleBlockProperties { QString version; ///< Version (displayed by the default template) QString folio; ///< Folio information (displayed by the default template) QString auto_page_num; - DateManagement useDate; ///< Wheter to use the date attribute + DateManagement useDate{UseDateValue}; ///< Wheter to use the date attribute QString template_name; ///< Name of the template used to render the title block - an empty string means "the default template provided by the application" DiagramContext context; ///< Container for the additional, user-defined fields - Qt::Edge display_at; ///< Edge to display the titleblock - QET::QetCollection collection; ///