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); }