diff --git a/diagram.cpp b/diagram.cpp index 1eae21c28..60087ddf7 100644 --- a/diagram.cpp +++ b/diagram.cpp @@ -379,3 +379,42 @@ QRectF Diagram::border() const { ); } +/// oublie la liste des elements et conducteurs en mouvement +void Diagram::invalidateMovedElements() { + if (!moved_elements_fetched) return; + moved_elements_fetched = false; + elements_to_move.clear(); + conducers_to_move.clear(); + conducers_to_update.clear(); +} + +/// reconstruit la liste des elements et conducteurs en mouvement +void Diagram::fetchMovedElements() { + // recupere les elements deplaces + foreach (QGraphicsItem *item, selectedItems()) { + if (Element *elmt = qgraphicsitem_cast(item)) { + elements_to_move << elmt; + } + } + + // pour chaque element deplace, determine les conducteurs qui seront modifies + foreach(Element *elmt, elements_to_move) { + foreach(Terminal *terminal, elmt -> terminals()) { + foreach(Conducer *conducer, terminal -> conducers()) { + Terminal *other_terminal; + if (conducer -> terminal1 == terminal) { + other_terminal = conducer -> terminal2; + } else { + other_terminal = conducer -> terminal1; + } + // si les deux elements du conducteur sont deplaces + if (elements_to_move.contains(static_cast(other_terminal -> parentItem()))) { + conducers_to_move << conducer; + } else { + conducers_to_update.insert(conducer, terminal); + } + } + } + } + moved_elements_fetched = true; +} diff --git a/diagram.h b/diagram.h index fbd57e77b..e8945e428 100644 --- a/diagram.h +++ b/diagram.h @@ -9,6 +9,7 @@ #include "borderinset.h" class Element; class Terminal; +class Conducer; class Diagram : public QGraphicsScene { Q_OBJECT @@ -29,6 +30,10 @@ class Diagram : public QGraphicsScene { QGraphicsLineItem *conducer_setter; bool draw_grid; bool use_border; + bool moved_elements_fetched; + QSet elements_to_move; + QSet conducers_to_move; + QHash conducers_to_update; // methodes public: @@ -55,6 +60,12 @@ class Diagram : public QGraphicsScene { QImage toImage(int = -1, int = -1, Qt::AspectRatioMode = Qt::KeepAspectRatio); QSize imageSize() const; + void invalidateMovedElements(); + void fetchMovedElements(); + const QSet &elementsToMove(); + const QSet &conducersToMove(); + const QHash &conducersToUpdate(); + private slots: void slot_checkSelectionEmptinessChange(); @@ -149,4 +160,22 @@ inline Diagram::BorderOptions Diagram::borderOptions() { return(retour); } +/// @return la liste des elements a deplacer +inline const QSet &Diagram::elementsToMove() { + if (!moved_elements_fetched) fetchMovedElements(); + return(elements_to_move); +} + +/// @return la liste des conducteurs a deplacer +inline const QSet &Diagram::conducersToMove() { + if (!moved_elements_fetched) fetchMovedElements(); + return(conducers_to_move); +} + +/// @return la liste des conducteurs a modifier (typiquement les conducteurs dont seul un element est deplace) +inline const QHash &Diagram::conducersToUpdate() { + if (!moved_elements_fetched) fetchMovedElements(); + return(conducers_to_update); +} + #endif diff --git a/element.cpp b/element.cpp index ed13bd4dc..7342396e6 100644 --- a/element.cpp +++ b/element.cpp @@ -1,5 +1,6 @@ #include "element.h" #include "diagram.h" +#include "conducer.h" #include "elementtextitem.h" #include @@ -103,21 +104,6 @@ QPixmap Element::pixmap() { return(apercu); } -/** - 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::ItemPositionHasChanged) { - foreach(QGraphicsItem *qgi, children()) { - if (Terminal *p = qgraphicsitem_cast(qgi)) p -> updateConducer(value.toPointF()); - } - } - return(QGraphicsItem::itemChange(change, value)); -} - /** Permet de specifier l'orientation de l'element @param o la nouvelle orientation de l'objet @@ -187,7 +173,7 @@ void Element::drawSelection(QPainter *painter, const QStyleOptionGraphicsItem *) t.setStyle(Qt::DashDotLine); painter -> setPen(t); // Le dessin se fait a partir du rectangle delimitant - painter -> drawRoundRect(boundingRect(), 10, 10); + painter -> drawRoundRect(boundingRect().adjusted(1, 1, -1, -1), 10, 10); painter -> restore(); } @@ -236,7 +222,7 @@ void Element::setPos(qreal x, qreal y) { } /** - Gere les mouvements de souris lies a l'element, notamment + Gere les mouvements de souris lies a l'element */ void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { if (e -> buttons() & Qt::LeftButton) { @@ -244,22 +230,41 @@ void Element::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { setPos(mapToParent(e -> pos()) - matrix().map(e -> buttonDownPos(Qt::LeftButton))); QPointF diff = pos() - oldPos; - // Recupere la liste des elements selectionnes - QList selectedItems; - if (scene()) { - selectedItems = scene() -> selectedItems(); - } else if (QGraphicsItem *parent = parentItem()) { - while (parent && parent -> isSelected()) selectedItems << parent; + // inutile de deplacer les autres elements s'il n'y a pas eu de mouvement concret + if (diff.isNull()) return; + + // recupere le schema parent + if (!scene()) return; + Diagram *diagram = qobject_cast(scene()); + if (!diagram) return; + + // deplace les elements selectionnes + foreach(Element *element, diagram -> elementsToMove()) { + if (element == this) continue; + element -> setPos(element -> pos() + diff); + }; + + // deplace certains conducteurs + foreach(Conducer *conducer, diagram -> conducersToMove()) { + conducer -> setPos(conducer -> pos() + diff); } - // Deplace tous les elements selectionnes - foreach (QGraphicsItem *item, selectedItems) { - if (!item -> parentItem() || !item -> parentItem() -> isSelected()) - if (item != this && qgraphicsitem_cast(item)) item -> setPos(item -> pos() + diff); + // recalcule les autres conducteurs + const QHash &conducers_modify = diagram -> conducersToUpdate(); + foreach(Conducer *conducer, conducers_modify.keys()) { + conducer -> updateWithNewPos(QRectF(), conducers_modify[conducer], conducers_modify[conducer] -> scenePos()); } } else e -> ignore(); } +void Element::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { + if (scene()) { + Diagram *diagram = qobject_cast(scene()); + if (diagram) diagram -> invalidateMovedElements(); + } + QGraphicsItem::mouseReleaseEvent(e); +} + /** Permet de savoir si un element XML (QDomElement) represente bien un element @param e Le QDomElement a valide diff --git a/element.h b/element.h index ff225866a..c544f0453 100644 --- a/element.h +++ b/element.h @@ -45,7 +45,6 @@ class Element : public QGraphicsItem { virtual QString nom() const = 0; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); - QVariant itemChange(GraphicsItemChange, const QVariant &); QRectF boundingRect() const; QSize setSize(int, int); QPixmap pixmap(); @@ -78,6 +77,7 @@ class Element : public QGraphicsItem { protected: void drawAxes(QPainter *, const QStyleOptionGraphicsItem *); void mouseMoveEvent(QGraphicsSceneMouseEvent *); + void mouseReleaseEvent(QGraphicsSceneMouseEvent *); private: bool peut_relier_ses_propres_terminals; diff --git a/terminal.cpp b/terminal.cpp index b032c81a2..2775a86e6 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -40,7 +40,7 @@ void Terminal::initialise(QPointF pf, QET::Orientation o) { setAcceptsHoverEvents(true); setAcceptedMouseButtons(Qt::LeftButton); hovered = false; - setToolTip("Terminal"); + setToolTip(QObject::tr("Borne")); } /**