diff --git a/dev_doc/enum_type_of_QGraphicsItem b/dev_doc/enum_type_of_QGraphicsItem index 8777203f8..7ab49a2a0 100644 --- a/dev_doc/enum_type_of_QGraphicsItem +++ b/dev_doc/enum_type_of_QGraphicsItem @@ -22,6 +22,7 @@ part terminal + 1106 part text + 1107 part text field + 1108 part rectangle + 1109 +part dynamic text field + 1110 ###QetGraphicsHandlerItem### QetGraphicsHandlerItem = 1200 diff --git a/sources/editor/elementscene.cpp b/sources/editor/elementscene.cpp index f15ad9805..7af876ab9 100644 --- a/sources/editor/elementscene.cpp +++ b/sources/editor/elementscene.cpp @@ -33,6 +33,7 @@ #include "ui/elementpropertieseditorwidget.h" #include "eseventinterface.h" #include "QetGraphicsItemModeler/qetgraphicshandleritem.h" +#include "partdynamictextfield.h" #include #include @@ -395,33 +396,25 @@ QRectF ElementScene::boundingRectFromXml(const QDomDocument &xml_document) { il sera rempli avec le contenu ajoute a l'element par le fromXml @return true si l'import a reussi, false sinon */ -void ElementScene::fromXml( - const QDomDocument &xml_document, - const QPointF &position, - bool consider_informations, - ElementContent *content_ptr -) { - QString error_message; +void ElementScene::fromXml(const QDomDocument &xml_document, const QPointF &position, bool consider_informations, ElementContent *content_ptr) +{ bool state = true; - // prend en compte les informations de l'element + //Consider the informations of the element if (consider_informations) { - state = applyInformations(xml_document, &error_message); + state = applyInformations(xml_document); } - // parcours des enfants de la definition : parties de l'element - if (state) { - ElementContent loaded_content = loadContent(xml_document, &error_message); - if (position != QPointF()) { - addContentAtPos(loaded_content, position, &error_message); - } else { - addContent(loaded_content, &error_message); - } + if (state) + { + ElementContent loaded_content = loadContent(xml_document); + if (position != QPointF()) + addContentAtPos(loaded_content, position); + else + addContent(loaded_content); - // renvoie le contenu ajoute a l'element - if (content_ptr) { + if (content_ptr) *content_ptr = loaded_content; - } } } @@ -433,9 +426,10 @@ void ElementScene::fromXml( QRectF ElementScene::elementSceneGeometricRect() const{ QRectF esgr; foreach (QGraphicsItem *qgi, items()) { - if (qgi -> type() == ElementPrimitiveDecorator::Type) continue; - if (qgi -> type() == QGraphicsRectItem::Type) continue; - if (qgi -> type() == PartTextField::Type) continue; + if (qgi->type() == ElementPrimitiveDecorator::Type) continue; + if (qgi->type() == QGraphicsRectItem::Type) continue; + if (qgi->type() == PartTextField::Type) continue; + if (qgi->type() == PartDynamicTextField::Type) continue; if (CustomElementPart *cep = dynamic_cast (qgi)) { esgr |= cep -> sceneGeometricRect(); } @@ -869,20 +863,16 @@ QRectF ElementScene::elementContentBoundingRect(const ElementContent &content) c Applique les informations (dimensions, hostpot, orientations, connexions internes, noms et informations complementaires) contenu dans un document XML. @param xml_document Document XML a analyser - @param error_message pointeur vers une QString ; si error_message est - different de 0, un message d'erreur sera stocke dedans si necessaire @return true si la lecture et l'application des informations s'est bien passee, false sinon. */ -bool ElementScene::applyInformations(const QDomDocument &xml_document, QString *error_message) { - // Root must be an element definition +bool ElementScene::applyInformations(const QDomDocument &xml_document) +{ + // Root must be an element definition QDomElement root = xml_document.documentElement(); - if (root.tagName() != "definition" || root.attribute("type") != "element") { - if (error_message) { - *error_message = tr("Ce document XML n'est pas une définition d'élément.", "error message"); - } + + if (root.tagName() != "definition" || root.attribute("type") != "element") return(false); - } //Extract info about element type m_elmt_type = root.attribute("link_type", "simple"); @@ -912,30 +902,44 @@ bool ElementScene::applyInformations(const QDomDocument &xml_document, QString * @param error_message pointeur vers une QString ; si error_message est different de 0, un message d'erreur sera stocke dedans si necessaire */ -ElementContent ElementScene::loadContent(const QDomDocument &xml_document, QString *error_message) { +/** + * @brief ElementScene::loadContent + * @param xml_document : xml dom document to analyze + * @return + */ +/** + * @brief ElementScene::loadContent + * Create and load the content describe in the xml document. + * @param xml_document + * @return the loaded content + */ +ElementContent ElementScene::loadContent(const QDomDocument &xml_document) +{ ElementContent loaded_parts; - // la racine est supposee etre une definition d'element + //The root is supposed to be an element definition QDomElement root = xml_document.documentElement(); - if (root.tagName() != "definition" || root.attribute("type") != "element") { - if (error_message) { - *error_message = tr("Ce document XML n'est pas une définition d'élément.", "error message"); - } - return(loaded_parts); - } - // chargement de la description graphique de l'element - for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) { + if (root.tagName() != "definition" || root.attribute("type") != "element") + return(loaded_parts); + + //Load the graphic description of the element + for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) + { QDomElement elmts = node.toElement(); - if (elmts.isNull()) continue; - if (elmts.tagName() == "description") { - - // = parcours des differentes parties du dessin + if (elmts.isNull()) + continue; + + if (elmts.tagName() == "description") + { int z = 1; - for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) { + for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) + { QDomElement qde = n.toElement(); - if (qde.isNull()) continue; - CustomElementPart *cep; + if (qde.isNull()) + continue; + CustomElementPart *cep = nullptr; + if (qde.tagName() == "line") cep = new PartLine (m_element_editor); else if (qde.tagName() == "rect") cep = new PartRectangle(m_element_editor); else if (qde.tagName() == "ellipse") cep = new PartEllipse (m_element_editor); @@ -945,12 +949,19 @@ ElementContent ElementScene::loadContent(const QDomDocument &xml_document, QStri else if (qde.tagName() == "text") cep = new PartText (m_element_editor); else if (qde.tagName() == "input") cep = new PartTextField(m_element_editor); else if (qde.tagName() == "arc") cep = new PartArc (m_element_editor); + else if (qde.tagName() == "dynamic_text") cep = new PartDynamicTextField (m_element_editor); else continue; - if (QGraphicsItem *qgi = dynamic_cast(cep)) { - if (!qgi -> zValue()) qgi -> setZValue(z++); - loaded_parts << qgi; + + if (QGraphicsItem *qgi = dynamic_cast(cep)) + { + if (!qgi->zValue()) + qgi->setZValue(z++); + + loaded_parts<fromXml(qde); } - cep -> fromXml(qde); + else + delete cep; } } } @@ -961,12 +972,9 @@ ElementContent ElementScene::loadContent(const QDomDocument &xml_document, QStri /** Ajoute le contenu content a cet element @param content contenu ( = liste de parties) a charger - @param error_message pointeur vers une QString ; si error_message est - different de 0, un message d'erreur sera stocke dedans si necessaire @return Le contenu ajoute */ -ElementContent ElementScene::addContent(const ElementContent &content, QString *error_message) { - Q_UNUSED(error_message); +ElementContent ElementScene::addContent(const ElementContent &content) { foreach(QGraphicsItem *part, content) { addPrimitive(part); } @@ -977,12 +985,9 @@ ElementContent ElementScene::addContent(const ElementContent &content, QString * Ajoute le contenu content a cet element @param content contenu ( = liste de parties) a charger @param pos Position du coin superieur gauche du contenu apres avoir ete ajoute - @param error_message pointeur vers une QString ; si error_message est - different de 0, un message d'erreur sera stocke dedans si necessaire @return Le contenu ajoute */ -ElementContent ElementScene::addContentAtPos(const ElementContent &content, const QPointF &pos, QString *error_message) { - Q_UNUSED(error_message); +ElementContent ElementScene::addContentAtPos(const ElementContent &content, const QPointF &pos) { // calcule le boundingRect du contenu a ajouter QRectF bounding_rect = elementContentBoundingRect(content); diff --git a/sources/editor/elementscene.h b/sources/editor/elementscene.h index 2d15745c1..184b8a508 100644 --- a/sources/editor/elementscene.h +++ b/sources/editor/elementscene.h @@ -141,10 +141,10 @@ class ElementScene : public QGraphicsScene private: QRectF elementContentBoundingRect(const ElementContent &) const; - bool applyInformations(const QDomDocument &, QString * = nullptr); - ElementContent loadContent(const QDomDocument &, QString * = nullptr); - ElementContent addContent(const ElementContent &, QString * = nullptr); - ElementContent addContentAtPos(const ElementContent &, const QPointF &, QString * = nullptr); + bool applyInformations(const QDomDocument &); + ElementContent loadContent(const QDomDocument &); + ElementContent addContent(const ElementContent &); + ElementContent addContentAtPos(const ElementContent &, const QPointF &); void addPrimitive(QGraphicsItem *); void initPasteArea(); static bool zValueLessThan(QGraphicsItem *, QGraphicsItem *); diff --git a/sources/editor/esevent/eseventadddynamictextfield.cpp b/sources/editor/esevent/eseventadddynamictextfield.cpp new file mode 100644 index 000000000..8d5242325 --- /dev/null +++ b/sources/editor/esevent/eseventadddynamictextfield.cpp @@ -0,0 +1,82 @@ +/* + Copyright 2006-2017 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 . +*/ +#include "eseventadddynamictextfield.h" +#include "elementscene.h" +#include "editorcommands.h" +#include "partdynamictextfield.h" + +#include + +/** + * @brief ESEventAddDynamicTextField::ESEventAddDynamicTextField + * @param scene + */ +ESEventAddDynamicTextField::ESEventAddDynamicTextField(ElementScene *scene) : + ESEventInterface(scene) +{ + m_text = new PartDynamicTextField(m_editor); + m_scene->addItem(m_text); + m_running = true; +} + +/** + * @brief ESEventAddDynamicTextField::~ESEventAddDynamicTextField + */ +ESEventAddDynamicTextField::~ESEventAddDynamicTextField() { + delete m_text; +} + +/** + * @brief ESEventAddDynamicTextField::mouseMoveEvent + * @param event + * @return + */ +bool ESEventAddDynamicTextField::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + QPointF pos = m_scene->snapToGrid(event->scenePos()); + updateHelpCross(pos); + m_text->setPos(pos); + return true; +} + +/** + * @brief ESEventAddDynamicTextField::mouseReleaseEvent + * @param event + * @return + */ +bool ESEventAddDynamicTextField::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + { + m_scene->undoStack().push(new AddPartCommand(QObject::tr("Champ texte dynamique"), m_scene, m_text)); + + //Set new text + m_text = new PartDynamicTextField(m_editor); + m_scene->addItem(m_text); + m_text->setPos(m_scene->snapToGrid(event->scenePos())); + + return true; + } + else if (event->button() == Qt::RightButton) + { + m_running = false; + return true; + } + + return false; +} diff --git a/sources/editor/esevent/eseventadddynamictextfield.h b/sources/editor/esevent/eseventadddynamictextfield.h new file mode 100644 index 000000000..880e4b1f6 --- /dev/null +++ b/sources/editor/esevent/eseventadddynamictextfield.h @@ -0,0 +1,44 @@ +/* + Copyright 2006-2017 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 . +*/ +#ifndef ESEVENTADDDYNAMICTEXTFIELD_H +#define ESEVENTADDDYNAMICTEXTFIELD_H + +#include "eseventinterface.h" + +class ElementScene; +class PartDynamicTextField; +class QGraphicsSceneMouseEvent; + +/** + * @brief The ESEventAddDynamicTextField class + * This ESEvent manage creation of dynamic text field in an ElementScene + */ +class ESEventAddDynamicTextField : public ESEventInterface +{ + public: + ESEventAddDynamicTextField(ElementScene *scene); + ~ESEventAddDynamicTextField() override; + + bool mouseMoveEvent (QGraphicsSceneMouseEvent *event) override; + bool mouseReleaseEvent (QGraphicsSceneMouseEvent *event) override; + + private: + PartDynamicTextField *m_text; +}; + +#endif // ESEVENTADDDYNAMICTEXTFIELD_H diff --git a/sources/editor/graphicspart/partdynamictextfield.cpp b/sources/editor/graphicspart/partdynamictextfield.cpp new file mode 100644 index 000000000..1ec9018fe --- /dev/null +++ b/sources/editor/graphicspart/partdynamictextfield.cpp @@ -0,0 +1,369 @@ +/* + Copyright 2006-2017 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 . +*/ +#include "partdynamictextfield.h" +#include "QPropertyUndoCommand/qpropertyundocommand.h" +#include "qetapp.h" +#include "elementscene.h" + +#include +#include +#include + +/** + * @brief PartDynamicTextField::PartDynamicTextField + * @param editor + * @param parent + */ +PartDynamicTextField::PartDynamicTextField(QETElementEditor *editor, QGraphicsItem *parent) : + QGraphicsTextItem(parent), + CustomElementPart(editor), + m_uuid(QUuid::createUuid()) +{ + setFont(QETApp::diagramTextsFont(9)); + setText("_"); + setTextFrom(DynamicElementTextItem::UserText); + setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable); + +} + +QString PartDynamicTextField::name() const +{ + return tr("Champ de texte dynamique", "element part name"); +} + +QString PartDynamicTextField::xmlName() const +{ + return QString("dynamic_text"); +} + +/** + * @brief PartDynamicTextField::startUserTransformation + * @param initial_selection_rect + * Start the user-induced transformation, provided this primitive is contained + * within the initial_selection_rect bounding rectangle. + */ +void PartDynamicTextField::startUserTransformation(const QRectF &initial_selection_rect) +{ + Q_UNUSED(initial_selection_rect) + m_saved_point = pos(); // scene coordinates, no need to mapFromScene() +} + +/** + * @brief PartDynamicTextField::handleUserTransformation + * @param initial_selection_rect + * @param new_selection_rect + * Handle the user-induced transformation from initial_selection_rect to new_selection_rect + */ +void PartDynamicTextField::handleUserTransformation(const QRectF &initial_selection_rect, const QRectF &new_selection_rect) +{ + QPointF new_pos = mapPoints(initial_selection_rect, new_selection_rect, QList() << m_saved_point).first(); + setPos(new_pos); +} + +/** + * @brief PartDynamicTextField::toXml + * @param document + * @return + */ +const QDomElement PartDynamicTextField::toXml(QDomDocument &dom_doc) const +{ + QDomElement root_element = dom_doc.createElement(xmlName()); + + root_element.setAttribute("x", QString::number(pos().x())); + root_element.setAttribute("y", QString::number(pos().y())); + root_element.setAttribute("z", QString::number(zValue())); + root_element.setAttribute("rotation", QString::number(QET::correctAngle(rotation()))); + root_element.setAttribute("font_size", font().pointSize()); + root_element.setAttribute("uuid", m_uuid.toString()); + + + QMetaEnum me = DynamicElementTextItem::textFromMetaEnum(); + root_element.setAttribute("text_from", me.valueToKey(m_text_from)); + + 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"); + dom_info_name.appendChild(dom_doc.createTextNode(m_info_name)); + root_element.appendChild(dom_info_name); + } + + //Composite text + if(!m_composite_text.isEmpty()) + { + QDomElement dom_comp_text = dom_doc.createElement("composite_text"); + dom_comp_text.appendChild(dom_doc.createTextNode(m_composite_text)); + root_element.appendChild(dom_comp_text); + } + + //tagg + if (!m_tagg.isEmpty()) + { + QDomElement dom_tagg = dom_doc.createElement("tagg"); + dom_tagg.appendChild(dom_doc.createTextNode(m_tagg)); + root_element.appendChild(dom_tagg); + } + + //Color + if(color() != QColor(Qt::black)) + { + QDomElement dom_color = dom_doc.createElement("color"); + dom_color.appendChild(dom_doc.createTextNode(color().name())); + root_element.appendChild(dom_color); + } + + return root_element; +} + +/** + * @brief PartDynamicTextField::fromXml + * @param element + */ +void PartDynamicTextField::fromXml(const QDomElement &dom_elmt) +{ + if (dom_elmt.tagName() != xmlName()) { + qDebug() << "PartDynamicTextField::fromXml : Wrong tagg name"; + return; + } + + 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()); + setFont(QETApp::diagramTextsFont(dom_elmt.attribute("font_size", QString::number(9)).toInt())); + m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString())); + + QMetaEnum me = DynamicElementTextItem::textFromMetaEnum(); + m_text_from = 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); + } + + //Info name + QDomElement dom_info_name = dom_elmt.firstChildElement("info_name"); + if(!dom_info_name.isNull()) + m_info_name = 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(); + + //tagg + QDomElement dom_tagg = dom_elmt.firstChildElement("tagg"); + if (!dom_tagg.isNull()) + m_tagg = dom_tagg.text(); + + //Color + QDomElement dom_color = dom_elmt.firstChildElement("color"); + if(!dom_color.isNull()) + setColor(QColor(dom_color.text())); +} + +/** + * @brief PartDynamicTextField::textFrom + * @return what the final text is created from. + */ +DynamicElementTextItem::TextFrom PartDynamicTextField::textFrom() const { + return m_text_from; +} + +/** + * @brief PartDynamicTextField::setTextFrom + * Set the final text is created from. + * @param text_from + */ +void PartDynamicTextField::setTextFrom(DynamicElementTextItem::TextFrom text_from) +{ + m_text_from = text_from; + emit textFromChanged(m_text_from); +} + +/** + * @brief PartDynamicTextField::tagg + * @return the tagg of this text + */ +QString PartDynamicTextField::tagg() const { + return m_tagg; +} + +/** + * @brief PartDynamicTextField::setTagg + * set the taggof this text + * @param tagg + */ +void PartDynamicTextField::setTagg(const QString &tagg) +{ + m_tagg = tagg; + emit taggChanged(m_tagg); +} + +/** + * @brief PartDynamicTextField::text + * @return the text of this text + */ +QString PartDynamicTextField::text() const { + return m_text; +} + +/** + * @brief PartDynamicTextField::setText + * Set the text of this text + * @param text + */ +void PartDynamicTextField::setText(const QString &text) +{ + m_text = text; + setPlainText(m_text); + emit textChanged(m_text); +} + +void PartDynamicTextField::setInfoName(const QString &info_name) +{ + m_info_name = info_name; + emit infoNameChanged(m_info_name); +} + +/** + * @brief PartDynamicTextField::infoName + * @return the info name of this text + */ +QString PartDynamicTextField::infoName() const{ + return m_info_name; +} + +/** + * @brief PartDynamicTextField::setCompositeText + * Set the composite text of this text item to @text + * @param text + */ +void PartDynamicTextField::setCompositeText(const QString &text) +{ + m_composite_text = text; + emit compositeTextChanged(m_composite_text); +} + +/** + * @brief PartDynamicTextField::compositeText + * @return the composite text of this text + */ +QString PartDynamicTextField::compositeText() const{ + return m_composite_text; +} + +/** + * @brief PartDynamicTextField::setColor + * @param color set text color to color + */ +void PartDynamicTextField::setColor(QColor color) +{ + setDefaultTextColor(color); + emit colorChanged(color); +} + +/** + * @brief PartDynamicTextField::color + * @return The color of this text + */ +QColor PartDynamicTextField::color() const { + return defaultTextColor(); +} + +/** + * @brief PartDynamicTextField::setFontSize + * @param s + */ +void PartDynamicTextField::setFontSize(int s) { + setFont(QETApp::diagramTextsFont(s)); + emit fontSizeChanged(s); +} + +int PartDynamicTextField::fontSize() const { + return font().pointSize(); +} + +/** + * @brief PartDynamicTextField::mouseMoveEvent + * @param event + */ +void PartDynamicTextField::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->buttons() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable)) + { + QPointF pos = event->scenePos() + (m_origine_pos - event->buttonDownScenePos(Qt::LeftButton)); + event->modifiers() == Qt::ControlModifier ? setPos(pos) : setPos(elementScene()->snapToGrid(pos)); + } + else + QGraphicsObject::mouseMoveEvent(event); +} + +/** + * @brief PartDynamicTextField::mousePressEvent + * @param event + */ +void PartDynamicTextField::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if(event->button() == Qt::LeftButton) + m_origine_pos = this->pos(); + + QGraphicsObject::mousePressEvent(event); +} + +/** + * @brief PartDynamicTextField::mouseReleaseEvent + * @param event + */ +void PartDynamicTextField::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if((event->button() & Qt::LeftButton) && (flags() & QGraphicsItem::ItemIsMovable) && m_origine_pos != pos()) + { + QPropertyUndoCommand *undo = new QPropertyUndoCommand(this, "pos", QVariant(m_origine_pos), QVariant(pos())); + undo->setText(tr("Déplacer un champ texte")); + undo->enableAnimation(); + elementScene()->undoStack().push(undo); + } + + QGraphicsObject::mouseReleaseEvent(event); +} + +/** + * @brief PartDynamicTextField::itemChange + * @param change + * @param value + * @return + */ +QVariant PartDynamicTextField::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) +{ + if (change == QGraphicsItem::ItemPositionHasChanged || change == QGraphicsItem::ItemSceneHasChanged) { + updateCurrentPartEditor(); + } else if (change == QGraphicsItem::ItemSelectedHasChanged) { + if (value.toBool() == true) { + updateCurrentPartEditor(); + } + } + return(QGraphicsTextItem::itemChange(change, value)); +} diff --git a/sources/editor/graphicspart/partdynamictextfield.h b/sources/editor/graphicspart/partdynamictextfield.h new file mode 100644 index 000000000..367f13998 --- /dev/null +++ b/sources/editor/graphicspart/partdynamictextfield.h @@ -0,0 +1,108 @@ +/* + Copyright 2006-2017 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 . +*/ +#ifndef PARTDYNAMICTEXTFIELD_H +#define PARTDYNAMICTEXTFIELD_H + +#include "customelementpart.h" +#include "QGraphicsTextItem" +#include "dynamicelementtextitem.h" + +/** + * @brief The PartDynamicTextField class + * This class represents an editable dynamic text field which may be used to compose the + * drawing of an electrical element within the element editor. + * The field will remain editable once the element is added onto + * a diagram + */ +class PartDynamicTextField : public QGraphicsTextItem, public CustomElementPart +{ + Q_OBJECT + + Q_PROPERTY(QString tagg READ tagg WRITE setTagg NOTIFY taggChanged) + Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) + Q_PROPERTY(DynamicElementTextItem::TextFrom textFrom READ textFrom WRITE setTextFrom NOTIFY textFromChanged) + Q_PROPERTY(QString infoName READ infoName WRITE setInfoName NOTIFY infoNameChanged) + Q_PROPERTY(QString compositeText READ compositeText WRITE setCompositeText NOTIFY compositeTextChanged) + Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(int fontSize READ fontSize WRITE setFontSize NOTIFY fontSizeChanged) + + public: + ///PROPERTY + void setProperty(const char *name, const QVariant &value) override {QGraphicsTextItem::setProperty(name, value);} + QVariant property(const char *name) const override {return QGraphicsTextItem::property(name);} + + signals: + void taggChanged(QString tagg); + void textChanged(QString text); + void textFromChanged(DynamicElementTextItem::TextFrom text_from); + void infoNameChanged(QString info); + void compositeTextChanged(QString text); + void colorChanged(QColor color); + void fontSizeChanged(int size); + + public: + PartDynamicTextField(QETElementEditor *editor, QGraphicsItem *parent = nullptr); + + enum {Type = UserType + 1110}; + int type() const override {return Type;} + + QString name() const override; + QString xmlName() const override; + bool isUseless() const override {return false;} + QRectF sceneGeometricRect() const override {return sceneBoundingRect();} + 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; + + DynamicElementTextItem::TextFrom textFrom() const; + void setTextFrom (DynamicElementTextItem::TextFrom text_from); + QString tagg() const; + void setTagg(const QString &tagg); + QString text() const; + void setText(const QString &text); + void setInfoName(const QString &info_name); + QString infoName() const; + void setCompositeText(const QString &text); + QString compositeText() const; + void setColor(QColor color); + QColor color() const; + void setFontSize(int s); + int fontSize()const; + + protected: + void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; + void mousePressEvent(QGraphicsSceneMouseEvent *event) override; + void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; + + private: + QPointF m_origine_pos, + m_saved_point; + QString m_tagg, + m_text, + m_info_name, + m_composite_text; + + DynamicElementTextItem::TextFrom m_text_from = DynamicElementTextItem::UserText; + QUuid m_uuid; + +}; + +#endif // PARTDYNAMICTEXTFIELD_H diff --git a/sources/editor/qetelementeditor.cpp b/sources/editor/qetelementeditor.cpp index 39372d728..e818fa3b2 100644 --- a/sources/editor/qetelementeditor.cpp +++ b/sources/editor/qetelementeditor.cpp @@ -40,6 +40,7 @@ #include "partterminal.h" #include "parttextfield.h" #include "styleeditor.h" +#include "dynamictextfieldeditor.h" #include "eseventaddline.h" #include "eseventaddrect.h" @@ -49,6 +50,7 @@ #include "eseventaddtext.h" #include "eseventaddtextfield.h" #include "eseventaddterminal.h" +#include "eseventadddynamictextfield.h" #include #include @@ -101,8 +103,8 @@ QETElementEditor::~QETElementEditor() { clearToolsDock(); // supprime les editeurs de primitives - qDeleteAll(editors_.begin(), editors_.end()); - editors_.clear(); + qDeleteAll(m_editors.begin(), m_editors.end()); + m_editors.clear(); } /** @@ -202,10 +204,10 @@ void QETElementEditor::setupActions() { connect(selectall, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_selectAll())); connect(deselectall, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_deselectAll())); connect(inv_select, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_invertSelection())); - connect(cut, SIGNAL(triggered()), ce_view, SLOT(cut())); - connect(copy, SIGNAL(triggered()), ce_view, SLOT(copy())); - connect(paste, SIGNAL(triggered()), ce_view, SLOT(paste())); - connect(paste_in_area, SIGNAL(triggered()), ce_view, SLOT(pasteInArea())); + connect(cut, SIGNAL(triggered()), m_view, SLOT(cut())); + connect(copy, SIGNAL(triggered()), m_view, SLOT(copy())); + connect(paste, SIGNAL(triggered()), m_view, SLOT(paste())); + connect(paste_in_area, SIGNAL(triggered()), m_view, SLOT(pasteInArea())); connect(paste_from_file, SIGNAL(triggered()), this, SLOT(pasteFromFile())); connect(paste_from_elmt, SIGNAL(triggered()), this, SLOT(pasteFromElement())); connect(edit_delete, SIGNAL(triggered()), m_elmt_scene, SLOT(slot_delete())); @@ -255,10 +257,10 @@ void QETElementEditor::setupActions() { zoom_fit -> setShortcut(QKeySequence(tr("Ctrl+9"))); zoom_reset -> setShortcut(QKeySequence(tr("Ctrl+0"))); - connect(zoom_in, SIGNAL(triggered()), ce_view, SLOT(zoomIn() )); - connect(zoom_out, SIGNAL(triggered()), ce_view, SLOT(zoomOut() )); - connect(zoom_fit, SIGNAL(triggered()), ce_view, SLOT(zoomFit() )); - connect(zoom_reset, SIGNAL(triggered()), ce_view, SLOT(zoomReset() )); + connect(zoom_in, SIGNAL(triggered()), m_view, SLOT(zoomIn() )); + connect(zoom_out, SIGNAL(triggered()), m_view, SLOT(zoomOut() )); + connect(zoom_fit, SIGNAL(triggered()), m_view, SLOT(zoomFit() )); + connect(zoom_reset, SIGNAL(triggered()), m_view, SLOT(zoomReset() )); /* @@ -275,6 +277,7 @@ void QETElementEditor::setupActions() { QAction *add_arc = new QAction(QET::Icons::PartArc, tr("Ajouter un arc de cercle"), parts); QAction *add_terminal = new QAction(QET::Icons::Terminal, tr("Ajouter une borne"), parts); QAction *add_textfield = new QAction(QET::Icons::PartTextField, tr("Ajouter un champ de texte"), parts); + QAction *add_dynamic_text_field = new QAction(QET::Icons::PartTextField, tr("Ajouter un champ texte dynamique"), parts); foreach (QAction *action, parts -> actions()) action -> setCheckable(true); @@ -286,6 +289,7 @@ void QETElementEditor::setupActions() { connect(add_arc, SIGNAL(triggered()), this, SLOT(addArc() )); connect(add_terminal, SIGNAL(triggered()), this, SLOT(addTerminal() )); connect(add_textfield, SIGNAL(triggered()), this, SLOT(addTextField() )); + connect(add_dynamic_text_field, &QAction::triggered, this, &QETElementEditor::addDynamicTextField); parts_toolbar = addToolBar(tr("Parties", "toolbar title")); @@ -440,7 +444,7 @@ void QETElementEditor::slot_updateMenus() { inv_select -> setEnabled(!read_only); paste_from_file -> setEnabled(!read_only); paste_from_elmt -> setEnabled(!read_only); - parts_list -> setEnabled(!read_only); + m_parts_list -> setEnabled(!read_only); // Action enabled if primitive selected deselectall -> setEnabled(selected_items); @@ -479,69 +483,70 @@ void QETElementEditor::slot_updateTitle() { void QETElementEditor::setupInterface() { // editeur m_elmt_scene = new ElementScene(this, this); - ce_view = new ElementView(m_elmt_scene, this); + m_view = new ElementView(m_elmt_scene, this); slot_setRubberBandToView(); - setCentralWidget(ce_view); + setCentralWidget(m_view); // widget par defaut dans le QDockWidget - default_informations = new QLabel(); + m_default_informations = new QLabel(); // ScrollArea pour accueillir un widget d'edition (change a la volee) - tools_dock_scroll_area_ = new QScrollArea(); - tools_dock_scroll_area_ -> setFrameStyle(QFrame::NoFrame); - tools_dock_scroll_area_ -> setAlignment(Qt::AlignHCenter|Qt::AlignTop); + m_tools_dock_scroll_area = new QScrollArea(); + m_tools_dock_scroll_area -> setFrameStyle(QFrame::NoFrame); + m_tools_dock_scroll_area -> setAlignment(Qt::AlignHCenter|Qt::AlignTop); // Pile de widgets pour accueillir les deux widgets precedents - tools_dock_stack_ = new QStackedWidget(); - tools_dock_stack_ -> insertWidget(0, default_informations); - tools_dock_stack_ -> insertWidget(1, tools_dock_scroll_area_); + m_tools_dock_stack = new QStackedWidget(); + m_tools_dock_stack -> insertWidget(0, m_default_informations); + m_tools_dock_stack -> insertWidget(1, m_tools_dock_scroll_area); // widgets d'editions pour les parties - editors_["arc"] = new ArcEditor(this); - editors_["ellipse"] = new EllipseEditor(this); - editors_["line"] = new LineEditor(this); - editors_["polygon"] = new PolygonEditor(this); - editors_["rect"] = new RectangleEditor(this); - editors_["terminal"] = new TerminalEditor(this); - editors_["text"] = new TextEditor(this); - editors_["input"] = new TextFieldEditor(this); - editors_["style"] = new StyleEditor(this); + m_editors["arc"] = new ArcEditor(this); + m_editors["ellipse"] = new EllipseEditor(this); + m_editors["line"] = new LineEditor(this); + m_editors["polygon"] = new PolygonEditor(this); + m_editors["rect"] = new RectangleEditor(this); + m_editors["terminal"] = new TerminalEditor(this); + m_editors["text"] = new TextEditor(this); + m_editors["input"] = new TextFieldEditor(this); + m_editors["style"] = new StyleEditor(this); + m_editors["dynamic_text"] = new DynamicTextFieldEditor(this); // panel sur le cote pour editer les parties - tools_dock = new QDockWidget(tr("Informations", "dock title"), this); - tools_dock -> setObjectName("informations"); - tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); - tools_dock -> setMinimumWidth(380); - addDockWidget(Qt::RightDockWidgetArea, tools_dock); - tools_dock -> setWidget(tools_dock_stack_); + m_tools_dock = new QDockWidget(tr("Informations", "dock title"), this); + m_tools_dock -> setObjectName("informations"); + m_tools_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_tools_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); + //m_tools_dock -> setMinimumWidth(380); + addDockWidget(Qt::RightDockWidgetArea, m_tools_dock); + m_tools_dock -> setWidget(m_tools_dock_stack); // panel sur le cote pour les annulations - undo_dock = new QDockWidget(tr("Annulations", "dock title"), this); - undo_dock -> setObjectName("undo"); - undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); - undo_dock -> setMinimumWidth(290); - addDockWidget(Qt::RightDockWidgetArea, undo_dock); + m_undo_dock = new QDockWidget(tr("Annulations", "dock title"), this); + m_undo_dock -> setObjectName("undo"); + m_undo_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_undo_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); + m_undo_dock -> setMinimumWidth(290); + addDockWidget(Qt::RightDockWidgetArea, m_undo_dock); QUndoView* undo_view = new QUndoView(&(m_elmt_scene -> undoStack()), this); undo_view -> setEmptyLabel(tr("Aucune modification")); - undo_dock -> setWidget(undo_view); + m_undo_dock -> setWidget(undo_view); // panel sur le cote pour la liste des parties - parts_list = new QListWidget(this); - parts_list -> setSelectionMode(QAbstractItemView::ExtendedSelection); + m_parts_list = new QListWidget(this); + m_parts_list -> setSelectionMode(QAbstractItemView::ExtendedSelection); connect(m_elmt_scene, SIGNAL(partsAdded()), this, SLOT(slot_createPartsList())); connect(m_elmt_scene, SIGNAL(partsRemoved()), this, SLOT(slot_createPartsList())); connect(m_elmt_scene, SIGNAL(partsZValueChanged()), this, SLOT(slot_createPartsList())); connect(m_elmt_scene, SIGNAL(selectionChanged()), this, SLOT(slot_updatePartsList())); - connect(parts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slot_updateSelectionFromPartsList())); - parts_dock = new QDockWidget(tr("Parties", "dock title"), this); - parts_dock -> setObjectName("parts_list"); - parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); - parts_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); - parts_dock -> setMinimumWidth(290); - tabifyDockWidget(undo_dock, parts_dock); - parts_dock -> setWidget(parts_list); + connect(m_parts_list, SIGNAL(itemSelectionChanged()), this, SLOT(slot_updateSelectionFromPartsList())); + m_parts_dock = new QDockWidget(tr("Parties", "dock title"), this); + m_parts_dock -> setObjectName("parts_list"); + m_parts_dock -> setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + m_parts_dock -> setFeatures(QDockWidget::AllDockWidgetFeatures); + m_parts_dock -> setMinimumWidth(290); + tabifyDockWidget(m_undo_dock, m_parts_dock); + m_parts_dock -> setWidget(m_parts_list); slot_updateInformations(); slot_createPartsList(); @@ -555,14 +560,14 @@ void QETElementEditor::setupInterface() { elements selectionnes et il est possible d'utiliser un rectangle de selection. */ void QETElementEditor::slot_setRubberBandToView() { - ce_view -> setDragMode(QGraphicsView::RubberBandDrag); + m_view -> setDragMode(QGraphicsView::RubberBandDrag); } /** Passe l'editeur d'element en mode immobile (utilise pour la lecture seule) */ void QETElementEditor::slot_setNoDragToView() { - ce_view -> setDragMode(QGraphicsView::NoDrag); + m_view -> setDragMode(QGraphicsView::NoDrag); } /** @@ -570,7 +575,8 @@ void QETElementEditor::slot_setNoDragToView() { Si plusieurs primitives sont selectionnees, seule leur quantite est affichee. Sinon, un widget d'edition approprie est mis en place. */ -void QETElementEditor::slot_updateInformations() { +void QETElementEditor::slot_updateInformations() +{ QList selected_qgis = m_elmt_scene -> selectedItems(); QList cep_list; bool style_editable = false; @@ -591,7 +597,21 @@ void QETElementEditor::slot_updateInformations() { } - clearToolsDock(); + if(selected_qgis.size() == 1) + { + QGraphicsItem *qgi = selected_qgis.first(); + if (CustomElementPart *selection = dynamic_cast(qgi)) + { + if (QWidget *widget = m_tools_dock_scroll_area->widget()) + { + if (ElementItemEditor *editor = dynamic_cast(widget)) + { + if(editor->currentPart() == selection) + return; + } + } + } + } //There's one selected item if (selected_qgis.size() == 1) @@ -599,15 +619,22 @@ void QETElementEditor::slot_updateInformations() { QGraphicsItem *qgi = selected_qgis.first(); if (CustomElementPart *selection = dynamic_cast(qgi)) { - // on en ajoute le widget d'edition + //The current editor already edit the selected part + if (QWidget *widget = m_tools_dock_scroll_area->widget()) + if (ElementItemEditor *editor = dynamic_cast(widget)) + if(editor->currentPart() == selection) + return; + + clearToolsDock(); + //We add the editor widget QString selection_xml_name = selection -> xmlName(); - ElementItemEditor *selection_editor = editors_[selection_xml_name]; + ElementItemEditor *selection_editor = m_editors[selection_xml_name]; if (selection_editor) { - if (selection_editor -> setPart(selection)) + if (selection_editor->setPart(selection)) { - tools_dock_scroll_area_ -> setWidget(selection_editor); - tools_dock_stack_ -> setCurrentIndex(1); + m_tools_dock_scroll_area -> setWidget(selection_editor); + m_tools_dock_stack -> setCurrentIndex(1); } else { @@ -619,13 +646,14 @@ void QETElementEditor::slot_updateInformations() { //There's several parts selecteds and all can be edited by style editor. else if (style_editable) { - ElementItemEditor *selection_editor = editors_["style"]; + clearToolsDock(); + ElementItemEditor *selection_editor = m_editors["style"]; if (selection_editor) { if (selection_editor -> setParts(cep_list)) { - tools_dock_scroll_area_ -> setWidget(selection_editor); - tools_dock_stack_ -> setCurrentIndex(1); + m_tools_dock_scroll_area -> setWidget(selection_editor); + m_tools_dock_stack -> setCurrentIndex(1); } else { @@ -636,26 +664,15 @@ void QETElementEditor::slot_updateInformations() { //Else we only display the number of selected items else { - default_informations -> setText(tr("%n partie(s) sélectionnée(s).", + clearToolsDock(); + m_default_informations -> setText(tr("%n partie(s) sélectionnée(s).", "", selected_qgis.size())); - default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); - tools_dock_stack_ -> setCurrentIndex(0); + m_default_informations -> setAlignment(Qt::AlignHCenter | Qt::AlignTop); + m_tools_dock_stack -> setCurrentIndex(0); } } -/** - Affiche le code XML correspondant a l'element dans son etat actuel dans - une boite de dialogue. -*/ -void QETElementEditor::xmlPreview() { - QET::QetMessageBox::information( - this, - "Export XML", - m_elmt_scene -> toXml().toString(4) - ); -} - /** * @brief QETElementEditor::checkElement * Do several check about element. @@ -919,7 +936,7 @@ void QETElementEditor::setReadOnly(bool ro) { read_only = ro; // active / desactive les interactions avec la scene - ce_view -> setInteractive(!ro); + m_view -> setInteractive(!ro); slot_updateMenus(); } @@ -995,6 +1012,14 @@ void QETElementEditor::addTerminal() { m_elmt_scene -> setEventInterface(new ESEventAddTerminal(m_elmt_scene)); } +/** + * @brief QETElementEditor::addDynamicTextField + * Set dynamic text field creation interface to scene + */ +void QETElementEditor::addDynamicTextField() { + m_elmt_scene->setEventInterface(new ESEventAddDynamicTextField(m_elmt_scene)); +} + /** * @brief QETElementEditor::UncheckAddPrimitive * Uncheck all action related to primitive @@ -1266,7 +1291,7 @@ bool QETElementEditor::canClose() { @return le widget enleve, ou 0 s'il n'y avait pas de widget a enlever */ QWidget *QETElementEditor::clearToolsDock() { - if (QWidget *previous_widget = tools_dock_scroll_area_ -> takeWidget()) { + if (QWidget *previous_widget = m_tools_dock_scroll_area -> takeWidget()) { previous_widget -> setParent(nullptr); previous_widget -> hide(); return(previous_widget); @@ -1293,7 +1318,7 @@ void QETElementEditor::copyAndPasteXml(const QDomDocument &xml_document) { } clipboard -> setText(clipboard_content); - ce_view -> pasteInArea(); + m_view -> pasteInArea(); } /** @@ -1314,15 +1339,15 @@ void QETElementEditor::closeEvent(QCloseEvent *qce) { */ void QETElementEditor::firstActivation(QEvent *event) { Q_UNUSED(event) - QTimer::singleShot(250, ce_view, SLOT(zoomFit())); + QTimer::singleShot(250, m_view, SLOT(zoomFit())); } /** Remplit la liste des parties */ void QETElementEditor::slot_createPartsList() { - parts_list -> blockSignals(true); - parts_list -> clear(); + m_parts_list -> blockSignals(true); + m_parts_list -> clear(); QList qgis = m_elmt_scene -> zItems(); // on ne construit plus la liste a partir de 200 primitives @@ -1337,14 +1362,14 @@ void QETElementEditor::slot_createPartsList() { QVariant v; v.setValue(qgi); qlwi -> setData(42, v); - parts_list -> addItem(qlwi); + m_parts_list -> addItem(qlwi); qlwi -> setSelected(qgi -> isSelected()); } } } else { - parts_list -> addItem(new QListWidgetItem(tr("Trop de primitives, liste non générée."))); + m_parts_list -> addItem(new QListWidgetItem(tr("Trop de primitives, liste non générée."))); } - parts_list -> blockSignals(false); + m_parts_list -> blockSignals(false); } /** @@ -1352,19 +1377,19 @@ void QETElementEditor::slot_createPartsList() { */ void QETElementEditor::slot_updatePartsList() { int items_count = m_elmt_scene -> items().count(); - if (parts_list -> count() != items_count) { + if (m_parts_list -> count() != items_count) { slot_createPartsList(); } else if (items_count <= QET_MAX_PARTS_IN_ELEMENT_EDITOR_LIST) { - parts_list -> blockSignals(true); + m_parts_list -> blockSignals(true); int i = 0; QList items = m_elmt_scene -> zItems(); for (int j = items.count() - 1 ; j >= 0 ; -- j) { QGraphicsItem *qgi = items[j]; - QListWidgetItem *qlwi = parts_list -> item(i); + QListWidgetItem *qlwi = m_parts_list -> item(i); if (qlwi) qlwi -> setSelected(qgi -> isSelected()); ++ i; } - parts_list -> blockSignals(false); + m_parts_list -> blockSignals(false); } } @@ -1374,15 +1399,15 @@ void QETElementEditor::slot_updatePartsList() { */ void QETElementEditor::slot_updateSelectionFromPartsList() { m_elmt_scene -> blockSignals(true); - parts_list -> blockSignals(true); - for (int i = 0 ; i < parts_list -> count() ; ++ i) { - QListWidgetItem *qlwi = parts_list -> item(i); + m_parts_list -> blockSignals(true); + for (int i = 0 ; i < m_parts_list -> count() ; ++ i) { + QListWidgetItem *qlwi = m_parts_list -> item(i); QGraphicsItem *qgi = qlwi -> data(42).value(); if (qgi) { qgi -> setSelected(qlwi -> isSelected()); } } - parts_list -> blockSignals(false); + m_parts_list -> blockSignals(false); m_elmt_scene -> blockSignals(false); slot_updateInformations(); slot_updateMenus(); @@ -1570,10 +1595,10 @@ void QETElementEditor::pasteFromElement() */ void QETElementEditor::updateCurrentPartEditor() { // si aucun widget d'edition n'est affiche, on ne fait rien - if (!tools_dock_stack_ -> currentIndex()) return; + if (!m_tools_dock_stack -> currentIndex()) return; // s'il y a un widget d'edition affiche, on le met a jour - if (ElementItemEditor *current_editor = dynamic_cast(tools_dock_scroll_area_ -> widget())) { + if (ElementItemEditor *current_editor = dynamic_cast(m_tools_dock_scroll_area -> widget())) { current_editor -> updateForm(); } } diff --git a/sources/editor/qetelementeditor.h b/sources/editor/qetelementeditor.h index a3da9cc68..426b39b38 100644 --- a/sources/editor/qetelementeditor.h +++ b/sources/editor/qetelementeditor.h @@ -51,25 +51,25 @@ class QETElementEditor : public QETMainWindow { /// menus QMenu *file_menu, *edit_menu, *paste_from_menu, *display_menu, *tools_menu; /// view widget for the editing scene - ElementView *ce_view; + ElementView *m_view; /// editing scene ElementScene *m_elmt_scene; /// container for widgets dedicated to primitive edition - QDockWidget *tools_dock; + QDockWidget *m_tools_dock; /// Stack of widgets for tools_dock - QStackedWidget *tools_dock_stack_; + QStackedWidget *m_tools_dock_stack; /// label displayed when several primitives are selected - QLabel *default_informations; + QLabel *m_default_informations; /// Hash associating primitive names with their matching edition widget - QHash editors_; + QHash m_editors; /// ScrollArea for the tools_dock DockWidget - QScrollArea *tools_dock_scroll_area_; + QScrollArea *m_tools_dock_scroll_area; /// container for the undo list - QDockWidget *undo_dock; + QDockWidget *m_undo_dock; /// Container for the list of existing primitives - QDockWidget *parts_dock; + QDockWidget *m_parts_dock; /// List of primitives - QListWidget *parts_list; + QListWidget *m_parts_list; /// actions for the "file" menu QAction *new_element, *open, *open_dxf, *open_file, *save, *save_as, *save_as_file, *reload, *quit; /// actions for the "edit" menu @@ -133,6 +133,7 @@ class QETElementEditor : public QETMainWindow { void addText(); void addTextField(); void addTerminal(); + void addDynamicTextField(); void UncheckAddPrimitive(); void slot_new(); @@ -153,7 +154,6 @@ class QETElementEditor : public QETMainWindow { void slot_createPartsList(); void slot_updatePartsList(); void slot_updateSelectionFromPartsList(); - void xmlPreview(); bool checkElement(); void pasteFromFile(); void pasteFromElement(); diff --git a/sources/editor/ui/dynamictextfieldeditor.cpp b/sources/editor/ui/dynamictextfieldeditor.cpp new file mode 100644 index 000000000..7f40d97b3 --- /dev/null +++ b/sources/editor/ui/dynamictextfieldeditor.cpp @@ -0,0 +1,162 @@ +/* + Copyright 2006-2017 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 . +*/ +#include "dynamictextfieldeditor.h" +#include "ui_dynamictextfieldeditor.h" +#include "customelementpart.h" +#include "partdynamictextfield.h" +#include "QPropertyUndoCommand/qpropertyundocommand.h" + +#include +#include +#include + +DynamicTextFieldEditor::DynamicTextFieldEditor(QETElementEditor *editor, PartDynamicTextField *text_field, QWidget *parent) : + ElementItemEditor(editor, parent), + ui(new Ui::DynamicTextFieldEditor) +{ + ui->setupUi(this); + ui->m_composite_text_pb->setDisabled(true); + ui->m_elmt_info_cb->setDisabled(true); + if(text_field) + setPart(text_field); +} + +DynamicTextFieldEditor::~DynamicTextFieldEditor() +{ + delete ui; + if(!m_connection_list.isEmpty()) + for(QMetaObject::Connection con : m_connection_list) + disconnect(con); +} + +/** + * @brief DynamicTextFieldEditor::setPart + * Set @part as current edited part of this widget. + * @param part + * @return true if @part can be edited by this widget + */ +bool DynamicTextFieldEditor::setPart(CustomElementPart *part) +{ + //Remove previous connection + if(!m_connection_list.isEmpty()) + for(QMetaObject::Connection con : m_connection_list) + disconnect(con); + + QGraphicsItem *qgi = part->toItem(); + if(!qgi) + return false; + else if (qgi->type() != PartDynamicTextField::Type) + return false; + + m_text_field = static_cast(qgi); + updateForm(); + + //Setup the connection + m_connection_list << connect(m_text_field, &PartDynamicTextField::colorChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::fontSizeChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::taggChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::textFromChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::textChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::infoNameChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::rotationChanged, [this](){this->updateForm();}); + m_connection_list << connect(m_text_field, &PartDynamicTextField::compositeTextChanged, [this]() {this->updateForm();}); + + return true; +} + +/** + * @brief DynamicTextFieldEditor::currentPart + * @return The current edited part, note they can return nullptr if + * there is not a currently edited part. + */ +CustomElementPart *DynamicTextFieldEditor::currentPart() const { + return m_text_field.data(); +} + +void DynamicTextFieldEditor::updateForm() +{ + if(m_text_field) + { + ui->m_x_sb->setValue(m_text_field.data()->x()); + ui->m_y_sb->setValue(m_text_field.data()->y()); + ui->m_rotation_sb->setValue(QET::correctAngle(m_text_field.data()->rotation())); + ui->m_user_text_le->setText(m_text_field.data()->text()); + ui->m_size_sb->setValue(m_text_field.data()->fontSize()); + ui->m_tagg_le->setText(m_text_field.data()->tagg()); + setColorPushButton(m_text_field.data()->color()); + } +} + +void DynamicTextFieldEditor::setColorPushButton(QColor color) +{ + QPalette palette; + palette.setColor(QPalette::Button, color); + ui->m_color_pb->setStyleSheet(QString("background-color: %1; min-height: 1.5em; border-style: outset; border-width: 2px; border-color: gray; border-radius: 4px;").arg(color.name())); +} + +void DynamicTextFieldEditor::on_m_x_sb_editingFinished() +{ + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "x", m_text_field.data()->x(), ui->m_x_sb->value()); + undo->setText(tr("Déplacer un champ texte dynamique")); + undo->enableAnimation(true); + undoStack().push(undo); +} + +void DynamicTextFieldEditor::on_m_y_sb_editingFinished() +{ + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "y", m_text_field.data()->y(), ui->m_y_sb->value()); + undo->setText(tr("Déplacer un champ texte dynamique")); + undo->enableAnimation(true); + undoStack().push(undo); +} + +void DynamicTextFieldEditor::on_m_rotation_sb_editingFinished() +{ + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "rotation", m_text_field.data()->rotation(), ui->m_rotation_sb->value()); + undo->setText(tr("Pivoter 2un champ texte dynamique")); + undo->enableAnimation(true); + undoStack().push(undo); +} + +void DynamicTextFieldEditor::on_m_user_text_le_editingFinished() +{ + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "text", m_text_field.data()->text(), ui->m_user_text_le->text()); + undo->setText(tr("Modifier le texte d'un champ texte dynamique")); + undoStack().push(undo); +} + +void DynamicTextFieldEditor::on_m_size_sb_editingFinished() +{ + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "fontSize", m_text_field.data()->fontSize(), ui->m_size_sb->value()); + undo->setText(tr("Modifier la taille d'un champ texte dynamique")); + undo->enableAnimation(true); + undoStack().push(undo); +} + +void DynamicTextFieldEditor::on_m_color_pb_clicked() +{ + QColor color = QColorDialog::getColor(m_text_field.data()->color(), this, tr("Couleur du texte")); + + if(color.isValid() && color != m_text_field.data()->color()) + { + QPropertyUndoCommand *undo = new QPropertyUndoCommand(m_text_field, "color", m_text_field.data()->color(), color); + undo->setText(tr("Modifier la couleur d'un champ texte dynamique")); + undoStack().push(undo); + setColorPushButton(m_text_field.data()->color()); + } +} diff --git a/sources/editor/ui/dynamictextfieldeditor.h b/sources/editor/ui/dynamictextfieldeditor.h new file mode 100644 index 000000000..9488fd251 --- /dev/null +++ b/sources/editor/ui/dynamictextfieldeditor.h @@ -0,0 +1,61 @@ +/* + Copyright 2006-2017 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 . +*/ +#ifndef DYNAMICTEXTFIELDEDITOR_H +#define DYNAMICTEXTFIELDEDITOR_H + +#include "elementitemeditor.h" +#include "partdynamictextfield.h" + +namespace Ui { + class DynamicTextFieldEditor; +} + +/** + * @brief The DynamicTextFieldEditor class + * This class provide a widget used to edit the property of a dynamic text field + */ +class DynamicTextFieldEditor : public ElementItemEditor +{ + Q_OBJECT + + public: + explicit DynamicTextFieldEditor(QETElementEditor *editor, PartDynamicTextField *text_field = nullptr, QWidget *parent = nullptr); + ~DynamicTextFieldEditor(); + + bool setPart(CustomElementPart *part) override; + CustomElementPart *currentPart() const override; + void updateForm() override; + + private: + void setColorPushButton(QColor color); + + private slots: + void on_m_x_sb_editingFinished(); + void on_m_y_sb_editingFinished(); + void on_m_rotation_sb_editingFinished(); + void on_m_user_text_le_editingFinished(); + void on_m_size_sb_editingFinished(); + void on_m_color_pb_clicked(); + + private: + Ui::DynamicTextFieldEditor *ui; + QPointer m_text_field; + QList m_connection_list; +}; + +#endif // DYNAMICTEXTFIELDEDITOR_H diff --git a/sources/editor/ui/dynamictextfieldeditor.ui b/sources/editor/ui/dynamictextfieldeditor.ui new file mode 100644 index 000000000..aded1e148 --- /dev/null +++ b/sources/editor/ui/dynamictextfieldeditor.ui @@ -0,0 +1,176 @@ + + + DynamicTextFieldEditor + + + + 0 + 0 + 336 + 264 + + + + Form + + + + + + Taille + + + + + + + Source du texte + + + + + + + Couleur + + + + + + + + + + Tagg + + + + + + + + Texte utilisateur + + + + + Information de l'élément + + + + + Texte composé + + + + + + + + + + + + + + + + + + + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + X + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + -5000.000000000000000 + + + 5000.000000000000000 + + + + + + + Y + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + -5000.000000000000000 + + + 5000.000000000000000 + + + + + + + Rotation + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + 359 + + + + + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/sources/qetgraphicsitem/customelement.cpp b/sources/qetgraphicsitem/customelement.cpp index fb6b62070..6f32c8349 100644 --- a/sources/qetgraphicsitem/customelement.cpp +++ b/sources/qetgraphicsitem/customelement.cpp @@ -24,6 +24,7 @@ #include "terminal.h" #include "diagramposition.h" #include "diagramcontent.h" +#include "dynamicelementtextitem.h" /** Constructeur de la classe CustomElement. Permet d'instancier un element @@ -95,11 +96,13 @@ bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) { return(false); } - // verifie basiquement que la version actuelle est capable de lire ce fichier - if (xml_def_elmt.hasAttribute("version")) { + //Check if the curent version can read the xml description + if (xml_def_elmt.hasAttribute("version")) + { bool conv_ok; qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok); - if (conv_ok && QET::version.toDouble() < element_version) { + if (conv_ok && QET::version.toDouble() < element_version) + { std::cerr << qPrintable( QObject::tr("Avertissement : l'élément " " a été enregistré avec une version" @@ -108,7 +111,7 @@ bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) { } } - // ces attributs doivent etre presents et valides + //This attribute must be present and valid int w, h, hot_x, hot_y; if ( !QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\ @@ -131,61 +134,81 @@ bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) { return(false); } - // initialisation du QPainter (pour dessiner l'element) + //Init the QPainter for draw the elemennt QPainter qp; qp.begin(&drawing); QPainter low_zoom_qp; low_zoom_qp.begin(&low_zoom_drawing); QPen tmp; - tmp.setWidthF(1.0); // ligne vaudou pour prise en compte du setCosmetic - ne pas enlever + tmp.setWidthF(1.0); //Vaudoo line to take into account the setCosmetic - don't remove tmp.setCosmetic(true); low_zoom_qp.setPen(tmp); - // extrait les noms de la definition XML + //Extract the names names.fromXml(xml_def_elmt); setToolTip(name()); - //load kind informations + //load kind informations kind_informations_.fromXml(xml_def_elmt.firstChildElement("kindInformations"), "kindInformation"); - // parcours des enfants de la definition : parties du dessin + //scroll of the Children of the Definition: Parts of the Drawing int parsed_elements_count = 0; - for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) { + for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) + { QDomElement elmts = node.toElement(); - if (elmts.isNull()) continue; - if (elmts.tagName() == "description") { - // gestion de la description graphique de l'element - // = parcours des differentes parties du dessin - for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) { + if (elmts.isNull()) + continue; + + if (elmts.tagName() == "description") + { + //Manage the graphic description = part of drawing + for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) + { QDomElement qde = n.toElement(); - if (qde.isNull()) continue; - if (parseElement(qde, qp)) { + if (qde.isNull()) + continue; + + if (parseElement(qde, qp)) + { ++ parsed_elements_count; QString current_tag = qde.tagName(); - if (current_tag != "terminal" && current_tag != "input") { + if (current_tag != "terminal" && current_tag != "input" && current_tag != "dynamic_text") + { forbid_antialiasing = true; parseElement(qde, low_zoom_qp); forbid_antialiasing = false; } - } else { - if (state) *state = 7; + } + else + { + if (state) + *state = 7; + return(false); } } } } - // fin du dessin + //End of the drawing qp.end(); low_zoom_qp.end(); - // il doit y avoir au moins un element charge - if (!parsed_elements_count) { - if (state) *state = 8; + + //They must be at least one parsed graphics part + if (!parsed_elements_count) + { + if (state) + *state = 8; + return(false); - } else { - if (state) *state = 0; + } + else + { + if (state) + *state = 0; + return(true); } } @@ -277,17 +300,19 @@ void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *options) @param qp Le QPainter a utiliser pour dessiner l'element perso @return true si l'analyse reussit, false sinon */ -bool CustomElement::parseElement(QDomElement &e, QPainter &qp) { - if (e.tagName() == "terminal") return(parseTerminal(e)); - else if (e.tagName() == "line") return(parseLine(e, qp)); - else if (e.tagName() == "rect") return(parseRect(e, qp)); - else if (e.tagName() == "ellipse") return(parseEllipse(e, qp)); - else if (e.tagName() == "circle") return(parseCircle(e, qp)); - else if (e.tagName() == "arc") return(parseArc(e, qp)); - else if (e.tagName() == "polygon") return(parsePolygon(e, qp)); - else if (e.tagName() == "text") return(parseText(e, qp)); - else if (e.tagName() == "input") return(parseInput(e)); - else return(true); // on n'est pas chiant, on ignore l'element inconnu +bool CustomElement::parseElement(QDomElement &e, QPainter &qp) +{ + if (e.tagName() == "terminal") return(parseTerminal(e)); + else if (e.tagName() == "line") return(parseLine(e, qp)); + else if (e.tagName() == "rect") return(parseRect(e, qp)); + else if (e.tagName() == "ellipse") return(parseEllipse(e, qp)); + else if (e.tagName() == "circle") return(parseCircle(e, qp)); + else if (e.tagName() == "arc") return(parseArc(e, qp)); + else if (e.tagName() == "polygon") return(parsePolygon(e, qp)); + else if (e.tagName() == "text") return(parseText(e, qp)); + else if (e.tagName() == "input") return(parseInput(e)); + else if (e.tagName() == "dynamic_text") return(parseDynamicText(e)); + else return(true); } /** @@ -719,6 +744,27 @@ ElementTextItem *CustomElement::parseInput(QDomElement &e) { return(eti); } +/** + * @brief CustomElement::parseDynamicText + * Create the dynamic text field describ in @dom_element + * @param dom_element + * @return + */ +DynamicElementTextItem *CustomElement::parseDynamicText(QDomElement &dom_element) +{ + DynamicElementTextItem *deti = new DynamicElementTextItem(this); + //Because the xml description of a .elmt file is the same as how a dynamic text field is save to xml in a .qet file + //wa call fromXml, we just change the tagg name (.elmt = dynamic_text, .qet = dynamic_elmt_text) + //and the uuid (because the uuid, is the uuid of the descritpion and not the uuid of instantiated dynamic text field) + + QDomElement dom(dom_element.cloneNode(true).toElement()); + dom.setTagName(DynamicElementTextItem::xmlTaggName()); + deti->fromXml(dom); + deti->m_uuid = QUuid::createUuid(); + this->addDynamicTextItem(deti); + return deti; +} + /** Analyse un element XML suppose representer une borne. Si l'analyse reussit, la borne est ajoutee a l'element. diff --git a/sources/qetgraphicsitem/customelement.h b/sources/qetgraphicsitem/customelement.h index 013d8827b..30388b4cb 100644 --- a/sources/qetgraphicsitem/customelement.h +++ b/sources/qetgraphicsitem/customelement.h @@ -54,45 +54,47 @@ class CustomElement : public FixedElement bool forbid_antialiasing; - QList list_lines_; - QList list_rectangles_; - QList list_circles_; - QList *> list_polygons_; - QList *> list_arcs_; + QList list_lines_; + QList list_rectangles_; + QList list_circles_; + QList *> list_polygons_; + QList *> list_arcs_; // methods public: - QList terminals() const override; - QList conductors() const override; - QList texts() const override; - QList lines() const override; - QList rectangles() const override; - QList circles() const override; - QList *> polygons() const override; - QList *> arcs() const override; - int terminalsCount() const override; - void paint(QPainter *, const QStyleOptionGraphicsItem *) override; - QString typeId() const override; - ElementsLocation location() const; - QString name() const override; - ElementTextItem* taggedText(const QString &tagg) const override; + QList terminals() const override; + QList conductors() const override; + QList texts() const override; + QList lines() const override; + QList rectangles() const override; + QList circles() const override; + QList *> polygons() const override; + QList *> arcs() const override; + int terminalsCount() const override; + void paint(QPainter *, const QStyleOptionGraphicsItem *) override; + QString typeId() const override; + ElementsLocation location() const; + QString name() const override; + ElementTextItem* taggedText(const QString &tagg) const override; protected: - virtual bool buildFromXml(const QDomElement &, int * = nullptr); - virtual bool parseElement(QDomElement &, QPainter &); - virtual bool parseLine(QDomElement &, QPainter &); - virtual bool parseRect(QDomElement &, QPainter &); - virtual bool parseEllipse(QDomElement &, QPainter &); - virtual bool parseCircle(QDomElement &, QPainter &); - virtual bool parseArc(QDomElement &, QPainter &); - virtual bool parsePolygon(QDomElement &, QPainter &); - virtual bool parseText(QDomElement &, QPainter &); - virtual ElementTextItem *parseInput(QDomElement &); - virtual Terminal *parseTerminal(QDomElement &); - virtual void setQPainterAntiAliasing(QPainter &, bool); - virtual bool validOrientationAttribute(const QDomElement &); - virtual void setPainterStyle(QDomElement &, QPainter &); - ElementTextItem* setTaggedText(const QString &tagg, const QString &newstr, const bool noeditable=false); + virtual bool buildFromXml(const QDomElement &, int * = nullptr); + virtual bool parseElement(QDomElement &, QPainter &); + virtual bool parseLine(QDomElement &, QPainter &); + virtual bool parseRect(QDomElement &, QPainter &); + virtual bool parseEllipse(QDomElement &, QPainter &); + virtual bool parseCircle(QDomElement &, QPainter &); + virtual bool parseArc(QDomElement &, QPainter &); + virtual bool parsePolygon(QDomElement &, QPainter &); + virtual bool parseText(QDomElement &, QPainter &); + virtual ElementTextItem *parseInput(QDomElement &); + virtual DynamicElementTextItem *parseDynamicText(QDomElement &); + virtual Terminal *parseTerminal(QDomElement &); + + virtual void setQPainterAntiAliasing(QPainter &, bool); + virtual bool validOrientationAttribute(const QDomElement &); + virtual void setPainterStyle(QDomElement &, QPainter &); + ElementTextItem* setTaggedText(const QString &tagg, const QString &newstr, const bool noeditable=false); }; diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.cpp b/sources/qetgraphicsitem/dynamicelementtextitem.cpp index 9779b4fba..7cb555c0e 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.cpp +++ b/sources/qetgraphicsitem/dynamicelementtextitem.cpp @@ -86,6 +86,19 @@ DynamicElementTextItem::DynamicElementTextItem(Element *parent_element) : DynamicElementTextItem::~DynamicElementTextItem() {} +/** + * @brief DynamicElementTextItem::textFromMetaEnum + * @return The QMetaEnum of the enum TextFrom + */ +QMetaEnum DynamicElementTextItem::textFromMetaEnum() +{ + DynamicElementTextItem deti; + return deti.metaObject()->enumerator(deti.metaObject()->indexOfEnumerator("TextFrom")); +} + +DynamicElementTextItem::DynamicElementTextItem() +{} + /** * @brief DynamicElementTextItem::toXml * Export this text to xml @@ -102,7 +115,7 @@ QDomElement DynamicElementTextItem::toXml(QDomDocument &dom_doc) const root_element.setAttribute("font_size", font().pointSize()); root_element.setAttribute("uuid", m_uuid.toString()); - QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("TextFrom")); + QMetaEnum me = textFromMetaEnum(); root_element.setAttribute("text_from", me.valueToKey(m_text_from)); QDomElement dom_text = dom_doc.createElement("text"); @@ -162,7 +175,7 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) setFont(QETApp::diagramTextsFont(dom_elmt.attribute("font_size", QString::number(9)).toInt())); m_uuid = QUuid(dom_elmt.attribute("uuid", QUuid::createUuid().toString())); - QMetaEnum me = metaObject()->enumerator(metaObject()->indexOfEnumerator("TextFrom")); + 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) { @@ -178,7 +191,10 @@ void DynamicElementTextItem::fromXml(const QDomElement &dom_elmt) //Text QDomElement dom_text = dom_elmt.firstChildElement("text"); if (!dom_text.isNull()) - setPlainText(dom_text.text()); + { + m_text = dom_text.text(); + setPlainText(m_text); + } //Info name QDomElement dom_info_name = dom_elmt.firstChildElement("info_name"); diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index 7ebdae892..4407f2e75 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -35,6 +35,7 @@ class DynamicElementTextItem : public DiagramTextItem { friend class DynamicTextItemDelegate; friend class CompositeTextEditDialog; + friend class CustomElement; Q_OBJECT @@ -64,7 +65,9 @@ class DynamicElementTextItem : public DiagramTextItem public: DynamicElementTextItem(Element *parent_element); ~DynamicElementTextItem() override; + static QMetaEnum textFromMetaEnum(); private: + DynamicElementTextItem (); DynamicElementTextItem(const DynamicElementTextItem &); public: diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 9c2784dad..7b4dca182 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -532,6 +532,12 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool } else { applyRotation(90*read_ori); } + + //Befor load the dynamic text field, + //we remove the dynamic text field created from the description of this element, to avoid doublons. + for(DynamicElementTextItem *deti : m_dynamic_text_list) + delete deti; + m_dynamic_text_list.clear(); //Dynamic texts for (QDomElement qde : QET::findInDomElement(e, "dynamic_texts", DynamicElementTextItem::xmlTaggName())) @@ -626,7 +632,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table m_element_informations.toXml(infos, "elementInformation"); element.appendChild(infos); } - + //Dynamic texts QDomElement dyn_text = document.createElement("dynamic_texts"); for (DynamicElementTextItem *deti : m_dynamic_text_list)