diff --git a/sources/ElementsCollection/fileelementcollectionitem.cpp b/sources/ElementsCollection/fileelementcollectionitem.cpp index f3f7f63a0..4aa22d3be 100644 --- a/sources/ElementsCollection/fileelementcollectionitem.cpp +++ b/sources/ElementsCollection/fileelementcollectionitem.cpp @@ -40,8 +40,8 @@ FileElementCollectionItem::FileElementCollectionItem() @return true if path exist. */ bool FileElementCollectionItem::setRootPath(const QString& path, - bool set_data, - bool hide_element) + bool set_data, + bool hide_element) { QDir dir(path); if (dir.exists()) @@ -190,16 +190,16 @@ QString FileElementCollectionItem::name() const */ QString FileElementCollectionItem::collectionPath() const { + QStandardItem* parent_ = parent(); if (isCollectionRoot()) { if (m_path == QETApp::commonElementsDirN()) return "common://"; else return "custom://"; } - else if (parent() && parent()->type() - == FileElementCollectionItem::Type) { - ElementCollectionItem *eci = - static_cast(parent()); + else if (parent_ && parent()->type() == FileElementCollectionItem::Type) + { + ElementCollectionItem *eci = static_cast(parent()); if (eci->isCollectionRoot()) return eci->collectionPath() + m_path; else @@ -276,7 +276,7 @@ void FileElementCollectionItem::setUpData() setFlags(Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled); - + //Set the local name and all informations of the element //in the data Qt::UserRole+1, these data will be use for search. ElementsLocation loc(collectionPath()); @@ -331,8 +331,8 @@ void FileElementCollectionItem::setUpIcon() @param hide_element */ void FileElementCollectionItem::setPathName(const QString& path_name, - bool set_data, - bool hide_element) + bool set_data, + bool hide_element) { m_path = path_name; @@ -353,7 +353,7 @@ void FileElementCollectionItem::populate(bool set_data, bool hide_element) //Get all directory in this directory. for(auto str : dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot, - QDir::Name)) + QDir::Name)) { FileElementCollectionItem *feci = new FileElementCollectionItem(); appendRow(feci); @@ -368,7 +368,7 @@ void FileElementCollectionItem::populate(bool set_data, bool hide_element) //Get all elmt file in this directory dir.setNameFilters(QStringList() << "*.elmt"); for(auto str : dir.entryList(QDir::Files | QDir::NoDotAndDotDot, - QDir::Name)) + QDir::Name)) { FileElementCollectionItem *feci = new FileElementCollectionItem(); appendRow(feci); diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp index 09947c2fe..3fea994d3 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp +++ b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.cpp @@ -25,17 +25,17 @@ @param size : the size of the handler */ QetGraphicsHandlerItem::QetGraphicsHandlerItem(qreal size) : - m_size(size) + m_size(size) { setFlag(QGraphicsItem::ItemIgnoresTransformations); - + m_handler_rect.setRect(0-m_size/2, 0-m_size/2, m_size, m_size); m_br.setRect(-1-m_size/2, -1-m_size/2, m_size+2, m_size+2); } /** @brief QetGraphicsHandlerItem::boundingRect - @return + @return */ QRectF QetGraphicsHandlerItem::boundingRect() const { diff --git a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h index 270b30123..bf1bd4071 100644 --- a/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h +++ b/sources/QetGraphicsItemModeler/qetgraphicshandleritem.h @@ -38,10 +38,10 @@ class QetGraphicsHandlerItem : public QGraphicsItem public: QetGraphicsHandlerItem(qreal size = 10); QRectF boundingRect() const override; - + enum { Type = UserType + 1200}; int type() const override {return Type;} - + void setColor(QColor color); protected: @@ -50,12 +50,11 @@ class QetGraphicsHandlerItem : public QGraphicsItem QWidget *widget) override; private: - QRectF m_handler_rect, - m_br; + QRectF m_handler_rect,m_br; qreal m_size; - QColor m_color; + QColor m_color{Qt::black}; QPen m_pen; - + public: static QVector handlerForPoint( const QVector &points, int size = 10); diff --git a/sources/borderproperties.cpp b/sources/borderproperties.cpp index a2aa3de5f..ef7bda874 100644 --- a/sources/borderproperties.cpp +++ b/sources/borderproperties.cpp @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -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() { } @@ -86,27 +78,26 @@ bool BorderProperties::operator==(const BorderProperties &bp) { bool BorderProperties::operator!=(const BorderProperties &bp) { return(!(*this == bp)); } - /** @brief BorderProperties::toXml - Exports dimensions as XML attributes added to element e. - \~French Exporte les dimensions sous formes d'attributs XML ajoutes a l'element e. - - \~ @param e : - XML element to which attributes will be added - \~French Element XML auquel seront ajoutes des attributs + @param dom_doc + @return */ -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 +106,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,11 +162,11 @@ 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(); - + rows_count = settings.value(prefix + "rows", rows_count).toInt(); rows_height = qRound(settings.value(prefix + "rowsize", rows_height).toDouble()); display_rows = settings.value(prefix + "displayrows", display_rows).toBool(); diff --git a/sources/borderproperties.h b/sources/borderproperties.h index 74df1e8bb..34e0ead08 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 &); - void toSettings(QSettings &, const QString & = QString()) const; - void fromSettings(QSettings &, const QString & = QString()); + QDomElement toXml(QDomDocument &dom_doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& e); + void toSettings(QSettings &, const QString & = QString()) const override; + void fromSettings(const QSettings &, const QString & = QString()) override; 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 026bab62f..a36208c55 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 39a7f93a6..6b576c389 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 b26853f8b..4f76b1a22 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() { } @@ -123,9 +119,9 @@ void SingleLineProperties::draw(QPainter *painter, @param size taille du segment */ void SingleLineProperties::drawGround(QPainter *painter, - QET::ConductorSegmentType direction, - QPointF center, - qreal size) { + QET::ConductorSegmentType direction, + QPointF center, + qreal size) { painter -> save(); // prepare le QPainter @@ -211,16 +207,21 @@ void SingleLineProperties::drawPen(QPainter *painter, } /** - Exporte les parametres du conducteur unifilaire sous formes d'attributs XML - ajoutes a l'element e. - @param e Element XML auquel seront ajoutes des attributs + @brief SingleLineProperties::toXml + @param doc + @return */ -void SingleLineProperties::toXml(QDomElement &e) const +QDomElement SingleLineProperties::toXml(QDomDocument &doc) const { - e.setAttribute("ground", hasGround ? "true" : "false"); - e.setAttribute("neutral", hasNeutral ? "true" : "false"); - e.setAttribute("phase", phases); - if (isPen()) e.setAttribute("pen", "true"); + 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,116 +292,142 @@ 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)); + QDomElement e = doc.createElement("defaultconductor"); - if (color != QColor(Qt::black)) - e.setAttribute("color", color.name()); + e.appendChild(createXmlProperty(doc, "type", typeToString(type))); + e.appendChild(createXmlProperty(doc, "color", color)); - 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, "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.appendChild(singleLineProperties.toXml(doc)); - 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(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)); 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)); + // get conductor color + propertyColor(e, "color", &color); + propertyBool(e, "bicolor", &m_bicolor); + propertyColor(e, "color2", &m_color_2); + propertyInteger(e, "dash-size", &m_dash_size); - QString bicolor_str = e.attribute("bicolor", "false"); - m_bicolor = bicolor_str == "true"? true : false; + // read style of conductor + QString style_string; + propertyString(e, "style", &style_string); + readStyle(style_string); - 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(); - - // read style of conductor - readStyle(e.attribute("style")); - - 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 - type = Multi; - - text = e.attribute("num"); - // 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(); - - QMetaEnum me = QMetaEnum::fromType(); - m_horizontal_alignment = Qt::Alignment( - me.keyToValue( - e.attribute( - "horizontal-alignment", - "AlignBottom" - ).toStdString().data())); - m_vertical_alignment = Qt::Alignment( - me.keyToValue( - e.attribute( - "vertical-alignment", - "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 + singleLineProperties.fromXml(e); + type = Single; + } + 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 #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; + if (type_t == "simple") m_show_text = false; + } + } + + propertyString(e, "num", &text); + + // get text color + 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(); + + 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; +} + +/** + @brief ConductorProperties::valideXml + @param e + @return +*/ +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; } /** @@ -393,8 +445,8 @@ void ConductorProperties::toSettings(QSettings &settings, const QString &prefix) settings.setValue(prefix + "text", text); settings.setValue(prefix + "text_color", text_color.name()); settings.setValue(prefix + "formula", m_formula); - settings.setValue(prefix + "cable", m_cable); - settings.setValue(prefix + "bus", m_bus); + //settings.setValue(prefix + "cable", m_cable); + //settings.setValue(prefix + "bus", m_bus); settings.setValue(prefix + "function", m_function); settings.setValue(prefix + "tension_protocol", m_tension_protocol); settings.setValue(prefix + "conductor_color", m_wire_color); @@ -417,7 +469,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)); @@ -437,8 +489,8 @@ void ConductorProperties::fromSettings(QSettings &settings, const QString &prefi QColor settings_text_color = QColor(settings.value(prefix + "text_color").toString()); text_color = (settings_text_color.isValid()? settings_text_color : QColor(Qt::black)); m_formula = settings.value(prefix + "formula", "").toString(); - m_cable = settings.value(prefix + "cable", "").toString(); - m_bus = settings.value(prefix + "bus", "").toString(); + //m_cable = settings.value(prefix + "cable", "").toString(); + //m_bus = settings.value(prefix + "bus", "").toString(); m_function = settings.value(prefix + "function", "").toString(); m_tension_protocol = settings.value(prefix + "tension_protocol", "").toString(); m_wire_color = settings.value(prefix + "conductor_color", "").toString(); @@ -448,7 +500,7 @@ void ConductorProperties::fromSettings(QSettings &settings, const QString &prefi m_show_text = settings.value(prefix + "displaytext", true).toBool(); m_one_text_per_folio = settings.value(prefix + "onetextperfolio", false).toBool(); verti_rotate_text = settings.value((prefix + "vertirotatetext"), "270").toDouble(); - horiz_rotate_text = settings.value((prefix + "horizrotatetext"), "0").toDouble(); + horiz_rotate_text = settings.value((prefix + "horizrotatetext"), "0").toDouble(); QMetaEnum me = QMetaEnum::fromType(); m_horizontal_alignment = Qt::Alignment(me.keyToValue(settings.value(prefix + "horizontal-alignment", "AlignBottom").toString().toStdString().data())); @@ -493,8 +545,8 @@ void ConductorProperties::applyForEqualAttributes(QList lis text = cp.text; text_color = cp.text_color; m_formula = cp.m_formula; - m_cable = cp.m_cable; - m_bus = cp.m_bus; + //m_cable = cp.m_cable; + //m_bus = cp.m_bus; m_function = cp.m_function; m_tension_protocol = cp.m_tension_protocol; m_wire_color = cp.m_wire_color; @@ -596,27 +648,27 @@ void ConductorProperties::applyForEqualAttributes(QList lis m_formula = s_value; equal = true; - //cable - s_value = clist.first().m_cable; - for(ConductorProperties cp : clist) - { - if (cp.m_cable != s_value) - equal = false; - } - if (equal) - m_cable = s_value; - equal = true; +// //cable +// s_value = clist.first().m_cable; +// for(ConductorProperties cp : clist) +// { +// if (cp.m_cable != s_value) +// equal = false; +// } +// if (equal) +// m_cable = s_value; +// equal = true; - //bus - s_value = clist.first().m_bus; - for(ConductorProperties cp : clist) - { - if (cp.m_bus != s_value) - equal = false; - } - if (equal) - m_bus = s_value; - equal = true; +// //bus +// s_value = clist.first().m_bus; +// for(ConductorProperties cp : clist) +// { +// if (cp.m_bus != s_value) +// equal = false; +// } +// if (equal) +// m_bus = s_value; +// equal = true; //function s_value = clist.first().m_function; @@ -783,8 +835,9 @@ bool ConductorProperties::operator==(const ConductorProperties &other) const other.text == text &&\ other.text_color == text_color &&\ other.m_formula == m_formula &&\ - other.m_cable == m_cable &&\ +/* other.m_cable == m_cable &&\ other.m_bus == m_bus &&\ +*/ other.m_function == m_function &&\ other.m_tension_protocol == m_tension_protocol &&\ other.m_wire_color == m_wire_color && \ @@ -842,7 +895,7 @@ void ConductorProperties::readStyle(const QString &style_string) { if (!match.hasMatch()) { qDebug()<<"no Match" - < #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,25 @@ class SingleLineProperties { unsigned short int phasesCount(); bool isPen() const; void draw(QPainter *, QET::ConductorSegmentType, const QRectF &); - void toXml(QDomElement &) const; - void fromXml(QDomElement &); - void toSettings(QSettings &, const QString & = QString()) const; - void fromSettings(QSettings &, const QString & = QString()); + QDomElement toXml(QDomDocument& doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& element); + void toSettings(QSettings &, const QString & = QString()) const override; + void fromSettings(const QSettings &, const QString & = QString()) override; /// 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 +68,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(); @@ -78,52 +82,45 @@ class ConductorProperties */ enum ConductorType { Single, Multi }; + //Attributes + ConductorType type{ConductorType::Single}; - //Attributes - ConductorType type; + // TODO: set default values! + QColor color{QColor(Qt::black)}, + m_color_2{QColor(Qt::black)}, + text_color{QColor(Qt::black)}; - QColor - color, - m_color_2, - text_color; + QString text, + m_function, + m_tension_protocol, + m_wire_color, + m_wire_section, + m_formula; - QString - text, - m_function, - m_tension_protocol, - m_wire_color, - m_wire_section, - m_formula, - m_bus, - m_cable; + int text_size{9}, + m_dash_size = 1; - int - text_size, - m_dash_size = 1; + double cond_size{1}, + verti_rotate_text, + horiz_rotate_text; - double - cond_size, - verti_rotate_text, - horiz_rotate_text; + bool m_show_text{true}, + m_one_text_per_folio{true}, + m_bicolor = false; - bool - m_show_text, - m_one_text_per_folio, - m_bicolor = false; + Qt::Alignment m_horizontal_alignment = Qt::AlignBottom, + m_vertical_alignment = Qt::AlignRight; - Qt::Alignment - 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 &); - void toSettings(QSettings &, const QString & = QString()) const; - void fromSettings(QSettings &, const QString & = QString()); + // methods + QDomElement toXml(QDomDocument &doc) const override; + bool fromXml(const QDomElement &) override; + static bool valideXml(QDomElement& element); + void toSettings(QSettings &, const QString & = QString()) const override; + void fromSettings(const QSettings &, const QString & = QString()) override; static QString typeToString(ConductorType); void applyForEqualAttributes(QList list); diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 5414c35bb..b3e77c47e 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -178,7 +178,7 @@ void Diagram::drawBackground(QPainter *p, const QRectF &r) { */ QPen pen; Diagram::background_color == Qt::black? pen.setColor(Qt::white) - : pen.setColor(Qt::black); + : pen.setColor(Qt::black); pen.setCosmetic(true); p->setPen(pen); @@ -324,9 +324,9 @@ void Diagram::keyPressEvent(QKeyEvent *event) { QSettings settings; int xKeyGrid = settings.value("diagrameditor/key_Xgrid", - Diagram::xKeyGrid).toInt(); + Diagram::xKeyGrid).toInt(); int yKeyGrid = settings.value("diagrameditor/key_Ygrid", - Diagram::yKeyGrid).toInt(); + Diagram::yKeyGrid).toInt(); int xKeyGridFine = settings.value("diagrameditor/key_fine_Xgrid", Diagram::xKeyGridFine).toInt(); int yKeyGridFine = settings.value("diagrameditor/key_fine_Ygrid", @@ -581,9 +581,9 @@ void Diagram::setConductorsAutonumName(const QString &name) { @return Une QImage representant le schema */ bool Diagram::toPaintDevice(QPaintDevice &pix, - int width, - int height, - Qt::AspectRatioMode aspectRatioMode) { + int width, + int height, + Qt::AspectRatioMode aspectRatioMode) { // determine the source area = schema content + margins // determine la zone source = contenu du schema + marges QRectF source_area; @@ -630,9 +630,9 @@ bool Diagram::toPaintDevice(QPaintDevice &pix, // renders itself // effectue le rendu lui-meme render(&p, - QRect(QPoint(0, 0),image_size), - source_area, - aspectRatioMode); + QRect(QPoint(0, 0),image_size), + source_area, + aspectRatioMode); p.end(); // restore selected items @@ -734,30 +734,30 @@ QDomDocument Diagram::toXml(bool whole_content) { // schema properties // proprietes du schema - if (whole_content) { + 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 = - document.createElement("defaultconductor"); - defaultConductorProperties.toXml(default_conductor); - dom_root.appendChild(default_conductor); + dom_root.appendChild(defaultConductorProperties.toXml(document)); // Conductor autonum - if (!m_conductors_autonum_name.isEmpty()) { - dom_root.setAttribute("conductorAutonum", - m_conductors_autonum_name); + if (!m_conductors_autonum_name.isEmpty()) + { + dom_root.setAttribute( + "conductorAutonum",m_conductors_autonum_name); } //Default New Element dom_root.setAttribute("freezeNewElement", - m_freeze_new_elements ? "true" : "false"); + m_freeze_new_elements ? "true" : "false"); //Default New Conductor dom_root.setAttribute("freezeNewConductor", - m_freeze_new_conductors_ - ? "true" : "false"); + m_freeze_new_conductors_ + ? "true" : "false"); //Element Folio Sequential Variables if (!m_elmt_unitfolio_max.isEmpty() @@ -771,10 +771,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "elementunitfolioseq"); folioSequentialsToXml(&m_elmt_unitfolio_max, - &elmtfolioseq, - "sequf_", - "unitfolioseq", - &document); + &elmtfolioseq, + "sequf_", + "unitfolioseq", + &document); elmtfoliosequential.appendChild(elmtfolioseq); } if (!m_elmt_tenfolio_max.isEmpty()) { @@ -782,10 +782,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "elementtenfolioseq"); folioSequentialsToXml(&m_elmt_tenfolio_max, - &elmtfolioseq, - "seqtf_", - "tenfolioseq", - &document); + &elmtfolioseq, + "seqtf_", + "tenfolioseq", + &document); elmtfoliosequential.appendChild(elmtfolioseq); } if (!m_elmt_hundredfolio_max.isEmpty()) { @@ -793,10 +793,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "elementhundredfolioseq"); folioSequentialsToXml(&m_elmt_hundredfolio_max, - &elmtfolioseq, - "seqhf_", - "hundredfolioseq", - &document); + &elmtfolioseq, + "seqhf_", + "hundredfolioseq", + &document); elmtfoliosequential.appendChild(elmtfolioseq); } dom_root.appendChild(elmtfoliosequential); @@ -814,10 +814,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "conductorunitfolioseq"); folioSequentialsToXml(&m_cnd_unitfolio_max, - &cndfolioseq, - "sequf_", - "unitfolioseq", - &document); + &cndfolioseq, + "sequf_", + "unitfolioseq", + &document); cndfoliosequential.appendChild(cndfolioseq); } if (!m_cnd_tenfolio_max.isEmpty()) { @@ -825,10 +825,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "conductortenfolioseq"); folioSequentialsToXml(&m_cnd_tenfolio_max, - &cndfolioseq, - "seqtf_", - "tenfolioseq", - &document); + &cndfolioseq, + "seqtf_", + "tenfolioseq", + &document); cndfoliosequential.appendChild(cndfolioseq); } if (!m_cnd_hundredfolio_max.isEmpty()) { @@ -836,10 +836,10 @@ QDomDocument Diagram::toXml(bool whole_content) { document.createElement( "conductorhundredfolioseq"); folioSequentialsToXml(&m_cnd_hundredfolio_max, - &cndfolioseq, - "seqhf_", - "hundredfolioseq", - &document); + &cndfolioseq, + "seqhf_", + "hundredfolioseq", + &document); cndfoliosequential.appendChild(cndfolioseq); } dom_root.appendChild(cndfoliosequential); @@ -914,24 +914,22 @@ 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; + // table de correspondance entre les adresses des bornes et leurs ids if (!list_elements.isEmpty()) { auto dom_elements = document.createElement("elements"); - for (auto elmt : list_elements) { - dom_elements.appendChild(elmt->toXml(document, - table_adr_id)); + for (auto elmt : list_elements) + { + dom_elements.appendChild(elmt->toXml(document)); } dom_root.appendChild(dom_elements); } if (!list_conductors.isEmpty()) { auto dom_conductors = document.createElement("conductors"); - for (auto cond : list_conductors) { - dom_conductors.appendChild(cond->toXml(document, - table_adr_id)); + for (auto cond : list_conductors) + { + dom_conductors.appendChild(cond->toXml(document)); } dom_root.appendChild(dom_conductors); } @@ -981,18 +979,18 @@ QDomDocument Diagram::toXml(bool whole_content) { @param doc */ void Diagram::folioSequentialsToXml(QHash *hash, - QDomElement *domElement, - const QString& seq_type, - const QString& type, - QDomDocument *doc) { + QStringList> *hash, + QDomElement *domElement, + const QString& seq_type, + const QString& type, + QDomDocument *doc) { QHash::iterator i; for (i = hash->begin(); i != hash->end(); i++) { QDomElement folioseq = doc->createElement(type); folioseq.setAttribute("title", i.key()); for (int j = 0; j < i.value().size(); j++) { folioseq.setAttribute(seq_type + QString::number(j+1), - i.value().at(j)); + i.value().at(j)); } domElement->appendChild(folioseq); } @@ -1030,9 +1028,9 @@ void Diagram::folioSequentialsToXml(QHash& table_adr_id, - QList& added_elements) { +Terminal* findTerminal( + int conductor_index, + QDomElement& conductor, + QHash& table_adr_id, + QList& added_elements) +{ assert(conductor_index == 1 || conductor_index == 2); 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 +1113,9 @@ 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 +1139,15 @@ 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,51 +1155,39 @@ Terminal* findTerminal(int conductor_index, } else return table_adr_id.value(id_p1); } + qDebug() << "Diagram::findTerminal(): No terminal found."; return nullptr; } /** @brief Diagram::fromXml - Imports the described schema in an XML element. If a position is - specified, the imported elements are positioned in such a way that the - upper left corner of the smallest rectangle that can surround them all - (the bounding rect) either at this position. - \~French Importe le schema decrit dans un element XML. - Si une position est precisee, - les elements importes sont positionnes de maniere a ce que le - coin superieur gauche du plus petit rectangle pouvant les entourant tous - (le bounding rect) soit a cette position. - \~ @param document : - The XML document to analyze - \~French Le document XML a analyser - \~ @param position : - The position of the diagram matters - \~French La position du schema importe - \~ @param consider_informations : - If true, additional information - (author, title, ...) will be taken into account - \~French Si vrai, les informations complementaires - (auteur, titre, ...) seront prises en compte - \~ @param content_ptr : - if this pointer to a DiagramContent is different from 0, - it will be filled with the content added to the schema by the fromXml - \~French si ce pointeur vers un DiagramContent est different de 0, - il sera rempli avec le contenu ajoute au schema par le fromXml - \~ @return - true if the import was successful, false otherwise - \~French true si l'import a reussi, false sinon + @param document + @param position + @param consider_informations + @param content_ptr + @return */ -bool Diagram::fromXml(QDomElement &document, - QPointF position, - bool consider_informations, - DiagramContent *content_ptr) { +bool Diagram::fromXml( + QDomElement &document, + QPointF position, + bool consider_informations, + DiagramContent *content_ptr) +{ const QDomElement& root = document; // The first element must be a diagram if (root.tagName() != "diagram") return(false); - // Read attributes of this diagram - if (consider_informations) - { + qDebug() << "Diagram::fromXml; Diagram: " << root.attribute("title"); + + // Read attributes of this diagram + if (consider_informations) { + // Version of diagram + bool conv_ok; + qreal version_value = root.attribute("version").toDouble(&conv_ok); + if (conv_ok) { + diagram_qet_version_ = version_value; + } + // Load border and titleblock border_and_titleblock.titleBlockFromXml(root); border_and_titleblock.borderFromXml(root); @@ -1203,6 +1200,7 @@ bool Diagram::fromXml(QDomElement &document, defaultConductorProperties.fromXml(default_conductor_elmt); } + // Load the autonum m_conductors_autonum_name = root.attribute("conductorAutonum"); @@ -1256,7 +1254,7 @@ bool Diagram::fromXml(QDomElement &document, if (root.hasAttribute("projectId")) { QETProject *other_project = QETApp::project( root.attribute("projectId", - "-1").toInt()); + "-1").toInt()); /* We try to paste from another project, * then befor paste elements, @@ -1268,8 +1266,8 @@ bool Diagram::fromXml(QDomElement &document, ElementCollectionHandler ech; foreach (QDomElement element_xml, QET::findInDomElement(root, - "elements", - "element")) { + "elements", + "element")) { if (!Element::valideXml(element_xml)) continue; QString type_id = element_xml.attribute("type"); @@ -1279,16 +1277,16 @@ bool Diagram::fromXml(QDomElement &document, type_id, other_project); ech.importFromProject(m_project, - location); + location); } } } } - //Load all elements from the XML + //Load all elements from the collection in the XML QList added_elements; QHash table_adr_id; foreach (QDomElement element_xml, - QET::findInDomElement(root, "elements", "element")) + QET::findInDomElement(root, "elements", "element")) // read all elements from the diagram { if (!Element::valideXml(element_xml)) continue; @@ -1303,9 +1301,9 @@ bool Diagram::fromXml(QDomElement &document, } int state = 0; - Element *nvel_elmt = - ElementFactory::Instance() -> createElement( - element_location, nullptr, &state); + + // Create element from the collection + Element *nvel_elmt = ElementFactory::Instance() -> createElement(element_location, nullptr, &state); // read element definition from the collection! if (state) { QString debug_message = @@ -1319,13 +1317,14 @@ bool Diagram::fromXml(QDomElement &document, } addItem(nvel_elmt); - //Loading fail, remove item from the diagram - if (!nvel_elmt->fromXml(element_xml, table_adr_id)) + + //Loading fail, remove item from the diagram + if (!nvel_elmt->fromXml(element_xml, table_adr_id)) // load element definition from the diagram { removeItem(nvel_elmt); delete nvel_elmt; qDebug() << "Diagram::fromXml() : Le chargement des " - "parametres d'un element a echoue"; + "parametres d'un element a echoue"; } else { added_elements << nvel_elmt; } @@ -1334,8 +1333,8 @@ bool Diagram::fromXml(QDomElement &document, // Load text QList added_texts; foreach (QDomElement text_xml, QET::findInDomElement(root, - "inputs", - "input")) { + "inputs", + "input")) { IndependentTextItem *iti = new IndependentTextItem(); iti -> fromXml(text_xml); addItem(iti); @@ -1345,8 +1344,8 @@ bool Diagram::fromXml(QDomElement &document, // Load image QList added_images; foreach (QDomElement image_xml, QET::findInDomElement(root, - "images", - "image")) { + "images", + "image")) { DiagramImageItem *dii = new DiagramImageItem (); dii -> fromXml(image_xml); addItem(dii); @@ -1356,8 +1355,8 @@ bool Diagram::fromXml(QDomElement &document, // Load shape QList added_shapes; foreach (QDomElement shape_xml, QET::findInDomElement(root, - "shapes", - "shape")) { + "shapes", + "shape")) { QetShapeItem *dii = new QetShapeItem (QPointF(0,0)); dii -> fromXml(shape_xml); addItem(dii); @@ -1366,35 +1365,37 @@ bool Diagram::fromXml(QDomElement &document, // Load conductor QList added_conductors; - foreach (QDomElement f, QET::findInDomElement(root, - "conductors", - "conductor")) + + foreach (QDomElement conductorElement, + QET::findInDomElement(root, "conductors", "conductor")) { - if (!Conductor::valideXml(f)) continue; + if (!Conductor::valideXml(conductorElement)) continue; //Check if terminal that conductor must be linked is know - Terminal* p1 = findTerminal(1, f, table_adr_id, added_elements); - Terminal* p2 = findTerminal(2, f, table_adr_id, added_elements); + Terminal* p1 = findTerminal(1, conductorElement, table_adr_id, added_elements); + Terminal* p2 = findTerminal(2, conductorElement, table_adr_id, added_elements); - if (p1 && p2 && p1 != p2) + if (p1 && p2 && p1 != p2) // why the condition for unequal is required? { Conductor *c = new Conductor(p1, p2); if (c->isValid()) { addItem(c); - c -> fromXml(f); + c -> fromXml(conductorElement); added_conductors << c; } else delete c; + } else { + qDebug() << "Diagramm::fromXML(): No matching terminals found."; } } //Load tables QVector added_tables; for (auto dom_table - : QETXML::subChild(root, + : QETXML::subChild(root, "tables", QetGraphicsTableItem::xmlTagName())) { @@ -1473,23 +1474,23 @@ bool Diagram::fromXml(QDomElement &document, @param autonumFolioSeqType */ void Diagram::folioSequentialsFromXml(const QDomElement &root, - QHash* hash, - const QString& folioSeq, - const QString& seq, - const QString& type, - const QString& autonumFolioSeqType) { + QHash* hash, + const QString& folioSeq, + const QString& seq, + const QString& type, + const QString& autonumFolioSeqType) { foreach (QDomElement folioSeqAutoNum, QET::findInDomElement(root, autonumFolioSeqType, folioSeq)) { for(QDomElement folioseq - = folioSeqAutoNum.firstChildElement(type); - !folioseq.isNull(); - folioseq = folioseq.nextSiblingElement(type)) { + = folioSeqAutoNum.firstChildElement(type); + !folioseq.isNull(); + folioseq = folioseq.nextSiblingElement(type)) { QString title = folioseq.attribute("title"); QStringList list; int i = 1; while (folioseq.hasAttribute(seq - + QString::number(i))) { + + QString::number(i))) { list << folioseq.attribute( seq + QString::number(i)); i++; @@ -1745,10 +1746,10 @@ void Diagram::insertFolioSeqHash(QHash *hash, - const QString& title, - const QString& type, - NumerotationContext *nc) { + QStringList> *hash, + const QString& title, + const QString& type, + NumerotationContext *nc) { int j = 0; for (int i = 0; i < nc->size(); i++) { if (nc->itemAt(i).at(0) == type) { @@ -1773,9 +1774,9 @@ void Diagram::changeZValue(QET::DepthOption option) DiagramContent dc(this); QUndoCommand *undo = new QUndoCommand(tr("Modifier la profondeur")); QList l = dc.items(DiagramContent::SelectedOnly | \ - DiagramContent::Elements | \ - DiagramContent::Shapes | \ - DiagramContent::Images); + DiagramContent::Elements | \ + DiagramContent::Shapes | \ + DiagramContent::Images); QList list; for(QGraphicsItem *item : l) list << item->toGraphicsObject(); @@ -2164,7 +2165,7 @@ void Diagram::adjustSceneRect() { QRectF old_rect = sceneRect(); setSceneRect(border_and_titleblock.borderAndTitleBlockRect().united( - itemsBoundingRect())); + itemsBoundingRect())); update(old_rect.united(sceneRect())); } diff --git a/sources/diagram.h b/sources/diagram.h index f0df1ff60..5eadddaf5 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -58,13 +58,13 @@ class Diagram : public QGraphicsScene friend QETProject; Q_OBJECT - + // constructors, destructor private: Diagram(QETProject *project); ~Diagram() override; Diagram(const Diagram &diagram); - + // ATTRIBUTES public: /** @@ -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; @@ -128,7 +128,7 @@ class Diagram : public QGraphicsScene bool m_freeze_new_elements; bool m_freeze_new_conductors_; QUuid m_uuid = QUuid::createUuid(); - + // METHODS protected: void drawBackground(QPainter *, const QRectF &) override; @@ -142,7 +142,7 @@ class Diagram : public QGraphicsScene void wheelEvent (QGraphicsSceneWheelEvent *event) override; void keyPressEvent (QKeyEvent *event) override; void keyReleaseEvent (QKeyEvent *) override; - + public: QUuid uuid(); void setEventInterface (DiagramEventInterface *event_interface); @@ -153,53 +153,42 @@ class Diagram : public QGraphicsScene void setConductorsAutonumName(const QString &name); static bool clipboardMayContainDiagram(); - + // methods related to parent project QETProject *project() const; int folioIndex() const; void showMe() {emit showDiagram(this);} bool isReadOnly() const; - + // methods related to conductor creation void setConductor(bool); void setConductorStart (QPointF); void setConductorStop(QPointF); QList < QSet > potentials(); - + // methods related to XML import/export QDomDocument toXml(bool = true); - bool initFromXml(QDomElement &, - QPointF = QPointF(), - bool = true, - DiagramContent * = nullptr); - bool fromXml(QDomDocument &, - QPointF = QPointF(), - bool = true, - DiagramContent * = nullptr); - bool fromXml(QDomElement &, - QPointF = QPointF(), - bool = true, - DiagramContent * = nullptr); - void folioSequentialsToXml(QHash*, - QDomElement *, - const QString&, - const QString&, - QDomDocument *); - void folioSequentialsFromXml(const QDomElement&, - QHash*, - const QString&, - const QString&, - const QString&, - const QString&); - + bool initFromXml(QDomElement &, QPointF = QPointF(), + bool = true, DiagramContent * = nullptr); + bool fromXml( + QDomDocument &, QPointF = QPointF(), + bool = true, DiagramContent * = nullptr); + bool fromXml( + QDomElement &, QPointF = QPointF(), + bool = true, DiagramContent * = nullptr); + void folioSequentialsToXml( + QHash*, QDomElement *, const QString&, + const QString&, QDomDocument *); + void folioSequentialsFromXml( + const QDomElement&, QHash*, const QString&, + const QString&, const QString&,const QString&); + void refreshContents(); - + // methods related to graphics items addition/removal on the diagram virtual void addItem (QGraphicsItem *item); virtual void removeItem (QGraphicsItem *item); - + // methods related to graphics options ExportProperties applyProperties(const ExportProperties &); void setDisplayGrid(bool); @@ -210,19 +199,19 @@ class Diagram : public QGraphicsScene BorderOptions borderOptions(); DiagramPosition convertPosition(const QPointF &); static QPointF snapToGrid(const QPointF &p); - + bool drawTerminals() const; void setDrawTerminals(bool); bool drawColoredConductors() const; void setDrawColoredConductors(bool); - + QString title() const; bool toPaintDevice(QPaintDevice &, int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio); QSize imageSize() const; - + bool isEmpty() const; - + QList elements() const; QList conductors() const; QSet selectedConductors() const; @@ -232,29 +221,29 @@ class Diagram : public QGraphicsScene ElementTextsMover &elementTextsMover(); bool usesElement(const ElementsLocation &); bool usesTitleBlockTemplate(const QString &); - + QUndoStack &undoStack(); QGIManager &qgiManager(); - + //methods related to element label Update Policy void freezeElements(bool freeze); void unfreezeElements(); void setFreezeNewElements(bool); bool freezeNewElements(); - + //methods related to conductor label Update Policy void freezeConductors(bool freeze); void setFreezeNewConductors(bool); bool freezeNewConductors(); - + //methods related to insertion and loading of folio sequential void insertFolioSeqHash (QHash *hash, const QString& title, const QString& seq, NumerotationContext *nc); void loadFolioSeqHash (QHash *hash, - const QString& title, const QString& seq, - NumerotationContext *nc); + const QString& title, const QString& seq, + NumerotationContext *nc); void changeZValue(QET::DepthOption option); public slots: @@ -262,12 +251,12 @@ class Diagram : public QGraphicsScene void titleChanged(const QString &); void titleBlockTemplateChanged(const QString &); void titleBlockTemplateRemoved(const QString &, - const QString & = QString()); + const QString & = QString()); void setTitleBlockTemplate(const QString &); void updateLabels(); void loadElmtFolioSeq(); void loadCndFolioSeq(); - + // methods related to graphics items selection void selectAll(); void deselectAll(); diff --git a/sources/diagramcontext.cpp b/sources/diagramcontext.cpp index b7e711099..2b41e597a 100644 --- a/sources/diagramcontext.cpp +++ b/sources/diagramcontext.cpp @@ -209,15 +209,17 @@ 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) { - int size = settings.beginReadArray(array_name); +void DiagramContext::fromSettings(const QSettings &settings, const QString &array_name) { + // TODO: find better solution than const cast + QSettings& s = const_cast(settings); + int size = s.beginReadArray(array_name); for (int i = 0 ; i < size; ++ i) { - settings.setArrayIndex(i); + s.setArrayIndex(i); QString key = settings.value("name").toString(); if (key.isEmpty()) continue; addValue(key, settings.value("value").toString()); } - settings.endArray(); + s.endArray(); } /** diff --git a/sources/diagramcontext.h b/sources/diagramcontext.h index f887b0ff6..cb1c0f3ec 100644 --- a/sources/diagramcontext.h +++ b/sources/diagramcontext.h @@ -79,7 +79,7 @@ class DiagramContext void fromXml(const QDomElement &, const QString & = "property"); void fromXml(const pugi::xml_node &dom_element, const QString &tag_name = "property"); void toSettings(QSettings &, const QString &) const; - void fromSettings(QSettings &, const QString &); + void fromSettings(const QSettings &, const QString &); static QString validKeyRegExp(); diff --git a/sources/editor/graphicspart/customelementgraphicpart.cpp b/sources/editor/graphicspart/customelementgraphicpart.cpp index ecfa68961..809450c0b 100644 --- a/sources/editor/graphicspart/customelementgraphicpart.cpp +++ b/sources/editor/graphicspart/customelementgraphicpart.cpp @@ -161,7 +161,8 @@ 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 +497,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,16 +511,17 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) { resetStyles(); + QString style_string; + propertyString(qde, "style", &style_string); //Get the list of pair style/value #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) // ### Qt 6: remove - QStringList styles = qde.attribute("style").split(";", QString::SkipEmptyParts); + QStringList styles = style_string.split(";", QString::SkipEmptyParts); #else #if TODO_LIST #pragma message("@TODO remove code for QT 5.14 or later") #endif QStringList styles = qde.attribute("style").split(";", Qt::SkipEmptyParts); #endif - //Check each pair of style QRegularExpression rx("^\\s*([a-z-]+)\\s*:\\s*([a-zA-Z-]+)\\s*$"); foreach (QString style, styles) @@ -863,7 +864,9 @@ void CustomElementGraphicPart::stylesFromXml(const QDomElement &qde) } } //Get antialiasing - _antialiased = qde.attribute("antialias") == "true"; + QString a; + propertyString(qde, "antialias", &a); + _antialiased = a == "true"; } diff --git a/sources/editor/graphicspart/customelementgraphicpart.h b/sources/editor/graphicspart/customelementgraphicpart.h index 4131c86a1..863c00878 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 9f3eaddc7..f771717ef 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 1b3430d8c..58c826546 100644 --- a/sources/editor/graphicspart/partarc.cpp +++ b/sources/editor/graphicspart/partarc.cpp @@ -97,40 +97,70 @@ void PartArc::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, } /** - @brief PartArc::toXml - Export this arc in xml - @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 -{ + * @brief PartArc::toXml + * Export this arc in xml + * @param xml_document : Xml document to use for create the xml element. + * @return : an xml element that describe this arc + */ +QDomElement PartArc::toXml(QDomDocument &xml_document) const + { QDomElement xml_element = xml_document.createElement("arc"); QPointF top_left(sceneTopLeft()); - xml_element.setAttribute("x", QString("%1").arg(top_left.x())); - xml_element.setAttribute("y", QString("%1").arg(top_left.y())); - xml_element.setAttribute("width", QString("%1").arg(rect().width())); - xml_element.setAttribute("height", QString("%1").arg(rect().height())); - //to maintain compatibility with the previous version, we write the angle in degrees. - xml_element.setAttribute("start", QString("%1").arg(m_start_angle / 16)); - xml_element.setAttribute("angle", QString("%1").arg(m_span_angle / 16)); - stylesToXml(xml_element); + + xml_element.appendChild(createXmlProperty(xml_document, "x", top_left.x())); + xml_element.appendChild(createXmlProperty(xml_document, "y", top_left.y())); + xml_element.appendChild(createXmlProperty(xml_document, "width", rect().width())); + xml_element.appendChild(createXmlProperty(xml_document, "height", rect().height())); + + //to maintain compatibility with the previous version, we write the angle in degrees. + xml_element.appendChild(createXmlProperty(xml_document, "start", m_start_angle / 16)); + xml_element.appendChild(createXmlProperty(xml_document, "angle", m_span_angle / 16)); + + + stylesToXml(xml_document, xml_element); return(xml_element); } /** - @brief PartArc::fromXml - Import the properties of this arc from a xml element. - @param qde : Xml document to use. -*/ -void PartArc::fromXml(const QDomElement &qde) { + * @brief PartArc::fromXml + * Import the properties of this arc from a xml element. + * @param qde : Xml document to use. + */ +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 9026f833f..f978d4819 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 a425628d3..7c29d56b3 100644 --- a/sources/editor/graphicspart/partdynamictextfield.cpp +++ b/sources/editor/graphicspart/partdynamictextfield.cpp @@ -88,45 +88,46 @@ void PartDynamicTextField::handleUserTransformation( } /** - @brief PartDynamicTextField::toXml - @param dom_doc - @return -*/ -const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const + * @brief PartDynamicTextField::toXml + * @param document + * @return + */ +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)); - else if(this -> alignment() &Qt::AlignLeft) - root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignLeft)); - else if(this -> alignment() &Qt::AlignHCenter) - root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignHCenter)); + if(this->alignment() &Qt::AlignRight) + root_element.appendChild(createXmlProperty(dom_doc, "Halignment", me.valueToKey(Qt::AlignRight))); + else if(this->alignment() &Qt::AlignLeft) + root_element.appendChild(createXmlProperty(dom_doc, "Halignment", me.valueToKey(Qt::AlignLeft))); + else if(this->alignment() &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)); - else if(this -> alignment() & Qt::AlignTop) - root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignTop)); - else if(this -> alignment() &Qt::AlignVCenter) - root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignVCenter)); + if(this->alignment() &Qt::AlignBottom) + root_element.appendChild(createXmlProperty(dom_doc, "Valignment", me.valueToKey(Qt::AlignBottom))); + else if(this->alignment() & Qt::AlignTop) + root_element.appendChild(createXmlProperty(dom_doc, "Valignment", me.valueToKey(Qt::AlignTop))); + else if(this->alignment() &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())); root_element.appendChild(dom_text); - //Info name if(!m_info_name.isEmpty()) { QDomElement dom_info_name = dom_doc.createElement("info_name"); @@ -152,25 +153,32 @@ const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const } /** - @brief PartDynamicTextField::fromXml - @param dom_elmt -*/ -void PartDynamicTextField::fromXml(const QDomElement &dom_elmt) { + * @brief PartDynamicTextField::fromXml + * @param element + */ +bool PartDynamicTextField::fromXml(const QDomElement &dom_elmt) +{ if (dom_elmt.tagName() != xmlName()) { qDebug() << "PartDynamicTextField::fromXml : Wrong tagg name"; - return; + return false; } + double x=0, y=0, z=0, rot=0; - QGraphicsTextItem::setPos( - dom_elmt.attribute("x", QString::number(0)).toDouble(), - 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 (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; - if (dom_elmt.hasAttribute("font")) { + 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 { @@ -181,21 +189,25 @@ 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"))) - setAlignment(Qt::Alignment( - me.keyToValue(dom_elmt.attribute("Valignment").toStdString().data())) | this -> alignment()); + 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(alignment.toStdString().data())) | this->alignment()); //Text QDomElement dom_text = dom_elmt.firstChildElement("text"); @@ -220,6 +232,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 2ed40a123..27a749b9a 100644 --- a/sources/editor/graphicspart/partdynamictextfield.h +++ b/sources/editor/graphicspart/partdynamictextfield.h @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -75,10 +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); QString text() const; @@ -116,7 +116,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 c121e6135..ad983f7a6 100644 --- a/sources/editor/graphicspart/partellipse.cpp +++ b/sources/editor/graphicspart/partellipse.cpp @@ -78,56 +78,85 @@ void PartEllipse::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio } /** - @brief PartEllipse::toXml - Export this ellipse in xml - @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 + * @brief PartEllipse::toXml + * Export this ellipse in xml + * @param xml_document : Xml document to use for create the xml element. + * @return : an xml element that describe this ellipse + */ +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); } /** - @brief PartEllipse::fromXml - Import the properties of this ellipse from a xml element. - @param qde : Xml document to use. -*/ -void PartEllipse::fromXml(const QDomElement &qde) + * @brief PartEllipse::fromXml + * Import the properties of this ellipse from a xml element. + * @param qde : Xml document to use. + */ +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 477db5111..274b8d7a2 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 304406e2e..7a1b0642b 100644 --- a/sources/editor/graphicspart/partline.cpp +++ b/sources/editor/graphicspart/partline.cpp @@ -104,46 +104,80 @@ void PartLine::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, } /** - @brief PartLine::toXml - Export this line in xml - @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 + * @brief PartLine::toXml + * Export this line in xml + * @param xml_document : Xml document to use for create the xml element. + * @return an xml element that describe this line + */ +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); } /** - @brief PartLine::fromXml - Import the properties of this line from a xml element. - @param qde : Xml document to use -*/ -void PartLine::fromXml(const QDomElement &qde) { + * @brief PartLine::fromXml + * Import the properties of this line from a xml element. + * @param qde : Xml document to use + */ +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 589335ba2..58c2384e0 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 0875781de..f971046d2 100644 --- a/sources/editor/graphicspart/partpolygon.cpp +++ b/sources/editor/graphicspart/partpolygon.cpp @@ -85,56 +85,71 @@ void PartPolygon::paint(QPainter *painter, const QStyleOptionGraphicsItem *optio } /** - @brief PartPolygon::fromXml - Import the properties of this polygon from a xml element - @param qde : Xml document to use -*/ -void PartPolygon::fromXml(const QDomElement &qde) + * @brief PartPolygon::fromXml + * Import the properties of this polygon from a xml element + * @param qde : Xml document to use + */ +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; } /** - @brief PartPolygon::toXml - Export this polygin in xml - @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 + * @brief PartPolygon::toXml + * Export this polygin in xml + * @param xml_document : Xml document to use for create the xml element + * @return an xml element that describe this polygon + */ +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 4922dc48a..b5ee71443 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 b087829cd..e662a553f 100644 --- a/sources/editor/graphicspart/partrectangle.cpp +++ b/sources/editor/graphicspart/partrectangle.cpp @@ -84,15 +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; if (x > rect.width()/2) { @@ -106,7 +106,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 +118,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 4c001fae6..55a47be7c 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 9fe3728a5..57cd0ac56 100644 --- a/sources/editor/graphicspart/partterminal.cpp +++ b/sources/editor/graphicspart/partterminal.cpp @@ -29,8 +29,9 @@ PartTerminal::PartTerminal(QETElementEditor *editor, QGraphicsItem *parent) : CustomElementGraphicPart(editor, parent) { d = new TerminalData(this); - 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 + 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(); setZValue(100000); } @@ -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); - setPos(d -> m_pos); +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,26 @@ 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 +QDomElement PartTerminal::toXml(QDomDocument &xml_document) const { - return d -> toXml(xml_document); + 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 0f323acff..074925082 100644 --- a/sources/editor/graphicspart/partterminal.h +++ b/sources/editor/graphicspart/partterminal.h @@ -53,12 +53,11 @@ 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( - QPainter *painter, - const QStyleOptionGraphicsItem *, - QWidget *) override; + bool fromXml(const QDomElement &) override; + QDomElement toXml(QDomDocument &) const override; + static bool valideXml(QDomElement& element); + + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; QPainterPath shape() const override; QPainterPath shadowShape() const override {return shape();} diff --git a/sources/editor/graphicspart/parttext.cpp b/sources/editor/graphicspart/parttext.cpp index 497d66b31..a69fd122d 100644 --- a/sources/editor/graphicspart/parttext.cpp +++ b/sources/editor/graphicspart/parttext.cpp @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -42,8 +42,8 @@ PartText::PartText(QETElementEditor *editor, QGraphicsItem *parent) : setAcceptHoverEvents(true); setDefaultTextColor(Qt::black); setPlainText(QObject::tr( - "T", - "default text when adding a text in the element editor")); + "T", + "default text when adding a text in the element editor")); adjustItemPosition(1); // adjust textfield position after line additions/deletions @@ -66,29 +66,49 @@ 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); + QFont font_ = this->font(); + 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 +116,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 cdadfbfab..5501dd144 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 6e35ce502..50dcd13ac 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 9555292ca..b9a5350f0 100644 --- a/sources/properties/propertiesinterface.cpp +++ b/sources/properties/propertiesinterface.cpp @@ -17,16 +17,313 @@ */ #include "propertiesinterface.h" -/** - @brief PropertiesInterface::PropertiesInterface -*/ +#include + +/*! + * 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"; +} + 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 e6c4724ab..1274a3821 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 @@ -30,40 +34,66 @@ class PropertiesInterface { public: - PropertiesInterface(); - virtual ~PropertiesInterface(); - /** - @brief toSettings - Save properties to setting file. - @param settings : is use for prefix a word - befor the name of each paramètre - @param QString - */ - virtual void toSettings (QSettings &settings, - const QString = QString()) const =0; - /** - @brief fromSettings - load properties to setting file. - @param settings : is use for prefix a word - befor the name of each paramètre - @param QString - */ - virtual void fromSettings (const QSettings &settings, - const QString = QString()) =0; - /** - @brief toXml - Save properties to xml element - @param xml_document - @return QDomElement - */ - virtual QDomElement toXml (QDomDocument &xml_document) const =0; - /** - @brief fromXml - load properties to xml element - @param xml_element - @return true / false - */ - virtual bool fromXml (const QDomElement &xml_element) =0; + PropertiesInterface(); + // Save/load properties to setting file. QString is use for prefix a word befor the name of each paramètre + virtual void toSettings (QSettings &settings, const QString& = QString()) const {Q_UNUSED(settings)}; + virtual void fromSettings (const QSettings &settings, const QString& = QString()) {Q_UNUSED(settings)}; + // Save/load properties to xml element + virtual QDomElement toXml (QDomDocument &xml_document) const =0; + 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 5fc00d72e..2b6772ba7 100644 --- a/sources/properties/terminaldata.cpp +++ b/sources/properties/terminaldata.cpp @@ -33,33 +33,15 @@ void TerminalData::setParent(QGraphicsObject* parent) q = parent; } -/** - @brief TerminalData::toSettings - Save properties to setting file. - - QString is use for prefix a word befor the name of each paramètre - @param settings UNUSED - @param prefix UNUSED -*/ -void TerminalData::toSettings(QSettings &settings, const QString prefix) const +void TerminalData::toSettings(QSettings& settings, const QString&) const { Q_UNUSED(settings); - Q_UNUSED(prefix); } -/** - @brief TerminalData::fromSettings - load properties to setting file. - - QString is use for prefix a word befor the name of each paramètre - @param settings UNUSED - @param prefix UNUSED -*/ -void TerminalData::fromSettings(const QSettings &settings, const QString prefix) +void TerminalData::fromSettings(const QSettings& settings, const QString&) { Q_UNUSED(settings); - Q_UNUSED(prefix); } /** @@ -76,66 +58,68 @@ 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 - - @note This method is only called from the PartTerminal - and should never called from the Terminal class - @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)) + qreal term_x = 0.0, term_y = 0.0; + + 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 - // 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); + // do not write uuid from this class, because only PartTerminal::fromXml need + // to write it to xml file. Terminal::fromXml does not need. - m_name = xml_element.attribute("name"); - // read the orientation of the terminal + //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; + // lit l'orientation de la borne - m_orientation = Qet::orientationFromString( - xml_element.attribute("orientation")); + m_orientation = orientationFromString(o); 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 f54344e61..7d2a07ebf 100644 --- a/sources/properties/terminaldata.h +++ b/sources/properties/terminaldata.h @@ -26,62 +26,58 @@ class TerminalData : public PropertiesInterface void init(); void setParent(QGraphicsObject* parent); - void toSettings(QSettings &settings, - const QString prefix = QString()) const override; - void fromSettings(const QSettings &settings, - const QString prefix = 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 - public: - /** - @brief m_orientation - Orientation of the terminal - */ - Qet::Orientation m_orientation; - /** - @brief second_point - Position of the second point of the terminal - in scene coordinates - */ - QPointF second_point; - /** - @brief m_uuid - Uuid of the terminal. + // Save/load properties to setting file. QString is use for prefix a word befor the name of each paramètre + void toSettings( + QSettings &settings, const QString& = QString()) const override; + void fromSettings( + const QSettings &settings, const QString& = QString()) override; + // Save/load properties to xml element + // This method is only called from the PartTerminal and should never called from the Terminal class + QDomElement toXml(QDomDocument &xml_element) const override; + bool fromXml(const QDomElement &xml_element) override; - In elementscene.cpp an element gets a new uuid when - saving the element. In the current state - each connection is made by using the local position - of the terminal and a dynamic id. In the new - case, each terminal should have it's own uuid to - identify it uniquely. When changing each time this - uuid, the conductor after updating the part is anymore - valid. So if in the loaded document a uuid exists, - use this one and don't create a new one. - */ - QUuid m_uuid; - /** - @brief m_name - Name of the element. - It can be used to create wiring harness tables - */ - QString m_name; + static bool valideXml(const QDomElement &xml_element); - /** - @brief m_pos - Position of the terminal. The second point is calculated - from this position and the orientation - @note - Important: this variable is only updated during read - from xml and not during mouse move! - It is used to store the initial position so that - PartTerminal and Terminal have access to it. - */ - QPointF m_pos; - private: - QGraphicsObject* q{nullptr}; + // must be public, because this class is a private member of PartTerminal/Terminal and they must + // access this data +public: + /*! + * \brief m_orientation + * Orientation of the terminal + */ + Qet::Orientation m_orientation{Qet::Orientation::North}; + /*! + * \brief second_point + * Position of the second point of the terminal in scene coordinates + */ + QPointF second_point{0,0}; + /*! + * \brief m_uuid + * Uuid of the terminal. + * + * In elementscene.cpp an element gets a new uuid when saving the element. In the current state + * each connection is made by using the local position of the terminal and a dynamic id. In the new + * case, each terminal should have it's own uuid to identify it uniquely. When changing each time this + * uuid, the conductor after updating the part is anymore valid. So if in the loaded document a uuid exists, + * use this one and don't create a new one. + */ + QUuid m_uuid; // default is an invalid uuid. + /*! + * \brief m_name + * Name of the element. It can be used to create wiring harness tables + */ + QString m_name; + + /*! + * \brief m_pos + * Position of the terminal. The second point is calculated from this position and the orientation + * Important: this variable is only updated during read from xml and not during mouse move! + * It is used to store the initial position so that PartTerminal and Terminal have access to it. + */ + QPointF m_pos{0,0}; +private: + QGraphicsObject* q{nullptr}; }; #endif // TERMINALDATA_H diff --git a/sources/properties/xrefproperties.cpp b/sources/properties/xrefproperties.cpp index dd864f5b0..633e3c80f 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; } /** @@ -43,8 +35,9 @@ XRefProperties::XRefProperties() @param settings: QSettings to use @param prefix: prefix before properties name */ -void XRefProperties::toSettings(QSettings &settings, - const QString prefix) const +void XRefProperties::toSettings( + QSettings &settings, + const QString &prefix) const { settings.setValue(prefix + "showpowerctc", m_show_power_ctc); QString display = m_display == Cross? "cross" : "contacts"; @@ -73,8 +66,7 @@ void XRefProperties::toSettings(QSettings &settings, @param settings: QSettings to use @param prefix: prefix before properties name */ -void XRefProperties::fromSettings(const QSettings &settings, - const QString prefix) +void XRefProperties::fromSettings(const QSettings &settings, const QString &prefix) { m_show_power_ctc = settings.value(prefix + "showpowerctc", true).toBool(); QString display = settings.value(prefix + "displayhas", "cross").toString(); @@ -103,58 +95,59 @@ 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); - - QString xrefpos; + 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")); 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 446060f52..b0f347e01 100644 --- a/sources/properties/xrefproperties.h +++ b/sources/properties/xrefproperties.h @@ -42,11 +42,9 @@ class XRefProperties : public PropertiesInterface Label }; - void toSettings (QSettings &settings, - const QString = QString()) const override; - void fromSettings (const QSettings &settings, - const QString = QString()) override; - QDomElement toXml (QDomDocument &xml_document) const override; + void toSettings (QSettings &settings, const QString& = QString()) const override; + void fromSettings (const QSettings &settings, const QString& = QString()) override; + QDomElement toXml (QDomDocument &xml_document) const override; bool fromXml(const QDomElement &xml_element) override; static QHash defaultProperties(); @@ -80,15 +78,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 23f5fe2d9..24cb36428 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -27,37 +27,6 @@ #include #include -/** - Permet de convertir une chaine de caracteres ("n", "s", "e" ou "w") - en orientation. Si la chaine fait plusieurs caracteres, seul le - premier est pris en compte. En cas d'incoherence, Qet::North est - retourne. - @param s Chaine de caractere cense representer une orientation - @return l'orientation designee par la chaine de caractere -*/ -Qet::Orientation Qet::orientationFromString(const QString &s) { - QChar c = s[0]; - if (c == 'e') return(Qet::East); - else if (c == 's') return(Qet::South); - else if (c == 'w') return (Qet::West); - else return(Qet::North); -} - -/** - @param o une orientation - @return une chaine de caractere representant l'orientation -*/ -QString Qet::orientationToString(Qet::Orientation o) { - QString ret; - switch(o) { - case Qet::North: ret = "n"; break; - case Qet::East : ret = "e"; break; - case Qet::South: ret = "s"; break; - case Qet::West : ret = "w"; break; - } - return(ret); -} - /** Indique si deux orientations de Borne sont sur le meme axe (Vertical / Horizontal). @param a La premiere orientation de Borne diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index b77fa014f..0dfdbb16c 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); @@ -580,41 +573,13 @@ ConductorTextItem *Conductor::textItem() const } /** - Methode de validation d'element XML - @param e Un element XML sense represente un Conducteur - @return true si l'element XML represente bien un Conducteur ; false sinon + @brief Conductor::valideXml + @param e + @return true */ -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); - - 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); - } - - // 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); +bool Conductor::valideXml(QDomElement &e) +{ + return true; } /** @@ -984,13 +949,16 @@ void Conductor::pointsToSegments(const QList& points_list) { /** @brief Conductor::fromXml Load the conductor and her information from xml element - @param dom_element + @param e @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,49 +972,48 @@ 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_; } -/** - @brief Conductor::toXml - Exporte les caracteristiques du conducteur sous forme d'une element XML. - @param dom_document : - 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())); +// does not support legacy method +// dom_element.setAttribute("terminal1", table_adr_id.value(terminal1)); +QDomElement Conductor::toXml(QDomDocument & doc) const +{ + QDomElement dom_element = doc.createElement("conductor"); + + 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,33 +1023,32 @@ 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 + 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 */ @@ -1096,14 +1062,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 2bc04ac8e..c5f872a12 100644 --- a/sources/qetgraphicsitem/conductor.h +++ b/sources/qetgraphicsitem/conductor.h @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -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 @@ -50,13 +51,13 @@ class Conductor : public QGraphicsObject signals: void propertiesChange(); - + public: Conductor(Terminal *, Terminal *); ~Conductor() override; bool isValid() const; - + private: Conductor(const Conductor &); @@ -66,7 +67,7 @@ class Conductor : public QGraphicsObject Terminal *terminal1; Terminal *terminal2; - + public: /** @brief type @@ -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 &); @@ -137,7 +136,7 @@ class Conductor : public QGraphicsObject {return m_autoNum_seq;} void setSequenceNum(const autonum::sequentialNumbers& sn); - QList junctions() const; + QList junctions() const; private: void setUpConnectionForFormula( @@ -146,10 +145,10 @@ class Conductor : public QGraphicsObject public: void setFreezeLabel(bool freeze); - + public slots: void displayedTextChanged(); - + protected: void mouseDoubleClickEvent( QGraphicsSceneMouseEvent *event) override; @@ -165,7 +164,7 @@ class Conductor : public QGraphicsObject private: void adjusteHandlerPos(); - + void handlerMousePressEvent( QetGraphicsHandlerItem *qghi, QGraphicsSceneMouseEvent *event); @@ -177,32 +176,32 @@ class Conductor : public QGraphicsObject QGraphicsSceneMouseEvent *event); void addHandler(); void removeHandler(); - - + + 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; @@ -211,7 +210,7 @@ class Conductor : public QGraphicsObject static QBrush conductor_brush; static bool pen_and_brush_initialized; QPainterPath m_path; - + private: void segmentsToPath(); void saveProfile(bool = true); diff --git a/sources/qetgraphicsitem/conductortextitem.cpp b/sources/qetgraphicsitem/conductortextitem.cpp index e15c24429..1f9a115dd 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,21 +60,36 @@ 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()); - moved_by_user_ = true; - } - if (e.hasAttribute("rotation")) { - setRotation(e.attribute("rotation").toDouble()); - rotate_by_user_ = true; - } + + 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; + } + + 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 a183c2be9..275595024 100644 --- a/sources/qetgraphicsitem/conductortextitem.h +++ b/sources/qetgraphicsitem/conductortextitem.h @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -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/diagramtextitem.cpp b/sources/qetgraphicsitem/diagramtextitem.cpp index 75818083a..b151ec09f 100644 --- a/sources/qetgraphicsitem/diagramtextitem.cpp +++ b/sources/qetgraphicsitem/diagramtextitem.cpp @@ -20,6 +20,8 @@ #include "qetapp.h" #include "richtext/richtexteditor_p.h" #include "diagram.h" +#include "dynamicelementtextitem.h" + /** @brief DiagramTextItem::DiagramTextItem @@ -218,12 +220,24 @@ QRectF DiagramTextItem::frameRect() const void DiagramTextItem::setHtml(const QString &text) { + DynamicElementTextItem* abc = dynamic_cast(this); + if (abc) { + if (abc->searchedElement) { + int stop = 1; + } + } QGraphicsTextItem::setHtml(text); m_is_html = true; } void DiagramTextItem::setPlainText(const QString &text) { + DynamicElementTextItem* abc = dynamic_cast(this); + if (abc) { + if (abc->searchedElement) { + int stop = 1; + } + } QGraphicsTextItem::setPlainText(text); m_is_html = false; } @@ -243,6 +257,16 @@ bool DiagramTextItem::isHtml() const */ void DiagramTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { + + DynamicElementTextItem* abc = dynamic_cast(this); + if (abc) { + if (abc->searchedElement) { + int stop = 1; + QString text = toPlainText(); + qDebug() << text; + } + } + painter -> setRenderHint(QPainter::Antialiasing, false); QGraphicsTextItem::paint(painter, option, widget); diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index f47840960..2e1b79540 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -54,7 +54,7 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) : this->m_parent_element->diagram()->undoStack().push(undo); } }); - + //Option when text is displayed in multiple line QTextOption option = document()->defaultTextOption(); option.setAlignment(Qt::AlignHCenter); @@ -87,7 +87,7 @@ DynamicElementTextItem::DynamicElementTextItem() QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const { QDomElement root_element = dom_doc.createElement(xmlTagName()); - + root_element.setAttribute("x", QString::number(pos().x())); root_element.setAttribute("y", QString::number(pos().y())); root_element.setAttribute("rotation", QString::number(QET::correctAngle(rotation()))); @@ -95,10 +95,10 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const root_element.setAttribute("frame", m_frame? "true" : "false"); root_element.setAttribute("text_width", QString::number(m_text_width)); root_element.setAttribute("font", font().toString()); - + QMetaEnum me = textFromMetaEnum(); root_element.setAttribute("text_from", me.valueToKey(m_text_from)); - + me = QMetaEnum::fromType(); if(this->alignment() &Qt::AlignRight) root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignRight)); @@ -106,19 +106,19 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignLeft)); else if(this->alignment() &Qt::AlignHCenter) root_element.setAttribute("Halignment", me.valueToKey(Qt::AlignHCenter)); - + if(this->alignment() &Qt::AlignBottom) root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignBottom)); else if(this->alignment() & Qt::AlignTop) root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignTop)); else if(this->alignment() &Qt::AlignVCenter) root_element.setAttribute("Valignment", me.valueToKey(Qt::AlignVCenter)); - - + + QDomElement dom_text = dom_doc.createElement("text"); dom_text.appendChild(dom_doc.createTextNode(toPlainText())); root_element.appendChild(dom_text); - + //Info name if(!m_info_name.isEmpty()) { @@ -126,7 +126,7 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const dom_info_name.appendChild(dom_doc.createTextNode(m_info_name)); root_element.appendChild(dom_info_name); } - + //Composite text if(!m_composite_text.isEmpty()) { @@ -134,7 +134,7 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const dom_comp_text.appendChild(dom_doc.createTextNode(m_composite_text)); root_element.appendChild(dom_comp_text); } - + //Color if(color() != QColor(Qt::black)) { @@ -142,7 +142,7 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const dom_color.appendChild(dom_doc.createTextNode(color().name())); root_element.appendChild(dom_color); } - + return root_element; } @@ -157,7 +157,7 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) qDebug() << "DynamicElementTextItem::fromXml : Wrong tagg name"; return; } - + QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble()); if (dom_elmt.hasAttribute("font")) @@ -177,11 +177,11 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) 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()); - + //Text from QMetaEnum me = textFromMetaEnum(); setTextFrom(DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data()))); - + me = QMetaEnum::fromType(); if(dom_elmt.hasAttribute("Halignment")) setAlignment(Qt::Alignment(me.keyToValue(dom_elmt.attribute("Halignment").toStdString().data()))); @@ -200,7 +200,7 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) QDomElement dom_info_name = dom_elmt.firstChildElement("info_name"); if(!dom_info_name.isNull()) setInfoName(dom_info_name.text()); - + //Composite text QDomElement dom_comp_text = dom_elmt.firstChildElement("composite_text"); if(!dom_comp_text.isNull()) @@ -210,10 +210,10 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) QDomElement dom_color = dom_elmt.firstChildElement("color"); if(!dom_color.isNull()) 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()); } @@ -241,7 +241,7 @@ ElementTextItemGroup *DynamicElementTextItem::parentGroup() const if(ElementTextItemGroup *grp = dynamic_cast(parentItem())) return grp; } - + return nullptr; } @@ -261,7 +261,7 @@ Element *DynamicElementTextItem::elementUseForInfo() const Element *elmt = parentElement(); if(!elmt) return nullptr; - + switch (elmt->linkType()) { case Element::Simple: @@ -325,15 +325,18 @@ DynamicElementTextItem::TextFrom DynamicElementTextItem::textFrom() const */ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_from) { + + if (searchedElement) + int stop = true; if(m_text_from == text_from) return; - + setNoEditable(text_from == UserText? false : true); clearFormulaConnection(); - + TextFrom old_text_from = m_text_from; m_text_from = text_from; - + if(m_text_from == UserText) { setPlainText(m_text); @@ -348,7 +351,7 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f } else setPlainText(elementUseForInfo()->elementInformations().value(m_info_name).toString()); - + if(old_text_from == UserText) connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); } @@ -361,15 +364,15 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f } else setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementUseForInfo()->elementInformations())); - + if(old_text_from == UserText) connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); } - + if(m_parent_element.data()->linkType() == Element::Master || m_parent_element.data()->linkType() == Element::Slave) updateXref(); - + emit textFromChanged(m_text_from); } @@ -389,6 +392,9 @@ QString DynamicElementTextItem::text() const */ void DynamicElementTextItem::setText(const QString &text) { + if (m_text == "14" && text == "") + int a = 54; + m_text_old = m_text; m_text = text; if(m_text_from == DynamicElementTextItem::UserText) setPlainText(m_text); @@ -405,7 +411,10 @@ void DynamicElementTextItem::setInfoName(const QString &info_name) QString old_info_name = m_info_name; m_info_name = info_name; - + if (searchedElement) + int stop = true; + + if(old_info_name == "label") { clearFormulaConnection(); @@ -429,7 +438,7 @@ void DynamicElementTextItem::setInfoName(const QString &info_name) } } else if (m_info_name == "label" && elementUseForInfo()) - { + { setupFormulaConnection(); updateLabel(); updateXref(); @@ -437,7 +446,7 @@ void DynamicElementTextItem::setInfoName(const QString &info_name) else if(elementUseForInfo() && m_text_from == DynamicElementTextItem::ElementInfo) { setPlainText(elementUseForInfo()->elementInformations().value(info_name).toString()); } - + emit infoNameChanged(info_name); } @@ -459,7 +468,7 @@ void DynamicElementTextItem::setCompositeText(const QString &text) { QString old_composite_text = m_composite_text; m_composite_text = text; - + if(old_composite_text.contains("%{label}")) { clearFormulaConnection(); @@ -478,7 +487,7 @@ void DynamicElementTextItem::setCompositeText(const QString &text) removeConnectionForReportFormula(m_report_formula); if(m_composite_text.contains("%{label}")) setConnectionForReportFormula(m_report_formula); - + updateReportText(); } else if (m_composite_text.contains("%{label}") && elementUseForInfo()) @@ -494,7 +503,7 @@ void DynamicElementTextItem::setCompositeText(const QString &text) dc = elementUseForInfo()->elementInformations(); setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, dc)); } - + emit compositeTextChanged(m_composite_text); } @@ -539,7 +548,7 @@ void DynamicElementTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event) if(m_slave_Xref_item) m_slave_Xref_item->setDefaultTextColor(Qt::black); } - + DiagramTextItem::mousePressEvent(event); } @@ -548,33 +557,33 @@ void DynamicElementTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event) @param event */ void DynamicElementTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) -{ +{ if((event->buttons() & Qt::LeftButton) && (flags() & ItemIsMovable)) { if(diagram() && m_first_move) diagram()->elementTextsMover().beginMovement(diagram(), this); - + if(m_first_move) { m_initial_position = pos(); if(parentElement()) parentElement()->setHighlighted(true); } - + QPointF current_parent_pos; QPointF button_down_parent_pos; current_parent_pos = mapToParent(mapFromScene(event->scenePos())); button_down_parent_pos = mapToParent(mapFromScene(event->buttonDownScenePos(Qt::LeftButton))); - + QPointF new_pos = m_initial_position + current_parent_pos - button_down_parent_pos; event->modifiers() == Qt::ControlModifier ? setPos(new_pos) : setPos(Diagram::snapToGrid(new_pos)); - + if(diagram()) diagram()->elementTextsMover().continueMovement(event); } else { event->ignore(); } - + if(m_first_move) m_first_move = false; } @@ -587,10 +596,10 @@ void DynamicElementTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (m_parent_element) m_parent_element->setHighlighted(false); - + if(m_parent_element && m_parent_element->diagram()) m_parent_element.data()->diagram()->elementTextsMover().endMovement(); - + if(!(event->modifiers() & Qt::ControlModifier)) QGraphicsTextItem::mouseReleaseEvent(event); } @@ -618,12 +627,12 @@ void DynamicElementTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *eve void DynamicElementTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { DiagramTextItem::hoverEnterEvent(event); - + //If the text is selected we set the real color, otherwise the editor will display the color of text as blue, //but this is not the color set by the user. if(isSelected()) return; - + if ((parentElement()->linkType() & Element::AllReport) && m_other_report) { if( (m_text_from == ElementInfo && m_info_name == "label") || @@ -642,25 +651,25 @@ void DynamicElementTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) void DynamicElementTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { DiagramTextItem::hoverLeaveEvent(event); - + if(m_user_color.isValid()) { setDefaultTextColor(m_user_color); m_user_color = QColor(); //m_user_color is now invalid } - + } void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { DiagramTextItem::paint(painter, option, widget); - + if (m_frame) { painter->save(); painter->setFont(QETApp::dynamicTextsItemFont(font().pointSize())); - - //Adjust the thickness according to the font size, + + //Adjust the thickness according to the font size, qreal w=0.3; if(font().pointSize() >= 5) { @@ -668,7 +677,7 @@ void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphics if(w > 2.5) w = 2.5; } - + QPen pen; pen.setColor(color()); pen.setWidthF(w); @@ -678,7 +687,7 @@ void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphics //Adjust the rounding of the rectangle according to the size of the font qreal ro = font().pointSizeF()/3; painter->drawRoundedRect(frameRect(), ro, ro); - + painter->restore(); } } @@ -691,7 +700,7 @@ QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange ch { if(m_parent_element.isNull()) return QGraphicsObject::itemChange(change, value); - + //If the parent is slave, we keep aware about the changement of master. if(m_parent_element.data()->linkType() == Element::Slave) { @@ -708,13 +717,13 @@ QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange ch m_report_formula = m_parent_element.data()->diagram()->project()->defaultReportProperties(); m_report_formula_con = connect(m_parent_element.data()->diagram()->project(), &QETProject::reportPropertiesChanged, this, &DynamicElementTextItem::reportFormulaChanged); } - + //Add connection to keep up to date the status of the element linked to the parent folio report of this text. connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::reportChanged); //The parent is already linked, we call reportChanged for init the connection if(!m_parent_element.data()->linkedElements().isEmpty()) reportChanged(); - + if(m_parent_element.data()->terminals().size()) { //Add connection to keep up date the conductors added or removed to the parent folio report element @@ -732,7 +741,7 @@ QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange ch if(!m_parent_element.data()->linkedElements().isEmpty()) updateXref(); } - + m_first_scene_change = false; return QGraphicsObject::itemChange(change, value); } @@ -741,7 +750,7 @@ QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange ch updateXref(); updateXref(); } - + return QGraphicsObject::itemChange(change, value); } @@ -749,7 +758,7 @@ bool DynamicElementTextItem::sceneEventFilter(QGraphicsItem *watched, QEvent *ev { if(watched != m_slave_Xref_item) return false; - + if(event->type() == QEvent::GraphicsSceneHoverEnter) { m_slave_Xref_item->setDefaultTextColor(Qt::blue); return true; @@ -762,7 +771,7 @@ bool DynamicElementTextItem::sceneEventFilter(QGraphicsItem *watched, QEvent *ev zoomToLinkedElement(); return true; } - + return false; } @@ -773,7 +782,7 @@ void DynamicElementTextItem::elementInfoChanged() if(element) { dc = element->elementInformations(); } - + QString final_text; @@ -799,12 +808,12 @@ void DynamicElementTextItem::elementInfoChanged() //connection if the label is created from a formula if (m_composite_text.contains("%{label}")) setupFormulaConnection(); - + final_text = autonum::AssignVariables::replaceVariable(m_composite_text, dc); } else if (m_text_from == UserText) final_text = m_text; - + setPlainText(final_text); emit plainTextChanged(); } @@ -823,16 +832,16 @@ void DynamicElementTextItem::masterChanged() m_master_element.clear(); updateXref(); } - + if(elementUseForInfo()) { m_master_element = elementUseForInfo(); if(m_text_from == ElementInfo || m_text_from == CompositeText) connect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); - + updateXref(); } - + //Because master changed we update this text elementInfoChanged(); } @@ -859,23 +868,23 @@ void DynamicElementTextItem::reportChanged() m_report_formula_con = connect(parentElement()->diagram()->project(), &QETProject::reportPropertiesChanged, this, &DynamicElementTextItem::reportFormulaChanged); } } - + bool text_have_label = false; - + if((textFrom() == ElementInfo && m_info_name == "label") || (textFrom() == CompositeText && m_composite_text.contains("%{label}"))) text_have_label = true; - + if(text_have_label) removeConnectionForReportFormula(m_report_formula); - + m_other_report.clear(); if(!m_parent_element.data()->linkedElements().isEmpty()) m_other_report = m_parent_element.data()->linkedElements().first(); - + //Because linked report was changed, we ensure there is a conductor watched setPotentialConductor(); - + if(text_have_label) { setConnectionForReportFormula(m_report_formula); @@ -890,7 +899,7 @@ void DynamicElementTextItem::reportChanged() void DynamicElementTextItem::reportFormulaChanged() { m_report_formula = parentElement()->diagram()->project()->defaultReportProperties(); - + if(m_text_from == ElementInfo && m_info_name == "label") updateReportText(); } @@ -899,11 +908,11 @@ void DynamicElementTextItem::setConnectionForReportFormula(const QString &formul { if(m_other_report.isNull() || formula.isEmpty()) return; - + Element *other_elmt = m_other_report.data(); QString string = formula; Diagram *other_diagram = m_other_report.data()->diagram(); - + //Because the variable %F is a reference to another text which can contain variables, //we must to replace %F by the real text, to check if the real text contain the variable %id if (other_diagram && string.contains("%F")) @@ -912,7 +921,7 @@ void DynamicElementTextItem::setConnectionForReportFormula(const QString &formul string.replace("%F", other_diagram->border_and_titleblock.folio()); connect(&other_diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateReportFormulaConnection); } - + if (other_diagram && (string.contains("%f") || string.contains("%id"))) { connect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText); @@ -928,11 +937,11 @@ void DynamicElementTextItem::removeConnectionForReportFormula(const QString &for { if(m_other_report.isNull() || formula.isEmpty()) return; - + Element *other_element = m_other_report.data(); QString string = formula; Diagram *other_diagram = m_other_report.data()->diagram(); - + //Because the variable %F is a reference to another text which can contain variables, //we must to replace %F by the real text, to check if the real text contain the variable %id if (other_diagram && string.contains("%F")) @@ -940,14 +949,14 @@ void DynamicElementTextItem::removeConnectionForReportFormula(const QString &for string.replace("%F", m_F_str); disconnect(&other_diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateReportFormulaConnection); } - + if (other_diagram && (string.contains("%f") || string.contains("%id"))) disconnect(other_diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%l")) disconnect(other_element, &Element::yChanged, this, &DynamicElementTextItem::updateReportText); if (string.contains("%c")) disconnect(other_element, &Element::xChanged, this, &DynamicElementTextItem::updateReportText); - + } /** @@ -960,25 +969,25 @@ void DynamicElementTextItem::setupFormulaConnection() (m_text_from == CompositeText && m_composite_text.contains("%{label}"))) { clearFormulaConnection(); - + Element *element = elementUseForInfo(); if (!element) return; - + Diagram *diagram = element->diagram(); QString formula = element->elementInformations().value("formula").toString(); //Label is frozen, so we don't update it. if (element->isFreezeLabel()) return; - + if (diagram && formula.contains("%F")) { m_F_str = diagram->border_and_titleblock.folio(); formula.replace("%F", m_F_str); m_formula_connection << connect(&diagram->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, this, &DynamicElementTextItem::updateLabel); } - + if (diagram && (formula.contains("%f") || formula.contains("%id"))) { m_formula_connection << connect(diagram->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateLabel); @@ -988,7 +997,7 @@ void DynamicElementTextItem::setupFormulaConnection() m_formula_connection << connect(element, &Element::yChanged, this, &DynamicElementTextItem::updateLabel); if (formula.contains("%c")) m_formula_connection << connect(element, &Element::xChanged, this, &DynamicElementTextItem::updateLabel); - + } } @@ -1003,7 +1012,7 @@ void DynamicElementTextItem::updateReportFormulaConnection() { if(!(m_parent_element.data()->linkType() & Element::AllReport)) return; - + removeConnectionForReportFormula(m_report_formula); setConnectionForReportFormula(m_report_formula); updateReportText(); @@ -1017,7 +1026,7 @@ void DynamicElementTextItem::updateReportText() { if(!(m_parent_element.data()->linkType() & Element::AllReport)) return; - + if (m_text_from == ElementInfo && m_info_name == "label") { if(m_other_report) @@ -1053,7 +1062,7 @@ void DynamicElementTextItem::updateLabel() if(element) { dc = element->elementInformations(); } - + if(m_text_from == ElementInfo && element) { setPlainText(element->actualLabel()); @@ -1101,7 +1110,7 @@ void DynamicElementTextItem::setPotentialConductor() { if(parentElement()->terminals().isEmpty()) return; - + /* * #First case, if m_watched_conductor is a conductor of the parent report, everything is ok * #Second case, if the conductors list of parent report element is not empty, @@ -1111,14 +1120,14 @@ void DynamicElementTextItem::setPotentialConductor() * #third case, if m_watched_conductor is null, we set a conductor of the linked report, if any. */ QList c_list = parentElement()->terminals().first()->conductors(); - + if(!c_list.isEmpty() && c_list.contains(m_watched_conductor.data())) return; else if(!c_list.isEmpty()) { if(!m_watched_conductor.isNull()) disconnect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged); - + m_watched_conductor = c_list.first(); connect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged); } @@ -1135,7 +1144,7 @@ void DynamicElementTextItem::setPotentialConductor() { if(!m_watched_conductor.isNull()) disconnect(m_watched_conductor.data(), &Conductor::propertiesChange, this, &DynamicElementTextItem::conductorPropertiesChanged); - + m_watched_conductor.clear(); } } @@ -1174,11 +1183,11 @@ void DynamicElementTextItem::conductorPropertiesChanged() QString DynamicElementTextItem::reportReplacedCompositeText() const { QString string; - + if(m_parent_element.data()->linkType() & Element::AllReport) { string = m_composite_text; - + if (string.contains("%{label}") && m_other_report) { Element *elmt = m_other_report.data(); @@ -1198,7 +1207,7 @@ QString DynamicElementTextItem::reportReplacedCompositeText() const string.replace("%{conductor_section}", m_watched_conductor.data()->properties().m_wire_section); } } - + return string; } @@ -1211,9 +1220,9 @@ void DynamicElementTextItem::zoomToLinkedElement() { if(!parentElement()) return; - + Element *zoomed_element = nullptr; - + if(parentElement()->linkType() == Element::Slave && m_master_element) { if ((m_text_from == ElementInfo && m_info_name == "label") || @@ -1226,18 +1235,18 @@ void DynamicElementTextItem::zoomToLinkedElement() (m_text_from == CompositeText && m_composite_text.contains("%{label}"))) zoomed_element = m_other_report.data(); } - + if(zoomed_element) { //Unselect and ungrab mouse to prevent unwanted //move when linked element is in the same scene of this. setSelected(false); ungrabMouse(); - + if(scene() != zoomed_element->scene()) zoomed_element->diagram()->showMe(); zoomed_element->setSelected(true); - + //Zoom to the element for(QGraphicsView *view : zoomed_element->scene()->views()) { @@ -1259,7 +1268,7 @@ void DynamicElementTextItem::updateXref() if(m_parent_element.data()->linkType() == Element::Master) { XRefProperties xrp = diagram()->project()->defaultXRefProperties(m_parent_element.data()->kindInformations()["type"].toString()); - + if(m_text_from == DynamicElementTextItem::ElementInfo && m_info_name == "label" && !m_parent_element.data()->linkedElements().isEmpty() && @@ -1286,13 +1295,13 @@ void DynamicElementTextItem::updateXref() XRefProperties xrp = diagram()->project()->defaultXRefProperties(m_master_element.data()->kindInformations()["type"].toString()); QString xref_label = xrp.slaveLabel(); xref_label = autonum::AssignVariables::formulaToLabel(xref_label, m_master_element.data()->rSequenceStruct(), m_master_element.data()->diagram(), m_master_element.data()); - + if(!m_slave_Xref_item) { m_slave_Xref_item = new QGraphicsTextItem(xref_label, this); m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5)); m_slave_Xref_item->installSceneEventFilter(this); - + m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::xChanged, this, &DynamicElementTextItem::updateXref); m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::yChanged, this, &DynamicElementTextItem::updateXref); m_update_slave_Xref_connection << connect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::updateXref); @@ -1314,7 +1323,7 @@ void DynamicElementTextItem::updateXref() delete m_Xref_item; m_Xref_item = nullptr; } - + if(m_slave_Xref_item) { delete m_slave_Xref_item; @@ -1325,6 +1334,8 @@ void DynamicElementTextItem::updateXref() void DynamicElementTextItem::setPlainText(const QString &text) { + if (text == "14") + searchedElement = true; if (toPlainText() == text) return; @@ -1335,13 +1346,13 @@ void DynamicElementTextItem::setPlainText(const QString &text) if (m_parent_element.data()->state() == QET::GIBuildingFromXml || m_parent_element.data()->state() == QET::GILoadingFromXml) update_alignment = false; - + if (update_alignment) { prepareAlignment(); } - + DiagramTextItem::setPlainText(text); - + //User define a text width if (m_text_width > 0) { @@ -1354,11 +1365,11 @@ void DynamicElementTextItem::setPlainText(const QString &text) } } } - + if (update_alignment) { finishAlignment(); } - + if (m_Xref_item) { m_Xref_item->autoPos(); } diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index 60c6a45c8..35bd14716 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -33,7 +33,7 @@ class CrossRefItem; @brief The DynamicElementTextItem class This class provide a simple text field of element who can be added or removed directly from the diagram editor. This text is created to compensate a big lack of the ElementTextItem : ElementTextItem can't be added or removed directly in the diagram editor - + */ class DynamicElementTextItem : public DiagramTextItem { @@ -77,7 +77,7 @@ class DynamicElementTextItem : public DiagramTextItem private: DynamicElementTextItem (); DynamicElementTextItem(const DynamicElementTextItem &); - + public: QDomElement toXml(QDomDocument &dom_doc) const override; void fromXml(const QDomElement &dom_elmt) override; @@ -104,6 +104,7 @@ class DynamicElementTextItem : public DiagramTextItem void setTextWidth(qreal width); void setXref_item(Qt::AlignmentFlag m_exHrefPos); + bool searchedElement{false}; protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; @@ -140,22 +141,20 @@ class DynamicElementTextItem : public DiagramTextItem m_master_element, m_other_report; QPointer m_watched_conductor; - QString - m_text, - m_info_name, - m_composite_text, - m_report_formula, - m_F_str; + QString m_text, + m_text_old, + m_info_name, + m_composite_text, + m_report_formula, + m_F_str; DynamicElementTextItem::TextFrom m_text_from = UserText; QUuid m_uuid; QMetaObject::Connection m_report_formula_con; - QList - m_formula_connection, - m_update_slave_Xref_connection; - QColor m_user_color; - bool - m_frame = false, - m_first_scene_change = true; + QList m_formula_connection, + m_update_slave_Xref_connection; + QColor m_user_color{QColor()}; + bool m_frame = false, + m_first_scene_change = true; CrossRefItem *m_Xref_item = nullptr; QGraphicsTextItem *m_slave_Xref_item = nullptr; qreal m_text_width = -1; diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index e12132489..3055ab903 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -73,16 +73,15 @@ class ElementXmlRetroCompatibility /** @brief Element::Element - @param location : location of this element - @param parent : parent graphics item - @param state : state of the instanciation - @param link_type + New element from xml + @param location, location of this element + @param parent, parent graphics item + @param state, state of the instanciation */ Element::Element( const ElementsLocation &location, QGraphicsItem *parent, - int *state, - kind link_type) : + int *state, kind link_type) : QetGraphicsItem(parent), m_link_type (link_type), m_location (location) @@ -96,7 +95,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 +387,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 @@ -476,7 +476,8 @@ bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state) if (elmts.tagName() == "description") { //Minor workaround to find if there is a "input" tagg as label. - //If not, we set the tagg "label" to the first "input. + //If not, we set the tagg "label" to the first "input. Why one must have a tagg label? + // is label a required field? QList input_field; bool have_label = false; for (QDomElement input_node = node.firstChildElement("input") ; @@ -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; @@ -534,13 +539,11 @@ bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state) m_state = QET::GIOK; return(false); } - else - { - if (state) - *state = 0; - m_state = QET::GIOK; - return(true); - } + + if (state) + *state = 0; + m_state = QET::GIOK; + return(true); } /** @@ -650,7 +653,11 @@ Terminal *Element::parseTerminal(const QDomElement &dom_element) return nullptr; } - Terminal *new_terminal = new Terminal(data, this); + if (!Terminal::valideXml(dom_element)) + return nullptr; + + 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 @@ -664,8 +671,7 @@ Terminal *Element::parseTerminal(const QDomElement &dom_element) else return (a->dockConductor().y() < b->dockConductor().y()); }); - - return(new_terminal); + return(new_terminal); // TODO: makes not sense } /** @@ -715,23 +721,37 @@ 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; - foreach(QDomElement qde, - QET::findInDomElement(e, "terminals", "terminal")) { + 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; } 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 +764,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); } @@ -788,6 +809,8 @@ bool Element::fromXml( QString fl = e.attribute("freezeLabel", "false"); m_freeze_label = fl == "false"? false : true; + // TODO: why element information is not read? + //Load Sequential Values if (e.hasAttribute("sequ_1") || e.hasAttribute("sequf_1") @@ -824,10 +847,9 @@ bool Element::fromXml( //************************// //***Dynamic texts item***// //************************// - for (const QDomElement& qde : QET::findInDomElement( - e, - "dynamic_texts", - DynamicElementTextItem::xmlTagName())) + // read from the diagram section + // this is not done in the older versions, because there only inputs are available. + for (const QDomElement& qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTagName())) { DynamicElementTextItem *deti = new DynamicElementTextItem(this); addDynamicTextItem(deti); @@ -837,27 +859,27 @@ 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 = m_converted_text_from_xml_description.keys(); QList successfully_converted; const QList dom_inputs = inputs; - for (DynamicElementTextItem *deti : conv_deti_list) + // TODO: Legacy (0.7 and prior) + for (DynamicElementTextItem *deti : conv_deti_list) // elements read from the element collection definition { - for(const QDomElement& dom_input : dom_inputs) + for(const QDomElement& dom_input : dom_inputs) // elements in the diagram section { - //we use the same method used in ElementTextItem::fromXml - //to compar and know if the input dom element is for one of the text stored. - //The comparaison is made from the text position : - //if the position of the text is the same as the position stored in 'input' dom element - //that mean this is the good text - if (qFuzzyCompare(qreal(dom_input.attribute("x").toDouble()), - m_converted_text_from_xml_description.value(deti).x()) && - qFuzzyCompare(qreal(dom_input.attribute("y").toDouble()), - m_converted_text_from_xml_description.value(deti).y())) + + //we use the same method used in ElementTextItem::fromXml to compar and know if the input dom element is for one of the text stored. + //The comparaison is made from the text position : if the position of the text is the same as the position stored in 'input' dom element + //that mean this is the good text + // This is only used when in the diagram description the text elements are stored in the "inputs" section. In 0.8 and higher, + // texts are stored in directly in the "dynamic_elmt_text" section + if (qFuzzyCompare(qreal(dom_input.attribute("x").toDouble()), m_converted_text_from_xml_description.value(deti).x()) && + qFuzzyCompare(qreal(dom_input.attribute("y").toDouble()), m_converted_text_from_xml_description.value(deti).y())) { //Once again this 'if', is only for retrocompatibility with old old old project //when element text with tagg "label" is not null, but the element information "label" is. @@ -1164,10 +1186,8 @@ bool Element::fromXml( \~ @return The XML element representing this electrical element \~French L'element XML representant cet element electrique */ -QDomElement Element::toXml( - QDomDocument &document, - QHash &table_adr_id) const + +QDomElement Element::toXml(QDomDocument &document) const { QDomElement element = document.createElement("element"); @@ -1194,19 +1214,6 @@ 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"); // for each child of the element @@ -1214,8 +1221,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 be31e69db..7b5326513 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; @@ -46,22 +46,20 @@ class Element : public QetGraphicsItem public: /** @brief The kind enum - Used to know the kind of this element - (master, slave, report ect...) + Used to know the kind of this element (master, slave, report ect...) */ - enum kind { - Simple = 1, - NextReport = 2, - PreviousReport = 4, - AllReport = 6, - Master = 8, - Slave = 16, - Terminale = 32}; + enum kind {Simple = 1, + NextReport = 2, + PreviousReport = 4, + AllReport = 6, + Master = 8, + Slave = 16, + Terminale = 32}; - Element(const ElementsLocation &location, - QGraphicsItem * = nullptr, - int *state = nullptr, - Element::kind link_type = Element::Simple); + Element( + const ElementsLocation &location, + QGraphicsItem * parent= nullptr, int *state = nullptr, + Element::kind link_type = Element::Simple); ~Element() override; private: Element(const Element &); @@ -130,17 +128,10 @@ 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 &); + virtual QDomElement toXml(QDomDocument &) const; QUuid uuid() const; int orientation() const; - //METHODS related to texts void addDynamicTextItem(DynamicElementTextItem *deti = nullptr); void removeDynamicTextItem(DynamicElementTextItem *deti); diff --git a/sources/qetgraphicsitem/elementtextitemgroup.cpp b/sources/qetgraphicsitem/elementtextitemgroup.cpp index aca072633..759b599a2 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 373ab7161..82ef48732 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.h +++ b/sources/qetgraphicsitem/elementtextitemgroup.h @@ -32,10 +32,10 @@ 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 - + Q_PROPERTY(QPointF pos READ pos WRITE setPos) Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) Q_PROPERTY(int verticalAdjustment READ verticalAdjustment WRITE setVerticalAdjustment NOTIFY verticalAdjustmentChanged) @@ -43,7 +43,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(bool holdToBottomPage READ holdToBottomPage WRITE setHoldToBottomPage NOTIFY holdToBottomPageChanged) Q_PROPERTY(bool frame READ frame WRITE setFrame NOTIFY frameChanged) - + public: signals: void rotationChanged(qreal); @@ -54,14 +54,14 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup void xChanged(); void yChanged(); void frameChanged(bool frame); - + public: ElementTextItemGroup(const QString &name, Element *parent); ~ElementTextItemGroup() override; void addToGroup(QGraphicsItem *item); void removeFromGroup(QGraphicsItem *item); void blockAlignmentUpdate(bool block); - + void setAlignment(Qt::Alignment alignement); Qt::Alignment alignment() const; void updateAlignment(); @@ -76,11 +76,11 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup QList texts() const; Diagram *diagram() const; Element *parentElement() const; - + QDomElement toXml(QDomDocument &dom_document) const; void fromXml(QDomElement &dom_element); static QString xmlTaggName() {return QString("texts_group");} - + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; @@ -88,7 +88,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup void setRotation(qreal angle); void setPos(const QPointF &pos); void setPos(qreal x, qreal y); - + protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; @@ -99,7 +99,7 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup void keyPressEvent(QKeyEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; - + private: void updateXref(); void adjustSlaveXrefPos(); @@ -108,11 +108,12 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup private: Qt::Alignment m_alignment = Qt::AlignJustify; QString m_name; - bool m_first_move = true, + bool + m_first_move = true, 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 7868f543c..e5a068e1b 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 059182e20..c5d697cfd 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 eba811c35..f53f0d99f 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 b7a79f9e8..84ca9efb4 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.cpp b/sources/qetgraphicsitem/slaveelement.cpp index 2289981b9..56279c56d 100644 --- a/sources/qetgraphicsitem/slaveelement.cpp +++ b/sources/qetgraphicsitem/slaveelement.cpp @@ -26,14 +26,13 @@ Default constructor @param location location of xml definition @param qgi parent QGraphicItem + @param s parent diagram @param state int used to know if the creation of element have error */ -SlaveElement::SlaveElement(const ElementsLocation &location, - QGraphicsItem *qgi, - int *state) : - Element(location, qgi, state, Element::Slave) +SlaveElement::SlaveElement( + const ElementsLocation &location, QGraphicsItem *parent, int *state) : + Element(location, parent, state, Element::Slave) { - m_xref_item = nullptr; } /** diff --git a/sources/qetgraphicsitem/slaveelement.h b/sources/qetgraphicsitem/slaveelement.h index 2aba4305c..e22f39782 100644 --- a/sources/qetgraphicsitem/slaveelement.h +++ b/sources/qetgraphicsitem/slaveelement.h @@ -25,17 +25,17 @@ class SlaveElement : public Element { Q_OBJECT public: - explicit SlaveElement ( + explicit SlaveElement ( const ElementsLocation &, - QGraphicsItem * = nullptr, + QGraphicsItem * parent= nullptr, int * = nullptr); ~SlaveElement() override; void linkToElement(Element *elmt) override; void unlinkAllElements() override; 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 a3de13335..ffbe4ceec 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; /** @@ -40,11 +40,8 @@ const qreal Terminal::Z = 1000; @param name of terminal @param hiddenName */ -void Terminal::init( - QString number, QString name, bool hiddenName) +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 +54,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); } @@ -214,10 +209,18 @@ void Terminal::setNumber(QString number) */ 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,24 @@ QDomElement Terminal::toXml(QDomDocument &doc) const @param terminal Le QDomElement a analyser @return true si le QDomElement passe en parametre est une borne, false sinon */ -bool Terminal::valideXml(QDomElement &terminal) -{ - // verifie le nom du tag +bool Terminal::valideXml(const QDomElement &terminal) { 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 +823,17 @@ bool Terminal::valideXml(QDomElement &terminal) @return true si la borne "se reconnait" (memes coordonnes, meme orientation), false sinon */ -bool Terminal::fromXml(QDomElement &terminal) +bool Terminal::fromXml(const QDomElement &terminal) { - number_terminal_ = terminal.attribute("number"); - name_terminal_ = terminal.attribute("name"); - name_terminal_hidden = terminal.attribute("nameHidden").toInt(); + 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 +870,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 7e0ca59f6..def336219 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 @@ -78,6 +80,10 @@ class Terminal : public QGraphicsObject Element *parentElement () const; QUuid uuid () const; + int ID() const; + QPointF dockPos(); + QPointF originPos(); + QList conductors() const; Qet::Orientation orientation() const; QPointF dockConductor() const; @@ -89,10 +95,12 @@ class Terminal : public QGraphicsObject 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 @@ -109,7 +117,8 @@ class Terminal : public QGraphicsObject static const qreal terminalSize; static const qreal Z; - // Various static colors used for hover effects + // 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 +151,18 @@ 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); @@ -176,16 +187,6 @@ 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 436fa300b..ad31d196c 100644 --- a/sources/qetproject.cpp +++ b/sources/qetproject.cpp @@ -1502,7 +1502,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()) @@ -1560,19 +1564,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.cpp b/sources/titleblock/helpercell.cpp index eb62d6355..a1c4212a6 100644 --- a/sources/titleblock/helpercell.cpp +++ b/sources/titleblock/helpercell.cpp @@ -23,12 +23,7 @@ */ HelperCell::HelperCell(QGraphicsItem *parent) : QGraphicsObject(parent), - QGraphicsLayoutItem(), - background_color(Qt::white), - foreground_color(Qt::black), - label(), - orientation(Qt::Horizontal), - index(-1) + QGraphicsLayoutItem() { setGraphicsItem(this); setFlag(QGraphicsItem::ItemIsSelectable, false); diff --git a/sources/titleblock/helpercell.h b/sources/titleblock/helpercell.h index e2b85c37a..dd701ada1 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 657ac488e..bcd0f9f98 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 9ecc4a1b2..7165e975f 100644 --- a/sources/titleblockproperties.cpp +++ b/sources/titleblockproperties.cpp @@ -1,17 +1,17 @@ /* Copyright 2006-2020 The QElectroTech Team This file is part of QElectroTech. - + QElectroTech is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. - + QElectroTech is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ @@ -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() { } @@ -69,13 +65,12 @@ bool TitleBlockProperties::operator!=(const TitleBlockProperties &ip) { return(!(*this == ip)); } - /** - Exporte le cartouche sous formes d'attributs XML ajoutes a l'element e. - @param e Element XML auquel seront ajoutes des attributs + @brief TitleBlockProperties::toXml + @param e */ -void TitleBlockProperties::toXml(QDomElement &e) const -{ +void TitleBlockProperties::toXml(QDomElement &e) const { + e.setAttribute("author", author); e.setAttribute("title", title); e.setAttribute("filename", filename); @@ -92,7 +87,7 @@ void TitleBlockProperties::toXml(QDomElement &e) const e.setAttribute("titleblocktemplate", template_name); e.setAttribute("titleblocktemplateCollection", QET::qetCollectionToString(collection)); } - + if (context.keys().count()) { QDomElement properties = e.ownerDocument().createElement("properties"); context.toXml(properties); @@ -100,36 +95,50 @@ 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); - - // reads the template used to render the title block - if (e.hasAttribute("titleblocktemplate")) - { - template_name = e.attribute("titleblocktemplate"); - collection = QET::qetCollectionFromString(e.attribute("titleblocktemplateCollection")); + 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 (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 context.clear(); foreach (QDomElement e, QET::findInDomElement(e, "properties")) { context.fromXml(e); } + return true; } /** @@ -161,7 +170,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 7f9ebeb0e..26daba62b 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; ///m_formula_le -> setText (m_properties.m_formula); ui->m_text_le -> setText (m_properties.text); ui->m_function_le -> setText (m_properties.m_function); - ui->m_cable_le -> setText (m_properties.m_cable); - ui->m_bus_le -> setText (m_properties.m_bus); +// ui->m_cable_le -> setText (m_properties.m_cable); +// ui->m_bus_le -> setText (m_properties.m_bus); ui->m_tension_protocol_le -> setText (m_properties.m_tension_protocol); ui->m_wire_color_le -> setText (m_properties.m_wire_color); ui->m_wire_section_le -> setText (m_properties.m_wire_section); @@ -130,8 +130,8 @@ ConductorProperties ConductorPropertiesWidget::properties() const properties_.text = ui -> m_text_le -> text(); properties_.text_color = ui -> m_text_color_kpb->color(); properties_.m_function = ui -> m_function_le->text(); - properties_.m_cable = ui -> m_cable_le->text(); - properties_.m_bus = ui -> m_bus_le->text(); +// properties_.m_cable = ui -> m_cable_le->text(); +// properties_.m_bus = ui -> m_bus_le->text(); properties_.m_tension_protocol = ui -> m_tension_protocol_le->text(); properties_.m_wire_color = ui -> m_wire_color_le->text(); properties_.m_wire_section = ui -> m_wire_section_le->text(); diff --git a/sources/ui/dynamicelementtextmodel.cpp b/sources/ui/dynamicelementtextmodel.cpp index dee5f2e4f..2e0536bfc 100644 --- a/sources/ui/dynamicelementtextmodel.cpp +++ b/sources/ui/dynamicelementtextmodel.cpp @@ -1269,6 +1269,8 @@ void DynamicElementTextModel::enableGroupRotationAndPos( void DynamicElementTextModel::itemDataChanged(QStandardItem *qsi) { DynamicElementTextItem *deti = textFromItem(qsi); + if (deti->searchedElement) + int stop = 1; ElementTextItemGroup *etig = groupFromItem(qsi); if (!deti && !etig) return; @@ -1414,6 +1416,10 @@ void DynamicElementTextModel::setConnection(ElementTextItemGroup *group, bool se void DynamicElementTextModel::updateDataFromText(DynamicElementTextItem *deti, ValueType type) { + + if (deti->searchedElement) + int stop = 1; + QStandardItem *qsi = m_texts_list.value(deti); if (!qsi) return;