Il est desormais possible de deplacer les champs de texte des elements.

git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/branches/0.3@967 bfdf4180-ca20-0410-9c96-a3a8aa849046
This commit is contained in:
xavier
2010-04-24 20:42:20 +00:00
parent d290131e1e
commit 88a4647d11
8 changed files with 311 additions and 10 deletions

View File

@@ -813,6 +813,7 @@ void Diagram::invalidateMovedElements() {
conductors_to_move.clear(); conductors_to_move.clear();
conductors_to_update.clear(); conductors_to_update.clear();
texts_to_move.clear(); texts_to_move.clear();
elements_texts_to_move.clear();
} }
/** /**
@@ -825,6 +826,8 @@ void Diagram::fetchMovedElements() {
elements_to_move << elmt; elements_to_move << elmt;
} else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item)) { } else if (IndependentTextItem *iti = qgraphicsitem_cast<IndependentTextItem *>(item)) {
texts_to_move << iti; texts_to_move << iti;
} else if (ElementTextItem *eti = qgraphicsitem_cast<ElementTextItem *>(item)) {
elements_texts_to_move << eti;
} }
} }
@@ -847,13 +850,14 @@ void Diagram::fetchMovedElements() {
} }
} }
} }
moved_elements_fetched = true; moved_elements_fetched = true;
} }
/** /**
Deplace les elements, conducteurs et textes selectionnes en gerant au Deplace les elements, conducteurs et textes independants selectionnes en
mieux les conducteurs (seuls les conducteurs dont un seul des elements gerant au mieux les conducteurs (seuls les conducteurs dont un seul des
est deplace sont recalcules, les autres sont deplaces). elements est deplace sont recalcules, les autres sont deplaces).
@param diff Translation a effectuer @param diff Translation a effectuer
@param dontmove QGraphicsItem (optionnel) a ne pas deplacer ; note : ce @param dontmove QGraphicsItem (optionnel) a ne pas deplacer ; note : ce
parametre ne concerne que les elements et les champs de texte. parametre ne concerne que les elements et les champs de texte.
@@ -887,6 +891,26 @@ void Diagram::moveElements(const QPointF &diff, QGraphicsItem *dontmove) {
} }
} }
/**
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 Permet de savoir si un element est utilise sur un schema
@param location Emplacement d'un element @param location Emplacement d'un element

View File

@@ -30,6 +30,7 @@ class DiagramPosition;
class DiagramTextItem; class DiagramTextItem;
class Element; class Element;
class ElementsLocation; class ElementsLocation;
class ElementTextItem;
class IndependentTextItem; class IndependentTextItem;
class QETProject; class QETProject;
class Terminal; class Terminal;
@@ -80,6 +81,7 @@ class Diagram : public QGraphicsScene {
QSet<Conductor *> conductors_to_move; QSet<Conductor *> conductors_to_move;
QHash<Conductor *, Terminal *> conductors_to_update; QHash<Conductor *, Terminal *> conductors_to_update;
QSet<IndependentTextItem *> texts_to_move; QSet<IndependentTextItem *> texts_to_move;
QSet<ElementTextItem *> elements_texts_to_move;
QGIManager *qgi_manager; QGIManager *qgi_manager;
QUndoStack *undo_stack; QUndoStack *undo_stack;
bool draw_terminals; bool draw_terminals;
@@ -158,12 +160,14 @@ class Diagram : public QGraphicsScene {
const QSet<Conductor *> &conductorsToMove(); const QSet<Conductor *> &conductorsToMove();
const QHash<Conductor *, Terminal *> &conductorsToUpdate(); const QHash<Conductor *, Terminal *> &conductorsToUpdate();
const QSet<IndependentTextItem *> &independentTextsToMove(); const QSet<IndependentTextItem *> &independentTextsToMove();
const QSet<ElementTextItem *> &elementTextsToMove();
QSet<DiagramTextItem *> selectedTexts() const; QSet<DiagramTextItem *> selectedTexts() const;
QSet<Conductor *> selectedConductors() const; QSet<Conductor *> selectedConductors() const;
DiagramContent content() const; DiagramContent content() const;
DiagramContent selectedContent(); DiagramContent selectedContent();
bool canRotateSelection() const; bool canRotateSelection() const;
void moveElements(const QPointF &, QGraphicsItem * = 0); void moveElements(const QPointF &, QGraphicsItem * = 0);
void moveElementsTexts(const QPointF &, ElementTextItem * = 0);
bool usesElement(const ElementsLocation &); bool usesElement(const ElementsLocation &);
QUndoStack &undoStack(); QUndoStack &undoStack();
@@ -292,6 +296,12 @@ inline const QSet<IndependentTextItem *> &Diagram::independentTextsToMove() {
return(texts_to_move); 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 /// @return la pile d'annulations de ce schema
inline QUndoStack &Diagram::undoStack() { inline QUndoStack &Diagram::undoStack() {
return(*undo_stack); return(*undo_stack);

View File

@@ -19,6 +19,7 @@
#include "element.h" #include "element.h"
#include "conductor.h" #include "conductor.h"
#include "diagram.h" #include "diagram.h"
#include "elementtextitem.h"
#include "independenttextitem.h" #include "independenttextitem.h"
#include "qgimanager.h" #include "qgimanager.h"
#include "diagram.h" #include "diagram.h"
@@ -366,6 +367,64 @@ void MoveElementsCommand::move(const QPointF &actual_movement) {
} }
} }
/**
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 Constructeur
@param dti Champ de texte modifie @param dti Champ de texte modifie

View File

@@ -27,6 +27,7 @@
class Diagram; class Diagram;
class DiagramTextItem; class DiagramTextItem;
class Element; class Element;
class ElementTextItem;
class IndependentTextItem; class IndependentTextItem;
/** /**
@@ -201,6 +202,36 @@ class MoveElementsCommand : public QUndoCommand {
bool first_redo; bool first_redo;
}; };
/**
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 Cette classe represente la modification d'un champ de texte
*/ */

View File

@@ -33,7 +33,7 @@ DiagramTextItem::DiagramTextItem(QGraphicsItem *parent, Diagram *parent_diagram)
{ {
setDefaultTextColor(Qt::black); setDefaultTextColor(Qt::black);
setFont(QETApp::diagramTextsFont()); setFont(QETApp::diagramTextsFont());
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemSendsGeometryChanges);
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable())); connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
} }
@@ -51,7 +51,7 @@ DiagramTextItem::DiagramTextItem(const QString &text, QGraphicsItem *parent, Dia
{ {
setDefaultTextColor(Qt::black); setDefaultTextColor(Qt::black);
setFont(QETApp::diagramTextsFont()); setFont(QETApp::diagramTextsFont());
setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable|QGraphicsItem::ItemSendsGeometryChanges);
connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable())); connect(this, SIGNAL(lostFocus()), this, SLOT(setNonFocusable()));
} }
@@ -98,6 +98,82 @@ void DiagramTextItem::rotateBy(const qreal &added_rotation) {
applyRotation(applied_added_rotation); applyRotation(applied_added_rotation);
} }
/**
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 Gere les changements dont ce champ de texte est informe
*/ */

View File

@@ -52,6 +52,10 @@ class DiagramTextItem : public QGraphicsTextItem {
qreal rotationAngle() const; qreal rotationAngle() const;
void setRotationAngle(const qreal &); void setRotationAngle(const qreal &);
void rotateBy(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: protected:
virtual QVariant itemChange(GraphicsItemChange, const QVariant &); virtual QVariant itemChange(GraphicsItemChange, const QVariant &);

View File

@@ -32,8 +32,7 @@ ElementTextItem::ElementTextItem(Element *parent_element, Diagram *parent_diagra
original_rotation_angle_(0.0) original_rotation_angle_(0.0)
{ {
// par defaut, les DiagramTextItem sont Selectable et Movable // par defaut, les DiagramTextItem sont Selectable et Movable
// on desactive Movable pour les textes des elements // cela nous convient, on ne touche pas a ces flags
setFlag(QGraphicsItem::ItemIsMovable, false);
// ajuste la position du QGraphicsItem lorsque le QTextDocument change // ajuste la position du QGraphicsItem lorsque le QTextDocument change
connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int))); connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int)));
@@ -52,8 +51,7 @@ ElementTextItem::ElementTextItem(const QString &text, Element *parent_element, D
original_rotation_angle_(0.0) original_rotation_angle_(0.0)
{ {
// par defaut, les DiagramTextItem sont Selectable et Movable // par defaut, les DiagramTextItem sont Selectable et Movable
// on desactive Movable pour les textes des elements // cela nous convient, on ne touche pas a ces flags
setFlag(QGraphicsItem::ItemIsMovable, false);
// ajuste la position du QGraphicsItem lorsque le QTextDocument change // ajuste la position du QGraphicsItem lorsque le QTextDocument change
connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int))); connect(document(), SIGNAL(blockCountChanged(int)), this, SLOT(adjustItemPosition(int)));
@@ -118,6 +116,15 @@ void ElementTextItem::fromXml(const QDomElement &e) {
qFuzzyCompare(qreal(e.attribute("y").toDouble()), _pos.y()) qFuzzyCompare(qreal(e.attribute("y").toDouble()), _pos.y())
) { ) {
setPlainText(e.attribute("text")); 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; qreal xml_rotation_angle;
if (QET::attributeIsAReal(e, "userrotation", &xml_rotation_angle)) { if (QET::attributeIsAReal(e, "userrotation", &xml_rotation_angle)) {
setRotationAngle(xml_rotation_angle); setRotationAngle(xml_rotation_angle);
@@ -131,12 +138,21 @@ void ElementTextItem::fromXml(const QDomElement &e) {
*/ */
QDomElement ElementTextItem::toXml(QDomDocument &document) const { QDomElement ElementTextItem::toXml(QDomDocument &document) const {
QDomElement result = document.createElement("input"); QDomElement result = document.createElement("input");
result.setAttribute("x", QString("%1").arg(originalPos().x())); result.setAttribute("x", QString("%1").arg(originalPos().x()));
result.setAttribute("y", QString("%1").arg(originalPos().y())); 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()); result.setAttribute("text", toPlainText());
if (rotationAngle() != originalRotationAngle()) { if (rotationAngle() != originalRotationAngle()) {
result.setAttribute("userrotation", QString("%1").arg(rotationAngle())); result.setAttribute("userrotation", QString("%1").arg(rotationAngle()));
} }
return(result); return(result);
} }
@@ -180,7 +196,7 @@ qreal ElementTextItem::originalRotationAngle() const {
*/ */
void ElementTextItem::adjustItemPosition(int new_block_count) { void ElementTextItem::adjustItemPosition(int new_block_count) {
Q_UNUSED(new_block_count); Q_UNUSED(new_block_count);
setPos(originalPos()); setPos(known_position_);
} }
/** /**
@@ -199,3 +215,80 @@ void ElementTextItem::applyRotation(const qreal &angle) {
QGraphicsTextItem::setTransform(rotation, true); 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));
}

View File

@@ -45,6 +45,7 @@ class ElementTextItem : public DiagramTextItem {
Element *parent_element_; Element *parent_element_;
bool follow_parent_rotations; bool follow_parent_rotations;
QPointF original_position; QPointF original_position;
QPointF known_position_;
qreal original_rotation_angle_; qreal original_rotation_angle_;
// methodes // methodes
@@ -70,6 +71,9 @@ class ElementTextItem : public DiagramTextItem {
protected: protected:
virtual void applyRotation(const qreal &); virtual void applyRotation(const qreal &);
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *);
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *);
virtual QVariant itemChange(GraphicsItemChange, const QVariant &);
}; };
/** /**