[qet] [967] Il est desormais possible de deplacer les champs de texte des elements.

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


Revision: 967
Author:   xavier
Date:     2010-04-24 22:42:20 +0200 (Sat, 24 Apr 2010)
Log Message:
-----------
Il est desormais possible de deplacer les champs de texte des elements.

Modified Paths:
--------------
    branches/0.3/sources/diagram.cpp
    branches/0.3/sources/diagram.h
    branches/0.3/sources/diagramcommands.cpp
    branches/0.3/sources/diagramcommands.h
    branches/0.3/sources/diagramtextitem.cpp
    branches/0.3/sources/diagramtextitem.h
    branches/0.3/sources/elementtextitem.cpp
    branches/0.3/sources/elementtextitem.h

Modified: branches/0.3/sources/diagram.cpp
===================================================================
--- branches/0.3/sources/diagram.cpp	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagram.cpp	2010-04-24 20:42:20 UTC (rev 967)
@@ -813,6 +813,7 @@
 	conductors_to_move.clear();
 	conductors_to_update.clear();
 	texts_to_move.clear();
+	elements_texts_to_move.clear();
 }
 
 /**
@@ -825,6 +826,8 @@
 			elements_to_move << elmt;
 		} else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item)) {
 			texts_to_move << iti;
+		} else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(item)) {
+			elements_texts_to_move << eti;
 		}
 	}
 	
@@ -847,13 +850,14 @@
 			}
 		}
 	}
+	
 	moved_elements_fetched = true;
 }
 
 /**
-	Deplace les elements, conducteurs et textes selectionnes en gerant au
-	mieux les conducteurs (seuls les conducteurs dont un seul des elements
-	est deplace sont recalcules, les autres sont deplaces).
+	Deplace les elements, conducteurs et textes independants selectionnes en
+	gerant au mieux les conducteurs (seuls les conducteurs dont un seul des
+	elements est deplace sont recalcules, les autres sont deplaces).
 	@param diff Translation a effectuer
 	@param dontmove QGraphicsItem (optionnel) a ne pas deplacer ; note : ce
 	parametre ne concerne que les elements et les champs de texte.
@@ -888,6 +892,26 @@
 }
 
 /**
+	Deplace les champs de textes selectionnes ET rattaches a un element
+	@param diff Translation a effectuer, exprimee dans les coordonnees de la
+	scene
+	@param dontmove ElementTextItem (optionnel) a ne pas deplacer
+*/
+void Diagram::moveElementsTexts(const QPointF &diff, ElementTextItem *dontmove) {
+	// inutile de deplacer les autres textes s'il n'y a pas eu de mouvement concret
+	if (diff.isNull()) return;
+	current_movement += diff;
+	
+	// deplace les champs de texte rattaches a un element
+	foreach(ElementTextItem *eti, elementTextsToMove()) {
+		if (dontmove && eti == dontmove) continue;
+		QPointF applied_movement = eti -> mapMovementToParent(eti-> mapMovementFromScene(diff));
+		eti -> setPos(eti -> pos() + applied_movement);
+	}
+	
+}
+
+/**
 	Permet de savoir si un element est utilise sur un schema
 	@param location Emplacement d'un element
 	@return true si l'element location est utilise sur ce schema, false sinon

Modified: branches/0.3/sources/diagram.h
===================================================================
--- branches/0.3/sources/diagram.h	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagram.h	2010-04-24 20:42:20 UTC (rev 967)
@@ -30,6 +30,7 @@
 class DiagramTextItem;
 class Element;
 class ElementsLocation;
+class ElementTextItem;
 class IndependentTextItem;
 class QETProject;
 class Terminal;
@@ -80,6 +81,7 @@
 	QSet<Conductor *> conductors_to_move;
 	QHash<Conductor *, Terminal *> conductors_to_update;
 	QSet<IndependentTextItem *> texts_to_move;
+	QSet<ElementTextItem *> elements_texts_to_move;
 	QGIManager *qgi_manager;
 	QUndoStack *undo_stack;
 	bool draw_terminals;
@@ -158,12 +160,14 @@
 	const QSet<Conductor *> &conductorsToMove();
 	const QHash<Conductor *, Terminal *> &conductorsToUpdate();
 	const QSet<IndependentTextItem *> &independentTextsToMove();
+	const QSet<ElementTextItem *> &elementTextsToMove();
 	QSet<DiagramTextItem *> selectedTexts() const;
 	QSet<Conductor *> selectedConductors() const;
 	DiagramContent content() const;
 	DiagramContent selectedContent();
 	bool canRotateSelection() const;
 	void moveElements(const QPointF &, QGraphicsItem * = 0);
+	void moveElementsTexts(const QPointF &, ElementTextItem * = 0);
 	bool usesElement(const ElementsLocation &);
 	
 	QUndoStack &undoStack();
@@ -292,6 +296,12 @@
 	return(texts_to_move);
 }
 
+/// @return la liste des textes rattaches a un element qui sont a deplacer
+inline const QSet<ElementTextItem *> &Diagram::elementTextsToMove() {
+	if (!moved_elements_fetched) fetchMovedElements();
+	return(elements_texts_to_move);
+}
+
 /// @return la pile d'annulations de ce schema
 inline QUndoStack &Diagram::undoStack() {
 	return(*undo_stack);

Modified: branches/0.3/sources/diagramcommands.cpp
===================================================================
--- branches/0.3/sources/diagramcommands.cpp	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagramcommands.cpp	2010-04-24 20:42:20 UTC (rev 967)
@@ -19,6 +19,7 @@
 #include "element.h"
 #include "conductor.h"
 #include "diagram.h"
+#include "elementtextitem.h"
 #include "independenttextitem.h"
 #include "qgimanager.h"
 #include "diagram.h"
@@ -368,6 +369,64 @@
 
 /**
 	Constructeur
+	@param diagram Schema sur lequel on deplace des champs de texte
+	@param texts Liste des textes deplaces
+	@param m translation subie par les elements
+	@param parent QUndoCommand parent
+*/
+MoveElementsTextsCommand::MoveElementsTextsCommand(
+	Diagram *diagram,
+	const QSet<ElementTextItem *> &texts,
+	const QPointF &m,
+	QUndoCommand *parent
+) :
+	QUndoCommand(parent),
+	diagram(diagram),
+	texts_to_move(texts),
+	movement(m),
+	first_redo(true)
+{
+	QString moved_content_sentence = QET::ElementsAndConductorsSentence(0, 0, texts_to_move.count());
+	
+	setText(
+		QString(
+			QObject::tr(
+				"d\351placer %1",
+				"undo caption - %1 is a sentence listing the moved content"
+			).arg(moved_content_sentence)
+		)
+	);
+}
+
+/// Destructeur
+MoveElementsTextsCommand::~MoveElementsTextsCommand() {
+}
+
+/// annule le deplacement
+void MoveElementsTextsCommand::undo() {
+	move(-movement);
+}
+
+/// refait le deplacement
+void MoveElementsTextsCommand::redo() {
+	if (first_redo) first_redo = false;
+	else move(movement);
+}
+
+/**
+	deplace les elements et conducteurs
+	@param actual_movement translation a effectuer sur les elements et conducteurs
+*/
+void MoveElementsTextsCommand::move(const QPointF &actual_movement) {
+	// deplace les textes
+	foreach(ElementTextItem *text, texts_to_move) {
+		QPointF applied_movement = text -> mapMovementToParent(text -> mapMovementFromScene(actual_movement));
+		text -> setPos(text -> pos() + applied_movement);
+	}
+}
+
+/**
+	Constructeur
 	@param dti Champ de texte modifie
 	@param before texte avant
 	@param after texte apres

Modified: branches/0.3/sources/diagramcommands.h
===================================================================
--- branches/0.3/sources/diagramcommands.h	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagramcommands.h	2010-04-24 20:42:20 UTC (rev 967)
@@ -27,6 +27,7 @@
 class Diagram;
 class DiagramTextItem;
 class Element;
+class ElementTextItem;
 class IndependentTextItem;
 
 /**
@@ -202,6 +203,36 @@
 };
 
 /**
+	Cette classe represente l'action de deplacer des champs de texte rattaches
+	a des elements sur un schema
+*/
+class MoveElementsTextsCommand : public QUndoCommand {
+	// constructeurs, destructeur
+	public:
+	MoveElementsTextsCommand(Diagram *, const QSet<ElementTextItem *> &, const QPointF &m, QUndoCommand * = 0);
+	virtual ~MoveElementsTextsCommand();
+	private:
+	MoveElementsTextsCommand(const MoveElementsTextsCommand &);
+	
+	// methodes
+	public:
+	virtual void undo();
+	virtual void redo();
+	virtual void move(const QPointF &);
+	
+	// attributs
+	private:
+	/// schema sur lequel on deplace les elements
+	Diagram *diagram;
+	/// liste des champs de texte a deplacer
+	QSet<ElementTextItem *> texts_to_move;
+	/// mouvement effectue
+	QPointF movement;
+	/// booleen pour ne pas executer le premier redo()
+	bool first_redo;
+};
+
+/**
 	Cette classe represente la modification d'un champ de texte
 */
 class ChangeDiagramTextCommand : public QUndoCommand {

Modified: branches/0.3/sources/diagramtextitem.cpp
===================================================================
--- branches/0.3/sources/diagramtextitem.cpp	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagramtextitem.cpp	2010-04-24 20:42:20 UTC (rev 967)
@@ -33,7 +33,7 @@
 {
 	setDefaultTextColor(Qt::black);
 	setFont(QETApp::diagramTextsFont());
-	setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
+	setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemSendsGeometryChanges);
 	connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
 }
 
@@ -51,7 +51,7 @@
 {
 	setDefaultTextColor(Qt::black);
 	setFont(QETApp::diagramTextsFont());
-	setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable);
+	setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemSendsGeometryChanges);
 	connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
 }
 
@@ -99,6 +99,82 @@
 }
 
 /**
+	Traduit en coordonnees de la scene un mouvement / vecteur initialement
+	exprime en coordonnees locales.
+	@param movement Vecteur exprime en coordonnees locales
+	@return le meme vecteur, exprime en coordonnees de la scene
+*/
+QPointF DiagramTextItem::mapMovementToScene(const QPointF &movement) const {
+	// on definit deux points en coordonnees locales
+	QPointF local_origin(0.0, 0.0);
+	QPointF local_movement_point(movement);
+	
+	// on les mappe sur la scene
+	QPointF scene_origin(mapToScene(local_origin));
+	QPointF scene_movement_point(mapToScene(local_movement_point));
+	
+	// on calcule le vecteur represente par ces deux points
+	return(scene_movement_point - scene_origin);
+}
+
+/**
+	Traduit en coordonnees locales un mouvement / vecteur initialement
+	exprime en coordonnees de la scene.
+	@param movement Vecteur exprime en coordonnees de la scene
+	@return le meme vecteur, exprime en coordonnees locales
+*/
+QPointF DiagramTextItem::mapMovementFromScene(const QPointF &movement) const {
+	// on definit deux points sur la scene
+	QPointF scene_origin(0.0, 0.0);
+	QPointF scene_movement_point(movement);
+	
+	// on les mappe sur ce QGraphicsItem
+	QPointF local_origin(mapFromScene(scene_origin));
+	QPointF local_movement_point(mapFromScene(scene_movement_point));
+	
+	// on calcule le vecteur represente par ces deux points
+	return(local_movement_point - local_origin);
+}
+
+/**
+	Traduit en coordonnees de l'item parent un mouvement / vecteur initialement
+	exprime en coordonnees locales.
+	@param movement Vecteur exprime en coordonnees locales
+	@return le meme vecteur, exprime en coordonnees du parent
+*/
+QPointF DiagramTextItem::mapMovementToParent(const QPointF &movement) const {
+	// on definit deux points en coordonnees locales
+	QPointF local_origin(0.0, 0.0);
+	QPointF local_movement_point(movement);
+	
+	// on les mappe sur la scene
+	QPointF parent_origin(mapToParent(local_origin));
+	QPointF parent_movement_point(mapToParent(local_movement_point));
+	
+	// on calcule le vecteur represente par ces deux points
+	return(parent_movement_point - parent_origin);
+}
+
+/**
+	Traduit en coordonnees locales un mouvement / vecteur initialement
+	exprime en coordonnees du parent.
+	@param movement Vecteur exprime en coordonnees du parent
+	@return le meme vecteur, exprime en coordonnees locales
+*/
+QPointF DiagramTextItem::mapMovementFromParent(const QPointF &movement) const {
+	// on definit deux points sur le parent
+	QPointF parent_origin(0.0, 0.0);
+	QPointF parent_movement_point(movement);
+	
+	// on les mappe sur ce QGraphicsItem
+	QPointF local_origin(mapFromParent(parent_origin));
+	QPointF local_movement_point(mapFromParent(parent_movement_point));
+	
+	// on calcule le vecteur represente par ces deux points
+	return(local_movement_point - local_origin);
+}
+
+/**
 	Gere les changements dont ce champ de texte est informe
 */
 QVariant DiagramTextItem::itemChange(GraphicsItemChange change, const QVariant &value) {

Modified: branches/0.3/sources/diagramtextitem.h
===================================================================
--- branches/0.3/sources/diagramtextitem.h	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/diagramtextitem.h	2010-04-24 20:42:20 UTC (rev 967)
@@ -52,6 +52,10 @@
 	qreal rotationAngle() const;
 	void setRotationAngle(const qreal &);
 	void rotateBy(const qreal &);
+	QPointF mapMovementToScene(const QPointF &) const;
+	QPointF mapMovementFromScene(const QPointF &) const;
+	QPointF mapMovementToParent(const QPointF &) const;
+	QPointF mapMovementFromParent(const QPointF &) const;
 	
 	protected:
 	virtual QVariant itemChange(GraphicsItemChange, const QVariant &);

Modified: branches/0.3/sources/elementtextitem.cpp
===================================================================
--- branches/0.3/sources/elementtextitem.cpp	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/elementtextitem.cpp	2010-04-24 20:42:20 UTC (rev 967)
@@ -32,8 +32,7 @@
 	original_rotation_angle_(0.0)
 {
 	// par defaut, les DiagramTextItem sont Selectable et Movable
-	// on desactive Movable pour les textes des elements
-	setFlag(QGraphicsItem::ItemIsMovable, false);
+	// cela nous convient, on ne touche pas a ces flags
 	
 	// ajuste la position du QGraphicsItem lorsque le QTextDocument change
 	connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int)));
@@ -52,8 +51,7 @@
 	original_rotation_angle_(0.0)
 {
 	// par defaut, les DiagramTextItem sont Selectable et Movable
-	// on desactive Movable pour les textes des elements
-	setFlag(QGraphicsItem::ItemIsMovable, false);
+	// cela nous convient, on ne touche pas a ces flags
 	
 	// ajuste la position du QGraphicsItem lorsque le QTextDocument change
 	connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int)));
@@ -118,6 +116,15 @@
 		qFuzzyCompare(qreal(e.attribute("y").toDouble()), _pos.y())
 	) {
 		setPlainText(e.attribute("text"));
+		
+		qreal user_pos_x, user_pos_y;
+		if (
+			QET::attributeIsAReal(e, "userx", &user_pos_x) &&
+			QET::attributeIsAReal(e, "usery", &user_pos_y)
+		) {
+			setPos(user_pos_x, user_pos_y);
+		}
+		
 		qreal xml_rotation_angle;
 		if (QET::attributeIsAReal(e, "userrotation", &xml_rotation_angle)) {
 			setRotationAngle(xml_rotation_angle);
@@ -131,12 +138,21 @@
 */
 QDomElement ElementTextItem::toXml(QDomDocument &document) const {
 	QDomElement result = document.createElement("input");
+	
 	result.setAttribute("x", QString("%1").arg(originalPos().x()));
 	result.setAttribute("y", QString("%1").arg(originalPos().y()));
+	
+	if (pos() != originalPos()) {
+		result.setAttribute("userx", QString("%1").arg(pos().x()));
+		result.setAttribute("usery", QString("%1").arg(pos().y()));
+	}
+	
 	result.setAttribute("text", toPlainText());
+	
 	if (rotationAngle() != originalRotationAngle()) {
 		result.setAttribute("userrotation", QString("%1").arg(rotationAngle()));
 	}
+	
 	return(result);
 }
 
@@ -180,7 +196,7 @@
 */
 void ElementTextItem::adjustItemPosition(int new_block_count) {
 	Q_UNUSED(new_block_count);
-	setPos(originalPos());
+	setPos(known_position_);
 }
 
 /**
@@ -199,3 +215,80 @@
 	
 	QGraphicsTextItem::setTransform(rotation, true);
 }
+
+/**
+	Gere les mouvements de souris lies au champ de texte
+*/
+void ElementTextItem::mouseMoveEvent(QGraphicsSceneMouseEvent *e) {
+	if (textInteractionFlags() & Qt::TextEditable) {
+		DiagramTextItem::mouseMoveEvent(e);
+	} else if ((flags() & QGraphicsItem::ItemIsMovable) && (e -> buttons() & Qt::LeftButton)) {
+		QPointF old_pos = pos();
+		/*
+			Utiliser e -> pos() directement aurait pour effet de positionner
+			l'origine du champ de texte a la position indiquee par le curseur,
+			ce qui n'est pas l'effet recherche
+			Au lieu de cela, on applique a la position actuelle le vecteur
+			definissant le mouvement effectue depuis la derniere position
+			cliquee avec le bouton gauche
+		*/
+		QPointF movement = e -> pos() - e -> buttonDownPos(Qt::LeftButton);
+		
+		/*
+			Les methodes pos() et setPos() travaillent toujours avec les
+			coordonnees de l'item parent (ou de la scene s'il n'y a pas d'item
+			parent). On n'oublie donc pas de mapper le mouvement fraichement
+			calcule sur l'item parent avant de l'appliquer.
+		*/
+		QPointF parent_movement = mapMovementToParent(movement);
+		setPos(pos() + parent_movement);
+		
+		/*
+			Comme setPos() n'est pas oblige d'appliquer exactement la valeur
+			qu'on lui fournit, on calcule le mouvement reellement applique.
+		*/
+		QPointF effective_movement = pos() - old_pos;
+		QPointF scene_effective_movement = mapMovementToScene(mapMovementFromParent(effective_movement));
+		
+		if (Diagram *diagram_ptr = diagram()) {
+			diagram_ptr -> moveElementsTexts(scene_effective_movement, this);
+		}
+	} else e -> ignore();
+}
+
+/**
+	Gere le relachement de souris
+	Cette methode cree un objet d'annulation pour le deplacement
+*/
+void ElementTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
+	if (Diagram *diagram_ptr = diagram()) {
+		if ((flags() & QGraphicsItem::ItemIsMovable) && (!diagram_ptr -> current_movement.isNull())) {
+			diagram_ptr -> undoStack().push(
+				new MoveElementsTextsCommand(
+					diagram_ptr,
+					diagram_ptr -> elementTextsToMove(),
+					diagram_ptr -> current_movement
+				)
+			);
+			diagram_ptr -> current_movement = QPointF();
+		}
+		diagram_ptr -> invalidateMovedElements();
+	}
+	if (!(e -> modifiers() & Qt::ControlModifier)) {
+		QGraphicsTextItem::mouseReleaseEvent(e);
+	}
+}
+
+/**
+	Gere les changements intervenant sur ce champ de texte
+	@param change Type de changement
+	@param value Valeur numerique relative au changement
+*/
+QVariant ElementTextItem::itemChange(GraphicsItemChange change, const QVariant &value) {
+	if (change == QGraphicsItem::ItemPositionHasChanged || change == QGraphicsItem::ItemSceneHasChanged) {
+		// memorise la nouvelle position "officielle" du champ de texte
+		// cette information servira a le recentrer en cas d'ajout / retrait de lignes
+		known_position_ = pos();
+	}
+	return(DiagramTextItem::itemChange(change, value));
+}

Modified: branches/0.3/sources/elementtextitem.h
===================================================================
--- branches/0.3/sources/elementtextitem.h	2010-04-24 20:27:03 UTC (rev 966)
+++ branches/0.3/sources/elementtextitem.h	2010-04-24 20:42:20 UTC (rev 967)
@@ -45,6 +45,7 @@
 	Element *parent_element_;
 	bool follow_parent_rotations;
 	QPointF original_position;
+	QPointF known_position_;
 	qreal original_rotation_angle_;
 	
 	// methodes
@@ -70,6 +71,9 @@
 	
 	protected:
 	virtual void applyRotation(const qreal &);
+	virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
+	virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
+	virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
 };
 
 /**


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