[qet] qet/qet: [5046] Element editor : dynamic text item can be added directly from the element editor (WIP)

[ Thread Index | Date Index | More lists.tuxfamily.org/qet Archives ]


Revision: 5046
Author:   blacksun
Date:     2017-09-25 19:44:02 +0200 (Mon, 25 Sep 2017)
Log Message:
-----------
Element editor : dynamic text item can be added directly from the element editor (WIP)

Modified Paths:
--------------
    trunk/dev_doc/enum_type_of_QGraphicsItem
    trunk/sources/editor/elementscene.cpp
    trunk/sources/editor/elementscene.h
    trunk/sources/editor/qetelementeditor.cpp
    trunk/sources/editor/qetelementeditor.h
    trunk/sources/qetgraphicsitem/customelement.cpp
    trunk/sources/qetgraphicsitem/customelement.h
    trunk/sources/qetgraphicsitem/dynamicelementtextitem.cpp
    trunk/sources/qetgraphicsitem/dynamicelementtextitem.h
    trunk/sources/qetgraphicsitem/element.cpp

Added Paths:
-----------
    trunk/sources/editor/esevent/eseventadddynamictextfield.cpp
    trunk/sources/editor/esevent/eseventadddynamictextfield.h
    trunk/sources/editor/graphicspart/partdynamictextfield.cpp
    trunk/sources/editor/graphicspart/partdynamictextfield.h
    trunk/sources/editor/ui/dynamictextfieldeditor.cpp
    trunk/sources/editor/ui/dynamictextfieldeditor.h
    trunk/sources/editor/ui/dynamictextfieldeditor.ui

Modified: trunk/dev_doc/enum_type_of_QGraphicsItem
===================================================================
--- trunk/dev_doc/enum_type_of_QGraphicsItem	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/dev_doc/enum_type_of_QGraphicsItem	2017-09-25 17:44:02 UTC (rev 5046)
@@ -22,6 +22,7 @@
 part text       + 1107
 part text field + 1108
 part rectangle  + 1109
+part dynamic text field + 1110
 
 ###QetGraphicsHandlerItem###
 QetGraphicsHandlerItem = 1200

Modified: trunk/sources/editor/elementscene.cpp
===================================================================
--- trunk/sources/editor/elementscene.cpp	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/editor/elementscene.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -33,6 +33,7 @@
 #include "ui/elementpropertieseditorwidget.h"
 #include "eseventinterface.h"
 #include "QetGraphicsItemModeler/qetgraphicshandleritem.h"
+#include "partdynamictextfield.h"
 
 #include <algorithm>
 #include <QKeyEvent>
@@ -395,33 +396,25 @@
 	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 @@
 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 <CustomElementPart*> (qgi)) {
 			esgr |= cep -> sceneGeometricRect();
 		}
@@ -869,20 +863,16 @@
 	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 @@
 	@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");
-		}
+	
+	if (root.tagName() != "definition" || root.attribute("type") != "element")
 		return(loaded_parts);
-	}
 	
-	// chargement de la description graphique de l'element
-	for (QDomNode node = root.firstChild() ; !node.isNull() ; node = node.nextSibling()) {
+		//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 @@
 				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<QGraphicsItem *>(cep)) {
-					if (!qgi -> zValue()) qgi -> setZValue(z++);
-					loaded_parts << qgi;
+				
+				if (QGraphicsItem *qgi = dynamic_cast<QGraphicsItem *>(cep))
+				{
+					if (!qgi->zValue())
+						qgi->setZValue(z++);
+					
+					loaded_parts<<qgi;
+					cep->fromXml(qde);
 				}
-				cep -> fromXml(qde);
+				else
+					delete cep;
 			}
 		}
 	}
@@ -961,12 +972,9 @@
 /**
 	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 @@
 	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);
 	

Modified: trunk/sources/editor/elementscene.h
===================================================================
--- trunk/sources/editor/elementscene.h	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/editor/elementscene.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -141,10 +141,10 @@
 	
 	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 *);

Added: trunk/sources/editor/esevent/eseventadddynamictextfield.cpp
===================================================================
--- trunk/sources/editor/esevent/eseventadddynamictextfield.cpp	                        (rev 0)
+++ trunk/sources/editor/esevent/eseventadddynamictextfield.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#include "eseventadddynamictextfield.h"
+#include "elementscene.h"
+#include "editorcommands.h"
+#include "partdynamictextfield.h"
+
+#include <QUndoStack>
+
+/**
+ * @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;
+}

Added: trunk/sources/editor/esevent/eseventadddynamictextfield.h
===================================================================
--- trunk/sources/editor/esevent/eseventadddynamictextfield.h	                        (rev 0)
+++ trunk/sources/editor/esevent/eseventadddynamictextfield.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#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

Added: trunk/sources/editor/graphicspart/partdynamictextfield.cpp
===================================================================
--- trunk/sources/editor/graphicspart/partdynamictextfield.cpp	                        (rev 0)
+++ trunk/sources/editor/graphicspart/partdynamictextfield.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#include "partdynamictextfield.h"
+#include "QPropertyUndoCommand/qpropertyundocommand.h"
+#include "qetapp.h"
+#include "elementscene.h"
+
+#include <QGraphicsSceneMouseEvent>
+#include <QFont>
+#include <QColor>
+
+/**
+ * @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<QPointF>() << 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));
+}

Added: trunk/sources/editor/graphicspart/partdynamictextfield.h
===================================================================
--- trunk/sources/editor/graphicspart/partdynamictextfield.h	                        (rev 0)
+++ trunk/sources/editor/graphicspart/partdynamictextfield.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#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

Modified: trunk/sources/editor/qetelementeditor.cpp
===================================================================
--- trunk/sources/editor/qetelementeditor.cpp	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/editor/qetelementeditor.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <QMessageBox>
 #include <QTextStream>
@@ -101,8 +103,8 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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::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,7 +560,7 @@
 	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);
 }
 
 /**
@@ -562,7 +567,7 @@
 	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 @@
 	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<QGraphicsItem *> selected_qgis = m_elmt_scene -> selectedItems();
 	QList<CustomElementPart *> cep_list;
 	bool style_editable = false;
@@ -591,7 +597,21 @@
 
 	}
 	
-	clearToolsDock();
+	if(selected_qgis.size() == 1)
+	{
+		QGraphicsItem *qgi = selected_qgis.first();
+		if (CustomElementPart *selection = dynamic_cast<CustomElementPart *>(qgi))
+		{
+			if (QWidget *widget = m_tools_dock_scroll_area->widget())
+			{
+				if (ElementItemEditor *editor = dynamic_cast<ElementItemEditor *>(widget))
+				{
+					if(editor->currentPart() == selection)
+						return;
+				}
+			}
+		}
+	}
 	
 		//There's one selected item
 	if (selected_qgis.size() == 1)
@@ -599,15 +619,22 @@
 		QGraphicsItem *qgi = selected_qgis.first();
 		if (CustomElementPart *selection = dynamic_cast<CustomElementPart *>(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<ElementItemEditor *>(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 @@
 		//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,27 +664,16 @@
 		//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.
  * If error is occured return false
@@ -919,7 +936,7 @@
 	read_only = ro;
 	
 	// active / desactive les interactions avec la scene
-	ce_view -> setInteractive(!ro);
+	m_view -> setInteractive(!ro);
 	
 	slot_updateMenus();
 }
@@ -996,6 +1013,14 @@
 }
 
 /**
+ * @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 @@
 	@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 @@
 	}
 	clipboard -> setText(clipboard_content);
 	
-	ce_view -> pasteInArea();
+	m_view -> pasteInArea();
 }
 
 /**
@@ -1314,7 +1339,7 @@
 */
 void QETElementEditor::firstActivation(QEvent *event) {
 	Q_UNUSED(event)
-	QTimer::singleShot(250, ce_view, SLOT(zoomFit()));
+	QTimer::singleShot(250, m_view, SLOT(zoomFit()));
 }
 
 /**
@@ -1321,8 +1346,8 @@
 	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<QGraphicsItem *> qgis = m_elmt_scene -> zItems();
 	
 	// on ne construit plus la liste a partir de 200 primitives
@@ -1337,14 +1362,14 @@
 				QVariant v;
 				v.setValue<QGraphicsItem *>(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_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<QGraphicsItem *> 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_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<QGraphicsItem *>();
 		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::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<ElementItemEditor *>(tools_dock_scroll_area_ -> widget())) {
+	if (ElementItemEditor *current_editor = dynamic_cast<ElementItemEditor *>(m_tools_dock_scroll_area -> widget())) {
 		current_editor -> updateForm();
 	}
 }

Modified: trunk/sources/editor/qetelementeditor.h
===================================================================
--- trunk/sources/editor/qetelementeditor.h	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/editor/qetelementeditor.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -51,25 +51,25 @@
 	/// 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<QString, ElementItemEditor *> editors_;
+	QHash<QString, ElementItemEditor *> 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 @@
 		void addText();
 		void addTextField();
 		void addTerminal();
+		void addDynamicTextField();
 		void UncheckAddPrimitive();
 
 	void slot_new();
@@ -153,7 +154,6 @@
 	void slot_createPartsList();
 	void slot_updatePartsList();
 	void slot_updateSelectionFromPartsList();
-	void xmlPreview();
 	bool checkElement();
 	void pasteFromFile();
 	void pasteFromElement();

Added: trunk/sources/editor/ui/dynamictextfieldeditor.cpp
===================================================================
--- trunk/sources/editor/ui/dynamictextfieldeditor.cpp	                        (rev 0)
+++ trunk/sources/editor/ui/dynamictextfieldeditor.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#include "dynamictextfieldeditor.h"
+#include "ui_dynamictextfieldeditor.h"
+#include "customelementpart.h"
+#include "partdynamictextfield.h"
+#include "QPropertyUndoCommand/qpropertyundocommand.h"
+
+#include <QPointer>
+#include <QGraphicsItem>
+#include <QColorDialog>
+
+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<PartDynamicTextField *>(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());
+	}
+}

Added: trunk/sources/editor/ui/dynamictextfieldeditor.h
===================================================================
--- trunk/sources/editor/ui/dynamictextfieldeditor.h	                        (rev 0)
+++ trunk/sources/editor/ui/dynamictextfieldeditor.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 <http://www.gnu.org/licenses/>.
+*/
+#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<PartDynamicTextField> m_text_field;
+		QList<QMetaObject::Connection> m_connection_list;
+};
+
+#endif // DYNAMICTEXTFIELDEDITOR_H

Added: trunk/sources/editor/ui/dynamictextfieldeditor.ui
===================================================================
--- trunk/sources/editor/ui/dynamictextfieldeditor.ui	                        (rev 0)
+++ trunk/sources/editor/ui/dynamictextfieldeditor.ui	2017-09-25 17:44:02 UTC (rev 5046)
@@ -0,0 +1,176 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>DynamicTextFieldEditor</class>
+ <widget class="QWidget" name="DynamicTextFieldEditor">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>336</width>
+    <height>264</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QGridLayout" name="gridLayout">
+   <item row="5" column="0">
+    <widget class="QLabel" name="label">
+     <property name="text">
+      <string>Taille</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="0">
+    <widget class="QLabel" name="label_4">
+     <property name="text">
+      <string>Source du texte</string>
+     </property>
+    </widget>
+   </item>
+   <item row="7" column="0">
+    <widget class="QLabel" name="label_3">
+     <property name="text">
+      <string>Couleur</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1" colspan="6">
+    <widget class="QComboBox" name="m_elmt_info_cb"/>
+   </item>
+   <item row="6" column="0">
+    <widget class="QLabel" name="label_2">
+     <property name="text">
+      <string>Tagg</string>
+     </property>
+    </widget>
+   </item>
+   <item row="1" column="1" colspan="6">
+    <widget class="QComboBox" name="m_text_from_cb">
+     <item>
+      <property name="text">
+       <string>Texte utilisateur</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Information de l'élément</string>
+      </property>
+     </item>
+     <item>
+      <property name="text">
+       <string>Texte composé</string>
+      </property>
+     </item>
+    </widget>
+   </item>
+   <item row="6" column="1" colspan="6">
+    <widget class="QLineEdit" name="m_tagg_le"/>
+   </item>
+   <item row="5" column="1" colspan="6">
+    <widget class="QSpinBox" name="m_size_sb"/>
+   </item>
+   <item row="4" column="1" colspan="6">
+    <widget class="QPushButton" name="m_composite_text_pb">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item row="0" column="0" colspan="7">
+    <widget class="QFrame" name="frame">
+     <property name="frameShape">
+      <enum>QFrame::NoFrame</enum>
+     </property>
+     <property name="frameShadow">
+      <enum>QFrame::Raised</enum>
+     </property>
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QLabel" name="label_5">
+        <property name="text">
+         <string>X</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QDoubleSpinBox" name="m_x_sb">
+        <property name="minimum">
+         <double>-5000.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>5000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="label_6">
+        <property name="text">
+         <string>Y</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QDoubleSpinBox" name="m_y_sb">
+        <property name="minimum">
+         <double>-5000.000000000000000</double>
+        </property>
+        <property name="maximum">
+         <double>5000.000000000000000</double>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="label_7">
+        <property name="text">
+         <string>Rotation</string>
+        </property>
+        <property name="alignment">
+         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QSpinBox" name="m_rotation_sb">
+        <property name="maximum">
+         <number>359</number>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item row="2" column="1" colspan="6">
+    <widget class="QLineEdit" name="m_user_text_le"/>
+   </item>
+   <item row="7" column="1" colspan="6">
+    <widget class="QPushButton" name="m_color_pb">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+   <item row="8" column="1">
+    <spacer name="verticalSpacer">
+     <property name="orientation">
+      <enum>Qt::Vertical</enum>
+     </property>
+     <property name="sizeHint" stdset="0">
+      <size>
+       <width>20</width>
+       <height>40</height>
+      </size>
+     </property>
+    </spacer>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>

Modified: trunk/sources/qetgraphicsitem/customelement.cpp
===================================================================
--- trunk/sources/qetgraphicsitem/customelement.cpp	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/qetgraphicsitem/customelement.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -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 @@
 		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 @@
 		}
 	}
 
-	// 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,7 +134,7 @@
 		return(false);
 	}
 
-	// initialisation du QPainter (pour dessiner l'element)
+		//Init the QPainter for draw the elemennt
 	QPainter qp;
 	qp.begin(&drawing);
 
@@ -138,38 +141,50 @@
 	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);
 				}
 			}
@@ -176,16 +191,24 @@
 		}
 	}
 
-	// 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 @@
 	@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);
 }
 
 /**
@@ -720,6 +745,27 @@
 }
 
 /**
+ * @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.
 	Une borne est definie par les attributs suivants :

Modified: trunk/sources/qetgraphicsitem/customelement.h
===================================================================
--- trunk/sources/qetgraphicsitem/customelement.h	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/qetgraphicsitem/customelement.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -54,45 +54,47 @@
 		bool forbid_antialiasing;
 
 
-	QList<QLineF *> list_lines_;
-	QList<QRectF *> list_rectangles_;
-	QList<QRectF *> list_circles_;
-	QList<QVector<QPointF> *> list_polygons_;
-	QList<QVector<qreal> *> list_arcs_;
+		QList<QLineF *> list_lines_;
+		QList<QRectF *> list_rectangles_;
+		QList<QRectF *> list_circles_;
+		QList<QVector<QPointF> *> list_polygons_;
+		QList<QVector<qreal> *> list_arcs_;
 	
 	// methods
 	public:
-	QList<Terminal *> terminals() const override;
-	QList<Conductor *> conductors() const override;
-	QList<ElementTextItem *> texts() const override;
-	QList<QLineF *> lines() const override;
-	QList<QRectF *> rectangles() const override;
-	QList<QRectF *> circles() const override;
-	QList<QVector<QPointF> *> polygons() const override;
-	QList<QVector<qreal> *> 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<Terminal *> terminals() const override;
+		QList<Conductor *> conductors() const override;
+		QList<ElementTextItem *> texts() const override;
+		QList<QLineF *> lines() const override;
+		QList<QRectF *> rectangles() const override;
+		QList<QRectF *> circles() const override;
+		QList<QVector<QPointF> *> polygons() const override;
+		QList<QVector<qreal> *> 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);
 
 };
 

Modified: trunk/sources/qetgraphicsitem/dynamicelementtextitem.cpp
===================================================================
--- trunk/sources/qetgraphicsitem/dynamicelementtextitem.cpp	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/qetgraphicsitem/dynamicelementtextitem.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -87,6 +87,19 @@
 {}
 
 /**
+ * @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
  * @param dom_doc
@@ -102,7 +115,7 @@
 	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 @@
 	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 @@
 		//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");

Modified: trunk/sources/qetgraphicsitem/dynamicelementtextitem.h
===================================================================
--- trunk/sources/qetgraphicsitem/dynamicelementtextitem.h	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/qetgraphicsitem/dynamicelementtextitem.h	2017-09-25 17:44:02 UTC (rev 5046)
@@ -35,6 +35,7 @@
 {
 	friend class DynamicTextItemDelegate;
 	friend class CompositeTextEditDialog;
+	friend class CustomElement;
 	
     Q_OBJECT
     
@@ -64,7 +65,9 @@
 	public:
 		DynamicElementTextItem(Element *parent_element);
 		~DynamicElementTextItem() override;
+		static QMetaEnum textFromMetaEnum();
 	private:
+		DynamicElementTextItem ();
 		DynamicElementTextItem(const DynamicElementTextItem &);
 		
 	public:

Modified: trunk/sources/qetgraphicsitem/element.cpp
===================================================================
--- trunk/sources/qetgraphicsitem/element.cpp	2017-09-24 17:05:59 UTC (rev 5045)
+++ trunk/sources/qetgraphicsitem/element.cpp	2017-09-25 17:44:02 UTC (rev 5046)
@@ -532,6 +532,12 @@
 	} 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 @@
 		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)


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/