From e6d73977c1b5b68fa69f9ec7234023e7fe2d10d9 Mon Sep 17 00:00:00 2001 From: blacksun Date: Thu, 23 Aug 2018 19:41:58 +0000 Subject: [PATCH] 1-Use the "implicite shared" of Qt for the QPicture and QPixmap of element (https://doc.qt.io/qt-5/implicit-sharing.html). This avoid to parse the same element definition each time user drop the same element in the diagram. Only the first element build the picture, all other get the created picture which is shared. 2- For use the "implicite shared" QPicture and QPixmap of element, now this isn't the element who build her picture, but a dedicated class who made only this job : build the QPicture and QPixmap of elements. 3- With the two previous novelty, the class CustomElement and GhostElement are became useless, and so was removed. Some few member function of CustomElement was moved to Element. git-svn-id: svn+ssh://svn.tuxfamily.org/svnroot/qet/qet/trunk@5492 bfdf4180-ca20-0410-9c96-a3a8aa849046 --- .../ElementsCollection/elementslocation.cpp | 31 +- sources/diagram.cpp | 23 +- sources/diagram.h | 1 - sources/diagramview.cpp | 2 - .../editor/graphicspart/customelementpart.cpp | 1 - sources/exportdialog.cpp | 74 +- sources/factory/elementpicturefactory.cpp | 624 ++++++++++ sources/factory/elementpicturefactory.h | 111 ++ sources/nomenclature.h | 1 - sources/qetapp.cpp | 2 + sources/qetdiagrameditor.cpp | 18 +- sources/qetdiagrameditor.h | 1 - sources/qetgraphicsitem/customelement.cpp | 1049 ----------------- sources/qetgraphicsitem/customelement.h | 118 -- .../qetgraphicsitem/dynamicelementtextitem.h | 2 +- sources/qetgraphicsitem/element.cpp | 438 +++++-- sources/qetgraphicsitem/element.h | 151 +-- sources/qetgraphicsitem/ghostelement.cpp | 185 --- sources/qetgraphicsitem/ghostelement.h | 53 - sources/qetgraphicsitem/masterelement.cpp | 6 +- sources/qetgraphicsitem/masterelement.h | 4 +- sources/qetgraphicsitem/reportelement.cpp | 2 +- sources/qetgraphicsitem/reportelement.h | 4 +- sources/qetgraphicsitem/simpleelement.cpp | 4 +- sources/qetgraphicsitem/simpleelement.h | 4 +- sources/qetgraphicsitem/slaveelement.cpp | 2 +- sources/qetgraphicsitem/slaveelement.h | 4 +- sources/qetgraphicsitem/terminalelement.cpp | 4 +- sources/qetgraphicsitem/terminalelement.h | 5 +- sources/ui/elementpropertieswidget.cpp | 38 +- 30 files changed, 1250 insertions(+), 1712 deletions(-) create mode 100644 sources/factory/elementpicturefactory.cpp create mode 100644 sources/factory/elementpicturefactory.h delete mode 100644 sources/qetgraphicsitem/customelement.cpp delete mode 100644 sources/qetgraphicsitem/customelement.h delete mode 100644 sources/qetgraphicsitem/ghostelement.cpp delete mode 100644 sources/qetgraphicsitem/ghostelement.h diff --git a/sources/ElementsCollection/elementslocation.cpp b/sources/ElementsCollection/elementslocation.cpp index 0772e5045..ee6557e02 100644 --- a/sources/ElementsCollection/elementslocation.cpp +++ b/sources/ElementsCollection/elementslocation.cpp @@ -20,9 +20,10 @@ #include "xmlelementcollection.h" #include "qetproject.h" #include "elementscollectioncache.h" -#include "elementfactory.h" +#include "elementpicturefactory.h" #include "element.h" #include "qetxml.h" +#include // make this class usable with QVariant int ElementsLocation::MetaTypeId = qRegisterMetaType("ElementsLocation"); @@ -645,14 +646,8 @@ QIcon ElementsLocation::icon() const if (cache->fetchElement(loc)) return QIcon(cache->pixmap()); } - else - { - ElementFactory *factory = ElementFactory::Instance(); - int state; - Element *elmt = factory->createElement(*this, nullptr, &state); - - if (state == 0) - return QIcon(elmt->pixmap()); + else { + return QIcon(ElementPictureFactory::instance()->pixmap(*this)); } return QIcon(); @@ -664,21 +659,9 @@ QIcon ElementsLocation::icon() const */ QString ElementsLocation::name() const { -// if (!m_project) -// { -// ElementsCollectionCache *cache = QETApp::collectionCache(); -// ElementsLocation loc(*this); //Make a copy of this to keep this method const -// if (cache->fetchElement(loc)) -// return cache->name(); -// else -// return QString(); -// } -// else -// { - NamesList nl; - nl.fromXml(xml()); - return nl.name(fileName()); -// } + NamesList nl; + nl.fromXml(xml()); + return nl.name(fileName()); } /** diff --git a/sources/diagram.cpp b/sources/diagram.cpp index c6c887412..927247a0c 100644 --- a/sources/diagram.cpp +++ b/sources/diagram.cpp @@ -18,14 +18,12 @@ #include #include "qetgraphicsitem/conductor.h" #include "qetgraphicsitem/conductortextitem.h" -#include "qetgraphicsitem/customelement.h" #include "factory/elementfactory.h" #include "diagram.h" #include "diagramcommands.h" #include "diagramcontent.h" #include "diagramposition.h" #include "exportdialog.h" -#include "qetgraphicsitem/ghostelement.h" #include "qetgraphicsitem/independenttextitem.h" #include "qetgraphicsitem/diagramimageitem.h" #include "qetgraphicsitem/qetshapeitem.h" @@ -900,9 +898,6 @@ bool Diagram::fromXml(QDomElement &document, QPointF position, bool consider_inf QString debug_message = QString("Diagram::fromXml() : Le chargement de la description de l'element %1 a echoue avec le code d'erreur %2").arg(element_location.path()).arg(state); qDebug() << qPrintable(debug_message); delete nvel_elmt; - - qDebug() << "Diagram::fromXml() : Utilisation d'un GhostElement en lieu et place de cet element."; - nvel_elmt = new GhostElement(element_location); } addItem(nvel_elmt); @@ -1450,19 +1445,6 @@ QString Diagram::title() const { return(border_and_titleblock.title()); } -/** - @return la liste des elements de ce schema -*/ -QList Diagram::customElements() const { - QList elements_list; - foreach(QGraphicsItem *qgi, items()) { - if (CustomElement *elmt = qgraphicsitem_cast(qgi)) { - elements_list << elmt; - } - } - return(elements_list); -} - QList Diagram::elements() const { QList element_list; foreach (QGraphicsItem *qgi, items()) { @@ -1498,8 +1480,9 @@ ElementTextsMover &Diagram::elementTextsMover() { @param location Emplacement d'un element @return true si l'element location est utilise sur ce schema, false sinon */ -bool Diagram::usesElement(const ElementsLocation &location) { - foreach(CustomElement *element, customElements()) { +bool Diagram::usesElement(const ElementsLocation &location) +{ + for(Element *element : elements()) { if (element -> location() == location) { return(true); } diff --git a/sources/diagram.h b/sources/diagram.h index 7991cc377..e094b6957 100644 --- a/sources/diagram.h +++ b/sources/diagram.h @@ -184,7 +184,6 @@ class Diagram : public QGraphicsScene bool isEmpty() const; - QList customElements() const; QList elements() const; QList conductors() const; QSet selectedConductors() const; diff --git a/sources/diagramview.cpp b/sources/diagramview.cpp index af1b4f3ac..94b31fea5 100644 --- a/sources/diagramview.cpp +++ b/sources/diagramview.cpp @@ -17,8 +17,6 @@ */ #include "diagramview.h" #include "diagram.h" -#include "qetgraphicsitem/customelement.h" -#include "qetgraphicsitem/ghostelement.h" #include "qetgraphicsitem/conductor.h" #include "diagramcommands.h" #include "diagramposition.h" diff --git a/sources/editor/graphicspart/customelementpart.cpp b/sources/editor/graphicspart/customelementpart.cpp index 206c7b2ae..3e7d572a8 100644 --- a/sources/editor/graphicspart/customelementpart.cpp +++ b/sources/editor/graphicspart/customelementpart.cpp @@ -16,7 +16,6 @@ along with QElectroTech. If not, see . */ #include "customelementpart.h" -#include "qetgraphicsitem/customelement.h" #include "qetelementeditor.h" /// @return le QETElementEditor auquel cet editeur appartient diff --git a/sources/exportdialog.cpp b/sources/exportdialog.cpp index 27530f924..17ca14722 100644 --- a/sources/exportdialog.cpp +++ b/sources/exportdialog.cpp @@ -28,12 +28,12 @@ #include "qetgraphicsitem/conductor.h" #include "qetgraphicsitem/diagramtextitem.h" #include "qetgraphicsitem/conductortextitem.h" -#include "qetgraphicsitem/customelement.h" -#include "qetgraphicsitem/ghostelement.h" #include "qetgraphicsitem/independenttextitem.h" #include "qetgraphicsitem/diagramimageitem.h" #include "qetgraphicsitem/qetshapeitem.h" #include "diagramfoliolist.h" +#include "elementpicturefactory.h" +#include "element.h" /** Constructeur @@ -496,27 +496,29 @@ void ExportDialog::generateDxf(Diagram *diagram, int width, int height, bool kee qreal hotspot_x = (elem_pos_x) * Createdxf::xScale; qreal hotspot_y = Createdxf::sheetHeight - (elem_pos_y) * Createdxf::yScale; - QList elmt_line = elmt -> lines(); - foreach(QLineF *line, elmt_line) { - qreal x1 = (elem_pos_x + line -> p1().x()) * Createdxf::xScale; - qreal y1 = Createdxf::sheetHeight - (elem_pos_y + line -> p1().y()) * Createdxf::yScale; + ElementPictureFactory::primitives primitives = ElementPictureFactory::instance()->getPrimitives(elmt->location()); + + for (QLineF line : primitives.m_lines) + { + qreal x1 = (elem_pos_x + line.p1().x()) * Createdxf::xScale; + qreal y1 = Createdxf::sheetHeight - (elem_pos_y + line.p1().y()) * Createdxf::yScale; QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle); x1 = transformed_point.x(); y1 = transformed_point.y(); - qreal x2 = (elem_pos_x + line -> p2().x()) * Createdxf::xScale; - qreal y2 = Createdxf::sheetHeight - (elem_pos_y + line -> p2().y()) * Createdxf::yScale; + qreal x2 = (elem_pos_x + line.p2().x()) * Createdxf::xScale; + qreal y2 = Createdxf::sheetHeight - (elem_pos_y + line.p2().y()) * Createdxf::yScale; transformed_point = rotation_transformed(x2, y2, hotspot_x, hotspot_y, rotation_angle); x2 = transformed_point.x(); y2 = transformed_point.y(); Createdxf::drawLine(file_path, x1, y1, x2, y2, 0); } - QList elmt_rectangle = elmt -> rectangles(); - foreach(QRectF *rect, elmt_rectangle) { - qreal x1 = (elem_pos_x + rect -> bottomLeft().x()) * Createdxf::xScale; - qreal y1 = Createdxf::sheetHeight - (elem_pos_y + rect -> bottomLeft().y()) * Createdxf::yScale; - qreal w = rect -> width() * Createdxf::xScale; - qreal h = rect -> height() * Createdxf::yScale; + for (QRectF rect : primitives.m_rectangles) + { + qreal x1 = (elem_pos_x + rect.bottomLeft().x()) * Createdxf::xScale; + qreal y1 = Createdxf::sheetHeight - (elem_pos_y + rect.bottomLeft().y()) * Createdxf::yScale; + qreal w = rect.width() * Createdxf::xScale; + qreal h = rect.height() * Createdxf::yScale; // opposite corner qreal x2 = x1 + w; qreal y2 = y1 + h; @@ -533,29 +535,29 @@ void ExportDialog::generateDxf(Diagram *diagram, int width, int height, bool kee Createdxf::drawRectangle(file_path, bottom_left_x, bottom_left_y, w, h, 0); } - QList elmt_circle = elmt -> circles(); - foreach(QRectF *circle_rect, elmt_circle) { - qreal x1 = (elem_pos_x + circle_rect ->center().x()) * Createdxf::xScale; - qreal y1 = Createdxf::sheetHeight - (elem_pos_y + circle_rect -> center().y()) * Createdxf::yScale; - qreal r = circle_rect -> width() * Createdxf::xScale / 2; + for (QRectF circle_rect : primitives.m_circles) + { + qreal x1 = (elem_pos_x + circle_rect.center().x()) * Createdxf::xScale; + qreal y1 = Createdxf::sheetHeight - (elem_pos_y + circle_rect.center().y()) * Createdxf::yScale; + qreal r = circle_rect.width() * Createdxf::xScale / 2; QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle); x1 = transformed_point.x(); y1 = transformed_point.y(); Createdxf::drawCircle(file_path, r, x1, y1, 0); } - QList *> elmt_polygon = elmt -> polygons(); - foreach(QVector *polygon, elmt_polygon) { - if (polygon -> size() == 0) + for (QVector polygon : primitives.m_polygons) + { + if (polygon.size() == 0) continue; - qreal x1 = (elem_pos_x + polygon -> at(0).x()) * Createdxf::xScale; - qreal y1 = Createdxf::sheetHeight - (elem_pos_y + polygon -> at(0).y()) * Createdxf::yScale; + qreal x1 = (elem_pos_x + polygon.at(0).x()) * Createdxf::xScale; + qreal y1 = Createdxf::sheetHeight - (elem_pos_y + polygon.at(0).y()) * Createdxf::yScale; QPointF transformed_point = rotation_transformed(x1, y1, hotspot_x, hotspot_y, rotation_angle); x1 = transformed_point.x(); y1 = transformed_point.y(); - for (int i = 1; i < polygon -> size(); ++i ) { - qreal x2 = (elem_pos_x + polygon -> at(i).x()) * Createdxf::xScale; - qreal y2 = Createdxf::sheetHeight - (elem_pos_y + polygon -> at(i).y()) * Createdxf::yScale; + for (int i = 1; i < polygon.size(); ++i ) { + qreal x2 = (elem_pos_x + polygon.at(i).x()) * Createdxf::xScale; + qreal y2 = Createdxf::sheetHeight - (elem_pos_y + polygon.at(i).y()) * Createdxf::yScale; QPointF transformed_point = rotation_transformed(x2, y2, hotspot_x, hotspot_y, rotation_angle); x2 = transformed_point.x(); y2 = transformed_point.y(); @@ -566,16 +568,16 @@ void ExportDialog::generateDxf(Diagram *diagram, int width, int height, bool kee } // Draw arcs and ellipses - QList *> elmt_arc = elmt -> arcs(); - foreach(QVector *arc, elmt_arc) { - if (arc -> size() == 0) + for (QVector arc : primitives.m_arcs) + { + if (arc.size() == 0) continue; - qreal x = (elem_pos_x + arc -> at(0)) * Createdxf::xScale; - qreal y = Createdxf::sheetHeight - (elem_pos_y + arc -> at(1)) * Createdxf::yScale; - qreal w = arc -> at(2) * Createdxf::xScale; - qreal h = arc -> at(3) * Createdxf::yScale; - qreal startAngle = arc -> at(4); - qreal spanAngle = arc -> at(5); + qreal x = (elem_pos_x + arc.at(0)) * Createdxf::xScale; + qreal y = Createdxf::sheetHeight - (elem_pos_y + arc.at(1)) * Createdxf::yScale; + qreal w = arc.at(2) * Createdxf::xScale; + qreal h = arc.at(3) * Createdxf::yScale; + qreal startAngle = arc.at(4); + qreal spanAngle = arc .at(5); Createdxf::drawArcEllipse(file_path, x, y, w, h, startAngle, spanAngle, hotspot_x, hotspot_y, rotation_angle, 0); } } diff --git a/sources/factory/elementpicturefactory.cpp b/sources/factory/elementpicturefactory.cpp new file mode 100644 index 000000000..1fed8ff00 --- /dev/null +++ b/sources/factory/elementpicturefactory.cpp @@ -0,0 +1,624 @@ +/* + Copyright 2006-2018 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#include "elementpicturefactory.h" +#include "elementslocation.h" +#include "qet.h" +#include "qetapp.h" +#include "partline.h" + +#include +#include +#include +#include +#include +#include + +ElementPictureFactory* ElementPictureFactory::m_factory = nullptr; + +/** + * @brief ElementPictureFactory::getPictures + * Set the picture of the element at location. + * Note, picture can be null + * @param location + * @param picture + * @param low_picture + */ +void ElementPictureFactory::getPictures(const ElementsLocation &location, QPicture &picture, QPicture &low_picture) +{ + if(!location.exist()) { + return; + } + + QUuid uuid = location.uuid(); + + if(m_pictures_H.keys().contains(uuid)) + { + picture = m_pictures_H.value(uuid); + low_picture = m_low_pictures_H.value(uuid); + } + else + { + if (build(location)) + { + picture = m_pictures_H.value(uuid); + low_picture = m_low_pictures_H.value(uuid); + } + } +} + +/** + * @brief ElementPictureFactory::pixmap + * @param location + * @return the pixmap of the element at @location + * Note pixmap can be null + */ +QPixmap ElementPictureFactory::pixmap(const ElementsLocation &location) +{ + QUuid uuid = location.uuid(); + if (m_pixmap_H.contains(uuid)) { + return m_pixmap_H.value(uuid); + } + + if(build(location)) + { + QDomElement dom = location.xml(); + //size + int w = dom.attribute("width").toInt(); + int h = dom.attribute("height").toInt(); + while (w % 10) ++ w; + while (h % 10) ++ h; + //hotspot + int hsx = qMin(dom.attribute("hotspot_x").toInt(), w); + int hsy = qMin(dom.attribute("hotspot_y").toInt(), h); + + QPixmap pix(w, h); + pix.fill(QColor(255, 255, 255, 0)); + + QPainter painter(&pix); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform, true); + painter.translate(hsx, hsy); + painter.drawPicture(0, 0, m_pictures_H.value(uuid)); + + m_pixmap_H.insert(uuid, pix); + return pix; + } + + return QPixmap(); +} + + +/** + * @brief ElementPictureFactory::getPrimitives + * @param location + * @return The primtive used to draw the element at @location + */ +ElementPictureFactory::primitives ElementPictureFactory::getPrimitives(const ElementsLocation &location) +{ + if(!m_primitives_H.contains(location.uuid())) + build(location); + + return m_primitives_H.value(location.uuid()); +} + + +bool ElementPictureFactory::build(const ElementsLocation &location) +{ + QDomElement dom = location.xml(); + + //Check if the curent version can read the xml description + if (dom.hasAttribute("version")) + { + bool conv_ok; + qreal element_version = dom.attribute("version").toDouble(&conv_ok); + if (conv_ok && QET::version.toDouble() < element_version) + { + std::cerr << qPrintable( + QObject::tr("Avertissement : l'élément " + " a été enregistré avec une version" + " ultérieure de QElectroTech.") + ) << std::endl; + } + } + + //This attributes must be present and valid + int w, h, hot_x, hot_y; + if (!QET::attributeIsAnInteger(dom, QString("width"), &w) ||\ + !QET::attributeIsAnInteger(dom, QString("height"), &h) ||\ + !QET::attributeIsAnInteger(dom, QString("hotspot_x"), &hot_x) ||\ + !QET::attributeIsAnInteger(dom, QString("hotspot_y"), &hot_y)) + { + return(false); + } + + QPicture pic; + QPicture low_pic; + primitives primitives_; + + m_pictures_H.insert(location.uuid(), pic); + m_low_pictures_H.insert(location.uuid(), low_pic); + m_primitives_H.insert(location.uuid(), primitives_); + + QPainter painter; + painter.begin(&pic); + painter.setRenderHint(QPainter::Antialiasing, true); + painter.setRenderHint(QPainter::TextAntialiasing, true); + painter.setRenderHint(QPainter::SmoothPixmapTransform,true); + + + QPainter low_painter; + low_painter.begin(&low_pic); + low_painter.setRenderHint(QPainter::Antialiasing, true); + low_painter.setRenderHint(QPainter::TextAntialiasing, true); + low_painter.setRenderHint(QPainter::SmoothPixmapTransform,true); + QPen tmp; + tmp.setWidthF(1.0); //Vaudoo line to take into account the setCosmetic - don't remove + tmp.setCosmetic(true); + low_painter.setPen(tmp); + + //scroll of the Children of the Definition: Parts of the Drawing + for (QDomNode node = dom.firstChild() ; !node.isNull() ; node = node.nextSibling()) + { + QDomElement elmts = node.toElement(); + if (elmts.isNull()) { + continue; + } + + if (elmts.tagName() == "description") + { + //Manage the graphic description = part of drawing + for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) + { + QDomElement qde = n.toElement(); + if (qde.isNull()) { + continue; + } + parseElement(qde, painter, primitives_); + primitives fake_prim; + parseElement(qde, low_painter, fake_prim); + } + } + } + + //End of the drawing + painter.end(); + low_painter.end(); + return true; +} + +void ElementPictureFactory::parseElement(const QDomElement &dom, QPainter &painter, primitives &prim) const +{ + if (dom.tagName() == "line") (parseLine (dom, painter, prim)); + else if (dom.tagName() == "rect") (parseRect (dom, painter, prim)); + else if (dom.tagName() == "ellipse") (parseEllipse(dom, painter, prim)); + else if (dom.tagName() == "circle") (parseCircle (dom, painter, prim)); + else if (dom.tagName() == "arc") (parseArc (dom, painter, prim)); + else if (dom.tagName() == "polygon") (parsePolygon(dom, painter, prim)); + else if (dom.tagName() == "text") (parseText (dom, painter, prim)); +} + +void ElementPictureFactory::parseLine(const QDomElement &dom, QPainter &painter, primitives &prim) const +{ + //This attributes must be present and valid + qreal x1, y1, x2, y2; + if (!QET::attributeIsAReal(dom, QString("x1"), &x1)) return; + if (!QET::attributeIsAReal(dom, QString("y1"), &y1)) return; + if (!QET::attributeIsAReal(dom, QString("x2"), &x2)) return; + if (!QET::attributeIsAReal(dom, QString("y2"), &y2)) return; + + Qet::EndType first_end = Qet::endTypeFromString(dom.attribute("end1")); + Qet::EndType second_end = Qet::endTypeFromString(dom.attribute("end2")); + qreal length1, length2; + if (!QET::attributeIsAReal(dom, QString("length1"), &length1)) length1 = 1.5; + if (!QET::attributeIsAReal(dom, QString("length2"), &length2)) length2 = 1.5; + + painter.save(); + setPainterStyle(dom, painter); + QPen t = painter.pen(); + t.setJoinStyle(Qt::MiterJoin); + painter.setPen(t); + + QLineF line(x1, y1, x2, y2); + + prim.m_lines << line; + + QPointF point1(line.p1()); + QPointF point2(line.p2()); + + qreal line_length(line.length()); + qreal pen_width = painter.pen().widthF(); + + //Check if we must to draw extremity + bool draw_1st_end, draw_2nd_end; + qreal reduced_line_length = line_length - (length1 * PartLine::requiredLengthForEndType(first_end)); + draw_1st_end = first_end && reduced_line_length >= 0; + if (draw_1st_end) { + reduced_line_length -= (length2 * PartLine::requiredLengthForEndType(second_end)); + } else { + reduced_line_length = line_length - (length2 * PartLine::requiredLengthForEndType(second_end)); + } + draw_2nd_end = second_end && reduced_line_length >= 0; + + //Draw first extremity + QPointF start_point, stop_point; + if (draw_1st_end) { + QList four_points1(PartLine::fourEndPoints(point1, point2, length1)); + if (first_end == Qet::Circle) { + painter.drawEllipse(QRectF(four_points1[0] - QPointF(length1, length1), QSizeF(length1 * 2.0, length1 * 2.0))); + start_point = four_points1[1]; + } else if (first_end == Qet::Diamond) { + painter.drawPolygon(QPolygonF() << four_points1[1] << four_points1[2] << point1 << four_points1[3]); + start_point = four_points1[1]; + } else if (first_end == Qet::Simple) { + painter.drawPolyline(QPolygonF() << four_points1[3] << point1 << four_points1[2]); + start_point = point1; + + } else if (first_end == Qet::Triangle) { + painter.drawPolygon(QPolygonF() << four_points1[0] << four_points1[2] << point1 << four_points1[3]); + start_point = four_points1[0]; + } + + //Adjust the begining according to the width of the pen + if (pen_width && (first_end == Qet::Simple || first_end == Qet::Circle)) { + start_point = QLineF(start_point, point2).pointAt(pen_width / 2.0 / line_length); + } + } else { + start_point = point1; + } + + //Draw second extremity + if (draw_2nd_end) { + QList four_points2(PartLine::fourEndPoints(point2, point1, length2)); + if (second_end == Qet::Circle) { + painter.drawEllipse(QRectF(four_points2[0] - QPointF(length2, length2), QSizeF(length2 * 2.0, length2 * 2.0))); + stop_point = four_points2[1]; + } else if (second_end == Qet::Diamond) { + painter.drawPolygon(QPolygonF() << four_points2[2] << point2 << four_points2[3] << four_points2[1]); + stop_point = four_points2[1]; + } else if (second_end == Qet::Simple) { + painter.drawPolyline(QPolygonF() << four_points2[3] << point2 << four_points2[2]); + stop_point = point2; + } else if (second_end == Qet::Triangle) { + painter.drawPolygon(QPolygonF() << four_points2[0] << four_points2[2] << point2 << four_points2[3] << four_points2[0]); + stop_point = four_points2[0]; + } + + //Adjust the end according to the width of the pen + if (pen_width && (second_end == Qet::Simple || second_end == Qet::Circle)) { + stop_point = QLineF(point1, stop_point).pointAt((line_length - (pen_width / 2.0)) / line_length); + } + } else { + stop_point = point2; + } + + painter.drawLine(start_point, stop_point); + + painter.restore(); +} + +void ElementPictureFactory::parseRect(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + //This attributes must be present and valid + qreal rect_x, rect_y, rect_w, rect_h, rect_rx, rect_ry; + if (!QET::attributeIsAReal(dom, QString("x"), &rect_x)) return; + if (!QET::attributeIsAReal(dom, QString("y"), &rect_y)) return; + if (!QET::attributeIsAReal(dom, QString("width"), &rect_w)) return; + if (!QET::attributeIsAReal(dom, QString("height"), &rect_h)) return; + rect_rx = dom.attribute("rx", "0").toDouble(); + rect_ry = dom.attribute("ry", "0").toDouble(); + + prim.m_rectangles << QRectF(rect_x, rect_y, rect_w, rect_h); + + painter.save(); + setPainterStyle(dom, painter); + + QPen p = painter.pen(); + p.setJoinStyle(Qt::MiterJoin); + painter.setPen(p); + + painter.drawRoundedRect(QRectF(rect_x, rect_y, rect_w, rect_h), rect_rx, rect_ry); + painter.restore(); +} + +void ElementPictureFactory::parseEllipse(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + //This attributes must be present and valid + qreal ellipse_x, ellipse_y, ellipse_l, ellipse_h; + if (!QET::attributeIsAReal(dom, QString("x"), &ellipse_x)) return; + if (!QET::attributeIsAReal(dom, QString("y"), &ellipse_y)) return; + if (!QET::attributeIsAReal(dom, QString("width"), &ellipse_l)) return; + if (!QET::attributeIsAReal(dom, QString("height"), &ellipse_h)) return; + painter.save(); + setPainterStyle(dom, painter); + + QVector arc; + arc.push_back(ellipse_x); + arc.push_back(ellipse_y); + arc.push_back(ellipse_l); + arc.push_back(ellipse_h); + arc.push_back(0); + arc.push_back(360); + prim.m_arcs << arc; + + painter.drawEllipse(QRectF(ellipse_x, ellipse_y, ellipse_l, ellipse_h)); + painter.restore(); +} + +void ElementPictureFactory::parseCircle(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + //This attributes must be present and valid + qreal cercle_x, cercle_y, cercle_r; + if (!QET::attributeIsAReal(dom, QString("x"), &cercle_x)) return; + if (!QET::attributeIsAReal(dom, QString("y"), &cercle_y)) return; + if (!QET::attributeIsAReal(dom, QString("diameter"), &cercle_r)) return; + painter.save(); + setPainterStyle(dom, painter); + QRectF circle_bounding_rect(cercle_x, cercle_y, cercle_r, cercle_r); + + prim.m_circles << circle_bounding_rect; + + painter.drawEllipse(circle_bounding_rect); + painter.restore(); +} + +void ElementPictureFactory::parseArc(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + //This attributes must be present and valid + qreal arc_x, arc_y, arc_l, arc_h, arc_s, arc_a; + if (!QET::attributeIsAReal(dom, QString("x"), &arc_x)) return; + if (!QET::attributeIsAReal(dom, QString("y"), &arc_y)) return; + if (!QET::attributeIsAReal(dom, QString("width"), &arc_l)) return; + if (!QET::attributeIsAReal(dom, QString("height"), &arc_h)) return; + if (!QET::attributeIsAReal(dom, QString("start"), &arc_s)) return; + if (!QET::attributeIsAReal(dom, QString("angle"), &arc_a)) return; + + painter.save(); + setPainterStyle(dom, painter); + + QVector arc; + arc.push_back(arc_x); + arc.push_back(arc_y); + arc.push_back(arc_l); + arc.push_back(arc_h); + arc.push_back(arc_s); + arc.push_back(arc_a); + prim.m_arcs << arc; + + painter.drawArc(QRectF(arc_x, arc_y, arc_l, arc_h), (int)(arc_s * 16), (int)(arc_a * 16)); + painter.restore(); +} + +void ElementPictureFactory::parsePolygon(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + int i = 1; + while(true) { + if (QET::attributeIsAReal(dom, QString("x%1").arg(i)) && QET::attributeIsAReal(dom, QString("y%1").arg(i))) ++ i; + else break; + } + if (i < 3) { + return; + } + + QVector points; // empty vector created instead of default initialized vector with i-1 elements. + for (int j = 1 ; j < i ; ++ j) { + points.insert( + j - 1, + QPointF( + dom.attribute(QString("x%1").arg(j)).toDouble(), + dom.attribute(QString("y%1").arg(j)).toDouble() + ) + ); + } + + painter.save(); + setPainterStyle(dom, painter); + if (dom.attribute("closed") == "false") painter.drawPolyline(points.data(), i-1); + else { + painter.drawPolygon(points.data(), i-1); + + // insert first point at the end again for DXF export. + points.push_back(points[0]); + } + + prim.m_polygons << points; + + painter.restore(); +} + +void ElementPictureFactory::parseText(const QDomElement &dom, QPainter &painter, ElementPictureFactory::primitives &prim) const +{ + Q_UNUSED(prim); + + qreal pos_x, pos_y; + int size; + if (!QET::attributeIsAReal(dom, "x", &pos_x) ||\ + !QET::attributeIsAReal(dom, "y", &pos_y) ||\ + !QET::attributeIsAnInteger(dom, "size", &size) ||\ + !dom.hasAttribute("text")) { + return; + } + + painter.save(); + setPainterStyle(dom, painter); + + //Get the font and metric + QFont used_font = QETApp::diagramTextsFont(size); + QFontMetrics qfm(used_font); + QColor text_color = (dom.attribute("color") != "white"? Qt::black : Qt::white); + + //Instanciate a QTextDocument (like the QGraphicsTextItem class) + //for generate the graphics rendering of the text + QTextDocument text_document; + text_document.setDefaultFont(used_font); + text_document.setPlainText(dom.attribute("text")); + + painter.setTransform(QTransform(), false); + painter.translate(pos_x, pos_y); + + qreal default_rotation_angle = 0.0; + if (QET::attributeIsAReal(dom, "rotation", &default_rotation_angle)) { + painter.rotate(default_rotation_angle); + } + + /* + Deplace le systeme de coordonnees du QPainter pour effectuer le rendu au + bon endroit ; note : on soustrait l'ascent() de la police pour + determiner le coin superieur gauche du texte alors que la position + indiquee correspond a la baseline. + */ + QPointF qpainter_offset(0.0, -qfm.ascent()); + + //adjusts the offset by the margin of the text document + text_document.setDocumentMargin(0.0); + + painter.translate(qpainter_offset); + + // force the palette used to render the QTextDocument + QAbstractTextDocumentLayout::PaintContext ctx; + ctx.palette.setColor(QPalette::Text, text_color); + text_document.documentLayout() -> draw(&painter, ctx); + + painter.restore(); +} + +/** + * @brief ElementPictureFactory::setPainterStyle + * apply the style store in dom to painter. + * @param dom + * @param painter + */ +void ElementPictureFactory::setPainterStyle(const QDomElement &dom, QPainter &painter) const +{ + QPen pen = painter.pen(); + QBrush brush = painter.brush(); + + pen.setJoinStyle(Qt::BevelJoin); + pen.setCapStyle(Qt::SquareCap); + + //Get the couples style/value + const QStringList styles = dom.attribute("style").split(";", QString::SkipEmptyParts); + + QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$"); + for (QString style : styles) { + if (rx.exactMatch(style)) { + QString style_name = rx.cap(1); + QString style_value = rx.cap(2); + if (style_name == "line-style") { + if (style_value == "dashed") pen.setStyle(Qt::DashLine); + else if (style_value == "dotted") pen.setStyle(Qt::DotLine); + else if (style_value == "dashdotted") pen.setStyle(Qt::DashDotLine); + else if (style_value == "normal") pen.setStyle(Qt::SolidLine); + } else if (style_name == "line-weight") { + if (style_value == "none") pen.setColor(QColor(0, 0, 0, 0)); + else if (style_value == "thin") pen.setWidth(0); + else if (style_value == "normal") pen.setWidthF(1.0); + else if (style_value == "hight") pen.setWidthF(2.0); + else if (style_value == "eleve") pen.setWidthF(5.0); + + } else if (style_name == "filling") { + if (style_value == "white") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::white); + } else if (style_value == "black") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::black); + } else if (style_value == "blue") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::blue); + } else if (style_value == "red") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::red); + } else if (style_value == "green") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::green); + } else if (style_value == "gray") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::gray); + } else if (style_value == "brun") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(QColor(97, 44, 0)); + } else if (style_value == "yellow") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::yellow); + } else if (style_value == "cyan") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::cyan); + } else if (style_value == "magenta") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::magenta); + } else if (style_value == "lightgray") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::lightGray); + } else if (style_value == "orange") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(QColor(255, 128, 0)); + } else if (style_value == "purple") { + brush.setStyle(Qt::SolidPattern); + brush.setColor(QColor(136, 28, 168)); + }else if (style_value == "hor") { + brush.setStyle(Qt::HorPattern); + brush.setColor(Qt::black); + } else if (style_value == "ver") { + brush.setStyle(Qt::VerPattern); + brush.setColor(Qt::black); + } else if (style_value == "bdiag") { + brush.setStyle(Qt::BDiagPattern); + brush.setColor(Qt::black); + } else if (style_value == "fdiag") { + brush.setStyle(Qt::FDiagPattern); + brush.setColor(Qt::black); + } else if (style_value == "none") { + brush.setStyle(Qt::NoBrush); + } + } else if (style_name == "color") { + if (style_value == "black") { + pen.setColor(QColor(0, 0, 0, pen.color().alpha())); + } else if (style_value == "white") { + pen.setColor(QColor(255, 255, 255, pen.color().alpha())); + } else if (style_value == "red") { + pen.setColor(Qt::red); + }else if (style_value == "blue") { + pen.setColor(Qt::blue); + }else if (style_value == "green") { + pen.setColor(Qt::green); + }else if (style_value == "gray") { + pen.setColor(Qt::gray); + }else if (style_value == "brun") { + pen.setColor(QColor(97, 44, 0)); + }else if (style_value == "yellow") { + pen.setColor(Qt::yellow); + }else if (style_value == "cyan") { + pen.setColor(Qt::cyan); + }else if (style_value == "magenta") { + pen.setColor(Qt::magenta); + }else if (style_value == "lightgray") { + pen.setColor(Qt::lightGray); + }else if (style_value == "orange") { + pen.setColor(QColor(255, 128, 0)); + }else if (style_value == "purple") { + pen.setColor(QColor(136, 28, 168)); + } else if (style_value == "none") { + pen.setBrush(Qt::transparent); + } + } + } + } + + painter.setPen(pen); + painter.setBrush(brush); +} diff --git a/sources/factory/elementpicturefactory.h b/sources/factory/elementpicturefactory.h new file mode 100644 index 000000000..f031b8e0b --- /dev/null +++ b/sources/factory/elementpicturefactory.h @@ -0,0 +1,111 @@ +/* + Copyright 2006-2018 The QElectroTech Team + This file is part of QElectroTech. + + QElectroTech is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + QElectroTech is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with QElectroTech. If not, see . +*/ +#ifndef ELEMENTPICTUREFACTORY_H +#define ELEMENTPICTUREFACTORY_H + +#include +#include +#include + +class ElementsLocation; +class QPicture; +class QUuid; +class QDomElement; +class QPainter; + +/** + * @brief The ElementPictureFactory class + * This class is singleton factory, use + * to create and get the picture use by elements + */ +class ElementPictureFactory +{ + public : + struct primitives + { + QList m_lines; + QList m_rectangles; + QList m_circles; + QList> m_polygons; + QList> m_arcs; + }; + + + /** + * @brief instance + * @return The instance of the factory + */ + static ElementPictureFactory* instance() + { + static QMutex mutex; + if (!m_factory) + { + mutex.lock(); + if (!m_factory) { + m_factory = new ElementPictureFactory(); + } + mutex.unlock(); + } + return m_factory; + } + + /** + * @brief dropInstance + * Drop the instance of factory + */ + static void dropInstance() + { + static QMutex mutex; + if (m_factory) + { + mutex.lock(); + delete m_factory; + m_factory = nullptr; + mutex.unlock(); + } + } + + void getPictures(const ElementsLocation &location, QPicture &picture, QPicture &low_picture); + QPixmap pixmap(const ElementsLocation &location); + ElementPictureFactory::primitives getPrimitives(const ElementsLocation &location); + + private: + ElementPictureFactory() {} + ElementPictureFactory (const ElementPictureFactory &); + ElementPictureFactory operator= (const ElementPictureFactory &); + ~ElementPictureFactory() {} + + bool build(const ElementsLocation &location); + void parseElement(const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseLine (const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseRect (const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseEllipse(const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseCircle (const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseArc (const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parsePolygon(const QDomElement &dom, QPainter &painter, primitives &prim) const; + void parseText (const QDomElement &dom, QPainter &painter, primitives &prim) const; + void setPainterStyle(const QDomElement &dom, QPainter &painter) const; + + QHash m_pictures_H; + QHash m_low_pictures_H; + QHash m_pixmap_H; + QHash m_primitives_H; + static ElementPictureFactory* m_factory; +}; + +#endif // ELEMENTPICTUREFACTORY_H diff --git a/sources/nomenclature.h b/sources/nomenclature.h index 4b0877dac..edc75d865 100644 --- a/sources/nomenclature.h +++ b/sources/nomenclature.h @@ -24,7 +24,6 @@ #include "diagram.h" #include "qetgraphicsitem/element.h" #include "diagramcontent.h" -#include "qetgraphicsitem/customelement.h" #include "diagramposition.h" class QETProject; diff --git a/sources/qetapp.cpp b/sources/qetapp.cpp index acf3604d8..75871e0ca 100644 --- a/sources/qetapp.cpp +++ b/sources/qetapp.cpp @@ -32,6 +32,7 @@ #include "generalconfigurationpage.h" #include "qetmessagebox.h" #include "projectview.h" +#include "elementpicturefactory.h" #include #include @@ -125,6 +126,7 @@ QETApp::~QETApp() delete m_common_tbt_collection; ElementFactory::dropInstance(); + ElementPictureFactory::dropInstance(); //Delete all backup files QDir dir(configDir() + "backup"); diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index 9b68b20c9..8a46b54a4 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -23,7 +23,6 @@ #include "qetgraphicsitem/element.h" #include "elementspanelwidget.h" #include "conductorpropertieswidget.h" -#include "qetgraphicsitem/customelement.h" #include "qetproject.h" #include "projectview.h" #include "recentfiles.h" @@ -1126,17 +1125,6 @@ Element *QETDiagramEditor::currentElement() const return(selected_elements.first()); } -/** - @return the selected element in the current diagram view, or 0 if: - * no diagram is being viewed in this editor. - * no element is selected - * more than one element is selected - * the selected element is not a custom element -*/ -CustomElement *QETDiagramEditor::currentCustomElement() const { - return(dynamic_cast(currentElement())); -} - /** Cette methode permet de retrouver le projet contenant un schema donne. @param diagram_view Schema dont il faut retrouver @@ -1332,8 +1320,8 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action) } else if (value == "rotate_selected_text") diagram->undoStack().push(new RotateTextsCommand(diagram)); - else if (value == "find_selected_element" && currentCustomElement()) - findElementInPanel(currentCustomElement()->location()); + else if (value == "find_selected_element" && currentElement()) + findElementInPanel(currentElement()->location()); else if (value == "edit_selected_element") dv->editSelection(); else if (value == "group_selected_texts") @@ -2117,7 +2105,7 @@ void QETDiagramEditor::editElementInEditor(const ElementsLocation &location) { diagram view. */ void QETDiagramEditor::editSelectedElementInEditor() { - if (CustomElement *selected_element = currentCustomElement()) { + if (Element *selected_element = currentElement()) { editElementInEditor(selected_element -> location()); } } diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index c779679fb..2a5755f35 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -84,7 +84,6 @@ class QETDiagramEditor : public QETMainWindow ProjectView *currentProjectView() const; DiagramView *currentDiagramView() const; Element *currentElement() const; - CustomElement * currentCustomElement() const; ProjectView *findProject(DiagramView *) const; ProjectView *findProject(Diagram *) const; ProjectView *findProject(QETProject *) const; diff --git a/sources/qetgraphicsitem/customelement.cpp b/sources/qetgraphicsitem/customelement.cpp deleted file mode 100644 index 1c18cdfcb..000000000 --- a/sources/qetgraphicsitem/customelement.cpp +++ /dev/null @@ -1,1049 +0,0 @@ -/* - Copyright 2006-2017 The QElectroTech Team - This file is part of QElectroTech. - - QElectroTech is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - QElectroTech is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QElectroTech. If not, see . -*/ -#include "customelement.h" -#include "diagram.h" -#include "qetapp.h" -#include "partline.h" -#include -#include "terminal.h" -#include "diagramposition.h" -#include "diagramcontent.h" -#include "dynamicelementtextitem.h" -#include "partdynamictextfield.h" - -/** - Constructeur de la classe CustomElement. Permet d'instancier un element - utilisable comme un element fixe a la difference que l'element perso est - construit a partir d'une description au format XML. Celle-ci est recuperee - a l'emplacement indique. - @param location Emplacement de la definition d'element a utiliser - @param qgi Le QGraphicsItem parent de cet element - @param s Le Schema affichant cet element - @param state Un pointeur facultatif vers un entier. La valeur de cet entier - sera changee de maniere a refleter le deroulement de l'instanciation : - - 0 : L'instanciation a reussi - - 1 : l'emplacement n'a pas permis d'acceder a une definition d'element - - 2 : la definition n'etait pas lisible - - 3 : la definition n'etait pas valide / exploitable / utilisable - - 4 : Le document XML n'est pas un element "definition" - - 5 : Les attributs de la definition ne sont pas presents et / ou valides - - 6 : La definition est vide - - 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue - - 8 : Aucune partie du dessin n'a pu etre chargee -*/ -CustomElement::CustomElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - Element(qgi), - location_(location), - forbid_antialiasing(false) -{ - - if(Q_UNLIKELY( !(location.isElement() && location.exist()) )) - { - if (state) *state = 1; - return; - } - - //Start from empty lists. - m_lines.clear(); - m_rectangles.clear(); - m_circles.clear(); - m_polygons.clear(); - m_arcs.clear(); - setPrefix(autonum::elementPrefixForLocation(location)); - - int elmt_state; - buildFromXml(location.xml(), &elmt_state); - if (state) *state = elmt_state; - if (elmt_state) return; - - if (state) *state = 0; -} - -/** - Construit l'element personnalise a partir d'un element XML representant sa - definition. - @param xml_def_elmt - @param state Un pointeur facultatif vers un entier. La valeur de cet entier - sera changee de maniere a refleter le deroulement de l'instanciation : - - 0 : La construction s'est bien passee - - 4 : Le document XML n'est pas un element "definition" - - 5 : Les attributs de la definition ne sont pas presents et / ou valides - - 6 : La definition est vide - - 7 : L'analyse d'un element XML decrivant une partie du dessin de l'element a echoue - - 8 : Aucune partie du dessin n'a pu etre chargee - @return true si le chargement a reussi, false sinon -*/ -bool CustomElement::buildFromXml(const QDomElement &xml_def_elmt, int *state) -{ - m_state = QET::GIBuildingFromXml; - - if (xml_def_elmt.tagName() != "definition" || xml_def_elmt.attribute("type") != "element") - { - if (state) *state = 4; - m_state = QET::GIOK; - return(false); - } - - //Check if the curent version can read the xml description - if (xml_def_elmt.hasAttribute("version")) - { - bool conv_ok; - qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok); - if (conv_ok && QET::version.toDouble() < element_version) - { - std::cerr << qPrintable( - QObject::tr("Avertissement : l'élément " - " a été enregistré avec une version" - " ultérieure de QElectroTech.") - ) << std::endl; - } - } - - //This attribute must be present and valid - int w, h, hot_x, hot_y; - if ( - !QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\ - !QET::attributeIsAnInteger(xml_def_elmt, QString("height"), &h) ||\ - !QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_x"), &hot_x) ||\ - !QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_y"), &hot_y) ||\ - !validOrientationAttribute(xml_def_elmt) - ) { - if (state) *state = 5; - m_state = QET::GIOK; - return(false); - } - - setSize(w, h); - setHotspot(QPoint(hot_x, hot_y)); - - //the definition must have childs - if (xml_def_elmt.firstChild().isNull()) - { - if (state) *state = 6; - m_state = QET::GIOK; - return(false); - } - - //Init the QPainter for draw the elemennt - QPainter qp; - qp.begin(&drawing); - - QPainter low_zoom_qp; - low_zoom_qp.begin(&low_zoom_drawing); - QPen tmp; - tmp.setWidthF(1.0); //Vaudoo line to take into account the setCosmetic - don't remove - tmp.setCosmetic(true); - low_zoom_qp.setPen(tmp); - - //Extract the names - names.fromXml(xml_def_elmt); - setToolTip(name()); - - //load kind informations - m_kind_informations.fromXml(xml_def_elmt.firstChildElement("kindInformations"), "kindInformation"); - //load element information - m_element_informations.fromXml(xml_def_elmt.firstChildElement("elementInformations"), "elementInformation"); - - //scroll of the Children of the Definition: Parts of the Drawing - int parsed_elements_count = 0; - for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) - { - QDomElement elmts = node.toElement(); - if (elmts.isNull()) - continue; - - if (elmts.tagName() == "description") - { - //Minor workaround to find if there is a "input" tagg as label. - //If not, we set the tagg "label" to the first "input. - QList input_field; - bool have_label = false; - for (QDomElement input_node = node.firstChildElement("input") ; !input_node.isNull() ; input_node = input_node.nextSiblingElement("input")) - { - if (!input_node.isNull()) - { - input_field << input_node; - if (input_node.attribute("tagg", "none") == "label") - have_label = true; - } - } - if(!have_label && !input_field.isEmpty()) - input_field.first().setAttribute("tagg", "label"); - - //Manage the graphic description = part of drawing - for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) - { - QDomElement qde = n.toElement(); - if (qde.isNull()) - continue; - - if (parseElement(qde, qp)) - { - ++ parsed_elements_count; - - QString current_tag = qde.tagName(); - if (current_tag != "terminal" && current_tag != "input" && current_tag != PartDynamicTextField::xmlTaggName()) - { - forbid_antialiasing = true; - parseElement(qde, low_zoom_qp, false); - forbid_antialiasing = false; - } - } - else - { - if (state) - *state = 7; - m_state = QET::GIOK; - return(false); - } - } - } - } - - //End of the drawing - qp.end(); - low_zoom_qp.end(); - - - //They must be at least one parsed graphics part - if (!parsed_elements_count) - { - if (state) - *state = 8; - m_state = QET::GIOK; - return(false); - } - else - { - if (state) - *state = 0; - m_state = QET::GIOK; - return(true); - } -} - -/** - Destructeur -*/ -CustomElement::~CustomElement() { - qDeleteAll (m_lines); - qDeleteAll (m_rectangles); - qDeleteAll (m_circles); - qDeleteAll (m_polygons); - qDeleteAll (m_arcs); - qDeleteAll (m_terminals); -} - -/// @return la liste des bornes de cet element -QList CustomElement::terminals() const { - return(m_terminals); -} - -/** - * @brief CustomElement::conductors - * @return The list of conductor docked to this element - * the list is sorted according to the position of the terminal where the conductor is docked - * from top to bottom, and left to right. - */ -QList CustomElement::conductors() const -{ - QList conductors; - - for(Terminal *t : m_terminals) - conductors << t -> conductors(); - - return(conductors); -} - -/// @return the list of lines -QList CustomElement::lines() const { - return(m_lines); -} - -/// @return the list of rectangles -QList CustomElement::rectangles() const { - return(m_rectangles); -} - -/// @return the list of bounding rectangles for circles -QList CustomElement::circles() const { - return(m_circles); -} - -/// @return the list of bounding rectangles for circles -QList *> CustomElement::polygons() const { - return(m_polygons); -} - -/// @return the list of arcs -QList *> CustomElement::arcs() const { - return(m_arcs); -} - -/** - Dessine le composant sur le Diagram - @param qp Le QPainter a utiliser pour dessiner l'element - @param options Les options graphiques -*/ -void CustomElement::paint(QPainter *qp, const QStyleOptionGraphicsItem *options) { - if (options && options -> levelOfDetail < 1.0) { - low_zoom_drawing.play(qp); - } else { - drawing.play(qp); - } -} - -/** - Analyse et prend en compte un element XML decrivant une partie du dessin - de l'element perso. Si l'analyse reussit, la partie est ajoutee au dessin. - Cette partie peut etre une borne, une ligne, une ellipse, un cercle, un arc - de cercle ou un polygone. Cette methode renvoie false si l'analyse - d'une de ces formes echoue. Si l'analyse reussit ou dans le cas d'une forme - inconnue, cette methode renvoie true. A l'exception des bornes, toutes les - formes peuvent avoir un attribut style. @see setPainterStyle - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseElement(QDomElement &e, QPainter &qp, bool addtolist) -{ - if (e.tagName() == "terminal") return(parseTerminal(e)); - else if (e.tagName() == "line") return(parseLine(e, qp, addtolist)); - else if (e.tagName() == "rect") return(parseRect(e, qp, addtolist)); - else if (e.tagName() == "ellipse") return(parseEllipse(e, qp, addtolist)); - else if (e.tagName() == "circle") return(parseCircle(e, qp, addtolist)); - else if (e.tagName() == "arc") return(parseArc(e, qp, addtolist)); - else if (e.tagName() == "polygon") return(parsePolygon(e, qp, addtolist)); - else if (e.tagName() == "text") return(parseText(e, qp, addtolist)); - else if (e.tagName() == "input") return(parseInput(e)); - else if (e.tagName() == "dynamic_text") return(parseDynamicText(e)); - else return(true); -} - -/** - Analyse un element XML suppose representer une ligne. Si l'analyse - reussit, la ligne est ajoutee au dessin. - La ligne est definie par les attributs suivants : - - x1, y1 : reels, coordonnees d'une extremite de la ligne - - x2, y2 : reels, coordonnees de l'autre extremite de la ligne - - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseLine(QDomElement &e, QPainter &qp, bool addtolist) { - // verifie la presence et la validite des attributs obligatoires - qreal x1, y1, x2, y2; - if (!QET::attributeIsAReal(e, QString("x1"), &x1)) return(false); - if (!QET::attributeIsAReal(e, QString("y1"), &y1)) return(false); - if (!QET::attributeIsAReal(e, QString("x2"), &x2)) return(false); - if (!QET::attributeIsAReal(e, QString("y2"), &y2)) return(false); - - Qet::EndType first_end = Qet::endTypeFromString(e.attribute("end1")); - Qet::EndType second_end = Qet::endTypeFromString(e.attribute("end2")); - qreal length1, length2; - if (!QET::attributeIsAReal(e, QString("length1"), &length1)) length1 = 1.5; - if (!QET::attributeIsAReal(e, QString("length2"), &length2)) length2 = 1.5; - - qp.save(); - setPainterStyle(e, qp); - QPen t = qp.pen(); - t.setJoinStyle(Qt::MiterJoin); - qp.setPen(t); - - QLineF line(x1, y1, x2, y2); - - if (addtolist){ - //Add line to the list - QLineF *newLine = new QLineF(line); - m_lines << newLine; - } - - QPointF point1(line.p1()); - QPointF point2(line.p2()); - - qreal line_length(line.length()); - qreal pen_width = qp.pen().widthF(); - - // determine s'il faut dessiner les extremites - bool draw_1st_end, draw_2nd_end; - qreal reduced_line_length = line_length - (length1 * PartLine::requiredLengthForEndType(first_end)); - draw_1st_end = first_end && reduced_line_length >= 0; - if (draw_1st_end) { - reduced_line_length -= (length2 * PartLine::requiredLengthForEndType(second_end)); - } else { - reduced_line_length = line_length - (length2 * PartLine::requiredLengthForEndType(second_end)); - } - draw_2nd_end = second_end && reduced_line_length >= 0; - - // dessine la premiere extremite - QPointF start_point, stop_point; - if (draw_1st_end) { - QList four_points1(PartLine::fourEndPoints(point1, point2, length1)); - if (first_end == Qet::Circle) { - qp.drawEllipse(QRectF(four_points1[0] - QPointF(length1, length1), QSizeF(length1 * 2.0, length1 * 2.0))); - start_point = four_points1[1]; - } else if (first_end == Qet::Diamond) { - qp.drawPolygon(QPolygonF() << four_points1[1] << four_points1[2] << point1 << four_points1[3]); - start_point = four_points1[1]; - } else if (first_end == Qet::Simple) { - qp.drawPolyline(QPolygonF() << four_points1[3] << point1 << four_points1[2]); - start_point = point1; - - } else if (first_end == Qet::Triangle) { - qp.drawPolygon(QPolygonF() << four_points1[0] << four_points1[2] << point1 << four_points1[3]); - start_point = four_points1[0]; - } - - // ajuste le depart selon l'epaisseur du trait - if (pen_width && (first_end == Qet::Simple || first_end == Qet::Circle)) { - start_point = QLineF(start_point, point2).pointAt(pen_width / 2.0 / line_length); - } - } else { - start_point = point1; - } - - // dessine la seconde extremite - if (draw_2nd_end) { - QList four_points2(PartLine::fourEndPoints(point2, point1, length2)); - if (second_end == Qet::Circle) { - qp.drawEllipse(QRectF(four_points2[0] - QPointF(length2, length2), QSizeF(length2 * 2.0, length2 * 2.0))); - stop_point = four_points2[1]; - } else if (second_end == Qet::Diamond) { - qp.drawPolygon(QPolygonF() << four_points2[2] << point2 << four_points2[3] << four_points2[1]); - stop_point = four_points2[1]; - } else if (second_end == Qet::Simple) { - qp.drawPolyline(QPolygonF() << four_points2[3] << point2 << four_points2[2]); - stop_point = point2; - } else if (second_end == Qet::Triangle) { - qp.drawPolygon(QPolygonF() << four_points2[0] << four_points2[2] << point2 << four_points2[3] << four_points2[0]); - stop_point = four_points2[0]; - } - - // ajuste l'arrivee selon l'epaisseur du trait - if (pen_width && (second_end == Qet::Simple || second_end == Qet::Circle)) { - stop_point = QLineF(point1, stop_point).pointAt((line_length - (pen_width / 2.0)) / line_length); - } - } else { - stop_point = point2; - } - - qp.drawLine(start_point, stop_point); - - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un rectangle. Si l'analyse - reussit, le rectangle est ajoute au dessin. - Le rectangle est defini par les attributs suivants : - - x : abscisse du coin superieur gauche du rectangle - - y : ordonnee du coin superieur gauche du rectangle - - width : largeur du rectangle - - height : hauteur du rectangle - - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseRect(QDomElement &e, QPainter &qp, bool addtolist) -{ - // verifie la presence des attributs obligatoires - qreal rect_x, rect_y, rect_w, rect_h, rect_rx, rect_ry; - if (!QET::attributeIsAReal(e, QString("x"), &rect_x)) return(false); - if (!QET::attributeIsAReal(e, QString("y"), &rect_y)) return(false); - if (!QET::attributeIsAReal(e, QString("width"), &rect_w)) return(false); - if (!QET::attributeIsAReal(e, QString("height"), &rect_h)) return(false); - rect_rx = e.attribute("rx", "0").toDouble(); - rect_ry = e.attribute("ry", "0").toDouble(); - - if (addtolist){ - //Add rectangle to the list - QRectF *rect = new QRectF(rect_x, rect_y, rect_w, rect_h); - m_rectangles << rect; - } - - qp.save(); - setPainterStyle(e, qp); - - // force le type de jointures pour les rectangles - QPen p = qp.pen(); - p.setJoinStyle(Qt::MiterJoin); - qp.setPen(p); - - qp.drawRoundedRect(QRectF(rect_x, rect_y, rect_w, rect_h), rect_rx, rect_ry); - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un cercle. Si l'analyse - reussit, le cercle est ajoute au dessin. - Le cercle est defini par les attributs suivants : - - x : abscisse du coin superieur gauche de la quadrature du cercle - - y : ordonnee du coin superieur gauche de la quadrature du cercle - - diameter : diametre du cercle - - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseCircle(QDomElement &e, QPainter &qp, bool addtolist) { - // verifie la presence des attributs obligatoires - qreal cercle_x, cercle_y, cercle_r; - if (!QET::attributeIsAReal(e, QString("x"), &cercle_x)) return(false); - if (!QET::attributeIsAReal(e, QString("y"), &cercle_y)) return(false); - if (!QET::attributeIsAReal(e, QString("diameter"), &cercle_r)) return(false); - qp.save(); - setPainterStyle(e, qp); - QRectF circle_bounding_rect(cercle_x, cercle_y, cercle_r, cercle_r); - - if (addtolist){ - // Add circle to list - QRectF *circle = new QRectF(circle_bounding_rect); - m_circles << circle; - } - - qp.drawEllipse(circle_bounding_rect); - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer une ellipse. Si l'analyse - reussit, l'ellipse est ajoutee au dessin. - L'ellipse est definie par les attributs suivants : - - x : abscisse du coin superieur gauche du rectangle dans lequel s'inscrit l'ellipse - - y : ordonnee du coin superieur gauche du rectangle dans lequel s'inscrit l'ellipse - - width : dimension de la diagonale horizontale de l'ellipse - - height : dimension de la diagonale verticale de l'ellipse - - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseEllipse(QDomElement &e, QPainter &qp, bool addtolist) { - // verifie la presence des attributs obligatoires - qreal ellipse_x, ellipse_y, ellipse_l, ellipse_h; - if (!QET::attributeIsAReal(e, QString("x"), &ellipse_x)) return(false); - if (!QET::attributeIsAReal(e, QString("y"), &ellipse_y)) return(false); - if (!QET::attributeIsAReal(e, QString("width"), &ellipse_l)) return(false); - if (!QET::attributeIsAReal(e, QString("height"), &ellipse_h)) return(false); - qp.save(); - setPainterStyle(e, qp); - - if (addtolist){ - QVector *arc = new QVector; - arc -> push_back(ellipse_x); - arc -> push_back(ellipse_y); - arc -> push_back(ellipse_l); - arc -> push_back(ellipse_h); - arc -> push_back(0); - arc -> push_back(360); - m_arcs << arc; - } - - qp.drawEllipse(QRectF(ellipse_x, ellipse_y, ellipse_l, ellipse_h)); - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un arc de cercle. Si l'analyse - reussit, l'arc de cercle est ajoute au dessin. - L'arc de cercle est defini par les quatres parametres d'une ellipse (en fait - l'ellipse dans laquelle s'inscrit l'arc de cercle) auxquels s'ajoutent les - attributs suivants : - - start : angle de depart : l'angle "0 degre" est a trois heures - - angle : etendue (en degres) de l'arc de cercle ; une valeur positive - va dans le sens contraire des aiguilles d'une montre - - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseArc(QDomElement &e, QPainter &qp, bool addtolist) { - // verifie la presence des attributs obligatoires - qreal arc_x, arc_y, arc_l, arc_h, arc_s, arc_a; - if (!QET::attributeIsAReal(e, QString("x"), &arc_x)) return(false); - if (!QET::attributeIsAReal(e, QString("y"), &arc_y)) return(false); - if (!QET::attributeIsAReal(e, QString("width"), &arc_l)) return(false); - if (!QET::attributeIsAReal(e, QString("height"), &arc_h)) return(false); - if (!QET::attributeIsAReal(e, QString("start"), &arc_s)) return(false); - if (!QET::attributeIsAReal(e, QString("angle"), &arc_a)) return(false); - - qp.save(); - setPainterStyle(e, qp); - - if (addtolist){ - QVector *arc = new QVector; - arc -> push_back(arc_x); - arc -> push_back(arc_y); - arc -> push_back(arc_l); - arc -> push_back(arc_h); - arc -> push_back(arc_s); - arc -> push_back(arc_a); - m_arcs << arc; - } - - qp.drawArc(QRectF(arc_x, arc_y, arc_l, arc_h), (int)(arc_s * 16), (int)(arc_a * 16)); - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un polygone. Si l'analyse - reussit, le polygone est ajoute au dessin. - Le polygone est defini par une serie d'attributs x1, x2, ..., xn et autant - d'attributs y1, y2, ..., yn representant les coordonnees des differents - points du polygone. - Il est possible d'obtenir un polygone non ferme en utilisant closed="false" - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parsePolygon(QDomElement &e, QPainter &qp, bool addtolist) { - int i = 1; - while(true) { - if (QET::attributeIsAReal(e, QString("x%1").arg(i)) && QET::attributeIsAReal(e, QString("y%1").arg(i))) ++ i; - else break; - } - if (i < 3) return(false); - QVector points; // empty vector created instead of default initialized vector with i-1 elements. - for (int j = 1 ; j < i ; ++ j) { - points.insert( - j - 1, - QPointF( - e.attribute(QString("x%1").arg(j)).toDouble(), - e.attribute(QString("y%1").arg(j)).toDouble() - ) - ); - } - - qp.save(); - setPainterStyle(e, qp); - if (e.attribute("closed") == "false") qp.drawPolyline(points.data(), i-1); - else { - qp.drawPolygon(points.data(), i-1); - - // insert first point at the end again for DXF export. - points.push_back(points[0]); - } - if (addtolist){ - // Add to list of polygons. - QVector *poly = new QVector(points); - m_polygons << poly; - } - - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un texte. Si l'analyse - reussit, le texte est ajoute au dessin. - Le texte est defini par une position, une chaine de caracteres et une - taille. - @param e L'element XML a analyser - @param qp Le QPainter a utiliser pour dessiner l'element perso - @return true si l'analyse reussit, false sinon -*/ -bool CustomElement::parseText(QDomElement &e, QPainter &qp, bool addtolist) { - Q_UNUSED(addtolist); - qreal pos_x, pos_y; - int size; - if ( - !QET::attributeIsAReal(e, "x", &pos_x) ||\ - !QET::attributeIsAReal(e, "y", &pos_y) ||\ - !QET::attributeIsAnInteger(e, "size", &size) ||\ - !e.hasAttribute("text") - ) return(false); - - qp.save(); - setPainterStyle(e, qp); - - // determine la police a utiliser et en recupere les metriques associees - QFont used_font = QETApp::diagramTextsFont(size); - QFontMetrics qfm(used_font); - QColor text_color = (e.attribute("color") != "white"? Qt::black : Qt::white); - - // instancie un QTextDocument (comme la classe QGraphicsTextItem) pour - // generer le rendu graphique du texte - QTextDocument text_document; - text_document.setDefaultFont(used_font); - text_document.setPlainText(e.attribute("text")); - - // Se positionne aux coordonnees indiquees dans la description du texte - qp.setTransform(QTransform(), false); - qp.translate(pos_x, pos_y); - - // Pivote le systeme de coordonnees du QPainter pour effectuer le rendu - // dans le bon sens - qreal default_rotation_angle = 0.0; - if (QET::attributeIsAReal(e, "rotation", &default_rotation_angle)) { - qp.rotate(default_rotation_angle); - } - - /* - Deplace le systeme de coordonnees du QPainter pour effectuer le rendu au - bon endroit ; note : on soustrait l'ascent() de la police pour - determiner le coin superieur gauche du texte alors que la position - indiquee correspond a la baseline. - */ - QPointF qpainter_offset(0.0, -qfm.ascent()); - - //adjusts the offset by the margin of the text document - text_document.setDocumentMargin(0.0); - - qp.translate(qpainter_offset); - - // force the palette used to render the QTextDocument - QAbstractTextDocumentLayout::PaintContext ctx; - ctx.palette.setColor(QPalette::Text, text_color); - text_document.documentLayout() -> draw(&qp, ctx); - - qp.restore(); - return(true); -} - -/** - Analyse un element XML suppose representer un champ de texte editable par - l'utilisateur. Si l'analyse reussit, le champ est ajoute au dessin. - Le texte est defini par : - - une position - - une chaine de caracteres facultative utilisee comme valeur par defaut - - une taille - - le fait de subir les rotations de l'element ou non - @param dom_element L'element XML a analyser - @return Un pointeur vers l'objet ElementTextItem ainsi cree si l'analyse reussit, 0 sinon -*/ -bool CustomElement::parseInput(QDomElement &dom_element) { - qreal pos_x, pos_y; - int size; - if ( - !QET::attributeIsAReal(dom_element, "x", &pos_x) ||\ - !QET::attributeIsAReal(dom_element, "y", &pos_y) ||\ - !QET::attributeIsAnInteger(dom_element, "size", &size) - ) return(false); - else - { - DynamicElementTextItem *deti = new DynamicElementTextItem(this); - deti->setText(dom_element.attribute("text", "_")); - deti->setFontSize(dom_element.attribute("size", QString::number(9)).toInt()); - deti->setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble()); - - if(dom_element.attribute("tagg", "none") != "none") - { - deti->setTextFrom(DynamicElementTextItem::ElementInfo); - deti->setInfoName(dom_element.attribute("tagg")); - } - - //the origin transformation point of PartDynamicTextField is the top left corner, no matter the font size - //The origin transformation point of ElementTextItem is the middle of left edge, and so by definition, change with the size of the font - //We need to use a QMatrix to find the pos of this text from the saved pos of text item - QMatrix matrix; - //First make the rotation - matrix.rotate(dom_element.attribute("rotation", "0").toDouble()); - QPointF pos = matrix.map(QPointF(0, -deti->boundingRect().height()/2)); - matrix.reset(); - //Second translate to the pos - QPointF p(dom_element.attribute("x", QString::number(0)).toDouble(), - dom_element.attribute("y", QString::number(0)).toDouble()); - matrix.translate(p.x(), p.y()); - deti->setPos(matrix.map(pos)); - m_converted_text_from_xml_description.insert(deti, p); - return true; - } - - return false; -} - -/** - * @brief CustomElement::parseDynamicText - * Create the dynamic text field describ in @dom_element - * @param dom_element - * @return - */ -DynamicElementTextItem *CustomElement::parseDynamicText(QDomElement &dom_element) -{ - DynamicElementTextItem *deti = new DynamicElementTextItem(this); - //Because the xml description of a .elmt file is the same as how a dynamic text field is save to xml in a .qet file - //wa call fromXml, we just change the tagg name (.elmt = dynamic_text, .qet = dynamic_elmt_text) - //and the uuid (because the uuid, is the uuid of the descritpion and not the uuid of instantiated dynamic text field) - - QDomElement dom(dom_element.cloneNode(true).toElement()); - dom.setTagName(DynamicElementTextItem::xmlTaggName()); - deti->fromXml(dom); - deti->m_uuid = QUuid::createUuid(); - this->addDynamicTextItem(deti); - return deti; -} - -/** - Analyse un element XML suppose representer une borne. Si l'analyse - reussit, la borne est ajoutee a l'element. - Une borne est definie par les attributs suivants : - - x, y : coordonnees de la borne - - orientation : orientation de la borne = Nord (n), Sud (s), Est (e) ou Ouest (w) - - @param e L'element XML a analyser - @return Un pointeur vers l'objet Terminal ainsi cree, 0 sinon -*/ -Terminal *CustomElement::parseTerminal(QDomElement &e) { - // verifie la presence et la validite des attributs obligatoires - qreal terminalx, terminaly; - Qet::Orientation terminalo; - if (!QET::attributeIsAReal(e, QString("x"), &terminalx)) return(nullptr); - if (!QET::attributeIsAReal(e, QString("y"), &terminaly)) return(nullptr); - if (!e.hasAttribute("orientation")) return(nullptr); - if (e.attribute("orientation") == "n") terminalo = Qet::North; - else if (e.attribute("orientation") == "s") terminalo = Qet::South; - else if (e.attribute("orientation") == "e") terminalo = Qet::East; - else if (e.attribute("orientation") == "w") terminalo = Qet::West; - else return(nullptr); - Terminal *new_terminal = new Terminal(terminalx, terminaly, terminalo, this); - m_terminals << new_terminal; - - //Sort from top to bottom and left to rigth - std::sort(m_terminals.begin(), m_terminals.end(), [](Terminal *a, Terminal *b) - { - if(a->dockConductor().y() == b->dockConductor().y()) - return (a->dockConductor().x() < b->dockConductor().x()); - else - return (a->dockConductor().y() < b->dockConductor().y()); - }); - - return(new_terminal); -} - -/** - Active / desactive l'antialiasing sur un QPainter - @param qp Le QPainter a modifier - @param aa Booleen a true pour activer l'antialiasing, a false pour le desactiver -*/ -void CustomElement::setQPainterAntiAliasing(QPainter &qp, bool aa) { - if (forbid_antialiasing) aa = false; - qp.setRenderHint(QPainter::Antialiasing, aa); - qp.setRenderHint(QPainter::TextAntialiasing, aa); - qp.setRenderHint(QPainter::SmoothPixmapTransform, aa); -} - -/** - Verifie si l'attribut "orientation" de l'element XML e correspond bien a la - syntaxe decrivant les orientations possibles pour un element. - Cette syntaxe comprend exactement 4 lettres : - - une pour le Nord - - une pour l'Est - - une pour le Sud - - une pour l'Ouest - - Pour chaque orientation, on indique si elle est : - - l'orientation par defaut : d - - une orientation autorisee : y - - une orientation interdire : n - - Exemple : "dnny" represente un element par defaut oriente vers le nord et qui - peut etre oriente vers l'ouest mais pas vers le sud ou vers l'est. - @param e Element XML - @return true si l'attribut "orientation" est valide, false sinon -*/ -bool CustomElement::validOrientationAttribute(const QDomElement &e) { - int ori = e.attribute("orientation").toInt(); - if(ori >= 0 && ori <=3) return true; - return false; -} - -/** - Applique les parametres de style definis dans l'attribut "style" de - l'element XML e au QPainter qp - Les styles possibles sont : - - line-style : style du trait - - dashed : trait en pointilles (tirets) - - dashdotted : Traits et points - - dotted : trait en pointilles (points) - - normal : trait plein [par defaut] - - line-weight : epaiseur du trait - - thin : trait fin - - normal : trait d'epaisseur 1 [par defaut] - - none : trait invisible - - forte : trait d'epaisseur 2 - - eleve : trait d'epaisseur 5 - - filling : remplissage de la forme - - white : remplissage blanc - - black : remplissage noir - - red : remplissage rouge - - blue : remplissage bleu - - green : remplissage vert - - gray : remplissage gris - - brun : remplissage marron - - yellow : remplissage jaune - - cyan : remplissage cyan - - lightgray : remplissage gris clair - - orange : remplissage orange - - purple : remplissage violet - - none : pas de remplissage [par defaut] - - color : couleur du trait et du texte - - white : trait noir [par defaut] - - black : trait blanc - - red : trait rouge - - blue : trait bleu - - green : trait vert - - gray : trait gris - - brun : trait marron - - yellow : trait jaune - - cyan : trait cyan - - lightgray : trait gris clair - - orange : trait orange - - purple : trait violet - - lignes Horizontales - - lignes Verticales - - hachures gauche - - hachures droite - - none : pas de contour - - Les autres valeurs ne sont pas prises en compte. - @param e L'element XML a parser - @param qp Le QPainter a modifier en fonction des styles -*/ -void CustomElement::setPainterStyle(QDomElement &e, QPainter &qp) { - // recupere le QPen et la QBrush du QPainter - QPen pen = qp.pen(); - QBrush brush = qp.brush(); - - // attributs par defaut - pen.setJoinStyle(Qt::BevelJoin); - pen.setCapStyle(Qt::SquareCap); - - // recupere la liste des couples style / valeur - QStringList styles = e.attribute("style").split(";", QString::SkipEmptyParts); - - // agit sur le QPen et la QBrush en fonction des valeurs rencontrees - QRegExp rx("^\\s*([a-z-]+)\\s*:\\s*([a-z-]+)\\s*$"); - foreach (QString style, styles) { - if (rx.exactMatch(style)) { - QString style_name = rx.cap(1); - QString style_value = rx.cap(2); - if (style_name == "line-style") { - if (style_value == "dashed") pen.setStyle(Qt::DashLine); - else if (style_value == "dotted") pen.setStyle(Qt::DotLine); - else if (style_value == "dashdotted") pen.setStyle(Qt::DashDotLine); - else if (style_value == "normal") pen.setStyle(Qt::SolidLine); - } else if (style_name == "line-weight") { - if (style_value == "none") pen.setColor(QColor(0, 0, 0, 0)); - else if (style_value == "thin") pen.setWidth(0); - else if (style_value == "normal") pen.setWidthF(1.0); - else if (style_value == "hight") pen.setWidthF(2.0); - else if (style_value == "eleve") pen.setWidthF(5.0); - - } else if (style_name == "filling") { - if (style_value == "white") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::white); - } else if (style_value == "black") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::black); - } else if (style_value == "blue") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::blue); - } else if (style_value == "red") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::red); - } else if (style_value == "green") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::green); - } else if (style_value == "gray") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::gray); - } else if (style_value == "brun") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(QColor(97, 44, 0)); - } else if (style_value == "yellow") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::yellow); - } else if (style_value == "cyan") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::cyan); - } else if (style_value == "magenta") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::magenta); - } else if (style_value == "lightgray") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::lightGray); - } else if (style_value == "orange") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(QColor(255, 128, 0)); - } else if (style_value == "purple") { - brush.setStyle(Qt::SolidPattern); - brush.setColor(QColor(136, 28, 168)); - }else if (style_value == "hor") { - brush.setStyle(Qt::HorPattern); - brush.setColor(Qt::black); - } else if (style_value == "ver") { - brush.setStyle(Qt::VerPattern); - brush.setColor(Qt::black); - } else if (style_value == "bdiag") { - brush.setStyle(Qt::BDiagPattern); - brush.setColor(Qt::black); - } else if (style_value == "fdiag") { - brush.setStyle(Qt::FDiagPattern); - brush.setColor(Qt::black); - } else if (style_value == "none") { - brush.setStyle(Qt::NoBrush); - } - } else if (style_name == "color") { - if (style_value == "black") { - pen.setColor(QColor(0, 0, 0, pen.color().alpha())); - } else if (style_value == "white") { - pen.setColor(QColor(255, 255, 255, pen.color().alpha())); - } else if (style_value == "red") { - pen.setColor(Qt::red); - }else if (style_value == "blue") { - pen.setColor(Qt::blue); - }else if (style_value == "green") { - pen.setColor(Qt::green); - }else if (style_value == "gray") { - pen.setColor(Qt::gray); - }else if (style_value == "brun") { - pen.setColor(QColor(97, 44, 0)); - }else if (style_value == "yellow") { - pen.setColor(Qt::yellow); - }else if (style_value == "cyan") { - pen.setColor(Qt::cyan); - }else if (style_value == "magenta") { - pen.setColor(Qt::magenta); - }else if (style_value == "lightgray") { - pen.setColor(Qt::lightGray); - }else if (style_value == "orange") { - pen.setColor(QColor(255, 128, 0)); - }else if (style_value == "purple") { - pen.setColor(QColor(136, 28, 168)); - } else if (style_value == "none") { - pen.setBrush(Qt::transparent); - } - } - } - } - - // affectation du QPen et de la QBrush modifies au QPainter - qp.setPen(pen); - qp.setBrush(brush); - - // mise en place (ou non) de l'antialiasing - setQPainterAntiAliasing(qp, e.attribute("antialias") == "true"); -} diff --git a/sources/qetgraphicsitem/customelement.h b/sources/qetgraphicsitem/customelement.h deleted file mode 100644 index 7bff33437..000000000 --- a/sources/qetgraphicsitem/customelement.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright 2006-2017 The QElectroTech Team - This file is part of QElectroTech. - - QElectroTech is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - QElectroTech is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QElectroTech. If not, see . -*/ -#ifndef CUSTOM_ELEMENT_H -#define CUSTOM_ELEMENT_H -#include "element.h" -#include "nameslist.h" -#include "elementslocation.h" -#include - -class Terminal; - -/** - This class represents an electrical element; it may be used like a fixed - element, the difference being that the CustomElement reads its description - (names, drawing, behavior) from an XML document. -*/ -class CustomElement : public Element -{ - Q_OBJECT - - // constructors, destructor - public: - CustomElement (const ElementsLocation &, QGraphicsItem * = nullptr, int * = nullptr); - - ~CustomElement() override; - - private: - CustomElement(const CustomElement &); - - // attributes - protected: - NamesList names; - ElementsLocation location_; - QPicture drawing; - QPicture low_zoom_drawing; - QList m_terminals; - QList m_dynamic_texts; - bool forbid_antialiasing; - - - QList m_lines; - QList m_rectangles; - QList m_circles; - QList *> m_polygons; - QList *> m_arcs; - - // methods - public: - QList terminals() const override; - QList conductors() const override; - QList lines() const override; - QList rectangles() const override; - QList circles() const override; - QList *> polygons() const override; - QList *> arcs() const override; - void paint(QPainter *, const QStyleOptionGraphicsItem *) override; - QString typeId() const override; - ElementsLocation location() const; - QString name() const override; - - protected: - virtual bool buildFromXml(const QDomElement &, int * = nullptr); - virtual bool parseElement(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseLine(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseRect(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseEllipse(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseCircle(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseArc(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parsePolygon(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseText(QDomElement &, QPainter &, bool addtolist = true); - virtual bool parseInput(QDomElement &); - virtual DynamicElementTextItem *parseDynamicText(QDomElement &); - virtual Terminal *parseTerminal(QDomElement &); - - virtual void setQPainterAntiAliasing(QPainter &, bool); - virtual bool validOrientationAttribute(const QDomElement &); - virtual void setPainterStyle(QDomElement &, QPainter &); -}; - -/** - @return The element type ID; considering a CustomElement, this means the - @location of its XML description. - @see location() -*/ -inline QString CustomElement::typeId() const { - return(location_.path()); -} - -/** - @return the location of the XML document describing this element. -*/ -inline ElementsLocation CustomElement::location() const { - return(location_); -} - -/** - @return The name of this element. -*/ -inline QString CustomElement::name() const { - return(names.name(location_.baseName())); -} - -#endif diff --git a/sources/qetgraphicsitem/dynamicelementtextitem.h b/sources/qetgraphicsitem/dynamicelementtextitem.h index e995130a0..2b4ca4d5a 100644 --- a/sources/qetgraphicsitem/dynamicelementtextitem.h +++ b/sources/qetgraphicsitem/dynamicelementtextitem.h @@ -38,7 +38,7 @@ class DynamicElementTextItem : public DiagramTextItem { friend class DynamicTextItemDelegate; friend class CompositeTextEditDialog; - friend class CustomElement; + friend class Element; Q_OBJECT diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index 3a535a5da..85bc24d2c 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -31,6 +31,8 @@ #include "changeelementinformationcommand.h" #include "dynamicelementtextitem.h" #include "elementtextitemgroup.h" +#include "elementpicturefactory.h" +#include "iostream" class ElementXmlRetroCompatibility { @@ -62,15 +64,38 @@ class ElementXmlRetroCompatibility }; /** - Constructeur pour un element sans scene ni parent -*/ -Element::Element(QGraphicsItem *parent) : + * @brief Element::Element + * @param location, location of this element + * @param parent, parent graphics item + * @param state, state of the instanciation + */ +Element::Element(const ElementsLocation &location, QGraphicsItem *parent, int *state) : QetGraphicsItem(parent), - must_highlight_(false), - m_mouse_over(false) + m_location (location) { + if(! (location.isElement() && location.exist())) + { + if (state) + { + *state = 1; + return; + } + } + int elmt_state; + buildFromXml(location.xml(), &elmt_state); + if (state) { + *state = elmt_state; + } + if (elmt_state) { + return; + } + if (state) { + *state = 0; + } + + setPrefix(autonum::elementPrefixForLocation(location)); m_link_type = Simple; - uuid_ = QUuid::createUuid(); + m_uuid = QUuid::createUuid(); setZValue(10); setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); setAcceptHoverEvents(true); @@ -85,11 +110,37 @@ Element::Element(QGraphicsItem *parent) : } /** - Destructeur -*/ + * @brief Element::~Element + */ Element::~Element() { - qDeleteAll(m_dynamic_text_list); + qDeleteAll (m_dynamic_text_list); + qDeleteAll (m_terminals); +} + +/** + * @brief Element::terminals + * @return the list of terminals of this element. + */ +QList Element::terminals() const { + return m_terminals; +} + +/** + * @brief Element::conductors + * @return The list of conductors docked to this element + * the list is sorted according to the position of the terminal where the conductor is docked + * from top to bottom, and left to right. + */ +QList Element::conductors() const +{ + QList conductors; + + for (Terminal *t : m_terminals) { + conductors << t -> conductors(); + } + + return(conductors); } void Element::editProperty() @@ -106,20 +157,11 @@ void Element::editProperty() } } - - -/** - @return true si l'element est mis en evidence -*/ -bool Element::isHighlighted() const { - return(must_highlight_); -} - /** @param hl true pour mettre l'element en evidence, false sinon */ void Element::setHighlighted(bool hl) { - must_highlight_ = hl; + m_must_highlight = hl; update(); } @@ -142,14 +184,20 @@ void Element::displayHelpLine(bool b) */ void Element::paint(QPainter *painter, const QStyleOptionGraphicsItem *options, QWidget *) { - - if (must_highlight_) drawHighlight(painter, options); + if (m_must_highlight) { + drawHighlight(painter, options); + } - //Draw the element himself - paint(painter, options); + if (options && options -> levelOfDetail < 1.0) { + painter->drawPicture(0, 0, m_low_zoom_picture); + } else { + painter->drawPicture(0, 0, m_picture); + } //Draw the selection rectangle - if ( isSelected() || m_mouse_over ) drawSelection(painter, options); + if ( isSelected() || m_mouse_over ) { + drawSelection(painter, options); + } } /** @@ -160,20 +208,20 @@ QRectF Element::boundingRect() const { } /** - Definit la taille de l'element sur le schema. Les tailles doivent etre - des multiples de 10 ; si ce n'est pas le cas, les dimensions indiquees - seront arrrondies aux dizaines superieures. - @param wid Largeur de l'element - @param hei Hauteur de l'element - @return La taille finale de l'element -*/ -QSize Element::setSize(int wid, int hei) { + * @brief Element::setSize + * Define the size of the element. + * The size must be a multiple of 10. + * If not, the dimensions indicated will be arrrondies to higher tens. + * @param wid + * @param hei + */ +void Element::setSize(int wid, int hei) +{ prepareGeometryChange(); - // chaque dimension indiquee est arrondie a la dizaine superieure + while (wid % 10) ++ wid; while (hei % 10) ++ hei; - // les dimensions finales sont conservees et retournees - return(dimensions = QSize(wid, hei)); + dimensions = QSize(wid, hei); } /** @@ -209,25 +257,11 @@ QPoint Element::hotspot() const { } /** - Selectionne l'element -*/ -void Element::select() { - setSelected(true); -} - -/** - Deselectionne l'element -*/ -void Element::deselect() { - setSelected(false); -} - -/** - @return La pixmap de l'element -*/ + * @brief Element::pixmap + * @return the pixmap of this element + */ QPixmap Element::pixmap() { - if (preview.isNull()) updatePixmap(); // on genere la pixmap si ce n'est deja fait - return(preview); + return ElementPictureFactory::instance()->pixmap(m_location); } /*** Methodes protegees ***/ @@ -301,20 +335,274 @@ void Element::drawHighlight(QPainter *painter, const QStyleOptionGraphicsItem *o } /** - Fonction initialisant et dessinant la pixmap de l'element. -*/ -void Element::updatePixmap() { - // Pixmap transparente faisant la taille de base de l'element - preview = QPixmap(dimensions); - preview.fill(QColor(255, 255, 255, 0)); - // QPainter sur la pixmap, avec antialiasing - QPainter p(&preview); - p.setRenderHint(QPainter::Antialiasing, true); - p.setRenderHint(QPainter::SmoothPixmapTransform, true); - // Translation de l'origine du repere de la pixmap - p.translate(hotspot_coord); - // L'element se dessine sur la pixmap - paint(&p, nullptr); + * @brief Element::buildFromXml + * Build this element from an xml description + * @param xml_def_elmt + * @param state + * Optional pointer which define the status of build + * 0 - evreything all right + * 4 - xml isn't a "definition" + * 5 - attribute of the definition isn't present or valid + * 6 - the definition is empty + * 7 - parsing of a xml node who describe a graphical part failed. + * 8 - No part of the drawing could be loaded + * @return + */ +bool Element::buildFromXml(const QDomElement &xml_def_elmt, int *state) +{ + m_state = QET::GIBuildingFromXml; + + if (xml_def_elmt.tagName() != "definition" || xml_def_elmt.attribute("type") != "element") + { + if (state) *state = 4; + m_state = QET::GIOK; + return(false); + } + + //Check if the curent version can read the xml description + if (xml_def_elmt.hasAttribute("version")) + { + bool conv_ok; + qreal element_version = xml_def_elmt.attribute("version").toDouble(&conv_ok); + if (conv_ok && QET::version.toDouble() < element_version) + { + std::cerr << qPrintable( + QObject::tr("Avertissement : l'élément " + " a été enregistré avec une version" + " ultérieure de QElectroTech.") + ) << std::endl; + } + } + + //This attribute must be present and valid + int w, h, hot_x, hot_y; + if ( + !QET::attributeIsAnInteger(xml_def_elmt, QString("width"), &w) ||\ + !QET::attributeIsAnInteger(xml_def_elmt, QString("height"), &h) ||\ + !QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_x"), &hot_x) ||\ + !QET::attributeIsAnInteger(xml_def_elmt, QString("hotspot_y"), &hot_y) + ) { + if (state) *state = 5; + m_state = QET::GIOK; + return(false); + } + + setSize(w, h); + setHotspot(QPoint(hot_x, hot_y)); + + //the definition must have childs + if (xml_def_elmt.firstChild().isNull()) + { + if (state) *state = 6; + m_state = QET::GIOK; + return(false); + } + //Extract the names + m_names.fromXml(xml_def_elmt); + setToolTip(name()); + + //load kind informations + m_kind_informations.fromXml(xml_def_elmt.firstChildElement("kindInformations"), "kindInformation"); + //load element information + m_element_informations.fromXml(xml_def_elmt.firstChildElement("elementInformations"), "elementInformation"); + + //scroll of the Children of the Definition: Parts of the Drawing + int parsed_elements_count = 0; + for (QDomNode node = xml_def_elmt.firstChild() ; !node.isNull() ; node = node.nextSibling()) + { + QDomElement elmts = node.toElement(); + if (elmts.isNull()) + continue; + + if (elmts.tagName() == "description") + { + //Minor workaround to find if there is a "input" tagg as label. + //If not, we set the tagg "label" to the first "input. + QList input_field; + bool have_label = false; + for (QDomElement input_node = node.firstChildElement("input") ; !input_node.isNull() ; input_node = input_node.nextSiblingElement("input")) + { + if (!input_node.isNull()) + { + input_field << input_node; + if (input_node.attribute("tagg", "none") == "label") + have_label = true; + } + } + if(!have_label && !input_field.isEmpty()) + input_field.first().setAttribute("tagg", "label"); + + //Parse the definition + for (QDomNode n = node.firstChild() ; !n.isNull() ; n = n.nextSibling()) + { + QDomElement qde = n.toElement(); + if (qde.isNull()) + continue; + + if (parseElement(qde)) { + ++ parsed_elements_count; + } + else + { + if (state) + *state = 7; + m_state = QET::GIOK; + return(false); + } + } + } + } + + ElementPictureFactory *epf = ElementPictureFactory::instance(); + epf->getPictures(m_location, const_cast(m_picture), const_cast(m_low_zoom_picture)); + + if(!m_picture.isNull()) + ++ parsed_elements_count; + + //They must be at least one parsed graphics part + if (!parsed_elements_count) + { + if (state) + *state = 8; + m_state = QET::GIOK; + return(false); + } + else + { + if (state) + *state = 0; + m_state = QET::GIOK; + return(true); + } +} + +/** + * @brief Element::parseElement + * Parse the element of the xml description of this element + * @param dom + * @return + */ +bool Element::parseElement(const QDomElement &dom) +{ + if (dom.tagName() == "terminal") return(parseTerminal(dom)); + else if (dom.tagName() == "input") return(parseInput(dom)); + else if (dom.tagName() == "dynamic_text") return(parseDynamicText(dom)); + else return(true); +} + +/** + * @brief Element::parseInput + * Parse the input (old text field) + * the parsed input are converted to dynamic text field, this function + * is only here to keep compatibility with old text. + * @param dom_element + * @return + */ +bool Element::parseInput(const QDomElement &dom_element) +{ + qreal pos_x, pos_y; + int size; + if ( + !QET::attributeIsAReal(dom_element, "x", &pos_x) ||\ + !QET::attributeIsAReal(dom_element, "y", &pos_y) ||\ + !QET::attributeIsAnInteger(dom_element, "size", &size) + ) return(false); + else + { + DynamicElementTextItem *deti = new DynamicElementTextItem(this); + deti->setText(dom_element.attribute("text", "_")); + deti->setFontSize(dom_element.attribute("size", QString::number(9)).toInt()); + deti->setRotation(dom_element.attribute("rotation", QString::number(0)).toDouble()); + + if(dom_element.attribute("tagg", "none") != "none") + { + deti->setTextFrom(DynamicElementTextItem::ElementInfo); + deti->setInfoName(dom_element.attribute("tagg")); + } + + //the origin transformation point of PartDynamicTextField is the top left corner, no matter the font size + //The origin transformation point of ElementTextItem is the middle of left edge, and so by definition, change with the size of the font + //We need to use a QMatrix to find the pos of this text from the saved pos of text item + QMatrix matrix; + //First make the rotation + matrix.rotate(dom_element.attribute("rotation", "0").toDouble()); + QPointF pos = matrix.map(QPointF(0, -deti->boundingRect().height()/2)); + matrix.reset(); + //Second translate to the pos + QPointF p(dom_element.attribute("x", QString::number(0)).toDouble(), + dom_element.attribute("y", QString::number(0)).toDouble()); + matrix.translate(p.x(), p.y()); + deti->setPos(matrix.map(pos)); + m_converted_text_from_xml_description.insert(deti, p); + return true; + } + + return false; +} + +/** + * @brief Element::parseDynamicText + * Create the dynamic text field describ in @dom_element + * @param dom_element + * @return + */ +DynamicElementTextItem *Element::parseDynamicText(const QDomElement &dom_element) +{ + DynamicElementTextItem *deti = new DynamicElementTextItem(this); + //Because the xml description of a .elmt file is the same as how a dynamic text field is save to xml in a .qet file + //wa call fromXml, we just change the tagg name (.elmt = dynamic_text, .qet = dynamic_elmt_text) + //and the uuid (because the uuid, is the uuid of the descritpion and not the uuid of instantiated dynamic text field) + + QDomElement dom(dom_element.cloneNode(true).toElement()); + dom.setTagName(DynamicElementTextItem::xmlTaggName()); + deti->fromXml(dom); + deti->m_uuid = QUuid::createUuid(); + this->addDynamicTextItem(deti); + return deti; +} + +Terminal *Element::parseTerminal(const QDomElement &dom_element) +{ + qreal terminalx, terminaly; + Qet::Orientation terminalo; + if (!QET::attributeIsAReal(dom_element, QString("x"), &terminalx)) { + return(nullptr); + } + if (!QET::attributeIsAReal(dom_element, QString("y"), &terminaly)) { + return(nullptr); + } + if (!dom_element.hasAttribute("orientation")) { + return(nullptr); + } + if (dom_element.attribute("orientation") == "n") { + terminalo = Qet::North; + } + else if (dom_element.attribute("orientation") == "s") { + terminalo = Qet::South; + } + else if (dom_element.attribute("orientation") == "e") { + terminalo = Qet::East; + } + else if (dom_element.attribute("orientation") == "w") { + terminalo = Qet::West; + } + else { + return(nullptr); + } + + Terminal *new_terminal = new Terminal(terminalx, terminaly, terminalo, this); + m_terminals << new_terminal; + + //Sort from top to bottom and left to rigth + std::sort(m_terminals.begin(), m_terminals.end(), [](Terminal *a, Terminal *b) + { + if(a->dockConductor().y() == b->dockConductor().y()) + return (a->dockConductor().x() < b->dockConductor().x()); + else + return (a->dockConductor().y() < b->dockConductor().y()); + }); + + return(new_terminal); } /** @@ -413,7 +701,7 @@ bool Element::fromXml(QDomElement &e, QHash &table_id_adr, bool foreach (QDomElement qdo, uuid_list) tmp_uuids_link << qdo.attribute("uuid"); //uuid of this element - uuid_= QUuid(e.attribute("uuid", QUuid::createUuid().toString())); + m_uuid= QUuid(e.attribute("uuid", QUuid::createUuid().toString())); //load prefix m_prefix = e.attribute("prefix"); @@ -726,7 +1014,7 @@ QDomElement Element::toXml(QDomDocument &document, QHash &table QDomElement element = document.createElement("element"); // type - element.setAttribute("type", typeId()); + element.setAttribute("type", m_location.path()); // uuid element.setAttribute("uuid", uuid().toString()); @@ -1258,3 +1546,15 @@ void Element::freezeNewAddedElement() { } else return; } + +/** + * @brief Element::name + * @return the human name of this element + */ +QString Element::name() const { + return m_names.name(m_location.baseName()); +} + +ElementsLocation Element::location() const { + return m_location; +} diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index 1413a73b3..9cd51a69e 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -22,13 +22,15 @@ #include "qetgraphicsitem.h" #include "diagramcontext.h" #include "assignvariables.h" +#include "elementslocation.h" +#include "nameslist.h" + #include +#include class QETProject; class Terminal; class Conductor; -class NumerotationContext; -class DiagramTextItem; class DynamicElementTextItem; class ElementTextItemGroup; @@ -43,7 +45,7 @@ class Element : public QetGraphicsItem // constructors, destructor public: - Element(QGraphicsItem * = nullptr); + Element(const ElementsLocation &location, QGraphicsItem * = nullptr, int *state = nullptr); ~Element() override; private: Element(const Element &); @@ -68,54 +70,7 @@ class Element : public QetGraphicsItem Master = 8, Slave = 16, Terminale = 32}; - - private: - QSize dimensions; - QPoint hotspot_coord; - QPixmap preview; - - // methods - public: - /// @return the list of terminals for this element - virtual QList terminals() const = 0; - /// @return the list of conductors attached to this element - virtual QList conductors() const = 0; - /// @return the list of lines items in this element - virtual QList lines() const = 0; - /// @return the list of rectangles items in this element - virtual QList rectangles() const = 0; - /// @return the list of bounding rectangles for circles items in this element - virtual QList circles() const = 0; - /// @return the list of polygons in this element - virtual QList *> polygons() const = 0; - /// @return the list of arcs in this element - virtual QList *> arcs() const = 0; - - QList > AlignedFreeTerminals () const; - - /** - *related method and attributes, - *about none graphic thing - *like the linked element or information about this element - */ - //METHODS related to linked element - public: - bool isFree () const; - virtual void linkToElement (Element *) {} - virtual void unlinkAllElements () {} - virtual void unlinkElement (Element *) {} - virtual void initLink (QETProject *); - QList linkedElements (); - virtual kind linkType() const {return m_link_type;} // @return the linkable type - void newUuid() {uuid_ = QUuid::createUuid();} //create new uuid for this element - - //ATTRIBUTES related to linked element - protected: - QList connected_elements; - QList tmp_uuids_link; - QUuid uuid_; - kind m_link_type; - + signals: void linkedElementChanged(); //This signal is emited when the linked elements with this element change void elementInfoChange(DiagramContext old_info, DiagramContext new_info); @@ -126,8 +81,13 @@ class Element : public QetGraphicsItem void textAddedToGroup(DynamicElementTextItem *text, ElementTextItemGroup *group); void textRemovedFromGroup(DynamicElementTextItem *text, ElementTextItemGroup *group); - //METHODS related to information + public: + QList terminals() const; + QList conductors() const; + QList > AlignedFreeTerminals () const; + + //METHODS related to information DiagramContext elementInformations ()const {return m_element_informations;} virtual void setElementInformations (DiagramContext dc); DiagramContext kindInformations () const {return m_kind_informations;} //@kind_information_ is used to store more information @@ -136,56 +96,29 @@ class Element : public QetGraphicsItem autonum::sequentialNumbers sequenceStruct () const {return m_autoNum_seq;} autonum::sequentialNumbers& rSequenceStruct() {return m_autoNum_seq;} - void setUpFormula(bool code_letter = true); void setPrefix(QString); QString getPrefix() const; void freezeLabel(bool freeze); bool isFreezeLabel() const {return m_freeze_label;} void freezeNewAddedElement(); - - //ATTRIBUTES - protected: - DiagramContext m_element_informations, m_kind_informations; - autonum::sequentialNumbers m_autoNum_seq; - bool m_freeze_label = false; - QString m_F_str; - - public: - virtual void paint(QPainter *, const QStyleOptionGraphicsItem *) = 0; - /// @return This element type ID - virtual QString typeId() const = 0; - /// @return the human name for this element - QString name() const override = 0; - - virtual bool isHighlighted() const; + + QString name() const override; + ElementsLocation location() const; virtual void setHighlighted(bool); void displayHelpLine(bool b = true); - void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; - QRectF boundingRect() const override; - QSize setSize(int, int); QSize size() const; QPixmap pixmap(); - - // methods related to the hotspot QPoint setHotspot(QPoint); - QPoint hotspot() const; - - // selection-related methods - void select(); - void deselect(); - + QPoint hotspot() const; void editProperty() override; - - // methods related to XML import/export static bool valideXml(QDomElement &); virtual bool fromXml(QDomElement &, QHash &, bool = false); virtual QDomElement toXml(QDomDocument &, QHash &) const; QUuid uuid() const; - - // orientation-related methods int orientation() const; - + + //METHODS related to texts void addDynamicTextItem(DynamicElementTextItem *deti = nullptr); void removeDynamicTextItem(DynamicElementTextItem *deti); QList dynamicTextItems() const; @@ -196,16 +129,34 @@ class Element : public QetGraphicsItem QList textGroups() const; bool addTextToGroup(DynamicElementTextItem *text, ElementTextItemGroup *group); bool removeTextFromGroup(DynamicElementTextItem *text, ElementTextItemGroup *group); + + //METHODS related to linked element + bool isFree () const; + virtual void linkToElement (Element *) {} + virtual void unlinkAllElements () {} + virtual void unlinkElement (Element *) {} + virtual void initLink (QETProject *); + QList linkedElements (); + virtual kind linkType() const {return m_link_type;} // @return the linkable type + void newUuid() {m_uuid = QUuid::createUuid();} //create new uuid for this element protected: void drawAxes(QPainter *, const QStyleOptionGraphicsItem *); + void setSize(int, int); private: - bool must_highlight_; void drawSelection(QPainter *, const QStyleOptionGraphicsItem *); void drawHighlight(QPainter *, const QStyleOptionGraphicsItem *); - void updatePixmap(); + bool buildFromXml(const QDomElement &, int * = nullptr); + bool parseElement(const QDomElement &dom); + bool parseInput(const QDomElement &dom_element); + DynamicElementTextItem *parseDynamicText(const QDomElement &dom_element); + Terminal *parseTerminal(const QDomElement &dom_element); + //Reimplemented from QGraphicsItem + public: + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) override; + QRectF boundingRect() const override; protected: void mouseMoveEvent ( QGraphicsSceneMouseEvent *event ) override; void mouseReleaseEvent ( QGraphicsSceneMouseEvent *event ) override; @@ -217,8 +168,30 @@ class Element : public QetGraphicsItem // are converted to dynamic text field, the QPointF is the original position of the text item, because the origin transformation point of text item // and dynamic text item are not the same, so we must to keep a track of this value, to be use in the function element::fromXml QHash m_converted_text_from_xml_description; + + //ATTRIBUTES related to linked element + QList connected_elements; + QList tmp_uuids_link; + QUuid m_uuid; + kind m_link_type; + + //ATTRIBUTES related to informations + DiagramContext m_element_informations, m_kind_informations; + autonum::sequentialNumbers m_autoNum_seq; + bool m_freeze_label = false; + QString m_F_str; + + ElementsLocation m_location; + NamesList m_names; + QList m_terminals; + const QPicture m_picture; + const QPicture m_low_zoom_picture; + private: - bool m_mouse_over; + bool m_must_highlight = false; + QSize dimensions; + QPoint hotspot_coord; + bool m_mouse_over = false; QString m_prefix; QList m_dynamic_text_list; QList m_texts_group; @@ -248,7 +221,7 @@ inline int Element::orientation() const { * @return the uuid of this element */ inline QUuid Element::uuid() const { - return uuid_; + return m_uuid; } /** diff --git a/sources/qetgraphicsitem/ghostelement.cpp b/sources/qetgraphicsitem/ghostelement.cpp deleted file mode 100644 index 671fe0698..000000000 --- a/sources/qetgraphicsitem/ghostelement.cpp +++ /dev/null @@ -1,185 +0,0 @@ -/* - Copyright 2006-2017 The QElectroTech Team - This file is part of QElectroTech. - - QElectroTech is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - QElectroTech is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QElectroTech. If not, see . -*/ -#include "ghostelement.h" -#include "qet.h" -#include "terminal.h" -#include "diagramcommands.h" - -/** - Constructeur - @param location Emplacement de la definition d'element a utiliser - @param qgi Le QGraphicsItem parent de cet element - @param d Le schema affichant cet element -*/ -GhostElement::GhostElement( - const ElementsLocation &location, - QGraphicsItem *qgi -) : - CustomElement(location, qgi) -{ - QString tooltip_string = QString( - tr("Élément manquant : %1") - ).arg(location_.toString()); - setToolTip(tooltip_string); -} - -/** - Destructeur -*/ -GhostElement::~GhostElement() { -} - - -/** - @param e L'element XML a analyser. - @param table_id_adr Reference vers la table de correspondance entre les IDs - du fichier XML et les adresses en memoire. Si l'import reussit, il faut y - ajouter les bons couples (id, adresse). - @return true si l'import a reussi, false sinon -*/ -bool GhostElement::fromXml(QDomElement &e, QHash &table_id_adr, bool handle_inputs_rotation) { - // instancie les bornes decrites dans l'element XML - terminalsFromXml(e, table_id_adr); - - // instancie les champs de texte decrits dans l'element XML - foreach(QDomElement qde, QET::findInDomElement(e, "inputs", "input")) { - qde.setAttribute("size", 9); // arbitraire - CustomElement::parseInput(qde); - } - - /* - maintenant que l'element fantome connait toutes les bornes et tous les - champs de texte, on peut determiner une taille appropriee - */ - QRect final_bounding_rect = minimalBoundingRect().united(childrenBoundingRect()).toAlignedRect(); - setSize(final_bounding_rect.width(), final_bounding_rect.height()); - setHotspot(QPoint() - final_bounding_rect.topLeft()); - - // on peut desormais confectionner le rendu de l'element - generateDrawings(); - - // position, selection - setPos(e.attribute("x").toDouble(), e.attribute("y").toDouble()); - setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); - - // orientation - bool conv_ok; - int read_ori = e.attribute("orientation").toInt(&conv_ok); - if (!conv_ok || read_ori < 0 || read_ori > 3) read_ori = 0; - if (handle_inputs_rotation) { - setRotation(rotation() + (90*read_ori)); - } else { - setRotation(90*read_ori); - } - return(true); -} - -/** - @return le bounding rect minimum, utilise si l'element fantome n'a ni champ - de texte ni borne. -*/ -QRectF GhostElement::minimalBoundingRect() const { - return( - QRectF( - QPointF(-10.0, -10.0), - QSizeF(20.0, 20.0) - ) - ); -} - -/** - Gere l'import des bornes - @param e L'element XML a analyser. - @param table_id_adr Reference vers la table de correspondance entre les IDs - du fichier XML et les adresses en memoire. Si l'import reussit, il faut y - ajouter les bons couples (id, adresse). - @return true si l'import a reussi, false sinon -*/ -bool GhostElement::terminalsFromXml(QDomElement &e, QHash &table_id_adr) { - // instancie les bornes decrites dans l'element XML - foreach(QDomElement qde, QET::findInDomElement(e, "terminals", "terminal")) { - if (!Terminal::valideXml(qde)) continue; - - // modifie certains attributs pour que l'analyse par la classe CustomElement reussisse - int previous_x_value = qde.attribute("x").toInt(); - int previous_y_value = qde.attribute("y").toInt(); - Qet::Orientation previous_ori_value = static_cast(qde.attribute("orientation").toInt()); - - qreal x_add = 0.0, y_add = 0.0; - if (previous_ori_value == Qet::North) y_add = -Terminal::terminalSize; - else if (previous_ori_value == Qet::East) x_add = Terminal::terminalSize; - else if (previous_ori_value == Qet::South) y_add = Terminal::terminalSize; - else if (previous_ori_value == Qet::West) x_add = -Terminal::terminalSize; - qde.setAttribute("x", previous_x_value + x_add); - qde.setAttribute("y", previous_y_value + y_add); - qde.setAttribute("orientation", previous_ori_value); - - if (Terminal *new_terminal = CustomElement::parseTerminal(qde)) { - table_id_adr.insert(qde.attribute("id").toInt(), new_terminal); - } - - // restaure les attributs modifies - qde.setAttribute("x", previous_x_value); - qde.setAttribute("y", previous_y_value); - qde.setAttribute("orientation", previous_ori_value); - } - return(true); -} - -/** - Genere les rendus de l'element fantome : il s'agit d'un rectangle - representant grosso modo l'espace que devait prendre l'element initial. - En son centre est dessine un point d'interrogation. Une petite croix indique - le point de saisie de l'element. -*/ -void GhostElement::generateDrawings() { - // style de dessin - QPen t(QBrush(Qt::black), 1.0); - - // rendu normal - QPainter qp; - qp.begin(&drawing); - qp.setPen(t); - qp.setRenderHint(QPainter::Antialiasing, false); - generateDrawing(&qp); - qp.end(); - - // rendu low_zoom - QPainter low_zoom_qp; - low_zoom_qp.begin(&low_zoom_drawing); - t.setCosmetic(true); - low_zoom_qp.setRenderHint(QPainter::Antialiasing, false); - low_zoom_qp.setPen(t); - generateDrawing(&low_zoom_qp); - low_zoom_qp.end(); -} - -/** - Genere un rendu de l'element fantome - @see generateDrawings -*/ -void GhostElement::generateDrawing(QPainter *painter) { - // une petite croix indique le point de saisie de l'element - painter -> drawLine(QLineF(-1.0, 0.0, 1.0, 0.0)); - painter -> drawLine(QLineF(0.0, -1.0, 0.0, 1.0)); - - // rectangle avec un point d'interrogation au centre - QRectF drawn_rect = boundingRect().adjusted(4.0, 4.0, -4.0, -4.0); - painter -> drawRect(drawn_rect); - painter -> drawText(drawn_rect, Qt::AlignHCenter | Qt::AlignVCenter, "?"); -} diff --git a/sources/qetgraphicsitem/ghostelement.h b/sources/qetgraphicsitem/ghostelement.h deleted file mode 100644 index e9f47ea19..000000000 --- a/sources/qetgraphicsitem/ghostelement.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - Copyright 2006-2017 The QElectroTech Team - This file is part of QElectroTech. - - QElectroTech is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 2 of the License, or - (at your option) any later version. - - QElectroTech is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with QElectroTech. If not, see . -*/ -#ifndef GHOST_ELEMENT_H -#define GHOST_ELEMENT_H -#include "customelement.h" -class QGraphicsItem; -class ElementsLocation; -class Terminal; -/** - The GhostElement class inherits CustomElement. A GhostElement aims at - visually replacing a CustomElement whose definition could not be loaded. - This way, instead of not loading an element, thus potentially losing its - position, its orientation, its child text items and conductors, one can - substitute a GhostElement. The GhostElement will extrapolate the position - of terminals and text items from the rest of the diagram. It is visually - rendered using a simple rectangle. -*/ -class GhostElement : public CustomElement { - - Q_OBJECT - - // constructor, destructor - public: - GhostElement(const ElementsLocation &, QGraphicsItem * = nullptr); - ~GhostElement() override; - - // methods - public: - bool fromXml(QDomElement &, QHash &, bool = false) override; - kind linkType() const override {return Simple;} - - protected: - QRectF minimalBoundingRect() const; - bool terminalsFromXml(QDomElement &, QHash &); - void generateDrawings(); - void generateDrawing(QPainter *); -}; -#endif diff --git a/sources/qetgraphicsitem/masterelement.cpp b/sources/qetgraphicsitem/masterelement.cpp index 1783dcecc..c0d8c8a25 100644 --- a/sources/qetgraphicsitem/masterelement.cpp +++ b/sources/qetgraphicsitem/masterelement.cpp @@ -30,7 +30,7 @@ * @param state int used to know if the creation of element have error */ MasterElement::MasterElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state) + Element(location, qgi, state) { m_link_type = Element::Master; } @@ -109,7 +109,7 @@ void MasterElement::unlinkElement(Element *elmt) */ void MasterElement::initLink(QETProject *project) { //Create the link with other element if needed - CustomElement::initLink(project); + Element::initLink(project); } /** @@ -132,7 +132,7 @@ QVariant MasterElement::itemChange(QGraphicsItem::GraphicsItemChange change, con m_first_scene_change = false; connect(diagram()->project(), &QETProject::XRefPropertiesChanged, this, &MasterElement::xrefPropertiesChanged); } - return CustomElement::itemChange(change, value); + return Element::itemChange(change, value); } void MasterElement::xrefPropertiesChanged() diff --git a/sources/qetgraphicsitem/masterelement.h b/sources/qetgraphicsitem/masterelement.h index 7acd31c06..e87f8bdf9 100644 --- a/sources/qetgraphicsitem/masterelement.h +++ b/sources/qetgraphicsitem/masterelement.h @@ -18,7 +18,7 @@ #ifndef MASTERELEMENT_H #define MASTERELEMENT_H -#include "customelement.h" +#include "element.h" class CrossRefItem; @@ -28,7 +28,7 @@ class CrossRefItem; * to be a master element. Master element can be linked with slave element * and display a cross ref item for know with what other element he is linked */ -class MasterElement : public CustomElement +class MasterElement : public Element { Q_OBJECT diff --git a/sources/qetgraphicsitem/reportelement.cpp b/sources/qetgraphicsitem/reportelement.cpp index f12e2987c..dd1f11c9e 100644 --- a/sources/qetgraphicsitem/reportelement.cpp +++ b/sources/qetgraphicsitem/reportelement.cpp @@ -24,7 +24,7 @@ #include "dynamicelementtextitem.h" ReportElement::ReportElement(const ElementsLocation &location, const QString& link_type,QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state) + Element(location, qgi, state) { link_type == "next_report"? m_link_type=NextReport : m_link_type=PreviousReport; link_type == "next_report"? m_inverse_report=PreviousReport : m_inverse_report=NextReport; diff --git a/sources/qetgraphicsitem/reportelement.h b/sources/qetgraphicsitem/reportelement.h index eaefa7d58..593c4ba33 100644 --- a/sources/qetgraphicsitem/reportelement.h +++ b/sources/qetgraphicsitem/reportelement.h @@ -18,14 +18,14 @@ #ifndef REPORTELEMENT_H #define REPORTELEMENT_H -#include "customelement.h" +#include "element.h" /** * @brief The ReportElement class *this class represent an element that can be linked to an other ReportElement * a folio report in a diagram is a element that show a wire go on an other folio */ -class ReportElement : public CustomElement +class ReportElement : public Element { Q_OBJECT diff --git a/sources/qetgraphicsitem/simpleelement.cpp b/sources/qetgraphicsitem/simpleelement.cpp index 59adc230c..2c78e4bdb 100644 --- a/sources/qetgraphicsitem/simpleelement.cpp +++ b/sources/qetgraphicsitem/simpleelement.cpp @@ -26,7 +26,7 @@ * @param state */ SimpleElement::SimpleElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state) + Element(location, qgi, state) { m_link_type = Simple; } @@ -43,5 +43,5 @@ SimpleElement::~SimpleElement() {} * call update label for setup it. */ void SimpleElement::initLink(QETProject *project) { - CustomElement::initLink(project); + Element::initLink(project); } diff --git a/sources/qetgraphicsitem/simpleelement.h b/sources/qetgraphicsitem/simpleelement.h index 1c51ded64..51d8832db 100644 --- a/sources/qetgraphicsitem/simpleelement.h +++ b/sources/qetgraphicsitem/simpleelement.h @@ -18,7 +18,7 @@ #ifndef SIMPLEELEMENT_H #define SIMPLEELEMENT_H -#include "customelement.h" +#include "element.h" class QETProject; @@ -26,7 +26,7 @@ class QETProject; * @brief The SimpleElement class *this class represente a simple element with no specific attribute */ -class SimpleElement : public CustomElement { +class SimpleElement : public Element { Q_OBJECT diff --git a/sources/qetgraphicsitem/slaveelement.cpp b/sources/qetgraphicsitem/slaveelement.cpp index ba93b6fd8..d41c2cde9 100644 --- a/sources/qetgraphicsitem/slaveelement.cpp +++ b/sources/qetgraphicsitem/slaveelement.cpp @@ -30,7 +30,7 @@ * @param state int used to know if the creation of element have error */ SlaveElement::SlaveElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state) + Element(location, qgi, state) { m_xref_item = nullptr; m_link_type = Slave; diff --git a/sources/qetgraphicsitem/slaveelement.h b/sources/qetgraphicsitem/slaveelement.h index 64ea6218f..d57dd9df9 100644 --- a/sources/qetgraphicsitem/slaveelement.h +++ b/sources/qetgraphicsitem/slaveelement.h @@ -18,10 +18,10 @@ #ifndef SLAVEELEMENT_H #define SLAVEELEMENT_H -#include "customelement.h" +#include "element.h" #include"properties/xrefproperties.h" -class SlaveElement : public CustomElement +class SlaveElement : public Element { Q_OBJECT public: diff --git a/sources/qetgraphicsitem/terminalelement.cpp b/sources/qetgraphicsitem/terminalelement.cpp index 20e0e1a1c..c17eacb4c 100644 --- a/sources/qetgraphicsitem/terminalelement.cpp +++ b/sources/qetgraphicsitem/terminalelement.cpp @@ -26,7 +26,7 @@ * @param state int used to know if the creation of element have error */ TerminalElement::TerminalElement(const ElementsLocation &location, QGraphicsItem *qgi, int *state) : - CustomElement(location, qgi, state) + Element(location, qgi, state) {m_link_type = Terminale;} TerminalElement::~TerminalElement() {} @@ -36,6 +36,6 @@ TerminalElement::~TerminalElement() {} * @param project */ void TerminalElement::initLink(QETProject *project) { - CustomElement::initLink(project); + Element::initLink(project); } diff --git a/sources/qetgraphicsitem/terminalelement.h b/sources/qetgraphicsitem/terminalelement.h index 3cd6e6ac8..50082d781 100644 --- a/sources/qetgraphicsitem/terminalelement.h +++ b/sources/qetgraphicsitem/terminalelement.h @@ -18,11 +18,12 @@ #ifndef TERMINALELEMENT_H #define TERMINALELEMENT_H -#include "customelement.h" + +#include "element.h" class QETProject; -class TerminalElement : public CustomElement +class TerminalElement : public Element { Q_OBJECT public: diff --git a/sources/ui/elementpropertieswidget.cpp b/sources/ui/elementpropertieswidget.cpp index a8fcd3c6e..dc7329f23 100644 --- a/sources/ui/elementpropertieswidget.cpp +++ b/sources/ui/elementpropertieswidget.cpp @@ -20,7 +20,6 @@ #include "elementinfowidget.h" #include "masterpropertieswidget.h" #include "linksingleelementwidget.h" -#include "ghostelement.h" #include "diagram.h" #include "diagramposition.h" #include "qeticons.h" @@ -216,10 +215,9 @@ bool ElementPropertiesWidget::setLiveEdit(bool live_edit) */ void ElementPropertiesWidget::findInPanel() { - CustomElement *custom_element = qobject_cast(m_element); - if (custom_element && m_diagram) + if (m_element && m_diagram) { - m_diagram->findElementRequired(custom_element->location()); + m_diagram->findElementRequired(m_element.data()->location()); emit findEditClicked(); } } @@ -230,11 +228,10 @@ void ElementPropertiesWidget::findInPanel() */ void ElementPropertiesWidget::editElement() { - CustomElement *custom_element = qobject_cast(m_element); - if (custom_element && m_diagram) + if (m_element && m_diagram) { - m_diagram->findElementRequired(custom_element->location()); - m_diagram->editElementRequired(custom_element->location()); + m_diagram->findElementRequired(m_element.data()->location()); + m_diagram->editElementRequired(m_element.data()->location()); emit findEditClicked(); } } @@ -342,19 +339,9 @@ void ElementPropertiesWidget::addGeneralWidget() */ QWidget *ElementPropertiesWidget::generalWidget() { - CustomElement *custom_element = qobject_cast(m_element); - GhostElement *ghost_element = qobject_cast(m_element); + QString description_string(tr("Élement\n")); - // type de l'element - QString description_string; - if (ghost_element) { - description_string += tr("Élément manquant"); - } else { - description_string += tr("Élément"); - } - description_string += "\n"; - - // some element characteristic + // some element characteristic description_string += QString(tr("Nom : %1\n")).arg(m_element -> name()); int folio_index = m_diagram -> folioIndex(); if (folio_index != -1) { @@ -364,10 +351,7 @@ QWidget *ElementPropertiesWidget::generalWidget() description_string += QString(tr("Rotation : %1°\n")).arg(m_element.data()->rotation()); description_string += QString(tr("Dimensions : %1*%2\n")).arg(m_element -> size().width()).arg(m_element -> size().height()); description_string += QString(tr("Bornes : %1\n")).arg(m_element -> terminals().count()); - - if (custom_element) { - description_string += QString(tr("Emplacement : %1\n")).arg(custom_element -> location().toString()); - } + description_string += QString(tr("Emplacement : %1\n")).arg(m_element.data()->location().toString()); // widget himself QWidget *general_widget = new QWidget (m_tab); @@ -399,12 +383,10 @@ QWidget *ElementPropertiesWidget::generalWidget() int margin = vlayout_->contentsMargins().left() + vlayout_->contentsMargins().right(); int widht_ = vlayout_->minimumSize().width()-margin; - if (pixmap.size().width() > widht_ || pixmap.size().height() > widht_) - { + if (pixmap.size().width() > widht_ || pixmap.size().height() > widht_) { pix->setPixmap(m_element->pixmap().scaled (widht_, widht_, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } - else - { + else { pix->setPixmap(pixmap); }