[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 &);
};
/**