diff --git a/conducer.cpp b/conducer.cpp index dc94270ad..91f883075 100644 --- a/conducer.cpp +++ b/conducer.cpp @@ -3,6 +3,7 @@ #include "conducersegment.h" #include "conducersegmentprofile.h" #include "element.h" +#include "diagram.h" #define PR(x) qDebug() << #x " = " << x; bool Conducer::pen_and_brush_initialized = false; @@ -55,7 +56,6 @@ Conducer::Conducer(Terminal *p1, Terminal* p2, Element *parent, QGraphicsScene * text_item -> setPlainText("_"); text_item -> setTextInteractionFlags(Qt::TextEditorInteraction); calculateTextItemPosition(); - scene -> addItem(text_item); text_item -> setParentItem(this); } @@ -457,6 +457,11 @@ void Conducer::destroy() { terminal2 -> removeConducer(this); } +/// @return le Diagram auquel ce conducteur appartient, ou 0 si ce conducteur est independant +Diagram *Conducer::diagram() const { + return(qobject_cast(scene())); +} + /** Methode de validation d'element XML @param e Un element XML sense represente un Conducteur @@ -523,14 +528,6 @@ void Conducer::mousePressEvent(QGraphicsSceneMouseEvent *e) { /** Gere les deplacements de souris sur le conducteur. @param e L'evenement decrivant le deplacement de souris. - @todo - -calculer le trajet du conducteur differemment selon l'etat du flag "trajet modifie" - -garder une liste des points constituants le trajet - -lorsque le fil est selectionne, dessiner ces points (cercles) - -lors d'un mousemoveevent: detecter la position du clic : si cela tombe dans la zone d'un point : - -deplacer ce point en consequence - -mettre le flag "trajet modifie" a true - -gerer les contraintes */ void Conducer::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { // clic gauche diff --git a/conducer.h b/conducer.h index 6fa707c27..0b7b1f122 100644 --- a/conducer.h +++ b/conducer.h @@ -50,6 +50,7 @@ class Conducer : public QGraphicsPathItem { virtual int type() const { return Type; } void destroy(); bool isDestroyed() const { return(destroyed); } + Diagram *diagram() const; void updateWithNewPos(const QRectF &, const Terminal *, const QPointF &); void update(const QRectF & = QRectF()); void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); diff --git a/customelement.cpp b/customelement.cpp index f7d78cbb3..d29050e46 100644 --- a/customelement.cpp +++ b/customelement.cpp @@ -421,7 +421,7 @@ bool CustomElement::parseTerminal(QDomElement &e) { else if (e.attribute("orientation") == "e") terminalo = QET::East; else if (e.attribute("orientation") == "w") terminalo = QET::West; else return(false); - list_terminals << new Terminal(terminalx, terminaly, terminalo, this); + list_terminals << new Terminal(terminalx, terminaly, terminalo, this, qobject_cast(scene())); return(true); } diff --git a/diagram.cpp b/diagram.cpp index d148d772c..d291eb0c2 100644 --- a/diagram.cpp +++ b/diagram.cpp @@ -9,7 +9,7 @@ Constructeur @param parent Le QObject parent du schema */ -Diagram::Diagram(QObject *parent) : QGraphicsScene(parent) { +Diagram::Diagram(QObject *parent) : QGraphicsScene(parent), qgi_manager(this) { setBackgroundBrush(Qt::white); conducer_setter = new QGraphicsLineItem(0, 0); conducer_setter -> setZValue(1000000); @@ -156,7 +156,6 @@ QImage Diagram::toImage(int width, int height, Qt::AspectRatioMode aspectRatioMo /** Permet de connaitre les dimensions qu'aura l'image generee par la methode toImage() @return La taille de l'image generee par toImage() - @todo tenir compte des arguments */ QSize Diagram::imageSize() const { // determine la zone source = contenu du schema + marges @@ -259,7 +258,6 @@ QDomDocument Diagram::toXml(bool diagram) { bool Diagram::fromXml(QDomDocument &document, QPointF position, bool consider_informations) { QDomElement racine = document.documentElement(); // le premier element doit etre un schema - /// @todo renommer schema en diagram if (racine.tagName() != "diagram") return(false); // lecture des attributs de ce schema diff --git a/diagram.h b/diagram.h index 4c58f1845..0c5fae12c 100644 --- a/diagram.h +++ b/diagram.h @@ -7,6 +7,7 @@ #include #include "qetdiagrameditor.h" #include "borderinset.h" +#include "qgimanager.h" class Element; class Terminal; class Conducer; @@ -34,6 +35,9 @@ class Diagram : public QGraphicsScene { QSet elements_to_move; QSet conducers_to_move; QHash conducers_to_update; + QGIManager qgi_manager; + QUndoStack undo_stack; + // methodes public: @@ -68,6 +72,9 @@ class Diagram : public QGraphicsScene { const QSet &conducersToMove(); const QHash &conducersToUpdate(); + QUndoStack &undoStack(); + QGIManager &qgiManager(); + private slots: void slot_checkSelectionEmptinessChange(); @@ -180,4 +187,14 @@ inline const QHash &Diagram::conducersToUpdate() { return(conducers_to_update); } +/// @return la pile d'annulations de ce schema +inline QUndoStack &Diagram::undoStack() { + return(undo_stack); +} + +/// @return le egstionnaire de QGraphicsItem de ce schema +inline QGIManager &Diagram::qgiManager() { + return(qgi_manager); +} + #endif diff --git a/diagramcommands.cpp b/diagramcommands.cpp new file mode 100644 index 000000000..2a6abdbd8 --- /dev/null +++ b/diagramcommands.cpp @@ -0,0 +1,132 @@ +#include "diagramcommands.h" +#include "element.h" +#include "conducer.h" +#include "diagram.h" +#include "qgimanager.h" +/** + Constructeur + @param name Nom de la partie ajoutee + @param parts Liste des parties deplacees + @param parent QUndoCommand parent +*/ +AddElementCommand::AddElementCommand( + Diagram *d, + Element *elmt, + const QPointF &p, + QUndoCommand *parent +) : + QUndoCommand(QObject::tr("ajout ") + elmt -> nom(), parent), + element(elmt), + diagram(d), + position(p) +{ + diagram -> qgiManager().manage(element); +} + +/// Destructeur +AddElementCommand::~AddElementCommand() { + diagram -> qgiManager().release(element); +} + +/// Annule l'ajout +void AddElementCommand::undo() { + diagram -> removeItem(element); +} + +/// Refait l'ajout +void AddElementCommand::redo() { + diagram -> addItem(element); + element -> setPos(position); + element -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); +} + +/** + Constructeur + @param d Schema auquel on ajoute un conducteur + @param t1 Premiere borne du conducteur + @param t2 Seconde borne du conducteur + @param parent QUndoCommand parent +*/ +AddConducerCommand::AddConducerCommand( + Diagram *d, + Conducer *c, + QUndoCommand *parent +) : + QUndoCommand(QObject::tr("ajout conducteur"), parent), + conducer(c), + diagram(d) +{ + diagram -> qgiManager().manage(conducer); +} + +/// Destructeur +AddConducerCommand::~AddConducerCommand() { + diagram -> qgiManager().release(conducer); +} + +/// Annule l'ajout +void AddConducerCommand::undo() { + // detache le conducteur sans le detruire + conducer -> terminal1 -> removeConducer(conducer); + conducer -> terminal2 -> removeConducer(conducer); + diagram -> removeItem(conducer); +} + +/// Refait l'ajout +void AddConducerCommand::redo() { + diagram -> addItem(conducer); +} + +/** + Constructeur +*/ +DeleteElementsCommand::DeleteElementsCommand( + Diagram *dia, + QSet elements, + QSet conducers, + QUndoCommand *parent +) : + QUndoCommand(parent), + removed_elements(elements), + removed_conducers(conducers), + diagram(dia) +{ + foreach(QGraphicsItem *qgi, removed_elements) diagram -> qgiManager().manage(qgi); + foreach(QGraphicsItem *qgi, removed_conducers) diagram -> qgiManager().manage(qgi); +} + +/// Destructeur +DeleteElementsCommand::~DeleteElementsCommand() { + foreach(QGraphicsItem *qgi, removed_elements) diagram -> qgiManager().release(qgi); + foreach(QGraphicsItem *qgi, removed_conducers) diagram -> qgiManager().release(qgi); +} + +/// annule les suppressions +void DeleteElementsCommand::undo() { + // remet les elements + foreach(Element *e, removed_elements) { + diagram -> addItem(e); + } + + // remet les conducteurs + foreach(Conducer *c, removed_conducers) { + diagram -> addItem(c); + c -> terminal1 -> addConducer(c); + c -> terminal2 -> addConducer(c); + } +} + +/// refait les suppressions +void DeleteElementsCommand::redo() { + // enleve les conducteurs + foreach(Conducer *c, removed_conducers) { + c -> terminal1 -> removeConducer(c); + c -> terminal2 -> removeConducer(c); + diagram -> removeItem(c); + } + + // enleve les elements + foreach(Element *e, removed_elements) { + diagram -> removeItem(e); + } +} diff --git a/diagramcommands.h b/diagramcommands.h new file mode 100644 index 000000000..e4b212fbd --- /dev/null +++ b/diagramcommands.h @@ -0,0 +1,79 @@ +#ifndef DIAGRAM_COMMANDS_H +#define DIAGRAM_COMMANDS_H +#include "diagram.h" +#include +/** + Cette classe represente l'action d'ajouter un element au schema +*/ +class AddElementCommand : public QUndoCommand { + // constructeurs, destructeur + public: + AddElementCommand(Diagram *, Element *, const QPointF &, QUndoCommand * = 0); + virtual ~AddElementCommand(); + private: + AddElementCommand(const AddElementCommand &); + + // methodes + virtual void undo(); + virtual void redo(); + + // attributs + private: + /// Element ajoute + Element *element; + /// schema sur lequel on ajoute l'element + Diagram *diagram; + /// position de l'element sur le schema + QPointF position; +}; + +/** + Cette classe represente l'action d'ajouter un conducteur au schema +*/ +class AddConducerCommand : public QUndoCommand { + // constructeurs, destructeur + public: + AddConducerCommand(Diagram *, Conducer *, QUndoCommand * = 0); + virtual ~AddConducerCommand(); + private: + AddConducerCommand(const AddConducerCommand &); + + // methodes + virtual void undo(); + virtual void redo(); + + // attributs + private: + /// Conducteur ajoute + Conducer *conducer; + /// schema auquel on ajoute le conducteur + Diagram *diagram; +}; + +/** + Cette classe represente l'action de supprimer des elements et / ou + conducteurs d'un schema +*/ +class DeleteElementsCommand : public QUndoCommand { + // constructeurs, destructeur + public: + DeleteElementsCommand(Diagram *, QSet, QSet, QUndoCommand * = 0); + virtual ~DeleteElementsCommand(); + private: + DeleteElementsCommand(const DeleteElementsCommand &); + + // methodes + virtual void undo(); + virtual void redo(); + + // attributs + private: + /// Liste des elements enleves + QSet removed_elements; + /// List des conducteurs enleves + QSet removed_conducers; + /// schema dont on supprime des elements et conducteurs + Diagram *diagram; +}; + +#endif diff --git a/diagramview.cpp b/diagramview.cpp index 44b7c5dac..82ef08b40 100644 --- a/diagramview.cpp +++ b/diagramview.cpp @@ -3,6 +3,7 @@ #include "customelement.h" #include "exportdialog.h" #include "conducer.h" +#include "diagramcommands.h" /** Initialise le DiagramView @@ -79,74 +80,23 @@ void DiagramView::selectInvert() { */ void DiagramView::supprimer() { - QList garbage_elmt; - QList garbage_conducers; + QSet garbage_elmt; + QSet garbage_conducers; // creation de deux listes : une pour les conducteurs, une pour les elements foreach (QGraphicsItem *qgi, scene -> selectedItems()) { // pour chaque qgi selectionne, il s'agit soit d'un element soit d'un conducteur - if (qgraphicsitem_cast(qgi)) { + if (Conducer * c = qgraphicsitem_cast(qgi)) { // s'il s'agit d'un conducteur, on le met dans la liste des conducteurs - if (!garbage_conducers.contains(qgi)) garbage_conducers.append(qgi); - } else if (qgraphicsitem_cast(qgi)) { + garbage_conducers << c; + } else if (Element *e = qgraphicsitem_cast(qgi)) { + garbage_elmt << e; // s'il s'agit d'un element, on veille a enlever ses conducteurs - if (!garbage_elmt.contains(qgi)) garbage_elmt.append(qgi); - // pour chaque enfant de l'element - foreach (QGraphicsItem *child, qgi -> children()) { - // si cet enfant est une borne - if (Terminal *p = qgraphicsitem_cast(child)) { - // alors chaque conducteur de la borne est recense - foreach (Conducer *f, p -> conducers()) { - if (!garbage_conducers.contains(f)) garbage_conducers.append(f); - } - } - } + garbage_conducers += e -> conducers().toSet(); } } scene -> clearSelection(); - - // "destroying" the wires, removing them from the scene and stocking them into the « garbage » - foreach (QGraphicsItem *qgi, garbage_conducers) { - if (Conducer *f = qgraphicsitem_cast(qgi)) { - f -> destroy(); - scene -> removeItem(f); - throwToGarbage(f); - } - } - - // removing the elements from the scene and stocking them into the « garbage » - foreach (QGraphicsItem *qgi, garbage_elmt) { - scene -> removeItem(qgi); - throwToGarbage(qgi); - } - resetCachedContent(); - QTimer::singleShot(5000, this, SLOT(flushGarbage())); -} - -/** - Envoie un item vers le "garbage" pour qu'il soit supprime plus tard - @param qgi L'item a supprimer -*/ -void DiagramView::throwToGarbage(QGraphicsItem *qgi) { - // pas de doublon dans le garbage (sinon ca va sentir la segfault) - bool qgi_deja_dans_le_garbage = false; - foreach(QGraphicsItem *gbg_qgi, garbage) { - if ((void *)gbg_qgi == (void *)qgi) { - qgi_deja_dans_le_garbage = true; - break; - } - } - if (!qgi_deja_dans_le_garbage) garbage.append(qgi); -} - -/** - Supprime tous les elements du "garbage" -*/ -void DiagramView::flushGarbage() { - foreach(QGraphicsItem *qgi, garbage) { - delete(qgi); - garbage.removeAll(qgi); - } + scene -> undoStack().push(new DeleteElementsCommand(scene, garbage_elmt, garbage_conducers)); } /** @@ -175,7 +125,8 @@ void DiagramView::dragEnterEvent(QDragEnterEvent *e) { gere les dragleaveevent @param e le QDragEnterEvent correspondant au drag'n drop sortant */ -void DiagramView::dragLeaveEvent(QDragLeaveEvent *) {} +void DiagramView::dragLeaveEvent(QDragLeaveEvent *) { +} /** accepte ou refuse le drag'n drop en fonction du type de donnees entrant @@ -194,11 +145,9 @@ void DiagramView::dropEvent(QDropEvent *e) { QString fichier = e -> mimeData() -> text(); int etat; Element *el = new CustomElement(fichier, 0, 0, &etat); - if (etat != 0) delete el; + if (etat) delete el; else { - scene -> addItem(el); - el -> setPos(mapToScene(e -> pos().x(), e -> pos().y())); - el -> setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); + diagram() -> undoStack().push(new AddElementCommand(diagram(), el, mapToScene(e -> pos()))); } } diff --git a/diagramview.h b/diagramview.h index 463c20712..b8c5a7879 100644 --- a/diagramview.h +++ b/diagramview.h @@ -44,7 +44,6 @@ class DiagramView : public QGraphicsView { private: bool private_enregistrer(QString &); void initialise(); - void throwToGarbage(QGraphicsItem *); void mousePressEvent(QMouseEvent *); void dragEnterEvent(QDragEnterEvent *); void dragLeaveEvent(QDragLeaveEvent *); @@ -74,7 +73,6 @@ class DiagramView : public QGraphicsView { void coller(); private slots: - void flushGarbage(); void slot_selectionChanged(); void adjustGridToZoom(); }; diff --git a/editor/editorcommands.cpp b/editor/editorcommands.cpp index 1af1827ed..a38632895 100644 --- a/editor/editorcommands.cpp +++ b/editor/editorcommands.cpp @@ -87,7 +87,8 @@ void MovePartsCommand::redo() { /** Constructeur @param name Nom de la partie ajoutee - @param parts Liste des parties deplacees + @param scene ElementScene concernee + @param p partie ajoutee @param parent QUndoCommand parent */ AddPartCommand::AddPartCommand( @@ -109,12 +110,12 @@ AddPartCommand::~AddPartCommand() { editor_scene -> qgiManager().release(part); } -/// Annule le deplacement +/// Annule l'ajout void AddPartCommand::undo() { editor_scene -> removeItem(part); } -/// Refait le deplacement +/// Refait l'ajout void AddPartCommand::redo() { // le premier appel a redo, lors de la construction de l'objet, ne doit pas se faire if (first_redo) { diff --git a/editor/editorcommands.h b/editor/editorcommands.h index 1a5a7ee82..c53f469dc 100644 --- a/editor/editorcommands.h +++ b/editor/editorcommands.h @@ -58,8 +58,8 @@ class MovePartsCommand : public QUndoCommand { }; /** - Cette classe represente l'action de deplacer une ou plusieurs - parties lors de l'edition d'un element + Cette classe represente l'action d'ajouter une partie lors de l'edition + d'un element */ class AddPartCommand : public QUndoCommand { // constructeurs, destructeur diff --git a/element.cpp b/element.cpp index ce04e448c..cb97d6251 100644 --- a/element.cpp +++ b/element.cpp @@ -457,3 +457,8 @@ QList Element::findInDomElement(QDomElement e, QString parent, QStr } return(return_list); } + +/// @return le Diagram auquel cet element appartient, ou 0 si cet element est independant +Diagram *Element::diagram() const { + return(qobject_cast(scene())); +} diff --git a/element.h b/element.h index f46517d7b..212b18632 100644 --- a/element.h +++ b/element.h @@ -43,6 +43,7 @@ class Element : public QGraphicsItem { virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0; virtual QString typeId() const = 0; virtual QString nom() const = 0; + Diagram *diagram() const; void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); QRectF boundingRect() const; diff --git a/elementtextitem.cpp b/elementtextitem.cpp index 4b0b27d9d..38e55fea5 100644 --- a/elementtextitem.cpp +++ b/elementtextitem.cpp @@ -1,4 +1,5 @@ #include "elementtextitem.h" +#include "diagram.h" /** Constructeur @@ -76,3 +77,8 @@ QDomElement ElementTextItem::toXml(QDomDocument &document) const { result.setAttribute("text", toPlainText()); return(result); } + +/// @return le Diagram auquel ce texte appartient, ou 0 si ce texte est independant +Diagram *ElementTextItem::diagram() const { + return(qobject_cast(scene())); +} diff --git a/elementtextitem.h b/elementtextitem.h index dca974501..314879649 100644 --- a/elementtextitem.h +++ b/elementtextitem.h @@ -2,6 +2,7 @@ #define ELEMENT_TEXT_ITEM_H #include #include +class Diagram; /** Cette classe represente un element de texte editable. Il est possible pour ce champ de texte de rester dans le sens de la lecture @@ -31,6 +32,7 @@ class ElementTextItem : public QGraphicsTextItem { void setPos(const QPointF &); void setPos(qreal, qreal); QPointF pos() const; + Diagram *diagram() const; }; /** diff --git a/ico/windows_icon/application_icon/qelectrotech.rc b/ico/windows_icon/application_icon/qelectrotech.rc index a977e72d1..787207f00 100644 --- a/ico/windows_icon/application_icon/qelectrotech.rc +++ b/ico/windows_icon/application_icon/qelectrotech.rc @@ -1 +1 @@ -IDI_ICON1 ICON DISCARDABLE "ico/windows_icon/application_icon/qet.ico" \ No newline at end of file +IDI_ICON1 ICON DISCARDABLE "ico/windows_icon/application_icon/qet.ico" diff --git a/qelectrotech.pro b/qelectrotech.pro index 7b3751a33..45122de8f 100644 --- a/qelectrotech.pro +++ b/qelectrotech.pro @@ -63,7 +63,8 @@ HEADERS += aboutqet.h \ editor/styleeditor.h \ editor/terminaleditor.h \ editor/texteditor.h \ - editor/textfieldeditor.h + editor/textfieldeditor.h \ + diagramcommands.h SOURCES += aboutqet.cpp \ borderinset.cpp \ conducer.cpp \ @@ -119,7 +120,8 @@ SOURCES += aboutqet.cpp \ editor/styleeditor.cpp \ editor/terminaleditor.cpp \ editor/texteditor.cpp \ - editor/textfieldeditor.cpp + editor/textfieldeditor.cpp \ + diagramcommands.cpp RESOURCES += qelectrotech.qrc TRANSLATIONS += lang/qet_en.ts lang/qt_fr.ts RC_FILE = ico/windows_icon/application_icon/qelectrotech.rc diff --git a/qetdiagrameditor.cpp b/qetdiagrameditor.cpp index f0874e15d..abee4f34e 100644 --- a/qetdiagrameditor.cpp +++ b/qetdiagrameditor.cpp @@ -1,6 +1,7 @@ #include "qetdiagrameditor.h" #include "qetapp.h" #include "diagramview.h" +#include "diagram.h" #include "elementspanelwidget.h" #include "aboutqet.h" @@ -94,7 +95,7 @@ QETDiagramEditor::~QETDiagramEditor() { void QETDiagramEditor::closeEvent(QCloseEvent *qce) { // quitte directement s'il n'y a aucun schema ouvert bool peut_quitter = true; - if (diagramEnCours()) { + if (currentDiagram()) { // sinon demande la permission de fermer chaque schema foreach(QWidget *fenetre, workspace.windowList()) { if (qobject_cast(fenetre)) { @@ -147,8 +148,10 @@ void QETDiagramEditor::actions() { imprimer = new QAction(QIcon(":/ico/print.png"), tr("Imprimer"), this); quitter_qet = new QAction(QIcon(":/ico/exit.png"), tr("&Quitter"), this); - annuler = new QAction(QIcon(":/ico/undo.png"), tr("Annu&ler"), this); - refaire = new QAction(QIcon(":/ico/redo.png"), tr("Re&faire"), this); + annuler = undo_group.createUndoAction(this, tr("Annuler")); + annuler -> setIcon(QIcon(":/ico/undo.png")); + refaire = undo_group.createRedoAction(this, tr("Refaire")); + refaire -> setIcon(QIcon(":/ico/redo.png")); couper = new QAction(QIcon(":/ico/cut.png"), tr("Co&uper"), this); copier = new QAction(QIcon(":/ico/copy.png"), tr("Cop&ier"), this); coller = new QAction(QIcon(":/ico/paste.png"), tr("C&oller"), this); @@ -228,7 +231,7 @@ void QETDiagramEditor::actions() { quitter_qet -> setStatusTip(tr("Ferme l'application QElectroTech")); annuler -> setStatusTip(tr("Annule l'action pr\351c\351dente")); - refaire -> setStatusTip(tr("Restaure l'action annul\351e")); + annuler -> setStatusTip(tr("Restaure l'action annul\351e")); couper -> setStatusTip(tr("Transf\350re les \351l\351ments s\351lectionn\351s dans le presse-papier")); copier -> setStatusTip(tr("Copie les \351l\351ments s\351lectionn\351s dans le presse-papier")); coller -> setStatusTip(tr("Place les \351l\351ments du presse-papier sur le sch\351ma")); @@ -435,7 +438,7 @@ void QETDiagramEditor::toolbar() { Imprime le schema courant */ void QETDiagramEditor::dialog_print() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> dialogPrint(); } @@ -444,7 +447,7 @@ void QETDiagramEditor::dialog_print() { Gere l'export de schema sous forme d'image */ void QETDiagramEditor::dialog_export() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> dialogExport(); } @@ -455,8 +458,8 @@ void QETDiagramEditor::dialog_export() { @return true si l'enregistrement a reussi, false sinon */ bool QETDiagramEditor::enregistrer() { - if (!diagramEnCours()) return(false); - return(diagramEnCours() -> enregistrer()); + if (!currentDiagram()) return(false); + return(currentDiagram() -> enregistrer()); } /** @@ -469,8 +472,8 @@ bool QETDiagramEditor::enregistrer() { @todo detecter le chemin du bureau automatiquement */ bool QETDiagramEditor::dialogue_enregistrer_sous() { - if (!diagramEnCours()) return(false); - return(diagramEnCours() -> enregistrer_sous()); + if (!currentDiagram()) return(false); + return(currentDiagram() -> enregistrer_sous()); } /** @@ -532,7 +535,7 @@ bool QETDiagramEditor::ouvrir() { @todo detecter les modifications et ne demander que si besoin est */ bool QETDiagramEditor::fermer() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return(false); return(sv -> close()); } @@ -540,7 +543,7 @@ bool QETDiagramEditor::fermer() { /** @return Le DiagramView qui a le focus dans l'interface MDI */ -DiagramView *QETDiagramEditor::diagramEnCours() const { +DiagramView *QETDiagramEditor::currentDiagram() const { return(qobject_cast(workspace.activeWindow())); } @@ -548,105 +551,105 @@ DiagramView *QETDiagramEditor::diagramEnCours() const { Effectue l'action "couper" sur le schema en cours */ void QETDiagramEditor::slot_couper() { - if(diagramEnCours()) diagramEnCours() -> couper(); + if(currentDiagram()) currentDiagram() -> couper(); } /** Effectue l'action "copier" sur le diagram en cours */ void QETDiagramEditor::slot_copier() { - if(diagramEnCours()) diagramEnCours() -> copier(); + if(currentDiagram()) currentDiagram() -> copier(); } /** Effectue l'action "coller" sur le schema en cours */ void QETDiagramEditor::slot_coller() { - if(diagramEnCours()) diagramEnCours() -> coller(); + if(currentDiagram()) currentDiagram() -> coller(); } /** Effectue l'action "zoom avant" sur le diagram en cours */ void QETDiagramEditor::slot_zoomPlus() { - if(diagramEnCours()) diagramEnCours() -> zoomPlus(); + if(currentDiagram()) currentDiagram() -> zoomPlus(); } /** Effectue l'action "zoom arriere" sur le schema en cours */ void QETDiagramEditor::slot_zoomMoins() { - if(diagramEnCours()) diagramEnCours() -> zoomMoins(); + if(currentDiagram()) currentDiagram() -> zoomMoins(); } /** Effectue l'action "zoom arriere" sur le diagram en cours */ void QETDiagramEditor::slot_zoomFit() { - if(diagramEnCours()) diagramEnCours() -> zoomFit(); + if(currentDiagram()) currentDiagram() -> zoomFit(); } /** Effectue l'action "zoom par defaut" sur le schema en cours */ void QETDiagramEditor::slot_zoomReset() { - if(diagramEnCours()) diagramEnCours() -> zoomReset(); + if(currentDiagram()) currentDiagram() -> zoomReset(); } /** Effectue l'action "selectionner tout" sur le schema en cours */ void QETDiagramEditor::slot_selectAll() { - if(diagramEnCours()) diagramEnCours() -> selectAll(); + if(currentDiagram()) currentDiagram() -> selectAll(); } /** Effectue l'action "deselectionenr tout" sur le schema en cours */ void QETDiagramEditor::slot_selectNothing() { - if(diagramEnCours()) diagramEnCours() -> selectNothing(); + if(currentDiagram()) currentDiagram() -> selectNothing(); } /** Effectue l'action "inverser la selection" sur le schema en cours */ void QETDiagramEditor::slot_selectInvert() { - if(diagramEnCours()) diagramEnCours() -> selectInvert(); + if(currentDiagram()) currentDiagram() -> selectInvert(); } /** Effectue l'action "supprimer" sur le schema en cours */ void QETDiagramEditor::slot_supprimer() { - if(diagramEnCours()) diagramEnCours() -> supprimer(); + if(currentDiagram()) currentDiagram() -> supprimer(); } /** Effectue l'action "pivoter" sur le schema en cours */ void QETDiagramEditor::slot_pivoter() { - if(diagramEnCours()) diagramEnCours() -> pivoter(); + if(currentDiagram()) currentDiagram() -> pivoter(); } /** Effectue l'action "mode selection" sur le schema en cours */ void QETDiagramEditor::slot_setSelectionMode() { - if(diagramEnCours()) diagramEnCours() -> setSelectionMode(); + if(currentDiagram()) currentDiagram() -> setSelectionMode(); } /** Effectue l'action "mode visualisation" sur le schema en cours */ void QETDiagramEditor::slot_setVisualisationMode() { - if(diagramEnCours()) diagramEnCours() -> setVisualisationMode(); + if(currentDiagram()) currentDiagram() -> setVisualisationMode(); } /** gere les actions ayant besoin d'un document ouvert */ void QETDiagramEditor::slot_updateActions() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); bool document_ouvert = (sv != 0); // actions ayant juste besoin d'un document ouvert @@ -669,9 +672,12 @@ void QETDiagramEditor::slot_updateActions() { expand_diagram -> setEnabled(document_ouvert); shrink_diagram -> setEnabled(document_ouvert); - // actions ayant aussi besoin d'un historique des actions - annuler -> setEnabled(document_ouvert); - refaire -> setEnabled(document_ouvert); + // affiche les actions correspondant au diagram view en cours + if (sv) undo_group.setActiveStack(&(sv -> diagram() -> undoStack())); + else { + annuler -> setEnabled(false); + refaire -> setEnabled(false); + } // actions ayant aussi besoin d'elements selectionnes bool elements_selectionnes = document_ouvert ? (sv -> hasSelectedItems()) : false; @@ -716,17 +722,18 @@ void QETDiagramEditor::slot_updateActions() { Ajoute un schema dans l'espace de travail @param sv L'objet DiagramView a ajouter a l'espace de travail */ -void QETDiagramEditor::addDiagramView(DiagramView *sv) { - if (!sv) return; +void QETDiagramEditor::addDiagramView(DiagramView *dv) { + if (!dv) return; + undo_group.addStack(&(dv -> diagram() -> undoStack())); // on maximise la nouvelle fenetre si la fenetre en cours est inexistante ou bien maximisee - DiagramView *s_v = diagramEnCours(); - bool maximise = ((!s_v) || (s_v -> windowState() & Qt::WindowMaximized)); + DiagramView *d_v = currentDiagram(); + bool maximise = ((!d_v) || (d_v -> windowState() & Qt::WindowMaximized)); // ajoute la fenetre - QWidget *p = workspace.addWindow(sv); - connect(sv, SIGNAL(selectionChanged()), this, SLOT(slot_updateActions())); - connect(sv, SIGNAL(modeChanged()), this, SLOT(slot_updateActions())); + QWidget *p = workspace.addWindow(dv); + connect(dv, SIGNAL(selectionChanged()), this, SLOT(slot_updateActions())); + connect(dv, SIGNAL(modeChanged()), this, SLOT(slot_updateActions())); // affiche la fenetre if (maximise) p -> showMaximized(); @@ -771,7 +778,7 @@ void QETDiagramEditor::slot_updateMenuFenetres() { QAction *action = menu_fenetres -> addAction(sv_titre); action -> setStatusTip(tr("Active la fen\352tre ") + sv_titre); action -> setCheckable(true); - action -> setChecked(sv == diagramEnCours()); + action -> setChecked(sv == currentDiagram()); connect(action, SIGNAL(triggered()), &windowMapper, SLOT(map())); windowMapper.setMapping(action, sv); } @@ -781,7 +788,7 @@ void QETDiagramEditor::slot_updateMenuFenetres() { Edite les informations du schema en cours */ void QETDiagramEditor::slot_editInfos() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> dialogEditInfos(); } @@ -790,7 +797,7 @@ void QETDiagramEditor::slot_editInfos() { Ajoute une colonne au schema en cours */ void QETDiagramEditor::slot_addColumn() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> addColumn(); } @@ -799,7 +806,7 @@ void QETDiagramEditor::slot_addColumn() { Enleve une colonne au schema en cours */ void QETDiagramEditor::slot_removeColumn() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> removeColumn(); } @@ -808,7 +815,7 @@ void QETDiagramEditor::slot_removeColumn() { Allonge le schema en cours en hauteur */ void QETDiagramEditor::slot_expand() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> expand(); } @@ -817,7 +824,7 @@ void QETDiagramEditor::slot_expand() { Retrecit le schema en cours en hauteur */ void QETDiagramEditor::slot_shrink() { - DiagramView *sv = diagramEnCours(); + DiagramView *sv = currentDiagram(); if (!sv) return; sv -> shrink(); } diff --git a/qetdiagrameditor.h b/qetdiagrameditor.h index cd8d469d3..4cc57d641 100644 --- a/qetdiagrameditor.h +++ b/qetdiagrameditor.h @@ -30,7 +30,7 @@ class QETDiagramEditor : public QMainWindow { void actions(); private: - DiagramView *diagramEnCours() const; + DiagramView *currentDiagram() const; void menus(); void toolbar(); @@ -121,5 +121,6 @@ class QETDiagramEditor : public QMainWindow { ElementsPanelWidget *pa; QMenu *menu_fenetres; QToolBar *barre_outils; + QUndoGroup undo_group; }; #endif diff --git a/terminal.cpp b/terminal.cpp index 2775a86e6..645c89b6e 100644 --- a/terminal.cpp +++ b/terminal.cpp @@ -2,6 +2,7 @@ #include "diagram.h" #include "element.h" #include "conducer.h" +#include "diagramcommands.h" QColor Terminal::couleur_neutre = QColor(Qt::blue); QColor Terminal::couleur_autorise = QColor(Qt::darkGreen); @@ -51,7 +52,6 @@ Terminal::Terminal() : couleur_hovered(Terminal::couleur_neutre) { initialise(QPointF(0.0, 0.0), QET::South); - diagram_scene = 0; } /** @@ -66,7 +66,6 @@ Terminal::Terminal(QPointF pf, QET::Orientation o, Element *e, Diagram *s) : couleur_hovered(Terminal::couleur_neutre) { initialise(pf, o); - diagram_scene = s; } /** @@ -241,7 +240,7 @@ void Terminal::hoverLeaveEvent(QGraphicsSceneHoverEvent *) { @param e L'evenement souris correspondant */ void Terminal::mousePressEvent(QGraphicsSceneMouseEvent *e) { - if (Diagram *s = qobject_cast(scene())) { + if (Diagram *s = diagram()) { s -> setConducerStart(mapToScene(QPointF(amarrage_conducer))); s -> setConducerStop(e -> scenePos()); s -> setConducer(true); @@ -265,11 +264,14 @@ void Terminal::mouseMoveEvent(QGraphicsSceneMouseEvent *e) { terminal_precedente -> update(); } + + Diagram *s = diagram(); + if (!s) return; // si la scene est un Diagram, on actualise le poseur de conducteur - if (Diagram *s = qobject_cast(scene())) s -> setConducerStop(e -> scenePos()); + s -> setConducerStop(e -> scenePos()); // on recupere la liste des qgi sous le pointeur - QList qgis = scene() -> items(e -> scenePos()); + QList qgis = s -> items(e -> scenePos()); /* le qgi le plus haut = le poseur de conducer @@ -326,7 +328,7 @@ void Terminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { terminal_precedente = NULL; couleur_hovered = couleur_neutre; // verifie que la scene est bien un Diagram - if (Diagram *s = qobject_cast(scene())) { + if (Diagram *s = diagram()) { // on arrete de dessiner l'apercu du conducteur s -> setConducer(false); // on recupere l'element sous le pointeur lors du MouseReleaseEvent @@ -346,7 +348,7 @@ void Terminal::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) { // derniere verification : verifier que cette borne n'est pas deja reliee a l'autre borne foreach (Conducer *f, liste_conducers) if (f -> terminal1 == p || f -> terminal2 == p) return; // autrement, on pose un conducteur - new Conducer(this, p, 0, scene()); + s -> undoStack().push(new AddConducerCommand(s, new Conducer(this, p))); } } @@ -436,3 +438,8 @@ bool Terminal::fromXml(QDomElement &terminal) { terminal.attribute("orientation").toInt() == sens ); } + +/// @return le Diagram auquel cette borne appartient, ou 0 si cette borne est independant +Diagram *Terminal::diagram() const { + return(qobject_cast(scene())); +} diff --git a/terminal.h b/terminal.h index 2cc97aebc..12b0c7cb9 100644 --- a/terminal.h +++ b/terminal.h @@ -36,6 +36,7 @@ class Terminal : public QGraphicsItem { bool addConducer(Conducer *); void removeConducer(Conducer *); int nbConducers() const; + Diagram *diagram() const; // methodes de lecture QList conducers() const; @@ -68,8 +69,6 @@ class Terminal : public QGraphicsItem { static QColor couleur_interdit; private: - // pointeur vers la QGraphicsScene de type Diagram (evite quelques casts en interne) - Diagram *diagram_scene; // coordonnees des points d'amarrage QPointF amarrage_conducer; QPointF amarrage_elmt;