diff --git a/borne.cpp b/borne.cpp index 50dac75ce..8c7ae9f6a 100644 --- a/borne.cpp +++ b/borne.cpp @@ -334,10 +334,19 @@ void Borne::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { /** Met a jour l'eventuel conducteur relie a la Borne. + @param newpos Position de l'element parent a prendre en compte */ -void Borne::updateConducteur() { - if (scene()) { - foreach (Conducteur *conducteur, liste_conducteurs) if (!conducteur -> isDestroyed()) conducteur -> update(QRectF()/*scene()->sceneRect()*/); +void Borne::updateConducteur(QPointF newpos) { + if (!scene() || !parentItem()) return; + foreach (Conducteur *conducteur, liste_conducteurs) { + if (conducteur -> isDestroyed()) continue; + if (newpos == QPointF()) conducteur -> update(QRectF()); + else { + // determine la translation subie par l'element parent + QPointF translation = newpos - parentItem() -> pos(); + // rafraichit le conducteur en tenant compte de la translation + conducteur -> updateWithNewPos(QRectF(), this, amarrageConducteur() + translation); + } } } @@ -409,3 +418,4 @@ bool Borne::fromXml(QDomElement &borne) { borne.attribute("orientation").toInt() == sens ); } + diff --git a/borne.h b/borne.h index 693c3a431..a974fda86 100644 --- a/borne.h +++ b/borne.h @@ -40,7 +40,7 @@ QList conducteurs() const; Borne::Orientation orientation() const; inline QPointF amarrageConducteur() const { return(mapToScene(amarrage_conducteur)); } - void updateConducteur(); + void updateConducteur(QPointF = QPointF()); // methodes relatives a l'import/export au format XML static bool valideXml(QDomElement &); diff --git a/conducteur.cpp b/conducteur.cpp index d01d3af1e..cddaa4d05 100644 --- a/conducteur.cpp +++ b/conducteur.cpp @@ -37,6 +37,18 @@ void Conducteur::update(const QRectF &rect = QRectF()) { QGraphicsPathItem::update(rect); } +/** + Met a jour la representation graphique du conducteur en considerant que la borne b + a pour position pos + @param rect Rectangle a mettre a jour + @param b Borne + @param pos position de la borne b +*/ +void Conducteur::updateWithNewPos(const QRectF &rect, const Borne *b, const QPointF &newpos) { + calculeConducteurWithNewPos(b, newpos); + QGraphicsPathItem::update(rect); +} + /** Met a jour la representation graphique du conducteur. @param x abscisse du rectangle a mettre a jour @@ -54,11 +66,32 @@ void Conducteur::update(qreal x, qreal y, qreal width, qreal height) { un conducteur uniquement compose de droites reliant les deux bornes. */ void Conducteur::calculeConducteur() { - QPainterPath t; - QPointF p1 = borne1 -> amarrageConducteur(); QPointF p2 = borne2 -> amarrageConducteur(); - + priv_calculeConducteur(p1, p2); +} + +/** + Met a jour le QPainterPath constituant le conducteur pour obtenir + un conducteur uniquement compose de droites reliant les deux bornes. +*/ +void Conducteur::calculeConducteurWithNewPos(const Borne *b, const QPointF &newpos) { + QPointF p1, p2; + if (b == borne1) { + p1 = newpos; + p2 = borne2 -> amarrageConducteur(); + } else if (b == borne2) { + p1 = borne1 -> amarrageConducteur(); + p2 = newpos; + } else { + p1 = borne1 -> amarrageConducteur(); + p2 = borne2 -> amarrageConducteur(); + } + priv_calculeConducteur(p1, p2); +} + +void Conducteur::priv_calculeConducteur(const QPointF &p1, const QPointF &p2) { + QPainterPath t; QPointF depart, arrivee; Borne::Orientation ori_depart, ori_arrivee; // distingue le depart de l'arrivee : le trajet se fait toujours de gauche a droite diff --git a/conducteur.h b/conducteur.h index 8be86593e..11f17ec7f 100644 --- a/conducteur.h +++ b/conducteur.h @@ -15,8 +15,9 @@ void destroy(); bool isDestroyed() const { return(destroyed); } - void update(const QRectF & rect); - void update(qreal x, qreal y, qreal width, qreal height); + void updateWithNewPos(const QRectF &, const Borne *, const QPointF &); + void update(const QRectF &); + void update(qreal, qreal, qreal, qreal); void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); static bool valideXml(QDomElement &); @@ -29,6 +30,8 @@ bool destroyed; void calculeConducteur(); + void calculeConducteurWithNewPos(const Borne *, const QPointF &); + void priv_calculeConducteur(const QPointF &, const QPointF &); bool surLeMemeAxe(Borne::Orientation, Borne::Orientation); bool estHorizontale(Borne::Orientation a); bool estVerticale(Borne::Orientation a); diff --git a/element.cpp b/element.cpp index a9346d3e3..3154303a5 100644 --- a/element.cpp +++ b/element.cpp @@ -98,10 +98,17 @@ QPixmap Element::pixmap() { } /** - @todo distinguer les bornes avec un cast dynamique + Gere les changements d'etat de l'element + @param change type du changement d'etat + @param value valeur du changement d'etat + @return la valeur du changement d'etat */ QVariant Element::itemChange(GraphicsItemChange change, const QVariant &value) { - if (change == QGraphicsItem::ItemPositionChange || change == QGraphicsItem::ItemSelectedChange) { + if (change == QGraphicsItem::ItemPositionChange) { + foreach(QGraphicsItem *qgi, children()) { + if (Borne *p = qgraphicsitem_cast(qgi)) p -> updateConducteur(value.toPointF()); + } + } else if (change == QGraphicsItem::ItemSelectedChange) { foreach(QGraphicsItem *qgi, children()) { if (Borne *p = qgraphicsitem_cast(qgi)) p -> updateConducteur(); } @@ -192,10 +199,6 @@ void Element::setPos(const QPointF &p) { int p_y = qRound(p.y() / 10.0) * 10; QGraphicsItem::setPos(p_x, p_y); } else QGraphicsItem::setPos(p); - // actualise les bornes / conducteurs - foreach(QGraphicsItem *qgi, children()) { - if (Borne *p = qgraphicsitem_cast(qgi)) p -> updateConducteur(); - } } /** @@ -215,7 +218,7 @@ void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { /*&& (flags() & ItemIsMovable)*/ // on le sait qu'il est movable if (e -> buttons() & Qt::LeftButton) { QPointF oldPos = pos(); - setPos(mapToParent(e->pos()) - matrix().map(e->buttonDownPos(Qt::LeftButton))); + setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton))); QPointF diff = pos() - oldPos; // Recupere la liste des elements selectionnes @@ -223,13 +226,13 @@ void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { if (scene()) { selectedItems = scene() -> selectedItems(); } else if (QGraphicsItem *parent = parentItem()) { - while (parent && parent->isSelected()) selectedItems << parent; + while (parent && parent -> isSelected()) selectedItems << parent; } // Deplace tous les elements selectionnes foreach (QGraphicsItem *item, selectedItems) { - if (!item->parentItem() || !item->parentItem()->isSelected()) - if (item != this) item->setPos(item->pos() + diff); + if (!item -> parentItem() || !item -> parentItem() -> isSelected()) + if (item != this) item -> setPos(item -> pos() + diff); } } else e -> ignore(); } diff --git a/schema.cpp b/schema.cpp index 231433daa..b1a938e4f 100644 --- a/schema.cpp +++ b/schema.cpp @@ -18,6 +18,7 @@ Schema::Schema(QObject *parent) : QGraphicsScene(parent) { poseur_de_conducteur -> setPen(t); poseur_de_conducteur -> setLine(QLineF(QPointF(0.0, 0.0), QPointF(0.0, 0.0))); doit_dessiner_grille = true; + translation = QPoint(0, 0); connect(this, SIGNAL(changed(const QList &)), this, SLOT(slot_checkSelectionChange())); } @@ -332,3 +333,54 @@ void Schema::slot_checkSelectionChange() { if (cache_selecteditems != selecteditems) emit(selectionChanged()); cache_selecteditems = selecteditems; } + +/** + Gere les mouvements de souris sur le schema et, ipso facto, les + deplacements d'elements. Cette fonction veille a ne deplacer que les + elements (les conducteurs sont remis a jour par les bornes des elements) + et tient compte de la grille. + @param mouseEvent Un QGraphicsSceneMouseEvent decrivant l'evenement + "mouvement de souris" +*/ +void Schema::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent) { + if (mouseEvent -> buttons() & Qt::LeftButton) { + translation += (mouseEvent -> scenePos() - mouseEvent -> lastScenePos()).toPoint(); + + bool doit_translater = false; + int coeffx = 0, coeffy = 0; + + if (translation.x() >= GRILLE_X) { + doit_translater = true; + coeffx = translation.x() / GRILLE_X; + translation.setX(translation.x() % GRILLE_X); + } else if (translation.x() <= -GRILLE_X) { + doit_translater = true; + coeffx = translation.x() / GRILLE_X; + translation.setX(translation.x() % GRILLE_X); + } + + if (translation.y() >= GRILLE_Y) { + doit_translater = true; + coeffy = translation.y() / GRILLE_Y; + translation.setY(translation.y() % GRILLE_Y); + } else if (translation.y() <= -GRILLE_Y) { + doit_translater = true; + coeffy = translation.y() / GRILLE_Y; + translation.setY(translation.y() % GRILLE_Y); + } + + if (doit_translater) { + // parcourt la listes des QGraphicsItem + foreach (QGraphicsItem *qgi, selectedItems()) { + // translate uniquement les elements (pas les conducteurs) + if (Element *e = qgraphicsitem_cast(qgi)) + e -> setPos(e -> pos() + QPointF(GRILLE_X * coeffx, GRILLE_Y * coeffy)); + } + } + } +} + +void Schema::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent) { + translation = QPoint(0, 0); + QGraphicsScene::mouseReleaseEvent(mouseEvent); +} diff --git a/schema.h b/schema.h index 42ff34539..0d3f9cbd0 100644 --- a/schema.h +++ b/schema.h @@ -33,10 +33,14 @@ QString folio; // vraiment necessaire ce truc ? QString nom_fichier; // meme remarque + protected: + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *); + virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *); private: QGraphicsLineItem *poseur_de_conducteur; bool doit_dessiner_grille; Element *elementFromXml(QDomElement &e, QHash &); + QPoint translation; private slots: void slot_checkSelectionChange();