diff --git a/sources/diagram.cpp b/sources/diagram.cpp index 1fa59ce4b..9893c664d 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -32,6 +32,7 @@ #include "qetgraphicsitem/independenttextitem.h" #include "qetapp.h" #include "qetgraphicsitem/diagramimageitem.h" +#include "qetgraphicsitem/qetshapeitem.h" const int Diagram::xGrid = 10; const int Diagram::yGrid = 10; @@ -345,9 +346,12 @@ QDomDocument Diagram::toXml(bool whole_content) { QList list_conductors; QList list_texts; QList list_images; + QList list_shapes; + QList list_items = items(); + ; // Determine les elements a "XMLiser" - foreach(QGraphicsItem *qgi, items()) { + foreach(QGraphicsItem *qgi, list_items) { if (Element *elmt = qgraphicsitem_cast(qgi)) { if (whole_content) list_elements << elmt; else if (elmt -> isSelected()) list_elements << elmt; @@ -364,6 +368,9 @@ QDomDocument Diagram::toXml(bool whole_content) { } else if (DiagramImageItem *dii = qgraphicsitem_cast(qgi)) { if (whole_content) list_images << dii; else if (dii -> isSelected()) list_images << dii; + } else if (QetShapeItem *dsi = dynamic_cast(qgi)) { + if (whole_content) list_shapes << dsi; + else if (dsi -> isSelected()) list_shapes << dsi; } } @@ -405,7 +412,17 @@ QDomDocument Diagram::toXml(bool whole_content) { } racine.appendChild(images); } - + + // save of basic shapes + if (!list_shapes.isEmpty()) { + QDomElement shapes = document.createElement("shapes"); + foreach (QetShapeItem *dii, list_shapes) { + dii ->setWritingXml(true); + shapes.appendChild(dii -> toXml(document)); + dii ->setWritingXml(false); + } + racine.appendChild(shapes); + } // on retourne le document XML ainsi genere return(document); } @@ -568,6 +585,14 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf addItem(dii); added_images << dii; } + + QList added_shapes; + foreach (QDomElement shape_xml, QET::findInDomElement(root, "shapes", "shape")) { + QetShapeItem *dii = new QetShapeItem (QPointF(0,0)); + dii -> fromXml(shape_xml); + addItem(dii); + added_shapes << dii; + } // gere la translation des nouveaux elements et texte si celle-ci est demandee if (position != QPointF()) { @@ -578,6 +603,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf foreach (Element *added_element, added_elements) added_items << added_element; foreach (DiagramTextItem *added_text, added_texts) added_items << added_text; foreach (DiagramImageItem *added_image, added_images) added_items << added_image; + foreach (QetShapeItem *added_shape, added_shapes) added_items << added_shape; foreach (QGraphicsItem *item, added_items) { QPointF csg = item -> mapToScene(item -> boundingRect()).boundingRect().topLeft(); qreal px = csg.x(); @@ -602,6 +628,9 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf foreach (DiagramImageItem *added_image, added_images) { added_image -> setPos(added_image -> pos().x() + diff_x, added_image -> pos().y() + diff_y); } + foreach (QetShapeItem *added_shape, added_shapes) { + added_shape -> setPos(added_shape -> pos().x() + diff_x, added_shape -> pos().y() + diff_y); + } } // chargement de tous les Conducteurs du fichier XML @@ -638,6 +667,7 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf content_ptr -> conductorsToMove = added_conductors.toSet(); content_ptr -> textFields = added_texts.toSet(); content_ptr -> images = added_images.toSet(); + content_ptr -> shapes = added_shapes.toSet(); } return(true); diff --git a/sources/diagramcommands.cpp b/sources/diagramcommands.cpp index e2854cc4e..732d4cbc9 100644 --- a/sources/diagramcommands.cpp +++ b/sources/diagramcommands.cpp @@ -136,6 +136,43 @@ void AddImageCommand::redo() { imageitem -> setPos(position - imageitem -> boundingRect().center()); } +/** + Constructeur + @param dia Schema auquel on ajoute une shape + @param shape Shape ajoute + @param pos Position a laquelle l'shape est ajoute + @param parent QUndoCommand parent + */ +AddShapeCommand::AddShapeCommand(Diagram *dia, QetShapeItem *shape, const QPointF &pos, QUndoCommand *parent): + QUndoCommand(QObject::tr("Ajouter une Shape", "undo caption"), parent), + shapeitem(shape), + diagram(dia), + position(pos) +{ + diagram -> qgiManager().manage(shapeitem); +} + +///Destructor +AddShapeCommand::~AddShapeCommand() { + diagram -> qgiManager().release(shapeitem); +} + +///Annule l'ajout +void AddShapeCommand::undo() { + diagram -> showMe(); + diagram -> removeItem(shapeitem); +} + +///Refait l'ajout +void AddShapeCommand::redo() { + diagram -> showMe(); + if (shapeitem ->diagram() != diagram) + diagram -> addItem(shapeitem); + //diagram -> addDiagramImageItem(imageitem); + //imageitem -> setPos(position - imageitem -> boundingRect().center()); +} + + /** Constructeur @param d Schema auquel on ajoute un conducteur diff --git a/sources/diagramcommands.h b/sources/diagramcommands.h index 383b8bc82..f89ce0b72 100644 --- a/sources/diagramcommands.h +++ b/sources/diagramcommands.h @@ -24,6 +24,7 @@ #include "diagramcontent.h" #include "titleblockproperties.h" #include "qet.h" +#include "qetgraphicsitem/qetshapeitem.h" class Diagram; class DiagramTextItem; class Element; @@ -111,6 +112,34 @@ class AddImageCommand : public QUndoCommand { }; + +/** + This command adds an image item to a particular diagram +*/ +class AddShapeCommand : public QUndoCommand { + //constructors, destructor + public: + AddShapeCommand (Diagram *, QetShapeItem *, const QPointF &, QUndoCommand * = 0); + virtual ~AddShapeCommand(); + private: + AddShapeCommand(const AddShapeCommand &); + + //methods + public: + virtual void undo(); + virtual void redo(); + + // attributes + private: + /// added shape item + QetShapeItem *shapeitem; + /// diagram the image item is added to + Diagram *diagram; + /// position of the image item on the diagram + QPointF position; + +}; + /** This command adds a conductor to a particular diagram. */ diff --git a/sources/diagramcontent.cpp b/sources/diagramcontent.cpp index d44a791cb..ca71b7814 100644 --- a/sources/diagramcontent.cpp +++ b/sources/diagramcontent.cpp @@ -35,6 +35,7 @@ DiagramContent::DiagramContent(const DiagramContent &other) : elements(other.elements), textFields(other.textFields), images(other.images), + shapes(other.shapes), conductorsToUpdate(other.conductorsToUpdate), conductorsToMove(other.conductorsToMove), otherConductors(other.otherConductors) @@ -71,6 +72,7 @@ void DiagramContent::clear() { elements.clear(); textFields.clear(); images.clear(); + shapes.clear(); conductorsToUpdate.clear(); conductorsToMove.clear(); otherConductors.clear(); @@ -86,6 +88,7 @@ QList DiagramContent::items(int filter) const { if (filter & Elements) foreach(QGraphicsItem *qgi, elements) items_list << qgi; if (filter & TextFields) foreach(QGraphicsItem *qgi, textFields) items_list << qgi; if (filter & Images) foreach(QGraphicsItem *qgi, images) items_list << qgi; + if (filter & Shapes) foreach(QGraphicsItem *qgi, shapes) items_list << qgi; if (filter & SelectedOnly) { foreach(QGraphicsItem *qgi, items_list) { if (!qgi -> isSelected()) items_list.removeOne(qgi); @@ -104,6 +107,7 @@ int DiagramContent::count(int filter) const { if (filter & Elements) foreach(Element *element, elements) { if (element -> isSelected()) ++ count; } if (filter & TextFields) foreach(DiagramTextItem *dti, textFields) { if (dti -> isSelected()) ++ count; } if (filter & Images) foreach(DiagramImageItem *dii, images) { if (dii -> isSelected()) ++ count; } + if (filter & Shapes) foreach(QetShapeItem *dsi, shapes) { if (dsi -> isSelected()) ++ count; } if (filter & ConductorsToMove) foreach(Conductor *conductor, conductorsToMove) { if (conductor -> isSelected()) ++ count; } if (filter & ConductorsToUpdate) foreach(Conductor *conductor, conductorsToUpdate) { if (conductor -> isSelected()) ++ count; } if (filter & OtherConductors) foreach(Conductor *conductor, otherConductors) { if (conductor -> isSelected()) ++ count; } @@ -112,6 +116,7 @@ int DiagramContent::count(int filter) const { if (filter & Elements) count += elements.count(); if (filter & TextFields) count += textFields.count(); if (filter & Images) count += images.count(); + if (filter & Shapes) count += shapes.count(); if (filter & ConductorsToMove) count += conductorsToMove.count(); if (filter & ConductorsToUpdate) count += conductorsToUpdate.count(); if (filter & OtherConductors) count += otherConductors.count(); @@ -130,13 +135,15 @@ QString DiagramContent::sentence(int filter) const { int conductors_count = conductors(filter).count(); int textfields_count = (filter & TextFields) ? textFields.count() : 0; int images_count = (filter & Images) ? images.count() : 0; + int shapes_count = (filter & Shapes) ? shapes.count() : 0; return( QET::ElementsAndConductorsSentence( elements_count, conductors_count, textfields_count, - images_count + images_count, + shapes_count ) ); } diff --git a/sources/diagramcontent.h b/sources/diagramcontent.h index 554d2646f..7166828c7 100644 --- a/sources/diagramcontent.h +++ b/sources/diagramcontent.h @@ -18,10 +18,12 @@ #ifndef DIAGRAM_CONTENT_H #define DIAGRAM_CONTENT_H #include +#include "qetgraphicsitem/qetshapeitem.h" class Conductor; class Element; class IndependentTextItem; class DiagramImageItem; + /** This class provides a container that makes the transmission of diagram content to other functions/methods easier. The different kind of items are made @@ -47,7 +49,8 @@ class DiagramContent { OtherConductors = 32, AnyConductor = 56, All = 63, - SelectedOnly = 64 + SelectedOnly = 64, + Shapes = 128 }; /// Hold electrical elements @@ -56,6 +59,8 @@ class DiagramContent { QSet textFields; /// Hold image QSet images; + /// Hold shape + QSet shapes; /// Hold conductors that would get updated considering electrical elements are moved QSet conductorsToUpdate; /// Hold conductors that would be moved as is considering electrical elements are moved diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index 18ea1d864..708853b3d 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -461,6 +461,9 @@ void DiagramView::mousePressEvent(QMouseEvent *e) { rubber_band_origin = mapToScene(e -> pos()); newItem = new QetShapeItem(rubber_band_origin, rubber_band_origin, QetShapeItem::Line, false); scene -> addItem(newItem); + // le place a la position pos en gerant l'annulation + //scene -> undoStack().push(new AddShapeCommand(scene, newItem, e->pos)); + //adjustSceneRect(); break; case addingRectangle: rubber_band_origin = mapToScene(e -> pos()); @@ -714,7 +717,7 @@ bool DiagramView::hasCopiableItems() { if ( qgraphicsitem_cast(qgi) || qgraphicsitem_cast(qgi) || - qgraphicsitem_cast(qgi) || + dynamic_cast(qgi) || qgraphicsitem_cast(qgi) ) { return(true); @@ -733,7 +736,7 @@ bool DiagramView::hasDeletableItems() { qgraphicsitem_cast(qgi) || qgraphicsitem_cast(qgi) || qgraphicsitem_cast(qgi) || - qgraphicsitem_cast(qgi) || + dynamic_cast(qgi) || qgraphicsitem_cast(qgi) ) { return(true); diff --git a/sources/exportdialog.cpp b/sources/exportdialog.cpp index af6a7076d..5cf4ef178 100644 --- a/sources/exportdialog.cpp +++ b/sources/exportdialog.cpp @@ -481,7 +481,7 @@ void ExportDialog::generateDxf(Diagram *diagram, int width, int height, bool kee list_texts << iti; } else if (DiagramImageItem *dii = qgraphicsitem_cast(qgi)) { list_images << dii; - } else if (QetShapeItem *dii = qgraphicsitem_cast(qgi)) { + } else if (QetShapeItem *dii = dynamic_cast(qgi)) { if (dii -> getType() == QetShapeItem::Line && dii -> getLine()) { list_lines << dii -> getLine(); } else if (dii -> getType() == QetShapeItem::Rectangle && dii -> getRectangle()) { diff --git a/sources/qet.cpp b/sources/qet.cpp index fb9be850b..7bce65ca0 100644 --- a/sources/qet.cpp +++ b/sources/qet.cpp @@ -201,7 +201,7 @@ bool QET::attributeIsAReal(const QDomElement &e, QString nom_attribut, qreal *re @return la proposition decrivant le nombre d'elements, de conducteurs et de textes */ -QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_count, int texts_count, int images_count) { +QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_count, int texts_count, int images_count, int shapes_count) { QString text; if (elements_count) { text += QObject::tr( @@ -270,6 +270,14 @@ QString QET::ElementsAndConductorsSentence(int elements_count, int conductors_co images_count ); } + + if (shapes_count) { + text += QObject::tr( + "%n image(s)", + "part of a sentence listing the content of a diagram", + shapes_count + ); + } return(text); } diff --git a/sources/qet.h b/sources/qet.h index c123e4a6a..e9ba4ac8a 100644 --- a/sources/qet.h +++ b/sources/qet.h @@ -152,7 +152,7 @@ namespace QET { bool orthogonalProjection(const QPointF &, const QLineF &, QPointF * = 0); bool attributeIsAnInteger(const QDomElement &, QString , int * = NULL); bool attributeIsAReal(const QDomElement &, QString , qreal * = NULL); - QString ElementsAndConductorsSentence(int, int, int = 0, int = 0); + QString ElementsAndConductorsSentence(int, int, int = 0, int = 0, int = 0); QList findInDomElement(const QDomElement &, const QString &); QList findInDomElement(const QDomElement &, const QString &, const QString &); QList forbiddenCharacters(); diff --git a/sources/qetgraphicsitem/qetshapeitem.cpp b/sources/qetgraphicsitem/qetshapeitem.cpp index 0ada1d7ff..d91741bfe 100644 --- a/sources/qetgraphicsitem/qetshapeitem.cpp +++ b/sources/qetgraphicsitem/qetshapeitem.cpp @@ -1,10 +1,12 @@ #include "qetshapeitem.h" + QetShapeItem::QetShapeItem(QPointF p1, QPointF p2, ShapeType type, bool lineAngle,QGraphicsItem *parent) : QetGraphicsItem(parent), _shapeStyle(Qt::DashLine), _lineAngle(lineAngle), - _isFullyBuilt(false) + _isFullyBuilt(false), + _writingXml(false) { _shapeType = type; _boundingRect = QRectF(p1, p2); @@ -96,24 +98,63 @@ QPainterPath QetShapeItem::shape() const void QetShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { - painter -> setRenderHint(QPainter::Antialiasing, false); - QRectF rec = boundingRect(); - QPen pen(Qt::black); - if (isSelected()) - pen.setColor(Qt::red); - pen.setStyle(_shapeStyle); - painter->setPen(pen); - switch(_shapeType) { - case Line: - if (_lineAngle) - painter -> drawLine(rec.topRight(), rec.bottomLeft()); - else - painter -> drawLine(rec.topLeft(), rec.bottomRight()); - break; - case Rectangle: - painter -> drawRect(rec); - break; - default: //(case Ellipse:) - painter ->drawEllipse(rec); + if (!_writingXml) { + painter -> setRenderHint(QPainter::Antialiasing, false); + QRectF rec = boundingRect(); + QPen pen(Qt::black); + if (isSelected()) + pen.setColor(Qt::red); + pen.setStyle(_shapeStyle); + painter->setPen(pen); + switch(_shapeType) { + case Line: + if (_lineAngle) + painter -> drawLine(rec.topRight(), rec.bottomLeft()); + else + painter -> drawLine(rec.topLeft(), rec.bottomRight()); + break; + case Rectangle: + painter -> drawRect(rec); + break; + default: //(case Ellipse:) + painter ->drawEllipse(rec); + } } } + + +bool QetShapeItem::fromXml(const QDomElement &e) +{ + if (!_writingXml) { + if (e.tagName() != "shape") return (false); + + _shapeType = QetShapeItem::ShapeType(e.attribute("type","0").toInt()); + _shapeStyle = Qt::PenStyle(e.attribute("style","0").toInt()); + _lineAngle = e.attribute("lineAngle","0").toInt(); + qreal x = e.attribute("x","0").toDouble(); + qreal y = e.attribute("y","0").toDouble(); + qreal w = e.attribute("w","0").toDouble(); + qreal h = e.attribute("h","0").toDouble(); + setBoundingRect(QRectF(x, y, w, h)); + setFullyBuilt(true); + } + + return (true); +} + + +QDomElement QetShapeItem::toXml(QDomDocument &document) const { + QDomElement result = document.createElement("shape"); + QRectF rec = boundingRect(); + + //write some attribute + result.setAttribute("type", QString::number(_shapeType)); + result.setAttribute("x", QString::number(rec.topLeft().x())); + result.setAttribute("y", QString::number(rec.topLeft().y())); + result.setAttribute("w", QString::number(rec.width())); + result.setAttribute("h", QString::number(rec.height())); + result.setAttribute("lineAngle", QString::number(_lineAngle)); + result.setAttribute("style", QString::number(_shapeStyle)); + + return(result); +} diff --git a/sources/qetgraphicsitem/qetshapeitem.h b/sources/qetgraphicsitem/qetshapeitem.h index e880c4356..88d5630ea 100644 --- a/sources/qetgraphicsitem/qetshapeitem.h +++ b/sources/qetgraphicsitem/qetshapeitem.h @@ -8,12 +8,12 @@ class QetShapeItem : public QetGraphicsItem public: enum ShapeType { - Line, + Line = 0, Rectangle, Ellipse }; - QetShapeItem(QPointF, QPointF, ShapeType, bool lineAngle = false, QGraphicsItem *parent = 0); + QetShapeItem(QPointF, QPointF = QPointF(0,0), ShapeType = Line, bool lineAngle = false, QGraphicsItem *parent = 0); virtual ~QetShapeItem(); void setStyle(Qt::PenStyle); @@ -25,6 +25,9 @@ class QetShapeItem : public QetGraphicsItem QLineF *getLine(); QRectF *getRectangle(); QRectF *getEllipse(); + virtual bool fromXml(const QDomElement &); + virtual QDomElement toXml(QDomDocument &document) const; + void setWritingXml(bool writing) { _writingXml = writing; } private: ShapeType _shapeType; @@ -35,6 +38,7 @@ class QetShapeItem : public QetGraphicsItem bool _isFullyBuilt; QPointF _lineP1; QPointF _lineP2; + bool _writingXml; virtual void editProperty() {}