diff --git a/sources/diagram.cpp b/sources/diagram.cpp index cf0e8a12c..61d7c0724 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -915,14 +915,15 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf nvel_elmt = new GhostElement(element_location); } - // charge les caracteristiques de l'element - if (nvel_elmt -> fromXml(element_xml, table_adr_id, handle_inputs_rotation)) { - // ajout de l'element au schema et a la liste des elements ajoutes - addItem(nvel_elmt); - added_elements << nvel_elmt; - } else { + addItem(nvel_elmt); + //Loading fail, remove item from the diagram + if (!nvel_elmt->fromXml(element_xml, table_adr_id, handle_inputs_rotation)) + { + removeItem(nvel_elmt); delete nvel_elmt; qDebug() << "Diagram::fromXml() : Le chargement des parametres d'un element a echoue"; + } else { + added_elements << nvel_elmt; } } diff --git a/sources/qetgraphicsitem/commentitem.cpp b/sources/qetgraphicsitem/commentitem.cpp index ee3d6f45b..97a1054fa 100644 --- a/sources/qetgraphicsitem/commentitem.cpp +++ b/sources/qetgraphicsitem/commentitem.cpp @@ -58,7 +58,7 @@ void CommentItem::autoPos() { if (m_text_parent) centerToParentBottom(this); - else + else if (m_element->diagram()) { XRefProperties xrp = m_element->diagram()->project()->defaultXRefProperties(m_element->kindInformations()["type"].toString()); centerToBottomDiagram(this, m_element, xrp.offset()); diff --git a/sources/qetgraphicsitem/crossrefitem.cpp b/sources/qetgraphicsitem/crossrefitem.cpp index 68274f833..af23caed1 100644 --- a/sources/qetgraphicsitem/crossrefitem.cpp +++ b/sources/qetgraphicsitem/crossrefitem.cpp @@ -23,6 +23,8 @@ #include "diagram.h" #include "qgraphicsitemutility.h" #include "assignvariables.h" +#include "dynamicelementtextitem.h" +#include "elementtextitemgroup.h" //define the height of the header. static int header = 5; @@ -31,38 +33,34 @@ static int cross_min_heigth = 33; /** * @brief CrossRefItem::CrossRefItem - * Default constructor - * @param elmt element to display the cross ref and also parent item. - * elmt must be in a diagram - */ -/** - * @brief CrossRefItem::CrossRefItem - * @param elmt + * @param elmt : element to display the cross ref */ CrossRefItem::CrossRefItem(Element *elmt) : QGraphicsObject(elmt), - m_element (elmt) -{ - Q_ASSERT_X(elmt->diagram(), "CrossRefItem constructor", "Parent element is not in a diagram"); + m_element(elmt) +{init();} - m_properties = elmt->diagram()->project()->defaultXRefProperties(elmt->kindInformations()["type"].toString()); - setAcceptHoverEvents(true); +/** + * @brief CrossRefItem::CrossRefItem + * @param elmt : element to display the cross ref + * @param text : If the Xref must be displayed under a text, the text. + */ +CrossRefItem::CrossRefItem(Element *elmt, DynamicElementTextItem *text) : + QGraphicsObject(text), + m_element (elmt), + m_text(text) +{init();} - QETProject *project = elmt->diagram()->project(); - connect(project, &QETProject::projectDiagramsOrderChanged, this, &CrossRefItem::updateLabel); - connect(project, &QETProject::diagramRemoved, this, &CrossRefItem::updateLabel); - connect(project, &QETProject::XRefPropertiesChanged, this, &CrossRefItem::updateProperties); - - //set specific behavior related to the parent item. - if(m_properties.snapTo() == XRefProperties::Bottom) - { - connect(elmt, SIGNAL(yChanged()), this, SLOT(autoPos())); - connect(elmt, SIGNAL(rotationChanged()), this, SLOT(autoPos())); - } else { - setTextParent(); - } - updateLabel(); -} +/** + * @brief CrossRefItem::CrossRefItem + * @param elmt : element to display the cross ref + * @param group : If the Xref must be displayed under a group, the group. + */ +CrossRefItem::CrossRefItem(Element *elmt, ElementTextItemGroup *group) : + QGraphicsObject(group), + m_element(elmt), + m_group(group) +{init();} /** * @brief CrossRefItem::~CrossRefItem @@ -70,6 +68,61 @@ CrossRefItem::CrossRefItem(Element *elmt) : */ CrossRefItem::~CrossRefItem() {} +/** + * @brief CrossRefItem::init + * init this Xref + */ +void CrossRefItem::init() +{ + if(!m_element->diagram()) + { + qDebug() << "CrossRefItem constructor", "element is not in a diagram"; + return; + } + + QETProject *project = m_element->diagram()->project(); + connect(project, &QETProject::XRefPropertiesChanged, this, &CrossRefItem::updateProperties); + + m_properties = m_element->diagram()->project()->defaultXRefProperties(m_element->kindInformations()["type"].toString()); + setAcceptHoverEvents(true); + + setUpConnection(); + linkedChanged(); + updateLabel(); +} + +/** + * @brief CrossRefItem::setUpConnection + * Set up several connection to keep up to date the Xref + */ +void CrossRefItem::setUpConnection() +{ + for(QMetaObject::Connection c : m_update_connection) + disconnect(c); + + m_update_connection.clear(); + QETProject *project = m_element->diagram()->project(); + bool set=false; + + if(m_properties.snapTo() == XRefProperties::Label && (m_text || m_group)) //Snap to label and parent is a text or a group + set=true; + else if(m_properties.snapTo() == XRefProperties::Bottom && !m_text && !m_group) //Snap to bottom of element and parent is the element itself + { + m_update_connection << connect(m_element, SIGNAL(yChanged()), this, SLOT(autoPos())); + m_update_connection << connect(m_element, SIGNAL(rotationChanged()), this, SLOT(autoPos())); + set=true; + } + + if(set) + { + m_update_connection << connect(project, &QETProject::projectDiagramsOrderChanged, this, &CrossRefItem::updateLabel); + m_update_connection << connect(project, &QETProject::diagramRemoved, this, &CrossRefItem::updateLabel); + m_update_connection << connect(m_element, &Element::linkedElementChanged, this, &CrossRefItem::linkedChanged); + linkedChanged(); + updateLabel(); + } +} + /** * @brief CrossRefItem::boundingRect * @return the bounding rect of this item @@ -115,25 +168,17 @@ QString CrossRefItem::elementPositionText(const Element *elmt, const bool &add_p void CrossRefItem::updateProperties() { XRefProperties xrp = m_element->diagram()->project()->defaultXRefProperties(m_element->kindInformations()["type"].toString()); - + if (m_properties != xrp) { - if (m_properties.snapTo() != xrp.snapTo()) - { - if (xrp.snapTo() == XRefProperties::Bottom) - { - setParentItem(m_element); - connect(m_element, SIGNAL(yChanged()), this, SLOT(autoPos())); - connect(m_element, SIGNAL(rotationChanged()), this, SLOT(autoPos())); - } - else - { - setTextParent(); - disconnect(m_element, SIGNAL(yChanged()), this, SLOT(autoPos())); - disconnect(m_element, SIGNAL(rotationChanged()), this, SLOT(autoPos())); - } - } m_properties = xrp; + hide(); + if(m_properties.snapTo() == XRefProperties::Label && (m_text || m_group)) //Snap to label and parent is text or group + show(); + else if((m_properties.snapTo() == XRefProperties::Bottom && !m_text && !m_group)) //Snap to bottom of element is the parent + show(); + + setUpConnection(); updateLabel(); } } @@ -168,11 +213,12 @@ void CrossRefItem::updateLabel() drawAsContacts(qp); } - AddExtraInfo(qp, "comment"); - AddExtraInfo(qp, "location"); +// AddExtraInfo(qp, "comment"); +// AddExtraInfo(qp, "location"); qp.end(); autoPos(); + update(); } /** @@ -187,6 +233,34 @@ void CrossRefItem::autoPos() { centerToParentBottom(this); } +bool CrossRefItem::sceneEvent(QEvent *event) +{ + //By default when a QGraphicsItem is a child of a QGraphicsItemGroup + //all events are forwarded to group. + //We override it, when this Xref is in a group + if(m_group) + { + switch (event->type()) + { + case QEvent::GraphicsSceneHoverEnter: + hoverEnterEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneHoverMove: + hoverMoveEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneHoverLeave: + hoverLeaveEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneMouseDoubleClick: + mouseDoubleClickEvent(static_cast(event)); + break; + } + return true; + } + + return QGraphicsObject::sceneEvent(event); +} + /** * @brief CrossRefItem::paint * Paint this item @@ -229,7 +303,7 @@ void CrossRefItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) void CrossRefItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { m_hovered_contact = nullptr; - QGraphicsObject::hoverEnterEvent(event); + QGraphicsObject::hoverEnterEvent(event); } void CrossRefItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) @@ -293,6 +367,25 @@ void CrossRefItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) QGraphicsObject::hoverLeaveEvent(event); } +void CrossRefItem::linkedChanged() +{ + for(QMetaObject::Connection c : m_slave_connection) + disconnect(c); + + m_slave_connection.clear(); + + if(!isVisible()) + return; + + for(Element *elmt : m_element->linkedElements()) + { + m_slave_connection << connect(elmt, &Element::xChanged, this, &CrossRefItem::updateLabel); + m_slave_connection << connect(elmt, &Element::yChanged, this, &CrossRefItem::updateLabel); + } + + updateLabel(); +} + /** * @brief CrossRefItem::buildHeaderContact * Draw the QPicture of m_hdr_no_ctc and m_hdr_nc_ctc @@ -718,17 +811,6 @@ void CrossRefItem::AddExtraInfo(QPainter &painter, QString type) } } -/** - * @brief CrossRefItem::setTextParent - * Set the text field tagged "label" of m_element - * parent of this item - */ -void CrossRefItem::setTextParent() { - ElementTextItem *eti = m_element->taggedText("label"); - if (eti) setParentItem(eti); - else qDebug() << "CrossRefItem,no text tagged 'label' found to set has parent"; -} - /** * @brief CrossRefItem::NOElements * @return The linked elements of @m_element wich are open or switch contact. diff --git a/sources/qetgraphicsitem/crossrefitem.h b/sources/qetgraphicsitem/crossrefitem.h index 87ccc38ad..6f35a0eb0 100644 --- a/sources/qetgraphicsitem/crossrefitem.h +++ b/sources/qetgraphicsitem/crossrefitem.h @@ -23,6 +23,8 @@ #include class Element; +class DynamicElementTextItem; +class ElementTextItemGroup; /** * @brief The CrossRefItem class @@ -42,8 +44,14 @@ class CrossRefItem : public QGraphicsObject //Methods public: explicit CrossRefItem(Element *elmt); + explicit CrossRefItem(Element *elmt, DynamicElementTextItem *text); + explicit CrossRefItem(Element *elmt, ElementTextItemGroup *group); ~CrossRefItem() override; - + private: + void init(); + void setUpConnection(); + + public: enum { Type = UserType + 1009 }; int type() const override { return Type; } @@ -68,6 +76,7 @@ class CrossRefItem : public QGraphicsObject void autoPos (); protected: + bool sceneEvent(QEvent *event) override; void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; void mouseDoubleClickEvent (QGraphicsSceneMouseEvent * event ) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; @@ -75,6 +84,7 @@ class CrossRefItem : public QGraphicsObject void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; private: + void linkedChanged(); void buildHeaderContact (); void setUpCrossBoundingRect (QPainter &painter); void drawAsCross (QPainter &painter); @@ -82,7 +92,6 @@ class CrossRefItem : public QGraphicsObject QRectF drawContact (QPainter &painter, int flags, Element *elmt); void fillCrossRef (QPainter &painter); void AddExtraInfo (QPainter &painter, QString); - void setTextParent (); QList NOElements() const; QList NCElements() const; @@ -96,7 +105,10 @@ class CrossRefItem : public QGraphicsObject int m_drawed_contacts; QMap m_hovered_contacts_map; Element *m_hovered_contact = nullptr; - + DynamicElementTextItem *m_text = nullptr; + ElementTextItemGroup *m_group = nullptr; + QList m_slave_connection; + QList m_update_connection; }; #endif // CROSSREFITEM_H diff --git a/sources/qetgraphicsitem/customelement.cpp b/sources/qetgraphicsitem/customelement.cpp index 8acb5a45b..92d51af31 100644 --- a/sources/qetgraphicsitem/customelement.cpp +++ b/sources/qetgraphicsitem/customelement.cpp @@ -737,33 +737,33 @@ bool CustomElement::parseInput(QDomElement &dom_element) { !QET::attributeIsAnInteger(dom_element, "size", &size) ) return(false); - //The text have a tagg, we create an element text item - if (dom_element.attribute("tagg", "none") != "none") - { - ElementTextItem *eti = new ElementTextItem(dom_element.attribute("text"), this); - eti -> setFont(QETApp::diagramTextsFont(size)); - eti -> setTagg(dom_element.attribute("tagg", "other")); - m_element_informations.addValue(dom_element.attribute("tagg", "other"), dom_element.attribute("text")); +// //The text have a tagg, we create an element text item +// if (dom_element.attribute("tagg", "none") != "none") +// { +// ElementTextItem *eti = new ElementTextItem(dom_element.attribute("text"), this); +// eti -> setFont(QETApp::diagramTextsFont(size)); +// eti -> setTagg(dom_element.attribute("tagg", "other")); +// m_element_informations.addValue(dom_element.attribute("tagg", "other"), dom_element.attribute("text")); - // position the text field - eti -> setOriginalPos(QPointF(pos_x, pos_y)); - eti -> setPos(pos_x, pos_y); +// // position the text field +// eti -> setOriginalPos(QPointF(pos_x, pos_y)); +// eti -> setPos(pos_x, pos_y); - // rotation of the text field - qreal original_rotation_angle = 0.0; - QET::attributeIsAReal(dom_element, "rotation", &original_rotation_angle); - eti -> setOriginalRotationAngle(original_rotation_angle); - eti -> setRotationAngle(original_rotation_angle); +// // rotation of the text field +// qreal original_rotation_angle = 0.0; +// QET::attributeIsAReal(dom_element, "rotation", &original_rotation_angle); +// eti -> setOriginalRotationAngle(original_rotation_angle); +// eti -> setRotationAngle(original_rotation_angle); - // behavior when the parent element is rotated - eti -> setFollowParentRotations(dom_element.attribute("rotate") == "true"); +// // behavior when the parent element is rotated +// eti -> setFollowParentRotations(dom_element.attribute("rotate") == "true"); - m_texts << eti; +// m_texts << eti; - connect(eti, &ElementTextItem::diagramTextChanged, this, &Element::textItemChanged); +// connect(eti, &ElementTextItem::diagramTextChanged, this, &Element::textItemChanged); - return(eti); - } +// return(eti); +// } //The text haven't got a tagg, so we convert it to a dynamic text item //and store it to m_converted_text_from_xml_description, instead of m_dynamic_text_list //because these dynamic text need post treatement @@ -773,7 +773,12 @@ bool CustomElement::parseInput(QDomElement &dom_element) { deti->setText(dom_element.attribute("text", "_")); deti->setFontSize(dom_element.attribute("size", QString::number(9)).toInt()); deti->setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble()); - + + if(dom_element.attribute("tagg", "none") != "none") + { + deti->setTextFrom(DynamicElementTextItem::ElementInfo); + deti->setInfoName(dom_element.attribute("tagg")); + } //the origin transformation point of PartDynamicTextField is the top left corner, no matter the font size //The origin transformation point of ElementTextItem is the middle of left edge, and so by definition, change with the size of the font diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index f3488e42f..6aa607302 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -24,6 +24,7 @@ #include "terminal.h" #include "conductor.h" #include "elementtextitemgroup.h" +#include "crossrefitem.h" #include #include @@ -41,7 +42,6 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) : setFont(QETApp::diagramTextsFont(9)); setText(tr("Texte")); setParentItem(parent_element); - connect(this, &DynamicElementTextItem::textEdited, [this](const QString &old_str, const QString &new_str) { if(this->m_parent_element && this->m_parent_element->diagram()) @@ -52,36 +52,6 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) : } }); - - //If the parent is slave, we keep aware about the changement of master. - if(parent_element->linkType() == Element::Slave) - { - connect(parent_element, &Element::linkedElementChanged, this, &DynamicElementTextItem::masterChanged); - //The parent is already linked, wa call master changed for init the connection - if(!parent_element->linkedElements().isEmpty()) - masterChanged(); - } - if(parent_element->linkType() & Element::AllReport) - { - //Get the report formula, and add connection to keep up to date the formula. - if (parent_element->diagram() && parent_element->diagram()->project()) - { - m_report_formula = parent_element->diagram()->project()->defaultReportProperties(); - m_report_formula_con = connect(parent_element->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(parent_element, &Element::linkedElementChanged, this, &DynamicElementTextItem::reportChanged); - //The parent is already linked, we call reportChanged for init the connection - if(!parent_element->linkedElements().isEmpty()) - reportChanged(); - - //Add connection to keep up date the conductors added or removed to the parent folio report element - connect(parent_element->terminals().first(), &Terminal::conductorWasAdded, this, &DynamicElementTextItem::conductorWasAdded); - connect(parent_element->terminals().first(), &Terminal::conductorWasRemoved, this, &DynamicElementTextItem::conductorWasRemoved); - //Get a conductor in the potential - setPotentialConductor(); - } } DynamicElementTextItem::~DynamicElementTextItem() @@ -168,43 +138,34 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) QGraphicsTextItem::setRotation(dom_elmt.attribute("rotation", QString::number(0)).toDouble()); setFont(QETApp::diagramTextsFont(dom_elmt.attribute("font_size", QString::number(9)).toInt())); m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString())); - m_frame = dom_elmt.attribute("frame", "false") == "true"? true : false; + setFrame(dom_elmt.attribute("frame", "false") == "true"? true : false); + //Text from QMetaEnum me = textFromMetaEnum(); - m_text_from = DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data())); - if(m_text_from == ElementInfo || m_text_from == CompositeText) - { - setNoEditable(true); - //We don't made the connection below if the parent element is a report, because report haven't got info. - if (!(parentElement()->linkType() & Element::AllReport) && elementUseForInfo()) - connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); - } - else { - setNoEditable(false); - } + setTextFrom(DynamicElementTextItem::TextFrom(me.keyToValue(dom_elmt.attribute("text_from").toStdString().data()))); //Text QDomElement dom_text = dom_elmt.firstChildElement("text"); if (!dom_text.isNull()) - { - m_text = dom_text.text(); - setPlainText(m_text); - } + setText(dom_text.text()); //Info name QDomElement dom_info_name = dom_elmt.firstChildElement("info_name"); if(!dom_info_name.isNull()) - m_info_name = dom_info_name.text(); + setInfoName(dom_info_name.text()); //Composite text QDomElement dom_comp_text = dom_elmt.firstChildElement("composite_text"); if(!dom_comp_text.isNull()) - m_composite_text = dom_comp_text.text(); + setCompositeText(dom_comp_text.text()); //Color 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); } /** @@ -224,10 +185,13 @@ Element *DynamicElementTextItem::parentElement() const { */ ElementTextItemGroup *DynamicElementTextItem::parentGroup() const { - if(group()) - return dynamic_cast(group()); - else - return nullptr; + if(parentItem()) + { + if(ElementTextItemGroup *grp = dynamic_cast(parentItem())) + return grp; + } + + return nullptr; } /** @@ -281,8 +245,16 @@ void DynamicElementTextItem::refreshLabelConnection() if ((m_text_from == ElementInfo && m_info_name == "label") || (m_text_from == CompositeText && m_composite_text.contains("%{label}"))) { - setupFormulaConnection(); - updateLabel(); + if(m_parent_element.data()->linkType() & Element::AllReport) + { + updateReportFormulaConnection(); + updateReportText(); + } + else + { + setupFormulaConnection(); + updateLabel(); + } } } @@ -301,15 +273,21 @@ DynamicElementTextItem::TextFrom DynamicElementTextItem::textFrom() const { */ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_from) { + if(m_text_from == text_from) + return; + setNoEditable(text_from == UserText? false : true); clearFormulaConnection(); - if(text_from == UserText) + TextFrom old_text_from = m_text_from; + m_text_from = text_from; + + if(m_text_from == UserText) { setPlainText(m_text); disconnect(m_parent_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); } - else if (text_from == ElementInfo && elementUseForInfo()) + else if (m_text_from == ElementInfo && elementUseForInfo()) { if(m_info_name == "label") { @@ -319,10 +297,10 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f else setPlainText(elementUseForInfo()->elementInformations().value(m_info_name).toString()); - if(m_text_from == UserText) + if(old_text_from == UserText) connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); } - else if (text_from == CompositeText && elementUseForInfo()) + else if (m_text_from == CompositeText && elementUseForInfo()) { if(m_composite_text.contains("%{label}")) { @@ -332,15 +310,15 @@ void DynamicElementTextItem::setTextFrom(DynamicElementTextItem::TextFrom text_f else setPlainText(autonum::AssignVariables::replaceVariable(m_composite_text, elementUseForInfo()->elementInformations())); - if(m_text_from == UserText) + if(old_text_from == UserText) connect(elementUseForInfo(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); } - - if(m_text_from != text_from) - { - m_text_from = text_from; - emit textFromChanged(m_text_from); - } + + if(m_parent_element.data()->linkType() == Element::Master || + m_parent_element.data()->linkType() == Element::Slave) + updateXref(); + + emit textFromChanged(m_text_from); } /** @@ -372,9 +350,13 @@ void DynamicElementTextItem::setInfoName(const QString &info_name) { QString old_info_name = m_info_name; m_info_name = info_name; + if(old_info_name == "label") + { clearFormulaConnection(); + updateXref(); + } if (m_parent_element && (m_parent_element.data()->linkType() & Element::AllReport)) //special treatment for report { @@ -393,9 +375,10 @@ void DynamicElementTextItem::setInfoName(const QString &info_name) } } else if (m_info_name == "label" && elementUseForInfo()) - { + { setupFormulaConnection(); updateLabel(); + updateXref(); } else if(elementUseForInfo()) { setPlainText(elementUseForInfo()->elementInformations().value(info_name).toString()); @@ -423,7 +406,10 @@ void DynamicElementTextItem::setCompositeText(const QString &text) m_composite_text = text; if(old_composite_text.contains("%{label}")) + { clearFormulaConnection(); + updateXref(); + } if (m_parent_element && (m_parent_element.data()->linkType() & Element::AllReport)) //special treatment for report { @@ -444,6 +430,7 @@ void DynamicElementTextItem::setCompositeText(const QString &text) { setupFormulaConnection(); updateLabel(); + updateXref(); } else { @@ -494,6 +481,8 @@ void DynamicElementTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { setDefaultTextColor(m_user_color); m_user_color = QColor(); //m_user_color is now invalid + if(m_slave_Xref_item) + m_slave_Xref_item->setDefaultTextColor(Qt::black); } DiagramTextItem::mousePressEvent(event); @@ -561,44 +550,7 @@ void DynamicElementTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void DynamicElementTextItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { DiagramTextItem::mouseDoubleClickEvent(event); - - if(!parentElement()) - return; - - Element *zoomed_element = nullptr; - - if(parentElement()->linkType() == Element::Slave && m_master_element) - { - if ((m_text_from == ElementInfo && m_info_name == "label") || - (m_text_from == CompositeText && m_composite_text.contains("%{label}"))) - zoomed_element = m_master_element.data(); - } - if((parentElement()->linkType() & Element::AllReport) && m_other_report) - { - if((m_text_from == ElementInfo && m_info_name == "label") || - (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()) - { - QRectF fit = zoomed_element->sceneBoundingRect(); - fit.adjust(-200, -200, 200, 200); - view->fitInView(fit, Qt::KeepAspectRatioByExpanding); - } - } + zoomToLinkedElement(); } /** @@ -617,26 +569,14 @@ void DynamicElementTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) if(isSelected()) return; - Element::kind type = parentElement()->linkType(); - bool blue = false; - - if ((type & Element::AllReport) && m_other_report) + if ((parentElement()->linkType() & Element::AllReport) && m_other_report) { if( (m_text_from == ElementInfo && m_info_name == "label") || (m_text_from == CompositeText && m_composite_text.contains("%{label}")) ) - blue = true; - } - else if (type == Element::Slave && m_master_element) - { - if( (m_text_from == ElementInfo && m_info_name == "label") || - (m_text_from == CompositeText && m_composite_text.contains("%{label}")) ) - blue = true; - } - - if(blue) - { - m_user_color = color(); - setDefaultTextColor(Qt::blue); + { + m_user_color = color(); + setDefaultTextColor(Qt::blue); + } } } @@ -696,6 +636,89 @@ void DynamicElementTextItem::paint(QPainter *painter, const QStyleOptionGraphics } } +QVariant DynamicElementTextItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + //The first time this text is added to a scene, we make several cheking and connection + //according to the link type of the parent element + if(change == QGraphicsItem::ItemSceneHasChanged && m_first_scene_change) + { + 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) + { + connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::masterChanged); + //The parent is already linked, wa call master changed for init the connection + if(!m_parent_element.data()->linkedElements().isEmpty()) + masterChanged(); + } + else if(m_parent_element.data()->linkType() & Element::AllReport) + { + //Get the report formula, and add connection to keep up to date the formula. + if (m_parent_element.data()->diagram() && m_parent_element.data()->diagram()->project()) + { + 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 + connect(m_parent_element.data()->terminals().first(), &Terminal::conductorWasAdded, this, &DynamicElementTextItem::conductorWasAdded); + connect(m_parent_element.data()->terminals().first(), &Terminal::conductorWasRemoved, this, &DynamicElementTextItem::conductorWasRemoved); + } + //Get a conductor in the potential + setPotentialConductor(); + } + else if(m_parent_element.data()->linkType() == Element::Master) + { + connect(m_parent_element.data(), &Element::linkedElementChanged, this, &DynamicElementTextItem::updateXref); + if(m_parent_element.data()->diagram()) + connect(m_parent_element.data()->diagram()->project(), &QETProject::XRefPropertiesChanged, this, &DynamicElementTextItem::updateXref); + if(!m_parent_element.data()->linkedElements().isEmpty()) + updateXref(); + } + + m_first_scene_change = false; + return QGraphicsObject::itemChange(change, value); + } + else if (change == QGraphicsItem::ItemParentHasChanged) + { + updateXref(); + updateXref(); + } + + return QGraphicsObject::itemChange(change, value); +} + +bool DynamicElementTextItem::sceneEventFilter(QGraphicsItem *watched, QEvent *event) +{ + if(watched != m_slave_Xref_item) + return false; + + if(event->type() == QEvent::GraphicsSceneHoverEnter) { + m_slave_Xref_item->setDefaultTextColor(Qt::blue); + return true; + } + else if(event->type() == QEvent::GraphicsSceneHoverLeave) { + m_slave_Xref_item->setDefaultTextColor(Qt::black); + return true; + } + else if(event->type() == QEvent::GraphicsSceneMouseDoubleClick) { + zoomToLinkedElement(); + return true; + } + + return false; +} + void DynamicElementTextItem::elementInfoChanged() { DiagramContext dc; @@ -734,6 +757,7 @@ void DynamicElementTextItem::elementInfoChanged() final_text = m_text; setPlainText(final_text); + emit plainTextChanged(); } /** @@ -745,13 +769,19 @@ void DynamicElementTextItem::masterChanged() { //First we remove the old connection if(!m_master_element.isNull() && (m_text_from == ElementInfo || m_text_from == CompositeText)) + { disconnect(m_master_element.data(), &Element::elementInfoChange, this, &DynamicElementTextItem::elementInfoChanged); + 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 @@ -916,6 +946,9 @@ void DynamicElementTextItem::clearFormulaConnection() void DynamicElementTextItem::updateReportFormulaConnection() { + if(!m_parent_element.data()->linkType() & Element::AllReport) + return; + removeConnectionForReportFormula(m_report_formula); setConnectionForReportFormula(m_report_formula); updateReportText(); @@ -926,7 +959,10 @@ void DynamicElementTextItem::updateReportFormulaConnection() * This function is only use when this text is owned by a report, and this text have for info the Label. */ void DynamicElementTextItem::updateReportText() -{ +{ + if(!m_parent_element.data()->linkType() & Element::AllReport) + return; + if (m_text_from == ElementInfo && m_info_name == "label" && m_other_report) { Element *elmt = m_other_report.data(); @@ -1003,6 +1039,9 @@ void DynamicElementTextItem::setPotentialConductor() { if(parentElement() && (parentElement()->linkType() & Element::AllReport)) { + 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, @@ -1095,3 +1134,142 @@ QString DynamicElementTextItem::reportReplacedCompositeText() const return string; } +/** + * @brief DynamicElementTextItem::zoomToLinkedElement + * If the parent element is a folio report or a slave element, + * and is linked, zoom to the linked element + */ +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") || + (m_text_from == CompositeText && m_composite_text.contains("%{label}"))) + zoomed_element = m_master_element.data(); + } + if((parentElement()->linkType() & Element::AllReport) && m_other_report) + { + if((m_text_from == ElementInfo && m_info_name == "label") || + (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()) + { + QRectF fit = zoomed_element->sceneBoundingRect(); + fit.adjust(-200, -200, 200, 200); + view->fitInView(fit, Qt::KeepAspectRatioByExpanding); + } + } +} + +/** + * @brief DynamicElementTextItem::updateXref + * Create or delete the Xref according to the current properties of the project + */ +void DynamicElementTextItem::updateXref() +{ + if(diagram()) + { + 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() && + xrp.snapTo() == XRefProperties::Label) + { + //For add a Xref, this text must not be in a group + if(!parentGroup()) + { + if(!m_Xref_item) + m_Xref_item = new CrossRefItem(m_parent_element.data(), this); + return; + } + } + } + else if (m_parent_element.data()->linkType() == Element::Slave) + { + if(m_master_element && !parentGroup() && + ( + (m_text_from == DynamicElementTextItem::ElementInfo && m_info_name == "label") || + (m_text_from == DynamicElementTextItem::CompositeText && m_composite_text.contains("%{label}")) + ) + ) + { + 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); + m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::projectDiagramsOrderChanged, this, &DynamicElementTextItem::updateXref); + m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::diagramRemoved, this, &DynamicElementTextItem::updateXref); + m_update_slave_Xref_connection << connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &DynamicElementTextItem::updateXref); + } + else + m_slave_Xref_item->setPlainText(xref_label); + + QRectF r = boundingRect(); + QPointF pos(r.center().x() - m_slave_Xref_item->boundingRect().width()/2, + r.bottom()); + m_slave_Xref_item->setPos(pos); + return; + } + } + } + + //There is no reason to have a xref, we delete it if exist + if(m_Xref_item) + { + delete m_Xref_item; + m_Xref_item = nullptr; + } + + if(m_slave_Xref_item) + { + delete m_slave_Xref_item; + m_slave_Xref_item = nullptr; + m_update_slave_Xref_connection.clear(); + } +} + +void DynamicElementTextItem::setPlainText(const QString &text) +{ + DiagramTextItem::setPlainText(text); + if(m_Xref_item) + m_Xref_item->autoPos(); + else if(m_slave_Xref_item) + { + QRectF r = boundingRect(); + QPointF pos(r.center().x() - m_slave_Xref_item->boundingRect().width()/2, + r.bottom()); + m_slave_Xref_item->setPos(pos); + } +} + diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index d6f6fd2ed..f6b72238e 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -19,12 +19,14 @@ #define DYNAMICELEMENTTEXTITEM_H #include "diagramtextitem.h" +#include "element.h" #include #include class Element; class Conductor; class ElementTextItemGroup; +class CrossRefItem; /** * @brief The DynamicElementTextItem class @@ -62,6 +64,7 @@ class DynamicElementTextItem : public DiagramTextItem void infoNameChanged(QString info); void compositeTextChanged(QString text); void frameChanged(bool frame); + void plainTextChanged(); public: DynamicElementTextItem(Element *parent_element); @@ -92,6 +95,8 @@ class DynamicElementTextItem : public DiagramTextItem void setFrame(const bool frame); bool frame() const; QUuid uuid() const; + void updateXref(); + void setPlainText(const QString &text); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event) override; @@ -101,6 +106,8 @@ class DynamicElementTextItem : public DiagramTextItem void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + bool sceneEventFilter(QGraphicsItem *watched, QEvent *event) override; private: void elementInfoChanged(); @@ -119,6 +126,7 @@ class DynamicElementTextItem : public DiagramTextItem void setPotentialConductor(); void conductorPropertiesChanged(); QString reportReplacedCompositeText() const; + void zoomToLinkedElement(); private: QPointer m_parent_element, @@ -133,9 +141,13 @@ class DynamicElementTextItem : public DiagramTextItem DynamicElementTextItem::TextFrom m_text_from = UserText; QUuid m_uuid; QMetaObject::Connection m_report_formula_con; - QList m_formula_connection; + QList m_formula_connection, + m_update_slave_Xref_connection; QColor m_user_color; - bool m_frame = false; + bool m_frame = false, + m_first_scene_change = true; + CrossRefItem *m_Xref_item = nullptr; + QGraphicsTextItem *m_slave_Xref_item = nullptr; }; #endif // DYNAMICELEMENTTEXTITEM_H diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 3fe9ed69c..baae8d875 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -69,7 +69,7 @@ Element::Element(QGraphicsItem *parent) : must_highlight_(false), m_mouse_over(false) { - link_type_ = Simple; + m_link_type = Simple; uuid_ = QUuid::createUuid(); setZValue(10); setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); @@ -386,18 +386,18 @@ bool Element::valideXml(QDomElement &e) { } /** - Methode d'import XML. Cette methode est appelee lors de l'import de contenu - XML (coller, import, ouverture de fichier...) afin que l'element puisse - gerer lui-meme l'importation de ses bornes. Ici, comme cette classe est - caracterisee par un nombre fixe de bornes, l'implementation exige de - retrouver exactement ses bornes dans le fichier XML. - @param e L'element XML a analyser. - @param table_id_adr Reference vers la table de correspondance entre les IDs - du fichier XML et les adresses en memoire. Si l'import reussit, il faut y - ajouter les bons couples (id, adresse). - @return true si l'import a reussi, false sinon - -*/ + * @brief Element::fromXml + * Import the parameters of this element from a xml document. + * When call this function ensure this element is already in a scene, because + * the dynamic text item and element text item group (in the xml file) are created in this function + * and need a diagram for create their Xref, when this element is linked to another. + * If not the Xref can be not displayed, until the next call of update Xref of the group or text item. + * @param e : the dom element where the parameter is stored + * @param table_id_adr : Reference to the mapping table between IDs of the XML file + * and the addresses in memory. If the import succeeds, it must be add the right couples (id, address). + * @param handle_inputs_rotation : apply the rotation of this element to his child text + * @return + */ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool handle_inputs_rotation) { QDomDocument doc = e.ownerDocument(); @@ -507,6 +507,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool //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) @@ -518,7 +519,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool //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())) - { + { deti->setText(dom_input.attribute("text")); qreal rotation = deti->rotation(); @@ -554,6 +555,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool inputs.removeAll(dom_input); m_dynamic_text_list.append(deti); m_converted_text_from_xml_description.remove(deti); + successfully_converted << deti; } } } @@ -591,17 +593,19 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool } //load informations - m_element_informations.fromXml(e.firstChildElement("elementInformations"), "elementInformation"); + DiagramContext dc; + dc.fromXml(e.firstChildElement("elementInformations"), "elementInformation"); /** * Since the commit 4791, the value used as "label" and "formula" is stored in differents keys (instead of the same key, "label" in previous version), * so, if "label" contain "%" (Use variable value), and "formula" does not exist, * this mean the label was made before commit 4791 (0.51 dev). So we swap the value stored in "label" to "formula" as expected. * @TODO remove this code at version 0.7 or more (probably useless). */ - if (m_element_informations["label"].toString().contains("%") && m_element_informations["formula"].toString().isNull()) + if (dc["label"].toString().contains("%") && dc["formula"].toString().isNull()) { - m_element_informations.addValue("formula", m_element_informations["label"]); + dc.addValue("formula", dc["label"]); } + setElementInformations(dc); /** * At the start of the 0.51 devel, if the text item with tagg "label" was edited directly in the diagram, @@ -626,6 +630,71 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool } } } + + /** + During the devel of the version 0.7, the "old text" was replaced by the dynamic element text item. + When open a project made befor the 0.7, we must to reproduce the same visual when the label are not empty and visible, + and comment are not empty and visible and/or location are not empty and visible. + we create a text group with inside the needed texts, label and comment and/or location. + */ + //#1 There must be old text converted to dynamic text + if(!successfully_converted.isEmpty()) + { + //#2 the element information must have label not empty and visible + //and a least comment or location not empty and visible + QString label = m_element_informations.value("label").toString(); + QString comment = m_element_informations.value("comment").toString(); + QString location = m_element_informations.value("location").toString(); + bool la = m_element_informations.keyMustShow("label"); + bool c = m_element_informations.keyMustShow("comment"); + bool lo = m_element_informations.keyMustShow("location"); + if(!label.isEmpty() && la && + ((!comment.isEmpty() && c) || (!location.isEmpty() && lo))) + { + //#2 in the converted list one text must have text from = element info and info name = label + for(DynamicElementTextItem *deti : successfully_converted) + { + if(deti->textFrom() == DynamicElementTextItem::ElementInfo && deti->infoName() == "label") + { + //Create the comment item + DynamicElementTextItem *comment_text = nullptr; + if(!comment.isEmpty() && c) + { + comment_text = new DynamicElementTextItem(this); + comment_text->setTextFrom(DynamicElementTextItem::ElementInfo); + comment_text->setInfoName("comment"); + comment_text->setFontSize(6); + comment_text->setFrame(true); + comment_text->setPos(deti->x(), deti->y()+10); //+10 is arbitrary, comment_text must be below deti + addDynamicTextItem(comment_text); + } + //create the location item + DynamicElementTextItem *location_text = nullptr; + if(!location.isEmpty() && lo) + { + location_text = new DynamicElementTextItem(this); + location_text->setTextFrom(DynamicElementTextItem::ElementInfo); + location_text->setInfoName("location"); + location_text->setFontSize(6); + location_text->setPos(deti->x(), deti->y()+20); //+20 is arbitrary, location_text must be below deti and comment + addDynamicTextItem(location_text); + } + + //Create the group + ElementTextItemGroup *group = addTextGroup(tr("Label + commentaire")); + addTextToGroup(deti, group); + if(comment_text) + addTextToGroup(comment_text, group); + if(location_text) + addTextToGroup(location_text, group); + group->setAlignment(Qt::AlignVCenter); + group->setVerticalAdjustment(-4); + + break; + } + } + } + } return(true); } diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index ca0850c91..b6d50cba6 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -117,7 +117,7 @@ class Element : public QetGraphicsItem virtual void unlinkElement (Element *) {} virtual void initLink (QETProject *); QList linkedElements (); - virtual kind linkType() const {return link_type_;} // @return the linkable type + virtual kind linkType() const {return m_link_type;} // @return the linkable type void newUuid() {uuid_ = QUuid::createUuid();} //create new uuid for this element //ATTRIBUTES related to linked element @@ -125,7 +125,7 @@ class Element : public QetGraphicsItem QList connected_elements; QList tmp_uuids_link; QUuid uuid_; - kind link_type_; + kind m_link_type; ElementTextItem* setTaggedText(const QString &tagg, const QString &newstr, const bool noeditable=false); signals: diff --git a/sources/qetgraphicsitem/elementtextitemgroup.cpp b/sources/qetgraphicsitem/elementtextitemgroup.cpp index 98e210e41..aff771c6e 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.cpp +++ b/sources/qetgraphicsitem/elementtextitemgroup.cpp @@ -21,6 +21,8 @@ #include "diagram.h" #include "addelementtextcommand.h" #include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "crossrefitem.h" +#include "qetapp.h" #include #include @@ -36,9 +38,11 @@ bool sorting(QGraphicsItem *qgia, QGraphicsItem *qgib) */ ElementTextItemGroup::ElementTextItemGroup(const QString &name, Element *parent) : QGraphicsItemGroup(parent), - m_name(name) + m_name(name), + m_parent_element(parent) { setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsMovable); + connect(parent, &Element::linkedElementChanged, this, &ElementTextItemGroup::updateXref); } ElementTextItemGroup::~ElementTextItemGroup() @@ -69,7 +73,13 @@ void ElementTextItemGroup::addToGroup(QGraphicsItem *item) connect(deti, &DynamicElementTextItem::textChanged, this, &ElementTextItemGroup::updateAlignment); connect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateAlignment); connect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateAlignment); - connect(deti, &DynamicElementTextItem::compositeTextChanged, this, &ElementTextItemGroup::updateAlignment); + connect(deti, &DynamicElementTextItem::compositeTextChanged, this, &ElementTextItemGroup::updateAlignment); + connect(deti, &DynamicElementTextItem::plainTextChanged, this, &ElementTextItemGroup::updateAlignment); + + connect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateXref); + connect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateXref); + + updateXref(); } } @@ -94,6 +104,12 @@ void ElementTextItemGroup::removeFromGroup(QGraphicsItem *item) disconnect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateAlignment); disconnect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateAlignment); disconnect(deti, &DynamicElementTextItem::compositeTextChanged, this, &ElementTextItemGroup::updateAlignment); + disconnect(deti, &DynamicElementTextItem::plainTextChanged, this, &ElementTextItemGroup::updateAlignment); + + disconnect(deti, &DynamicElementTextItem::textFromChanged, this, &ElementTextItemGroup::updateXref); + disconnect(deti, &DynamicElementTextItem::infoNameChanged, this, &ElementTextItemGroup::updateXref); + + updateXref(); } } @@ -124,7 +140,8 @@ void ElementTextItemGroup::updateAlignment() { prepareGeometryChange(); - QList texts = childItems(); + QList texts = this->texts(); + if (texts.size() > 1) { prepareGeometryChange(); @@ -169,6 +186,11 @@ void ElementTextItemGroup::updateAlignment() setTransformOriginPoint(boundingRect().topLeft()); } + + if(m_Xref_item) + m_Xref_item->autoPos(); + if(m_slave_Xref_item) + adjustSlaveXrefPos(); } /** @@ -334,8 +356,8 @@ QRectF ElementTextItemGroup::boundingRect() const //if we move an item already in the group, the bounding rect of the group stay unchanged. //We reimplement this function to avoid this behavior. QRectF rect; - for(QGraphicsItem *qgi : childItems()) - { + for(QGraphicsItem *qgi : texts()) + { QRectF r(qgi->pos(), QSize(qgi->boundingRect().width(), qgi->boundingRect().height())); rect = rect.united(r); } @@ -414,6 +436,38 @@ void ElementTextItemGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) QGraphicsItemGroup::mouseReleaseEvent(event); } +void ElementTextItemGroup::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + if(m_slave_Xref_item) + { + if(m_slave_Xref_item->boundingRect().contains(mapToItem(m_slave_Xref_item, event->pos()))) + { + if(parentElement()->linkType() == Element::Slave && !parentElement()->linkedElements().isEmpty()) + { + m_slave_Xref_item->setDefaultTextColor(Qt::black); + Element *elmt = parentElement()->linkedElements().first(); + + //Unselect and ungrab mouse to prevent unwanted + //move when linked element is in the same scene of this. + setSelected(false); + ungrabMouse(); + + if(scene() != elmt->scene()) + elmt->diagram()->showMe(); + elmt->setSelected(true); + + //Zoom to the element + for(QGraphicsView *view : elmt->scene()->views()) + { + QRectF fit = elmt->sceneBoundingRect(); + fit.adjust(-200, -200, 200, 200); + view->fitInView(fit, Qt::KeepAspectRatioByExpanding); + } + } + } + } +} + /** * @brief ElementTextItemGroup::keyPressEvent * @param event @@ -447,3 +501,111 @@ void ElementTextItemGroup::keyPressEvent(QKeyEvent *event) event->ignore(); } +void ElementTextItemGroup::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + //The pos of the event is not in this item coordinate, + //but in child item hovered by the mouse, so we use the scene pos. + if(m_slave_Xref_item && + m_slave_Xref_item->boundingRect().contains(m_slave_Xref_item->mapFromScene(event->scenePos()))) + m_slave_Xref_item->setDefaultTextColor(Qt::blue); + + QGraphicsItemGroup::hoverEnterEvent(event); +} + +void ElementTextItemGroup::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + if(m_slave_Xref_item) + m_slave_Xref_item->setDefaultTextColor(Qt::black); + + QGraphicsItemGroup::hoverLeaveEvent(event); +} + +void ElementTextItemGroup::updateXref() +{ + if(m_parent_element->diagram()) + { + QETProject *project = m_parent_element->diagram()->project(); + + if(m_parent_element->linkType() == Element::Master && + !m_parent_element->linkedElements().isEmpty()) + { + + XRefProperties xrp = project->defaultXRefProperties(m_parent_element->kindInformations()["type"].toString()); + + if(xrp.snapTo() == XRefProperties::Label) + { + //At least one text owned by this group must be set with + //textFrom -> element info and element info name -> label + //for display a xref + for(DynamicElementTextItem *deti : texts()) + { + if(deti->textFrom() == DynamicElementTextItem::ElementInfo && + deti->infoName() == "label") + { + if(!m_Xref_item) + m_Xref_item = new CrossRefItem(m_parent_element, this); + m_Xref_item->autoPos(); + return; + } + } + } + } + else if(m_parent_element->linkType() == Element::Slave && + !m_parent_element->linkedElements().isEmpty()) + { + Element *master_elmt = m_parent_element->linkedElements().first(); + for(DynamicElementTextItem *deti : texts()) + { + if((deti->textFrom() == DynamicElementTextItem::ElementInfo && deti->infoName() == "label") || + (deti->textFrom() == DynamicElementTextItem::CompositeText && deti->compositeText().contains("%{label"))) + { + XRefProperties xrp = project->defaultXRefProperties(master_elmt->kindInformations()["type"].toString()); + QString xref_label = xrp.slaveLabel(); + xref_label = autonum::AssignVariables::formulaToLabel(xref_label, master_elmt->rSequenceStruct(), master_elmt->diagram(), master_elmt); + + if(!m_slave_Xref_item) + { + m_slave_Xref_item = new QGraphicsTextItem(xref_label, this); + m_slave_Xref_item->setFont(QETApp::diagramTextsFont(5)); + + m_update_slave_Xref_connection << connect(master_elmt, &Element::xChanged, this, &ElementTextItemGroup::updateXref); + m_update_slave_Xref_connection << connect(master_elmt, &Element::yChanged, this, &ElementTextItemGroup::updateXref); + m_update_slave_Xref_connection << connect(master_elmt, &Element::elementInfoChange, this, &ElementTextItemGroup::updateXref); + m_update_slave_Xref_connection << connect(project, &QETProject::projectDiagramsOrderChanged, this, &ElementTextItemGroup::updateXref); + m_update_slave_Xref_connection << connect(project, &QETProject::diagramRemoved, this, &ElementTextItemGroup::updateXref); + m_update_slave_Xref_connection << connect(project, &QETProject::XRefPropertiesChanged, this, &ElementTextItemGroup::updateXref); + } + else + m_slave_Xref_item->setPlainText(xref_label); + + adjustSlaveXrefPos(); + return; + } + } + + } + } + + + //There is no reason to have a xref, we delete it if exist + if(m_Xref_item) + { + delete m_Xref_item; + m_Xref_item = nullptr; + } + if(m_slave_Xref_item) + { + delete m_slave_Xref_item; + m_slave_Xref_item = nullptr; + m_update_slave_Xref_connection.clear(); + } +} + +void ElementTextItemGroup::adjustSlaveXrefPos() +{ + QRectF r = boundingRect(); + QPointF pos(r.center().x() - m_slave_Xref_item->boundingRect().width()/2, + r.bottom()); + m_slave_Xref_item->setPos(pos); +} + diff --git a/sources/qetgraphicsitem/elementtextitemgroup.h b/sources/qetgraphicsitem/elementtextitemgroup.h index 55432edde..04f6e1c7e 100644 --- a/sources/qetgraphicsitem/elementtextitemgroup.h +++ b/sources/qetgraphicsitem/elementtextitemgroup.h @@ -25,6 +25,7 @@ class Element; class DynamicElementTextItem; class Diagram; +class CrossRefItem; /** * @brief The ElementTextItemGroup class @@ -77,7 +78,14 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup void mousePressEvent(QGraphicsSceneMouseEvent *event) override; void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; void keyPressEvent(QKeyEvent *event) override; + void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; + + private: + void updateXref(); + void adjustSlaveXrefPos(); private: Qt::Alignment m_alignment = Qt::AlignJustify; @@ -85,6 +93,10 @@ class ElementTextItemGroup : public QObject, public QGraphicsItemGroup bool m_first_move = true; QPointF m_mouse_to_origin_movement; int m_vertical_adjustment = 0; + CrossRefItem *m_Xref_item = nullptr; + Element *m_parent_element = nullptr; + QList m_update_slave_Xref_connection; + QGraphicsTextItem *m_slave_Xref_item = nullptr; }; #endif // ELEMENTTEXTITEMGROUP_H diff --git a/sources/qetgraphicsitem/masterelement.cpp b/sources/qetgraphicsitem/masterelement.cpp index e1de49e94..d78ff41fb 100644 --- a/sources/qetgraphicsitem/masterelement.cpp +++ b/sources/qetgraphicsitem/masterelement.cpp @@ -19,6 +19,7 @@ #include "crossrefitem.h" #include "elementtextitem.h" #include "diagram.h" +#include "dynamicelementtextitem.h" #include /** @@ -30,10 +31,10 @@ * @param state int used to know if the creation of element have error */ MasterElement::MasterElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state), - m_Xref_item (nullptr) + CustomElement(location, qgi, state) { - link_type_ = Master; + m_link_type = Element::Master; + connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext))); connect(this, &Element::updateLabel, [this]() {this->updateLabel(this->elementInformations(), this->elementInformations());}); } @@ -60,13 +61,12 @@ void MasterElement::linkToElement(Element *elmt) connected_elements << elmt; elmt->linkToElement(this); - if (!m_Xref_item) m_Xref_item = new CrossRefItem(this); //create cross ref item if not yet - - connect(elmt, SIGNAL(xChanged()), m_Xref_item, SLOT(updateLabel())); - connect(elmt, SIGNAL(yChanged()), m_Xref_item, SLOT(updateLabel())); - connect(elmt, SIGNAL(updateLabel()), m_Xref_item, SLOT(updateLabel())); - connect(&elmt->diagram()->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, m_Xref_item, &CrossRefItem::updateLabel); - m_Xref_item -> updateLabel(); + XRefProperties xrp = diagram()->project()->defaultXRefProperties(kindInformations()["type"].toString()); + if (!m_Xref_item && xrp.snapTo() == XRefProperties::Bottom) + m_Xref_item = new CrossRefItem(this); //create cross ref item if not yet + else + aboutDeleteXref(); + emit linkedElementChanged(); } } @@ -100,13 +100,6 @@ void MasterElement::unlinkElement(Element *elmt) elmt -> unlinkElement (this); elmt -> setHighlighted (false); - //update the graphics cross ref - disconnect(elmt, SIGNAL(xChanged()), m_Xref_item, SLOT(updateLabel())); - disconnect(elmt, SIGNAL(yChanged()), m_Xref_item, SLOT(updateLabel())); - disconnect(elmt, SIGNAL(updateLabel()), m_Xref_item, SLOT(updateLabel())); - disconnect(&elmt->diagram()->border_and_titleblock, &BorderTitleBlock::titleBlockFolioChanged, m_Xref_item, &CrossRefItem::updateLabel); - - m_Xref_item -> updateLabel(); aboutDeleteXref(); emit linkedElementChanged(); } @@ -154,23 +147,32 @@ void MasterElement::updateLabel(DiagramContext old_info, DiagramContext new_info new_info["label"].toString().isEmpty() ? eti->setVisible(true) : eti -> setVisible(new_info.keyMustShow("label")); } +} - //Delete or update the xref - if (m_Xref_item) { - m_Xref_item -> updateLabel(); - aboutDeleteXref(); +QVariant MasterElement::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if(change == QGraphicsItem::ItemSceneHasChanged && m_first_scene_change) + { + m_first_scene_change = false; + connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &MasterElement::xrefPropertiesChanged); } - else { - QString comment = elementInformations()["comment"].toString(); - bool must_show_comment = elementInformations().keyMustShow("comment"); + return CustomElement::itemChange(change, value); +} - QString location = elementInformations()["location"].toString(); - bool must_show_location = elementInformations().keyMustShow("location"); - - if (! (comment.isEmpty() || !must_show_comment) || !(location.isEmpty() || !must_show_location)) { +void MasterElement::xrefPropertiesChanged() +{ + if(!diagram()) + return; + + XRefProperties xrp = diagram()->project()->defaultXRefProperties(kindInformations()["type"].toString()); + if(xrp.snapTo() == XRefProperties::Bottom) + { + //We create a Xref, and just after we call aboutDeleteXref, + //because the Xref may be useless. + if(!m_Xref_item) m_Xref_item = new CrossRefItem(this); - } } + aboutDeleteXref(); } /** @@ -183,15 +185,23 @@ void MasterElement::updateLabel(DiagramContext old_info, DiagramContext new_info * option show power contact is disable, the cross isn't draw. * @return */ -bool MasterElement::aboutDeleteXref() { - if(!m_Xref_item) return true; - if(!linkedElements().isEmpty()) return false; - - if (m_Xref_item -> boundingRect().isNull()) { +void MasterElement::aboutDeleteXref() +{ + if(!m_Xref_item) + return; + + XRefProperties xrp = diagram()->project()->defaultXRefProperties(kindInformations()["type"].toString()); + if (xrp.snapTo() != XRefProperties::Bottom && m_Xref_item) + { delete m_Xref_item; m_Xref_item = nullptr; - return true; + return; + } + + if (m_Xref_item->boundingRect().isNull()) + { + delete m_Xref_item; + m_Xref_item = nullptr; + return; } - - return false; } diff --git a/sources/qetgraphicsitem/masterelement.h b/sources/qetgraphicsitem/masterelement.h index fdafd72d3..640cd3192 100644 --- a/sources/qetgraphicsitem/masterelement.h +++ b/sources/qetgraphicsitem/masterelement.h @@ -43,12 +43,17 @@ class MasterElement : public CustomElement public slots: void updateLabel(DiagramContext old_info, DiagramContext new_info); + + protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; private: - bool aboutDeleteXref (); + void xrefPropertiesChanged(); + void aboutDeleteXref (); private: - CrossRefItem *m_Xref_item; + CrossRefItem *m_Xref_item = nullptr; + bool m_first_scene_change = true; }; #endif // MASTERELEMENT_H diff --git a/sources/qetgraphicsitem/reportelement.cpp b/sources/qetgraphicsitem/reportelement.cpp index d172bf8cc..6517f2a94 100644 --- a/sources/qetgraphicsitem/reportelement.cpp +++ b/sources/qetgraphicsitem/reportelement.cpp @@ -22,6 +22,7 @@ #include "diagram.h" #include "terminal.h" #include "conductor.h" +#include "dynamicelementtextitem.h" ReportElement::ReportElement(const ElementsLocation &location, QString link_type,QGraphicsItem *qgi, int *state) : CustomElement(location, qgi, state), @@ -40,7 +41,7 @@ ReportElement::ReportElement(const ElementsLocation &location, QString link_type if (m_text_field) m_text_field -> setNoEditable(); - link_type == "next_report"? link_type_=NextReport : link_type_=PreviousReport; + link_type == "next_report"? m_link_type=NextReport : m_link_type=PreviousReport; link_type == "next_report"? m_inverse_report=PreviousReport : m_inverse_report=NextReport; //We make these connections, to be always aware about the conductor properties diff --git a/sources/qetgraphicsitem/simpleelement.cpp b/sources/qetgraphicsitem/simpleelement.cpp index 3d49785df..52737fc18 100644 --- a/sources/qetgraphicsitem/simpleelement.cpp +++ b/sources/qetgraphicsitem/simpleelement.cpp @@ -32,7 +32,7 @@ SimpleElement::SimpleElement(const ElementsLocation &location, QGraphicsItem *qg m_comment_item (nullptr), m_location_item (nullptr) { - link_type_ = Simple; + m_link_type = Simple; connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext))); connect(this, &Element::updateLabel, [this]() {this->updateLabel(this->elementInformations(), this->elementInformations());}); } @@ -84,17 +84,17 @@ void SimpleElement::updateLabel(DiagramContext old_info, DiagramContext new_info new_info["label"].toString().isEmpty() ? eti->setVisible(true) : eti -> setVisible(new_info.keyMustShow("label")); } - //Comment and Location of element - QString comment = new_info["comment"].toString(); - bool must_show = new_info.keyMustShow("comment"); - QString location = new_info["location"].toString(); - bool must_show_location = new_info.keyMustShow("location"); +// //Comment and Location of element +// QString comment = new_info["comment"].toString(); +// bool must_show = new_info.keyMustShow("comment"); +// QString location = new_info["location"].toString(); +// bool must_show_location = new_info.keyMustShow("location"); - if ((!(comment.isEmpty() || !must_show) && !m_comment_item)||(!(location.isEmpty() || !must_show_location) && !m_comment_item)) { - m_comment_item = new CommentItem(this); - } - else if (((comment.isEmpty() || !must_show) && m_comment_item) && ((location.isEmpty() || !must_show_location) && m_comment_item)) { - delete m_comment_item; - m_comment_item = nullptr; - } +// if ((!(comment.isEmpty() || !must_show) && !m_comment_item)||(!(location.isEmpty() || !must_show_location) && !m_comment_item)) { +// m_comment_item = new CommentItem(this); +// } +// else if (((comment.isEmpty() || !must_show) && m_comment_item) && ((location.isEmpty() || !must_show_location) && m_comment_item)) { +// delete m_comment_item; +// m_comment_item = nullptr; +// } } diff --git a/sources/qetgraphicsitem/slaveelement.cpp b/sources/qetgraphicsitem/slaveelement.cpp index c1bc053be..788982b4e 100644 --- a/sources/qetgraphicsitem/slaveelement.cpp +++ b/sources/qetgraphicsitem/slaveelement.cpp @@ -20,6 +20,7 @@ #include "qetapp.h" #include "elementtextitem.h" #include "diagram.h" +#include "dynamicelementtextitem.h" /** * @brief SlaveElement::SlaveElement @@ -33,7 +34,8 @@ SlaveElement::SlaveElement(const ElementsLocation &location, QGraphicsItem *qgi, CustomElement(location, qgi, state) { m_xref_item = nullptr; - link_type_ = Slave; + m_link_type = Slave; + connect(this, SIGNAL(updateLabel()), this, SLOT(updateLabel())); } diff --git a/sources/qetgraphicsitem/terminalelement.cpp b/sources/qetgraphicsitem/terminalelement.cpp index ec846519c..da36288df 100644 --- a/sources/qetgraphicsitem/terminalelement.cpp +++ b/sources/qetgraphicsitem/terminalelement.cpp @@ -32,7 +32,7 @@ TerminalElement::TerminalElement(const ElementsLocation &location, QGraphicsItem m_comment_item (nullptr), m_location_item (nullptr) { - link_type_ = Terminale; + m_link_type = Terminale; connect(this, SIGNAL(elementInfoChange(DiagramContext, DiagramContext)), this, SLOT(updateLabel(DiagramContext, DiagramContext))); connect(this, &Element::updateLabel, [this]() {this->updateLabel(this->elementInformations(), this->elementInformations());}); @@ -80,18 +80,18 @@ void TerminalElement::updateLabel(DiagramContext old_info, DiagramContext new_in new_info["label"].toString().isEmpty() ? eti->setVisible(true) : eti -> setVisible(new_info.keyMustShow("label")); } - //Comment and Location of element - QString comment = new_info["comment"].toString(); - bool must_show = new_info.keyMustShow("comment"); - QString location = new_info["location"].toString(); - bool must_show_location = new_info.keyMustShow("location"); +// //Comment and Location of element +// QString comment = new_info["comment"].toString(); +// bool must_show = new_info.keyMustShow("comment"); +// QString location = new_info["location"].toString(); +// bool must_show_location = new_info.keyMustShow("location"); - if ((!(comment.isEmpty() || !must_show) && !m_comment_item)||(!(location.isEmpty() || !must_show_location) && !m_comment_item)) { - m_comment_item = new CommentItem(this); - } - else if (((comment.isEmpty() || !must_show) && m_comment_item) && ((location.isEmpty() || !must_show_location) && m_comment_item)) { - delete m_comment_item; - m_comment_item = nullptr; - } +// if ((!(comment.isEmpty() || !must_show) && !m_comment_item)||(!(location.isEmpty() || !must_show_location) && !m_comment_item)) { +// m_comment_item = new CommentItem(this); +// } +// else if (((comment.isEmpty() || !must_show) && m_comment_item) && ((location.isEmpty() || !must_show_location) && m_comment_item)) { +// delete m_comment_item; +// m_comment_item = nullptr; +// } }