From e6f77ec369ee63213d707b47f222dccb80a7b47c Mon Sep 17 00:00:00 2001 From: Martin Marmsoler Date: Tue, 26 May 2020 18:47:24 +0200 Subject: [PATCH] Use uuid instead of an index to connect multiple elements --- sources/diagram.cpp | 83 ++++++++++++++++++++------- sources/properties/terminaldata.cpp | 8 ++- sources/properties/terminaldata.h | 2 + sources/qetgraphicsitem/conductor.cpp | 46 ++++++++++++--- sources/qetgraphicsitem/element.cpp | 2 +- sources/qetgraphicsitem/terminal.cpp | 13 ++--- sources/qetgraphicsitem/terminal.h | 5 +- 7 files changed, 117 insertions(+), 42 deletions(-) diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 6cccf6e56..dcd99b12e 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -863,6 +863,53 @@ bool Diagram::initFromXml(QDomElement &document, QPointF position, bool consider return(from_xml); } +/*! + * \brief findTerminal + * Find terminal to which the conductor should be connected + * \param conductor_index 1 or 2 depending on which terminal is searched + * \param f Conductor xml element + * \param table_adr_id Hash table to all terminal id assignement (legacy) + * \param added_elements Elements found in the xml file + * \return + */ +Terminal* findTerminal(int conductor_index, QDomElement& f, 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)); + // 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; + foreach (auto element, added_elements) { + if (element->uuid() != element_uuid) + continue; + element_found = true; + QUuid terminal_uuid = QUuid(f.attribute(terminal_index)); + foreach (auto terminal, element->terminals()) { + if (terminal->uuid() != terminal_uuid) + continue; + + return terminal; + } + qDebug() << "Diagram::fromXml() : "<< terminal_index << ":" << terminal_uuid << "not found in " << element_index << ":" << element_uuid; + break; + } + if (!element_found) + qDebug() << "Diagram::fromXml() : " << element_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(); + if (!table_adr_id.contains(id_p1)) { + qDebug() << "Diagram::fromXml() : terminal id " << id_p1 << " not found"; + } else + return table_adr_id.value(id_p1); + } + return nullptr; +} + /** Importe le schema decrit dans un element XML. Si une position est precisee, les elements importes sont positionnes de maniere a ce que le @@ -1031,26 +1078,22 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf if (!Conductor::valideXml(f)) continue; //Check if terminal that conductor must be linked is know - int id_p1 = f.attribute("terminal1").toInt(); - int id_p2 = f.attribute("terminal2").toInt(); - if (table_adr_id.contains(id_p1) && table_adr_id.contains(id_p2)) - { - Terminal *p1 = table_adr_id.value(id_p1); - Terminal *p2 = table_adr_id.value(id_p2); - if (p1 != p2) - { - Conductor *c = new Conductor(p1, p2); - if (c->isValid()) - { - addItem(c); - c -> fromXml(f); - added_conductors << c; - } - else - delete c; - } - } - else qDebug() << "Diagram::fromXml() : Le chargement du conducteur" << id_p1 << id_p2 << "a echoue"; + + Terminal* p1 = findTerminal(1, f, table_adr_id, added_elements); + Terminal* p2 = findTerminal(2, f, table_adr_id, added_elements); + + if (p1 && p2 && p1 != p2) + { + Conductor *c = new Conductor(p1, p2); + if (c->isValid()) + { + addItem(c); + c -> fromXml(f); + added_conductors << c; + } + else + delete c; + } } //Load tables diff --git a/sources/properties/terminaldata.cpp b/sources/properties/terminaldata.cpp index 6e4c9af8c..f90f3e64d 100644 --- a/sources/properties/terminaldata.cpp +++ b/sources/properties/terminaldata.cpp @@ -5,14 +5,17 @@ TerminalData::TerminalData(): PropertiesInterface() { - + init(); } TerminalData::TerminalData(QGraphicsObject *parent): PropertiesInterface(), q(parent) { + init(); +} +void TerminalData::init() { } TerminalData::~TerminalData() @@ -69,7 +72,8 @@ bool TerminalData::fromXml (const QDomElement &xml_element) 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, in the constructor of PartTerminal already one is created + // 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); diff --git a/sources/properties/terminaldata.h b/sources/properties/terminaldata.h index fd1990f5e..edaba6827 100644 --- a/sources/properties/terminaldata.h +++ b/sources/properties/terminaldata.h @@ -21,6 +21,8 @@ public: TerminalData(QGraphicsObject* parent); ~TerminalData(); + void init(); + void setParent(QGraphicsObject* parent); // Save/load properties to setting file. QString is use for prefix a word befor the name of each paramètre diff --git a/sources/qetgraphicsitem/conductor.cpp b/sources/qetgraphicsitem/conductor.cpp index 0c2ad3031..8609e8a68 100644 --- a/sources/qetgraphicsitem/conductor.cpp +++ b/sources/qetgraphicsitem/conductor.cpp @@ -579,13 +579,27 @@ bool Conductor::valideXml(QDomElement &e){ if (!e.hasAttribute("terminal2")) return(false); bool conv_ok; - // parse l'abscisse - e.attribute("terminal1").toInt(&conv_ok); - if (!conv_ok) return(false); + // 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 - e.attribute("terminal2").toInt(&conv_ok); - if (!conv_ok) return(false); + 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); } @@ -994,8 +1008,23 @@ QDomElement Conductor::toXml(QDomDocument &dom_document, QHash dom_element.setAttribute("x", QString::number(pos().x())); dom_element.setAttribute("y", QString::number(pos().y())); - dom_element.setAttribute("terminal1", table_adr_id.value(terminal1)); - dom_element.setAttribute("terminal2", table_adr_id.value(terminal2)); + + // Terminal is uniquely identified by the uuid of the terminal and the element + if (terminal1->uuid().isNull()) { + // legacy method to identify the terminal + dom_element.setAttribute("terminal1", table_adr_id.value(terminal1)); // for backward compability + } else { + dom_element.setAttribute("element1", terminal1->parentElement()->uuid().toString()); + dom_element.setAttribute("terminal1", terminal1->uuid().toString()); + } + + if (terminal2->uuid().isNull()) { + // legacy method to identify the terminal + dom_element.setAttribute("terminal2", table_adr_id.value(terminal2)); // for backward compability + } else { + dom_element.setAttribute("element2", terminal2->parentElement()->uuid().toString()); + dom_element.setAttribute("terminal2", terminal2->uuid().toString()); + } dom_element.setAttribute("freezeLabel", m_freeze_label? "true" : "false"); // on n'exporte les segments du conducteur que si ceux-ci ont @@ -1031,7 +1060,8 @@ QDomElement Conductor::toXml(QDomDocument &dom_document, QHash /** * @brief Conductor::pathFromXml - * Generate the path from 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 */ diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 9a25d0fa0..00051e56e 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -1047,7 +1047,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table foreach(Terminal *t, terminals()) { // alors on enregistre la borne QDomElement terminal = t -> toXml(document); - terminal.setAttribute("id", id_terminal); + terminal.setAttribute("id", id_terminal); // for backward compatibility table_adr_id.insert(t, id_terminal ++); xml_terminals.appendChild(terminal); } diff --git a/sources/qetgraphicsitem/terminal.cpp b/sources/qetgraphicsitem/terminal.cpp index df6728ac2..1f7d0fe0d 100644 --- a/sources/qetgraphicsitem/terminal.cpp +++ b/sources/qetgraphicsitem/terminal.cpp @@ -43,7 +43,6 @@ const qreal Terminal::Z = 1000; void Terminal::init(QString number, QString name, bool hiddenName) { hovered_color_ = Terminal::neutralColor; - m_uuid = QUuid::createUuid(); // calcul de la position du point d'amarrage a l'element dock_elmt_ = d->m_pos; @@ -709,13 +708,12 @@ QList Terminal::conductors() const { */ QDomElement Terminal::toXml(QDomDocument &doc) const { QDomElement qdo = doc.createElement("terminal"); - qdo.setAttribute("x", QString("%1").arg(dock_elmt_.x())); - qdo.setAttribute("y", QString("%1").arg(dock_elmt_.y())); + qdo.setAttribute("x", QString("%1").arg(dock_elmt_.x())); // for backward compatibility + qdo.setAttribute("y", QString("%1").arg(dock_elmt_.y()));// for backward compatibility qdo.setAttribute("orientation", d->m_orientation); qdo.setAttribute("number", number_terminal_); qdo.setAttribute("name", name_terminal_); qdo.setAttribute("nameHidden", name_terminal_hidden); - qdo.setAttribute("uuid", m_uuid.toString()); return(qdo); } @@ -764,9 +762,6 @@ bool Terminal::fromXml(QDomElement &terminal) { number_terminal_ = terminal.attribute("number"); name_terminal_ = terminal.attribute("name"); name_terminal_hidden = terminal.attribute("nameHidden").toInt(); - QString uuid = terminal.attribute("uuid"); - if (!uuid.isEmpty()) - m_uuid = uuid; return ( qFuzzyCompare(terminal.attribute("x").toDouble(), dock_elmt_.x()) && @@ -797,6 +792,10 @@ Element *Terminal::parentElement() const { return(parent_element_); } +QUuid Terminal::uuid() const { + return d->m_uuid; +} + /** * @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 b343159b9..83a855a19 100644 --- a/sources/qetgraphicsitem/terminal.h +++ b/sources/qetgraphicsitem/terminal.h @@ -67,6 +67,7 @@ class Terminal : public QGraphicsObject int conductorsCount () const; Diagram *diagram () const; Element *parentElement () const; + QUuid uuid () const; QList conductors() const; Qet::Orientation orientation() const; @@ -138,10 +139,6 @@ class Terminal : public QGraphicsObject /// Name of Terminal QString name_terminal_; bool name_terminal_hidden; - - /// Unique identifier of the terminal - /// This uuid is different to the uuid of the part terminal it represents - QUuid m_uuid; private: void init(QString number, QString name, bool hiddenName);