diff --git a/qelectrotech.pro b/qelectrotech.pro index d01819027..41ff33226 100644 --- a/qelectrotech.pro +++ b/qelectrotech.pro @@ -170,7 +170,8 @@ HEADERS += $$files(sources/*.h) \ $$files(sources/TerminalStrip/GraphicsItem/properties/*.h) \ $$files(sources/xml/*.h) \ $$files(sources/dxf/*.h) \ - $$files(sources/qet_elementscaler/*.h) + $$files(sources/qet_elementscaler/*.h) \ + $$files(sources/svg/*.h) SOURCES += $$files(sources/*.cpp) \ $$files(sources/editor/*.cpp) \ @@ -213,7 +214,8 @@ SOURCES += $$files(sources/*.cpp) \ $$files(sources/TerminalStrip/GraphicsItem/properties/*.cpp) \ $$files(sources/xml/*.cpp) \ $$files(sources/dxf/*.cpp) \ - $$files(sources/qet_elementscaler/*.cpp) + $$files(sources/qet_elementscaler/*.cpp) \ + $$files(sources/svg/*.cpp) # Needed for use promote QTreeWidget in terminalstripeditor.ui INCLUDEPATH += sources/TerminalStrip/ui diff --git a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp index 02b74e4b8..7328a0096 100644 --- a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp @@ -35,13 +35,14 @@ namespace TerminalStripDrawer const QUuid m_uuid; }; - class DemoRealTerminal : public AbstractRealTerminalInterface - { - public: - DemoRealTerminal(const QString &label, const QUuid &bridge) : + class DemoRealTerminal : public AbstractRealTerminalInterface + { + public: + DemoRealTerminal(const QString &label, const QString &xref, const QUuid &bridge) : m_label { label }, + m_xref{ xref }, m_bridge { bridge } - {} + {} QString label() const override { return m_label; @@ -55,10 +56,14 @@ namespace TerminalStripDrawer return new DemoBridge { m_bridge }; } - private: - QString m_label; - QUuid m_bridge; - }; + QString xref() const override { + return m_xref; + } + + private: + QString m_label, m_xref; + QUuid m_bridge; + }; class DemoPhysicalTerminal : public AbstractPhysicalTerminalInterface { @@ -102,51 +107,63 @@ namespace TerminalStripDrawer QVector > real_terminals_vector; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("1_A1"), + lvl_1)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("1_A2"), + lvl_2)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("1_A3"), + lvl_3)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("1_A4"), + lvl_4)}; m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; + new DemoPhysicalTerminal {real_terminals_vector}}; - real_terminals_vector.clear(); + real_terminals_vector.clear(); real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("2_A1"), + lvl_1)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("2_A2"), + lvl_2)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("2_A3"), + lvl_3)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("2_A4"), + lvl_4)}; m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; + new DemoPhysicalTerminal {real_terminals_vector}}; - real_terminals_vector.clear(); + + real_terminals_vector.clear(); real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("24vdc"), - lvl_1)}; + new DemoRealTerminal( QStringLiteral("24vdc"), + QStringLiteral("3_A1"), + lvl_1)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("0vdc"), - lvl_2)}; + new DemoRealTerminal( QStringLiteral("0vdc"), + QStringLiteral("3_A2"), + lvl_2)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("signal"), - lvl_3)}; + new DemoRealTerminal( QStringLiteral("signal"), + QStringLiteral("3_A3"), + lvl_3)}; real_terminals_vector << QSharedPointer { - new DemoRealTerminal( QStringLiteral("teach"), - lvl_4)}; + new DemoRealTerminal( QStringLiteral("teach"), + QStringLiteral("3_A4"), + lvl_4)}; m_physical_terminal << QSharedPointer { - new DemoPhysicalTerminal {real_terminals_vector}}; - } - + new DemoPhysicalTerminal {real_terminals_vector}}; + } } diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index f0b8801c9..82fba3498 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -16,16 +16,24 @@ along with QElectroTech. If not, see . */ #include "terminalstriplayoutpattern.h" -#include +#include "../../../utils/qetutils.h" TerminalStripLayoutPattern::TerminalStripLayoutPattern() { + m_font.setPixelSize(15); updateHeaderTextOption(); updateTerminalsTextOption(); } +/** + * @brief TerminalStripLayoutPattern::setHeaderTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ void TerminalStripLayoutPattern::setHeaderTextAlignment(const Qt::Alignment &alignment) { + if (!alignment) return; m_header_text_alignment = alignment; updateHeaderTextOption(); } @@ -39,22 +47,61 @@ QTextOption TerminalStripLayoutPattern::headerTextOption() const { return m_header_text_option; } -void TerminalStripLayoutPattern::setTerminalsTextAlignment(const QVector &alignment) +QFont TerminalStripLayoutPattern::font() const { + return m_font; +} + +void TerminalStripLayoutPattern::setFont(const QFont &font) { + m_font = font; + QETUtils::pixelSizedFont(m_font); +} + +/** + * @brief TerminalStripLayoutPattern::setTerminalsTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ +void TerminalStripLayoutPattern::setTerminalsTextAlignment(const Qt::Alignment &alignment) { + if (!alignment) return; m_terminals_text_alignment = alignment; updateTerminalsTextOption(); } -QVector TerminalStripLayoutPattern::terminalsTextAlignment() const +Qt::Alignment TerminalStripLayoutPattern::terminalsTextAlignment() const { return m_terminals_text_alignment; } -QVector TerminalStripLayoutPattern::terminalsTextOption() const +QTextOption TerminalStripLayoutPattern::terminalsTextOption() const { return m_terminals_text_option; } +/** + * @brief TerminalStripLayoutPattern::setXrefTextAlignment + * Set text alignment to @param alignment. If alignment have no + * flag this function do nothing + * @param alignment + */ +void TerminalStripLayoutPattern::setXrefTextAlignment(const Qt::Alignment &alignment) +{ + if (!alignment) return; + m_xref_text_alignment = alignment; + updateTerminalsTextOption(); +} + +Qt::Alignment TerminalStripLayoutPattern::xrefTextAlignment() const +{ + return m_xref_text_alignment; +} + +QTextOption TerminalStripLayoutPattern::xrefTextOption() const +{ + return m_xref_text_option; +} + void TerminalStripLayoutPattern::updateHeaderTextOption() { m_header_text_option.setAlignment(m_header_text_alignment); @@ -63,16 +110,9 @@ void TerminalStripLayoutPattern::updateHeaderTextOption() void TerminalStripLayoutPattern::updateTerminalsTextOption() { - if (m_terminals_text_option.size() == - m_terminals_text_alignment.size()) - { - for (auto i = 0 ; i #include #include #include @@ -43,45 +44,46 @@ class TerminalStripLayoutPattern TerminalStripLayoutPattern(); //Header of terminal strip - QRect m_header_rect{0,30,50,130}; + QRectF m_header_rect{0,30,50,130}; Qt::Orientation m_header_text_orientation{Qt::Horizontal}; void setHeaderTextAlignment(const Qt::Alignment &alignment); Qt::Alignment headerTextAlignment() const; QTextOption headerTextOption() const; //Spacer between the header and the terminals - QRect m_spacer_rect{0, 50, 10, 90}; + QRectF m_spacer_rect{0, 50, 10, 90}; + + //Font + QFont font() const; + void setFont (const QFont &font); //Terminals - QVector m_terminal_rect + QVector m_terminal_rect { - QRect{0, 0, 20, 190}, - QRect{0, 10, 20, 170}, - QRect{0, 20, 20, 150}, - QRect{0, 30, 20, 130} + QRectF{0, 0, 20, 190}, + QRectF{0, 10, 20, 170}, + QRectF{0, 20, 20, 150}, + QRectF{0, 30, 20, 130} }; - void setTerminalsTextAlignment(const QVector &alignment); - QVector terminalsTextAlignment() const; - QVector terminalsTextOption() const; + //Terminal text + void setTerminalsTextAlignment(const Qt::Alignment &alignment); + Qt::Alignment terminalsTextAlignment() const; + QTextOption terminalsTextOption() const; + qreal m_terminals_text_height{50}; + qreal m_terminals_text_y{35}; + Qt::Orientation m_terminals_text_orientation {Qt::Vertical}; - QVector m_terminals_text_rect - { - QRect{0,35,20,50}, - QRect{0,35,20,50}, - QRect{0,35,20,50}, - QRect{0,35,20,50} - }; - QVector m_terminals_text_orientation - { - Qt::Vertical, - Qt::Vertical, - Qt::Vertical, - Qt::Vertical - }; + //Xref text + void setXrefTextAlignment(const Qt::Alignment &alignment); + Qt::Alignment xrefTextAlignment() const; + QTextOption xrefTextOption() const; + qreal m_xref_text_height{60}; + qreal m_xref_text_y{95}; + Qt::Orientation m_xref_text_orientation {Qt::Vertical}; - int m_bridge_point_d{5}; - QVector m_bridge_point_y_offset{50,70,90,110}; + qreal m_bridge_point_d{5}; + QVector m_bridge_point_y_offset{50,70,90,110}; QUuid m_uuid{QUuid::createUuid()}; QString m_name; @@ -90,24 +92,17 @@ class TerminalStripLayoutPattern void updateHeaderTextOption(); void updateTerminalsTextOption(); - private: + private: + QFont m_font; Qt::Alignment m_header_text_alignment{Qt::AlignCenter}; QTextOption m_header_text_option; - QVector m_terminals_text_alignment - { - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter - }; - QVector m_terminals_text_option - { - QTextOption(), - QTextOption(), - QTextOption(), - QTextOption() - }; + Qt::Alignment + m_terminals_text_alignment {Qt::AlignRight | Qt::AlignVCenter}, + m_xref_text_alignment {Qt::AlignLeft | Qt::AlignVCenter}; + QTextOption + m_terminals_text_option{QTextOption()}, + m_xref_text_option{QTextOption()}; }; #endif // TERMINALSTRIPLAYOUTPATTERN_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 16c2b5146..5bb7ab6f4 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -16,6 +16,7 @@ along with QElectroTech. If not, see . */ #include "terminalstripdrawer.h" + #include namespace TerminalStripDrawer { @@ -42,12 +43,13 @@ void TerminalStripDrawer::setStrip(QSharedPointersave(); + if (m_strip && m_pattern) + { + m_united_xref_text_rect = QRectF(); + //To draw text, QPainter need a Qrect. Instead of create an instance + //for each text, we re-use the same instance of QRect. + QRect text_rect; + painter->save(); auto pen_{painter->pen()}; pen_.setColor(Qt::black); @@ -56,16 +58,20 @@ void TerminalStripDrawer::paint(QPainter *painter) auto brush_ = painter->brush(); brush_.setColor(Qt::white); - painter->setPen(pen_); - painter->setBrush(brush_); + painter->setFont(m_pattern->font()); - if (m_preview_draw) - { - painter->save(); - painter->setPen(Qt::blue); - painter->drawRect(boundingRect()); - painter->restore(); - } + painter->setPen(pen_); + painter->setBrush(brush_); + + if (m_preview_draw) + { + painter->save(); + painter->setPen(Qt::blue); + painter->drawRect(boundingRect()); + painter->drawLine(QPointF{boundingRect().left(), boundingRect().center().y()}, + QPointF{boundingRect().right(), boundingRect().center().y()}); + painter->restore(); + } //Draw header painter->drawRect(m_pattern->m_header_rect); @@ -84,14 +90,13 @@ void TerminalStripDrawer::paint(QPainter *painter) text_rect.setRect(0,0,m_pattern->m_header_rect.height(),m_pattern->m_header_rect.width()); } - const auto text_{m_strip->installation() + " " + m_strip->location() + " " + m_strip->name()}; - painter->drawText(text_rect, text_, m_pattern->headerTextOption()); + const auto text_{m_strip->installation() + " " + m_strip->location() + " " + m_strip->name()}; + painter->drawText(text_rect, text_, m_pattern->headerTextOption()); painter->restore(); - //Move painter pos to next drawing - painter->translate(m_pattern->m_header_rect.width(),0); - - int x_offset{m_pattern->m_header_rect.width()}; + //Move painter pos to next drawing + painter->translate(m_pattern->m_header_rect.width(),0); + qreal x_offset{m_pattern->m_header_rect.width()}; //Draw spacer painter->drawRect(m_pattern->m_spacer_rect); @@ -99,22 +104,30 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->translate(m_pattern->m_spacer_rect.width(),0); x_offset += m_pattern->m_spacer_rect.width(); + //Draw terminals + const auto terminals_text_orientation{m_pattern->m_terminals_text_orientation}; + const auto terminals_text_option{m_pattern->terminalsTextOption()}; + const auto terminals_text_height{m_pattern->m_terminals_text_height}; + const auto terminals_text_y{m_pattern->m_terminals_text_y}; + QRectF terminal_rect; - //Draw terminals - const auto terminals_text_rect{m_pattern->m_terminals_text_rect}; - const auto terminals_text_orientation{m_pattern->m_terminals_text_orientation}; - const auto terminals_text_option{m_pattern->terminalsTextOption()}; - QRect terminal_rect; + const auto xref_text_orientation{m_pattern->m_xref_text_orientation}; + const auto xref_text_option{m_pattern->xrefTextOption()}; + const auto xref_text_height{m_pattern->m_xref_text_height}; + const auto xref_text_y{m_pattern->m_xref_text_y}; + QRectF xref_rect; QHash> bridges_anchor_points; - //Loop over physical terminals - for (const auto &physical_t : m_strip->physicalTerminal()) - { - //Get the good offset according to how many level have the current physical terminal - const QVector> real_terminal_vector{physical_t->realTerminals()}; - const auto real_t_count{real_terminal_vector.size()}; - const auto offset_{4 - real_t_count}; + m_hovered_xref = hoverTerminal{}; + int physical_index = 0; + //Loop over physical terminals + for (const auto &physical_t : m_strip->physicalTerminal()) + { + //Get the good offset according to how many level have the current physical terminal + const QVector> real_terminal_vector{physical_t->realTerminals()}; + const auto real_t_count{real_terminal_vector.size()}; + const auto offset_{4 - real_t_count}; //Loop over real terminals for (auto i=0 ; im_terminal_rect[index_]; - //Draw terminal rect - painter->drawRect(terminal_rect); - //Draw a stronger line if the current terminal have level - //and the current level is the first - if (real_t_count > 1 && i == 0) - { - painter->save(); - pen_ = painter->pen(); - pen_.setWidth(4); - pen_.setCapStyle(Qt::FlatCap); - painter->setPen(pen_); - const auto p1 { terminal_rect.topLeft() }; - //We can't use terminal_rect.bottomLeft for p2 because - //the returned value deviate from the true value - //(see Qt documentation about QRect) - const QPoint p2 { p1.x(), p1.y() + terminal_rect.height() }; - painter->drawLine(p1, p2); - painter->restore(); + terminal_rect = m_pattern->m_terminal_rect[index_]; + //Draw terminal rect + painter->drawRect(terminal_rect); + //Draw a stronger line if the current terminal have level + //and the current level is the first + if (real_t_count > 1 && i == 0) + { + painter->save(); + pen_ = painter->pen(); + pen_.setWidth(4); + pen_.setCapStyle(Qt::FlatCap); + painter->setPen(pen_); + const auto p1 { terminal_rect.topLeft() }; + //We can't use terminal_rect.bottomLeft for p2 because + //the returned value deviate from the true value + //(see Qt documentation about QRect) + const QPointF p2 { p1.x(), p1.y() + terminal_rect.height() }; + painter->drawLine(p1, p2); + painter->restore(); + } + + if(m_preview_draw) + { + painter->save(); + painter->setPen(Qt::yellow); + painter->drawLine(QPointF{terminal_rect.x(), terminal_rect.y() + terminal_rect.height()/2}, + QPointF{terminal_rect.width(), terminal_rect.y() + terminal_rect.height()/2}); + painter->restore(); } - //Draw text - painter->save(); - if (terminals_text_orientation[index_] == Qt::Horizontal) - { - text_rect = terminals_text_rect[index_]; - } - else - { - const auto rect_{terminals_text_rect[index_]}; - painter->translate(rect_.bottomLeft()); - painter->rotate(270); - text_rect.setRect(0, 0, rect_.height(), terminal_rect.width()); - } + //Draw text + painter->save(); + text_rect.setRect(0, terminals_text_y, terminal_rect.width(), terminals_text_height); + if (terminals_text_orientation == Qt::Vertical) + { + painter->translate(text_rect.bottomLeft()); + painter->rotate(270); + text_rect.setRect(0, 0, text_rect.height(), text_rect.width()); + } - const auto shared_real_terminal{real_terminal_vector[i]}; + const auto shared_real_terminal{real_terminal_vector[i]}; painter->drawText(text_rect, shared_real_terminal ? shared_real_terminal->label() : QLatin1String(), - terminals_text_option[index_]); + terminals_text_option); if (m_preview_draw) { @@ -172,16 +190,60 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); - //Add bridge anchor - if (shared_real_terminal->isBridged()) + //Draw xref + xref_rect.setRect(0, xref_text_y, terminal_rect.width(), xref_text_height); + painter->save(); + if (xref_text_orientation == Qt::Vertical) { - painter->save(); - if (QScopedPointer bridge_ { - shared_real_terminal->bridge() }) - { - const auto x_anchor{terminal_rect.width()/2}; - const auto y_anchor {m_pattern->m_bridge_point_y_offset[index_]}; - const auto radius_anchor{m_pattern->m_bridge_point_d/2}; + painter->translate(xref_rect.bottomLeft()); + painter->rotate(270); + xref_rect.setRect(0, 0, xref_rect.height(), xref_rect.width()); + } + + QTransform transform; + transform.translate(x_offset, 0); + + if (xref_text_orientation == Qt::Vertical) + { + transform.translate(0, xref_text_y + xref_text_height); + transform.rotate(270); + } + + auto xref_string = shared_real_terminal->xref(); + + const auto mapped_xref_text_rect = transform.mapRect(painter->boundingRect(xref_rect, xref_string, xref_text_option)); + if (m_united_xref_text_rect.isNull()) { + m_united_xref_text_rect = mapped_xref_text_rect; + } else { + m_united_xref_text_rect = m_united_xref_text_rect.united(mapped_xref_text_rect); + } + + //if mouse hover the xref text, draw it in blue to advise user the xref is clickable. + if (!m_mouse_hover_pos.isNull() && mapped_xref_text_rect.contains(m_mouse_hover_pos)) { + painter->setPen(Qt::blue); + m_hovered_xref.physical = physical_index; + m_hovered_xref.real = i; + } + + painter->drawText(xref_rect, xref_string, xref_text_option); + + if (m_preview_draw) + { + painter->setPen(Qt::blue); + painter->drawRect(xref_rect); + } + painter->restore(); + + //Add bridge anchor + if (shared_real_terminal->isBridged()) + { + painter->save(); + if (QScopedPointer bridge_ { + shared_real_terminal->bridge() }) + { + const auto x_anchor{terminal_rect.width()/2}; + const auto y_anchor {m_pattern->m_bridge_point_y_offset[index_]}; + const auto radius_anchor{m_pattern->m_bridge_point_d/2}; painter->setBrush(Qt::SolidPattern); painter->drawEllipse(QPointF(x_anchor, y_anchor), @@ -194,12 +256,13 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->restore(); } - //Move painter pos to next drawing - painter->translate(terminal_rect.width(),0); - x_offset += terminal_rect.width(); - } - } - painter->restore(); + //Move painter pos to next drawing + painter->translate(terminal_rect.width(),0); + x_offset += terminal_rect.width(); + } + physical_index++; + } + painter->restore(); //Draw the bridges for (const auto &points_ : qAsConst(bridges_anchor_points)) @@ -216,7 +279,7 @@ void TerminalStripDrawer::paint(QPainter *painter) QRectF TerminalStripDrawer::boundingRect() const { - return QRect{0, 0, width(), height()};; + return QRectF{0, 0, width(), height()};; } void TerminalStripDrawer::setLayout(QSharedPointer layout) @@ -233,7 +296,42 @@ void TerminalStripDrawer::setPreviewDraw(bool draw) { m_preview_draw = draw; } -int TerminalStripDrawer::height() const +void TerminalStripDrawer::setMouseHoverPos(const QPointF &pos) +{ + m_last_mouse_pos_in_xrefs_rect = m_united_xref_text_rect.contains(m_mouse_hover_pos); + m_mouse_hover_pos = pos; +} + +/** + * @brief TerminalStripDrawer::mouseHoverXref + * @return True if the mouse position (given through the function setMouseHoverPos) + * hover the rect of a xref. + */ +bool TerminalStripDrawer::mouseHoverXref() const { + return m_united_xref_text_rect.contains(m_mouse_hover_pos); +} + +bool TerminalStripDrawer::needUpdate() +{ + if (mouseHoverXref()) { + return true; + } else if (m_last_mouse_pos_in_xrefs_rect) { + return true; + } + return false; +} + +/** + * @brief TerminalStripDrawer::hoveredXref + * @return the current terminal hovered by the mouse + * in the xref bounding rectangle + */ +hoverTerminal TerminalStripDrawer::hoveredXref() const +{ + return m_hovered_xref; +} + +qreal TerminalStripDrawer::height() const { if (m_pattern) { @@ -251,11 +349,11 @@ int TerminalStripDrawer::height() const return 0; } -int TerminalStripDrawer::width() const +qreal TerminalStripDrawer::width() const { - if (m_pattern) - { - int width_{m_pattern->m_header_rect.width() + m_pattern->m_spacer_rect.width()}; + if (m_pattern) + { + qreal width_{m_pattern->m_header_rect.width() + m_pattern->m_spacer_rect.width()}; if (m_strip) { diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index e7e3c1f72..fea1b44dc 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -27,23 +27,35 @@ class TerminalStrip; namespace TerminalStripDrawer { - class AbstractBridgeInterface - { - public: - AbstractBridgeInterface() {} - virtual ~AbstractBridgeInterface() {} - virtual QUuid uuid() const = 0; + /** + * @brief The hoverTerminal struct + * Just a little struct use to know what is the physical and real terminal + * when the mouse hover the Xref string of a terminal. + * If mouse don't hover a Xref the value is set to -1; + */ + struct hoverTerminal{ + int physical{-1}; + int real{-1}; }; - class AbstractRealTerminalInterface - { - public: - AbstractRealTerminalInterface() {} - virtual ~AbstractRealTerminalInterface() {} - virtual QString label() const = 0; - virtual bool isBridged() const = 0; - virtual AbstractBridgeInterface* bridge() const = 0; - }; + class AbstractBridgeInterface + { + public: + AbstractBridgeInterface() {} + virtual ~AbstractBridgeInterface() {} + virtual QUuid uuid() const = 0; + }; + + class AbstractRealTerminalInterface + { + public: + AbstractRealTerminalInterface() {} + virtual ~AbstractRealTerminalInterface() {} + virtual QString label() const = 0; + virtual bool isBridged() const = 0; + virtual AbstractBridgeInterface* bridge() const = 0; + virtual QString xref() const = 0; + }; class AbstractPhysicalTerminalInterface { @@ -79,15 +91,24 @@ namespace TerminalStripDrawer void setPreviewDraw(bool draw = true); - private: - int height() const; - int width() const; + void setMouseHoverPos(const QPointF &pos); + bool mouseHoverXref() const; + bool needUpdate(); + hoverTerminal hoveredXref() const; - private: - QSharedPointer m_strip; - QSharedPointer m_pattern; - bool m_preview_draw { false }; - }; + private: + qreal height() const; + qreal width() const; + + private: + QSharedPointer m_strip; + QSharedPointer m_pattern; + bool m_preview_draw { false }; + QPointF m_mouse_hover_pos; + QRectF m_united_xref_text_rect; + bool m_last_mouse_pos_in_xrefs_rect{false}; + hoverTerminal m_hovered_xref; + }; } #endif // TERMINALSTRIPDRAWER_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp index 48650a629..6c4b79529 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp @@ -22,6 +22,8 @@ #include "../../project/projectpropertieshandler.h" #include "../../qetgraphicsitem/qgraphicsitemutility.h" #include "../terminalstrip.h" +#include "../physicalterminal.h" +#include "../realterminal.h" #include "../ui/terminalstripeditorwindow.h" #include "trueterminalstrip.h" @@ -94,12 +96,52 @@ QString TerminalStripItem::name() const { return tr("plan de bornes"); } +void TerminalStripItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverMoveEvent(event); + m_drawer.setMouseHoverPos(hoverMousePos()); + if (m_drawer.needUpdate()) { + update(); + } +} + +void TerminalStripItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + QetGraphicsItem::hoverLeaveEvent(event); + m_drawer.setMouseHoverPos(QPointF{}); +} + void TerminalStripItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED (event); + const auto hovered = m_drawer.hoveredXref(); + if (m_strip) { - TerminalStripEditorWindow::edit(m_strip); + if (hovered.physical >= 0 && + hovered.real >= 0) + { + if (const auto physical_terminal = m_strip->physicalTerminal(hovered.physical); + !physical_terminal.isNull()) + { + if (const auto real_terminal = physical_terminal->realTerminal(hovered.real); + !real_terminal.isNull() && + real_terminal->isElement()) + { + if (QPointer element = real_terminal->element(); + !element.isNull()) + { + //Unselect and ungrab mouse to prevent unwanted + //move when element is in the same scene of this. + setSelected(false); + ungrabMouse(); + QetGraphicsItem::showItem(element); + } + } + } + } else { + TerminalStripEditorWindow::edit(m_strip); + } } } diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h index 60eff199e..e54759f94 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h @@ -46,18 +46,19 @@ class TerminalStripItem : public QetGraphicsItem QRectF boundingRect() const override; QString name() const override; - void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; - void refreshPending(); - void setLayout(QSharedPointer layout); + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; + void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; + void refreshPending(); + void setLayout(QSharedPointer layout); private: void setDefaultLayout(); private: QPointer m_strip; - TerminalStripDrawer::TerminalStripDrawer m_drawer; - QUuid m_pending_strip_uuid; - + TerminalStripDrawer::TerminalStripDrawer m_drawer; + QUuid m_pending_strip_uuid; }; #endif // TERMINALSTRIPITEM_H diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp index 8e230272c..5ba160aef 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp @@ -20,6 +20,7 @@ #include "../realterminal.h" #include "../terminalstrip.h" #include "../terminalstripbridge.h" +#include "../../autoNum/assignvariables.h" #include "terminalstripdrawer.h" @@ -118,9 +119,18 @@ namespace TerminalStripDrawer return new TrueBridge(m_real->bridge()); } - TrueBridge::TrueBridge(QSharedPointer bridge) : - m_bridge { bridge } - {} + QString TrueRealTerminal::xref() const + { + if (m_real && m_real->isElement()) { + return autonum::AssignVariables::genericXref(m_real->element()); + } else { + return QString{}; + } + } + + TrueBridge::TrueBridge(QSharedPointer bridge) : + m_bridge { bridge } + {} QUuid TrueBridge::uuid() const { diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h index 27b5cb7e1..03bafa916 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h @@ -51,13 +51,14 @@ namespace TerminalStripDrawer QSharedPointer m_physical; }; - class TrueRealTerminal : public AbstractRealTerminalInterface - { - public: - TrueRealTerminal(QSharedPointer real); - QString label() const override; - bool isBridged() const override; - AbstractBridgeInterface* bridge() const override; + class TrueRealTerminal : public AbstractRealTerminalInterface + { + public: + TrueRealTerminal(QSharedPointer real); + QString label() const override; + bool isBridged() const override; + AbstractBridgeInterface* bridge() const override; + QString xref() const override; private: QSharedPointer m_real; diff --git a/sources/TerminalStrip/physicalterminal.cpp b/sources/TerminalStrip/physicalterminal.cpp index f9c06de3e..2b7548416 100644 --- a/sources/TerminalStrip/physicalterminal.cpp +++ b/sources/TerminalStrip/physicalterminal.cpp @@ -189,6 +189,20 @@ QVector> PhysicalTerminal::realTerminals() const { return m_real_terminal; } +/** + * @brief PhysicalTerminal::realTerminal + * @param pos + * @return the real terminal at position pos. + * Note that the returned QSharedPointer can be null + */ +QSharedPointer PhysicalTerminal::realTerminal(int pos) const +{ + if (pos < m_real_terminal.size()) { + return m_real_terminal.at(pos); + } + else return QSharedPointer{}; +} + /** * @brief uuid * @return the uuid of this physical terminal diff --git a/sources/TerminalStrip/physicalterminal.h b/sources/TerminalStrip/physicalterminal.h index 4e2fe4576..af38831a1 100644 --- a/sources/TerminalStrip/physicalterminal.h +++ b/sources/TerminalStrip/physicalterminal.h @@ -86,6 +86,7 @@ class PhysicalTerminal int levelCount() const; int levelOf(const QSharedPointer &terminal) const; QVector> realTerminals() const; + QSharedPointer realTerminal(int pos) const; QUuid uuid() const; int pos() const; int realTerminalCount() const; diff --git a/sources/TerminalStrip/terminalstrip.cpp b/sources/TerminalStrip/terminalstrip.cpp index 2222a50fb..6b4b202d1 100644 --- a/sources/TerminalStrip/terminalstrip.cpp +++ b/sources/TerminalStrip/terminalstrip.cpp @@ -1037,8 +1037,10 @@ bool TerminalStrip::fromXml(QDomElement &xml_element) } } - auto raw_ptr = new PhysicalTerminal(this, real_t_vector); - m_physical_terminals.append(raw_ptr->sharedRef()); + if (!real_t_vector.isEmpty()) { + auto raw_ptr = new PhysicalTerminal(this, real_t_vector); + m_physical_terminals.append(raw_ptr->sharedRef()); + } } } diff --git a/sources/TerminalStrip/ui/freeterminaleditor.cpp b/sources/TerminalStrip/ui/freeterminaleditor.cpp index d538427d2..4adebcc4d 100644 --- a/sources/TerminalStrip/ui/freeterminaleditor.cpp +++ b/sources/TerminalStrip/ui/freeterminaleditor.cpp @@ -32,16 +32,20 @@ */ FreeTerminalEditor::FreeTerminalEditor(QETProject *project, QWidget *parent) : QWidget(parent), - ui(new Ui::FreeTerminalEditor), - m_project(project) + ui(new Ui::FreeTerminalEditor), + m_project(project) { ui->setupUi(this); ui->m_table_view->setItemDelegate(new FreeTerminalModelDelegate(ui->m_table_view)); - m_model = new FreeTerminalModel(m_project, this); + m_model = new FreeTerminalModel(m_project, this); ui->m_table_view->setModel(m_model); ui->m_table_view->setCurrentIndex(m_model->index(0,0)); + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + //Disabled the move if the table is currently edited (yellow cell) connect(m_model, &FreeTerminalModel::dataChanged, this, [=] { this->setDisabledMove(); @@ -135,6 +139,31 @@ void FreeTerminalEditor::apply() reload(); } +/** + * @brief FreeTerminalEditor::setProject + * Set @project as project handled by this editor. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void FreeTerminalEditor::setProject(QETProject *project) +{ + if(m_project) { + disconnect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + m_project = project; + if (m_model) { + m_model->setProject(project); + } + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalEditor::reload); + } + reload(); +} + void FreeTerminalEditor::on_m_type_cb_activated(int index) { if (m_model) diff --git a/sources/TerminalStrip/ui/freeterminaleditor.h b/sources/TerminalStrip/ui/freeterminaleditor.h index 09f80b0a9..a2437fea0 100644 --- a/sources/TerminalStrip/ui/freeterminaleditor.h +++ b/sources/TerminalStrip/ui/freeterminaleditor.h @@ -19,8 +19,8 @@ #define FREETERMINALEDITOR_H #include +#include "../../qetproject.h" -class QETProject; class RealTerminal; class FreeTerminalModel; class QTableView; @@ -40,6 +40,8 @@ class FreeTerminalEditor : public QWidget void reload(); void apply(); + void setProject(QETProject *project); + private slots: void on_m_type_cb_activated(int index); void on_m_function_cb_activated(int index); @@ -52,7 +54,7 @@ class FreeTerminalEditor : public QWidget private: Ui::FreeTerminalEditor *ui; - QETProject *m_project = nullptr; - FreeTerminalModel *m_model = nullptr; + QPointer m_project; + FreeTerminalModel *m_model {nullptr}; }; #endif // FREETERMINALEDITOR_H diff --git a/sources/TerminalStrip/ui/freeterminalmodel.cpp b/sources/TerminalStrip/ui/freeterminalmodel.cpp index 546851ea7..bf5bc2296 100644 --- a/sources/TerminalStrip/ui/freeterminalmodel.cpp +++ b/sources/TerminalStrip/ui/freeterminalmodel.cpp @@ -56,10 +56,30 @@ FreeTerminalModel::Column FreeTerminalModel::columnTypeForIndex(const QModelInde * @param parent */ FreeTerminalModel::FreeTerminalModel(QETProject *project, QObject *parent) : - QAbstractTableModel(parent), - m_project(project) + QAbstractTableModel(parent) { + setProject(project); +} + +/** + * @brief FreeTerminalModel::setProject + * Set @project as project handled by this model. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void FreeTerminalModel::setProject(QETProject *project) { - fillTerminalVector(); + if(m_project) { + disconnect(m_project, &QObject::destroyed, this, &FreeTerminalModel::clear); + } + m_project = project; + if (m_project) { + connect(m_project, &QObject::destroyed, this, &FreeTerminalModel::clear); + } + clear(); } /** @@ -305,20 +325,22 @@ QVector > FreeTerminalModel::realTerminalForIndex(c */ void FreeTerminalModel::fillTerminalVector() { - ElementProvider provider_(m_project); - auto free_terminal_vector = provider_.freeTerminal(); + if (m_project) { + ElementProvider provider_(m_project); + auto free_terminal_vector = provider_.freeTerminal(); - std::sort(free_terminal_vector.begin(), free_terminal_vector.end(), - [](TerminalElement *a, TerminalElement *b) - { - return QETUtils::sortBeginIntString(a->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString(), - b->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString()); - }); + std::sort(free_terminal_vector.begin(), free_terminal_vector.end(), + [](TerminalElement *a, TerminalElement *b) + { + return QETUtils::sortBeginIntString(a->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString(), + b->elementData().m_informations.value(QETInformation::ELMT_LABEL).toString()); + }); - for (const auto &terminal_ : free_terminal_vector) { - m_terminal_vector.append(terminal_->realTerminal()); - m_real_t_data.append(modelRealTerminalData::data(terminal_->realTerminal())); - } + for (const auto &terminal_ : free_terminal_vector) { + m_terminal_vector.append(terminal_->realTerminal()); + m_real_t_data.append(modelRealTerminalData::data(terminal_->realTerminal())); + } + } } /**************************************************************** diff --git a/sources/TerminalStrip/ui/freeterminalmodel.h b/sources/TerminalStrip/ui/freeterminalmodel.h index 3aaa88a60..fa69097de 100644 --- a/sources/TerminalStrip/ui/freeterminalmodel.h +++ b/sources/TerminalStrip/ui/freeterminalmodel.h @@ -47,6 +47,7 @@ class FreeTerminalModel : public QAbstractTableModel public: explicit FreeTerminalModel(QETProject *project, QObject *parent = nullptr); + void setProject(QETProject *project); int rowCount(const QModelIndex &parent) const override; int columnCount(const QModelIndex &parent) const override; diff --git a/sources/TerminalStrip/ui/terminalstripeditor.cpp b/sources/TerminalStrip/ui/terminalstripeditor.cpp index d9ad4e0eb..5fef14c44 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditor.cpp @@ -84,6 +84,12 @@ TerminalStripEditor::~TerminalStripEditor() { delete ui; } +void TerminalStripEditor::setProject(QETProject *project) +{ + m_project = project; + setCurrentStrip(nullptr); +} + /** * @brief TerminalStripEditor::setCurrentStrip * Set the current terminal strip edited to \p strip_ @@ -98,27 +104,15 @@ void TerminalStripEditor::setCurrentStrip(TerminalStrip *strip_) if (m_current_strip) { disconnect(m_current_strip, &TerminalStrip::orderChanged, this, &TerminalStripEditor::reload); disconnect(m_current_strip, &TerminalStrip::bridgeChanged, this, &TerminalStripEditor::reload); + disconnect(m_current_strip, &QObject::destroyed, this, &TerminalStripEditor::clear); } ui->m_move_to_cb->clear(); - if (!strip_) - { - ui->m_installation_le ->clear(); - ui->m_location_le ->clear(); - ui->m_name_le ->clear(); - ui->m_comment_le ->clear(); - ui->m_description_te ->clear(); - m_current_strip = nullptr; - - ui->m_table_widget->setModel(nullptr); - if (m_model) { - m_model->deleteLater(); - m_model = nullptr; - } + if (!strip_) { + clear(); } - else - { + else { ui->m_installation_le ->setText(strip_->installation()); ui->m_location_le ->setText(strip_->location()); ui->m_name_le ->setText(strip_->name()); @@ -159,6 +153,7 @@ void TerminalStripEditor::setCurrentStrip(TerminalStrip *strip_) connect(m_current_strip, &TerminalStrip::orderChanged, this, &TerminalStripEditor::reload); connect(m_current_strip, &TerminalStrip::bridgeChanged, this, &TerminalStripEditor::reload); + connect(m_current_strip, &QObject::destroyed, this, &TerminalStripEditor::clear); } } @@ -230,6 +225,22 @@ void TerminalStripEditor::apply() reload(); } +void TerminalStripEditor::clear() +{ + ui->m_installation_le ->clear(); + ui->m_location_le ->clear(); + ui->m_name_le ->clear(); + ui->m_comment_le ->clear(); + ui->m_description_te ->clear(); + m_current_strip.clear(); + + ui->m_table_widget->setModel(nullptr); + if (m_model) { + m_model->deleteLater(); + m_model = nullptr; + } +} + /** * @brief TerminalStripEditor::spanMultiLevelTerminals * Span row of m_table_widget for multi-level terminal diff --git a/sources/TerminalStrip/ui/terminalstripeditor.h b/sources/TerminalStrip/ui/terminalstripeditor.h index 36750e31e..f64dd78b0 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.h +++ b/sources/TerminalStrip/ui/terminalstripeditor.h @@ -41,11 +41,13 @@ class TerminalStripEditor : public QWidget public: explicit TerminalStripEditor(QETProject *project, QWidget *parent = nullptr); ~TerminalStripEditor() override; + void setProject(QETProject *project); void setCurrentStrip(TerminalStrip *strip_); void reload(); void apply(); private: + void clear(); void spanMultiLevelTerminals(); void selectionChanged(); QSize setUpBridgeCellWidth(); @@ -67,9 +69,9 @@ class TerminalStripEditor : public QWidget private: Ui::TerminalStripEditor *ui; - QETProject *m_project {nullptr}; - TerminalStrip *m_current_strip {nullptr}; - TerminalStripModel *m_model {nullptr}; + QPointer m_project; + QPointer m_current_strip; + TerminalStripModel *m_model {nullptr}; }; #endif // TERMINALSTRIPEDITOR_H diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp index d22a723d9..81ddd2d29 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.cpp @@ -51,10 +51,15 @@ void TerminalStripEditorWindow::edit(TerminalStrip *strip) TerminalStripEditorWindow::TerminalStripEditorWindow(QETProject *project, QWidget *parent) : QMainWindow(parent), - ui(new Ui::TerminalStripEditorWindow), - m_project(project) + ui(new Ui::TerminalStripEditorWindow), + m_project(project) { ui->setupUi(this); + if (auto diagram_editor = QETApp::diagramEditor(project)) { + ui->m_tool_bar->addSeparator(); + ui->m_tool_bar->addAction(diagram_editor->undo); + ui->m_tool_bar->addAction(diagram_editor->redo); + } ui->m_remove_terminal->setDisabled(true); addTreeDockWidget(); @@ -76,6 +81,18 @@ TerminalStripEditorWindow::~TerminalStripEditorWindow() delete ui; } +/** + * @brief TerminalStripEditorWindow::setProject + * @param project + */ +void TerminalStripEditorWindow::setProject(QETProject *project) +{ + m_project = project; + m_tree_dock->setProject(project); + m_free_terminal_editor->setProject(project); + m_terminal_strip_editor->setProject(project); +} + void TerminalStripEditorWindow::setCurrentStrip(TerminalStrip *strip) { m_tree_dock->setSelectedStrip(strip); } @@ -200,4 +217,3 @@ void TerminalStripEditorWindow::on_m_button_box_clicked(QAbstractButton *button) void TerminalStripEditorWindow::on_m_stacked_widget_currentChanged(int arg1) { ui->m_button_box->setHidden(arg1 == EMPTY_PAGE); } - diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.h b/sources/TerminalStrip/ui/terminalstripeditorwindow.h index 911fe1a5e..4b3e9f2d0 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.h +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.h @@ -43,17 +43,19 @@ class TerminalStripEditorWindow : public QMainWindow //instance in her destrucor and then window_ become a dangling pointer. static QPointer window_; - public: - static TerminalStripEditorWindow* instance(QETProject *project, QWidget *parent = nullptr) { - static QMutex mutex_; - if (!window_) { - mutex_.lock(); - if (!window_) - window_ = new TerminalStripEditorWindow{project, parent}; - mutex_.unlock(); - } - return window_; - } + public: + static TerminalStripEditorWindow* instance(QETProject *project, QWidget *parent = nullptr) { + static QMutex mutex_; + if (!window_) { + mutex_.lock(); + if (!window_) + window_ = new TerminalStripEditorWindow{project, parent}; + mutex_.unlock(); + } else { + window_->setProject(project); + } + return window_; + } static void dropInstance () { static QMutex mutex; @@ -71,7 +73,8 @@ class TerminalStripEditorWindow : public QMainWindow explicit TerminalStripEditorWindow(QETProject *project, QWidget *parent = nullptr); ~TerminalStripEditorWindow(); - void setCurrentStrip(TerminalStrip *strip); + void setProject(QETProject *project); + void setCurrentStrip(TerminalStrip *strip); private slots: void on_m_add_terminal_strip_triggered(); @@ -87,7 +90,7 @@ class TerminalStripEditorWindow : public QMainWindow private: Ui::TerminalStripEditorWindow *ui{nullptr}; - QETProject *m_project {nullptr}; + QPointer m_project; TerminalStripTreeDockWidget *m_tree_dock{nullptr}; FreeTerminalEditor *m_free_terminal_editor {nullptr}; TerminalStripEditor *m_terminal_strip_editor {nullptr}; diff --git a/sources/TerminalStrip/ui/terminalstripeditorwindow.ui b/sources/TerminalStrip/ui/terminalstripeditorwindow.ui index 43cb3eaa7..f390f33cf 100644 --- a/sources/TerminalStrip/ui/terminalstripeditorwindow.ui +++ b/sources/TerminalStrip/ui/terminalstripeditorwindow.ui @@ -33,12 +33,12 @@ 0 0 1364 - 21 + 23 - + toolBar diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index 6bf75e6e8..a3d9cbd9b 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -15,6 +15,8 @@ You should have received a copy of the GNU General Public License along with QElectroTech. If not, see . */ +#include + #include "terminalstriplayouteditor.h" #include "ui_terminalstriplayouteditor.h" #include "../GraphicsItem/properties/terminalstriplayoutpattern.h" @@ -54,12 +56,10 @@ void TerminalStripLayoutEditor::valueEdited() return; } - //auto *data_ = m_layout.data(); - - m_layout.data()->m_header_rect.setRect(0, - ui->m_y_header_sb->value(), - ui->m_width_header_sb->value(), - ui->m_height_header_sb->value()); + m_layout.data()->m_header_rect.setRect(0, + ui->m_y_header_sb->value(), + ui->m_width_header_sb->value(), + ui->m_height_header_sb->value()); m_layout.data()->m_spacer_rect.setRect(0, ui->m_y_spacer_sb->value(), @@ -91,9 +91,13 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->m_bridge_point_y_offset[2] = ui->m_bridge_point_2_sb->value(); m_layout.data()->m_bridge_point_y_offset[3] = ui->m_bridge_point_3_sb->value(); - m_layout.data()->m_header_text_orientation = ui->m_header_text_orientation_cb->currentIndex() == 0 ? - Qt::Horizontal : - Qt::Vertical; + auto font_ = ui->m_font_cb->currentFont(); + font_.setPixelSize(ui->m_font_size_sb->value()); + m_layout->setFont(font_); + + m_layout.data()->m_header_text_orientation = ui->m_header_text_orientation_cb->currentIndex() == 0 ? + Qt::Horizontal : + Qt::Vertical; switch (ui->m_header_text_alignment_cb->currentIndex()) { case 0: @@ -104,34 +108,46 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->setHeaderTextAlignment(Qt::AlignRight | Qt::AlignVCenter); break; } - m_layout.data()->m_terminals_text_orientation[0] = ui->m_terminal_text_orientation_cb->currentIndex() == 0 ? - Qt::Horizontal : - Qt::Vertical; + //Terminal text + m_layout.data()->m_terminals_text_orientation = ui->m_terminal_text_orientation_cb->currentIndex() == 0 ? + Qt::Horizontal : + Qt::Vertical; - switch (ui->m_terminal_text_alignment_cb->currentIndex()) { - case 0: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter, - Qt::AlignLeft | Qt::AlignVCenter }); - break; - case 1: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter, - Qt::AlignHCenter | Qt::AlignVCenter }); - break; - default: - m_layout.data()->setTerminalsTextAlignment( - QVector { Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter, - Qt::AlignRight | Qt::AlignVCenter }); - break; + switch (ui->m_terminal_text_alignment_cb->currentIndex()) { + case 0: + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment {Qt::AlignLeft | Qt::AlignVCenter}); + break; + case 1: + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment { Qt::AlignHCenter | Qt::AlignVCenter}); + break; + default: + m_layout.data()->setTerminalsTextAlignment(Qt::Alignment { Qt::AlignRight | Qt::AlignVCenter}); + break; + } + + m_layout.data()->m_terminals_text_y = ui->m_terminal_text_y_sb->value(); + m_layout.data()->m_terminals_text_height = ui->m_terminal_text_height_sb->value(); + + //Xref text + m_layout.data()->m_xref_text_orientation = ui->m_xref_orientation_cb->currentIndex() == 0 ? + Qt::Horizontal : + Qt::Vertical; + + switch (ui->m_xref_alignment_cb->currentIndex()) { + case 0: + m_layout.data()->setXrefTextAlignment(Qt::Alignment {Qt::AlignLeft | Qt::AlignVCenter}); + break; + case 1: + m_layout.data()->setXrefTextAlignment(Qt::Alignment { Qt::AlignHCenter | Qt::AlignVCenter}); + break; + default: + m_layout.data()->setXrefTextAlignment(Qt::Alignment { Qt::AlignRight | Qt::AlignVCenter}); + break; } + m_layout.data()->m_xref_text_y = ui->m_xref_y_sb->value(); + m_layout.data()->m_xref_text_height = ui->m_xref_height_sb->value(); + updateUi(); m_preview_strip_item.update(); } @@ -180,17 +196,21 @@ void TerminalStripLayoutEditor::updateUi() ui->m_bridge_point_2_sb->setValue(bridge_point[2]); ui->m_bridge_point_3_sb->setValue(bridge_point[3]); - if (data->m_header_text_orientation == Qt::Horizontal) { - ui->m_header_text_orientation_cb->setCurrentIndex(0); - } else { - ui->m_header_text_orientation_cb->setCurrentIndex(1); - } + const auto font = m_layout->font(); + ui->m_font_size_sb->setValue(font.pixelSize()); + ui->m_font_cb->setCurrentFont(font); - if (data->m_terminals_text_orientation[0] == Qt::Horizontal) { - ui->m_terminal_text_orientation_cb->setCurrentIndex(0); - } else { - ui->m_terminal_text_orientation_cb->setCurrentIndex(1); - } + if (data->m_header_text_orientation == Qt::Horizontal) { + ui->m_header_text_orientation_cb->setCurrentIndex(0); + } else { + ui->m_header_text_orientation_cb->setCurrentIndex(1); + } + + if (data->m_terminals_text_orientation == Qt::Horizontal) { + ui->m_terminal_text_orientation_cb->setCurrentIndex(0); + } else { + ui->m_terminal_text_orientation_cb->setCurrentIndex(1); + } const auto header_alignment = data->headerTextAlignment(); if (header_alignment &Qt::AlignLeft) { @@ -201,15 +221,38 @@ void TerminalStripLayoutEditor::updateUi() ui->m_header_text_alignment_cb->setCurrentIndex(2); } - const auto terminal_alignment = data->terminalsTextAlignment().at(0); - if (terminal_alignment &Qt::AlignLeft) { - ui->m_terminal_text_alignment_cb->setCurrentIndex(0); - } else if (terminal_alignment &Qt::AlignHCenter) { - ui->m_terminal_text_alignment_cb->setCurrentIndex(1); - } else if (terminal_alignment &Qt::AlignRight) { - ui->m_terminal_text_alignment_cb->setCurrentIndex(2); + //Terminal text + const auto terminal_alignment = data->terminalsTextAlignment(); + if (terminal_alignment &Qt::AlignLeft) { + ui->m_terminal_text_alignment_cb->setCurrentIndex(0); + } else if (terminal_alignment &Qt::AlignHCenter) { + ui->m_terminal_text_alignment_cb->setCurrentIndex(1); + } else if (terminal_alignment &Qt::AlignRight) { + ui->m_terminal_text_alignment_cb->setCurrentIndex(2); } + ui->m_terminal_text_y_sb->setValue(data->m_terminals_text_y); + ui->m_terminal_text_height_sb->setValue(data->m_terminals_text_height); + + //Xref text + if (data->m_xref_text_orientation == Qt::Horizontal) { + ui->m_xref_orientation_cb->setCurrentIndex(0); + } else { + ui->m_xref_orientation_cb->setCurrentIndex(1); + } + + const auto xref_alignment = data->xrefTextAlignment(); + if (xref_alignment &Qt::AlignLeft) { + ui->m_xref_alignment_cb->setCurrentIndex(0); + } else if (xref_alignment &Qt::AlignHCenter) { + ui->m_xref_alignment_cb->setCurrentIndex(1); + } else if (xref_alignment &Qt::AlignRight) { + ui->m_xref_alignment_cb->setCurrentIndex(2); + } + + ui->m_xref_y_sb->setValue(data->m_xref_text_y); + ui->m_xref_height_sb->setValue(data->m_xref_text_height); + m_ui_updating = false; updatePreview(); } @@ -225,4 +268,3 @@ void TerminalStripLayoutEditor::on_m_display_preview_help_clicked(bool checked) m_preview_strip_item.m_drawer.setPreviewDraw(checked); m_preview_strip_item.update(); } - diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.h b/sources/TerminalStrip/ui/terminalstriplayouteditor.h index 64c4d4431..e0a539d13 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.h +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.h @@ -74,10 +74,9 @@ class TerminalStripLayoutEditor : public QWidget void resizeEvent(QResizeEvent *event) override; void showEvent(QShowEvent *event) override; - private slots: - void valueEdited(); - - void on_m_display_preview_help_clicked(bool checked); + private slots: + void valueEdited(); + void on_m_display_preview_help_clicked(bool checked); private: void updateUi(); diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index eca92386e..c9a762252 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -6,8 +6,8 @@ 0 0 - 767 - 544 + 961 + 624 @@ -17,17 +17,17 @@ QLayout::SetMaximumSize - - - - Borne niveau 0 : + + + + 1000 - - - - En tête : + + + + 1000 @@ -38,37 +38,6 @@ - - - - - - - Point de pont - - - - - - - 1000 - - - - - - - Qt::Horizontal - - - - - - - 1000 - - - @@ -76,15 +45,43 @@ - - - - Afficher l'aide + + + + 1000 - - + + + + 1000 + + + + + + + Borne niveau 0 : + + + + + + + 1000 + + + + + + + 1000 + + + + + 1000 @@ -97,22 +94,39 @@ - - + + + + + 1000 - - + + - Largeur + Borne niveau 3 : - - + + + + Borne niveau 2 : + + + + + + + 1000 + + + + + 1000 @@ -125,17 +139,48 @@ - - + + - Hauteur + Afficher l'aide + + + false - - + + - Prévisualisation : + Largeur + + + + + + + 1000 + + + + + + + Espace : + + + + + + + Qt::Horizontal + + + + + + + 1000 @@ -146,35 +191,14 @@ - - - - 1000 + + + + Borne niveau 1 : - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - + @@ -189,26 +213,21 @@ 0 - - + + - Gauche + Horizontal - Centre - - - - - Droite + Vertical - + @@ -227,21 +246,136 @@ - + + + + Orientation + + + + - Alignement du texte d'en tête : + Alignement - - + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Police : + + + + + + + + + + Taille : + + + + + + + 1 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + - Alignement du texte de borne : + Texte d'en tête + + + Qt::AlignCenter - + + + + Origine vertical + + + + + + + Longueur maximal + + + + + + + 1000 + + + + + + + 30 + + + 1000 + + + + + + + + Gauche + + + + + Centre + + + + + Droite + + + + + @@ -255,8 +389,28 @@ - - + + + + Texte borne + + + Qt::AlignCenter + + + + + + + Référence croisée + + + Qt::AlignCenter + + + + + Horizontal @@ -269,23 +423,66 @@ - - - - Orientation du texte de borne : + + + + + Gauche + + + + + Centre + + + + + Droite + + + + + + + + 1000 - - - - Orientation du texte d'en tête : + + + + 30 + + + 1000 + + + + 1000 + + + + + + + 1000 + + + + + + + En tête : + + + @@ -293,34 +490,6 @@ - - - - Borne niveau 2 : - - - - - - - 1000 - - - - - - - Espace : - - - - - - - 1000 - - - @@ -328,69 +497,55 @@ - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - 1000 - - - - - - - Borne niveau 3 : - - - - - - - 1000 - - - - - - - Borne niveau 1 : - - - - - + + Qt::Horizontal + + + + 1000 + + + + + + + 1000 + + + + + + + Hauteur + + + + + + + Point de pont + + + + + + + 1000 + + + + + + + Prévisualisation : + + + @@ -811,6 +966,134 @@ + + m_font_cb + currentFontChanged(QFont) + TerminalStripLayoutEditor + valueEdited() + + + 245 + 276 + + + 445 + 277 + + + + + m_font_size_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 507 + 277 + + + 445 + 277 + + + + + m_terminal_text_y_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 207 + 383 + + + 445 + 277 + + + + + m_terminal_text_height_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 430 + 383 + + + 445 + 277 + + + + + m_xref_alignment_cb + currentIndexChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 365 + + + 480 + 311 + + + + + m_xref_height_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 431 + + + 480 + 311 + + + + + m_xref_orientation_cb + currentIndexChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 333 + + + 480 + 311 + + + + + m_xref_y_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 836 + 398 + + + 480 + 311 + + + valueEdited() diff --git a/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp b/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp index 3a9a34e6e..960dd1eb4 100644 --- a/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp +++ b/sources/TerminalStrip/ui/terminalstriptreedockwidget.cpp @@ -30,11 +30,10 @@ TerminalStripTreeDockWidget::TerminalStripTreeDockWidget(QETProject *project, QWidget *parent) : QDockWidget(parent), - ui(new Ui::TerminalStripTreeDockWidget), - m_project(project) + ui(new Ui::TerminalStripTreeDockWidget) { ui->setupUi(this); - buildTree(); + setProject(project); #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) ui->m_tree_view->expandRecursively(ui->m_tree_view->rootIndex()); @@ -48,6 +47,32 @@ TerminalStripTreeDockWidget::~TerminalStripTreeDockWidget() delete ui; } +/** + * @brief TerminalStripTreeDockWidget::setProject + * Set @project as project handled by this tree dock. + * If a previous project was setted, everything is clear. + * This function track the destruction of the project, + * that mean if the project pointer is deleted + * no need to call this function with a nullptr, + * everything is made inside this class. + * @param project + */ +void TerminalStripTreeDockWidget::setProject(QETProject *project) +{ + if(m_project && m_project_destroy_connection) { + disconnect(m_project_destroy_connection); + } + m_project = project; + if (m_project) { + m_project_destroy_connection = connect(m_project, &QObject::destroyed, [this](){ + this->m_current_strip.clear(); + this->reload(); + }); + } + m_current_strip.clear(); + reload(); +} + /** * @brief TerminalStripTreeDockWidget::reload */ @@ -205,6 +230,9 @@ void TerminalStripTreeDockWidget::on_m_tree_view_currentItemChanged(QTreeWidgetI */ void TerminalStripTreeDockWidget::buildTree() { + if(!m_project) { + return; + } auto title_ = m_project->title(); if (title_.isEmpty()) { diff --git a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h index ffc82bbbb..1274bc7fb 100644 --- a/sources/TerminalStrip/ui/terminalstriptreedockwidget.h +++ b/sources/TerminalStrip/ui/terminalstriptreedockwidget.h @@ -49,6 +49,7 @@ class TerminalStripTreeDockWidget : public QDockWidget explicit TerminalStripTreeDockWidget(QETProject *project, QWidget *parent = nullptr); ~TerminalStripTreeDockWidget(); + void setProject(QETProject *project = nullptr); void reload(); bool currentIsStrip() const; TerminalStrip* currentStrip() const; @@ -74,11 +75,12 @@ class TerminalStripTreeDockWidget : public QDockWidget QPointer m_project; QPointer m_current_strip; - QHash m_item_strip_H; + QHash> m_item_strip_H; QHash> m_uuid_terminal_H; QHash> m_uuid_strip_H; QVector m_strip_changed_connection; - bool m_current_is_free_terminal{false}; + bool m_current_is_free_terminal{false}; + QMetaObject::Connection m_project_destroy_connection; }; #endif // TERMINALSTRIPTREEDOCKWIDGET_H diff --git a/sources/diagramcontent.cpp b/sources/diagramcontent.cpp index 30bbcc5c1..4c279c4c9 100644 --- a/sources/diagramcontent.cpp +++ b/sources/diagramcontent.cpp @@ -59,7 +59,15 @@ DiagramContent::DiagramContent(Diagram *diagram, bool selected) : { switch (item->type()) { - case Element::Type: { m_elements << qgraphicsitem_cast(item); break;} + case Element::Type: + { + auto element = qgraphicsitem_cast(item); + m_elements << element; + if (element->elementData().m_type == ElementData::Terminal) { + m_terminal_elements << static_cast(element); + } + break; + } case IndependentTextItem::Type: { m_text_fields << qgraphicsitem_cast(item); break;} case Conductor::Type: { diff --git a/sources/diagramcontent.h b/sources/diagramcontent.h index 4a12b7ad3..479fc4b71 100644 --- a/sources/diagramcontent.h +++ b/sources/diagramcontent.h @@ -21,6 +21,8 @@ #include #include +#include "../qetgraphicsitem/terminalelement.h" + class QGraphicsItem; class Conductor; class Element; @@ -81,6 +83,7 @@ class DiagramContent QList m_selected_items; QVector m_tables; QVector m_terminal_strip; + QVector> m_terminal_elements; QList selectedTexts() const; diff --git a/sources/qetdiagrameditor.cpp b/sources/qetdiagrameditor.cpp index ca1868d97..b184017e0 100644 --- a/sources/qetdiagrameditor.cpp +++ b/sources/qetdiagrameditor.cpp @@ -1469,12 +1469,21 @@ void QETDiagramEditor::selectionGroupTriggered(QAction *action) if (!dv || value.isEmpty()) return; - if (value == "delete_selection") - { - diagram->clearSelection(); - diagram->undoStack().push(new DeleteQGraphicsItemCommand(diagram, dc)); - dv->adjustSceneRect(); - } + if (value == "delete_selection") + { + if (DeleteQGraphicsItemCommand::hasNonDeletableTerminal(dc)) { + QET::QetMessageBox::information(this, + tr("Suppression de borne impossible"), + tr("La suppression ne peut être effectué car la selection " + "possède une ou plusieurs bornes ponté et/ou appartenant à une borne à niveau multiple.\n" + "Déponter et/ou supprimer les niveaux des bornes concerné " + "afin de pouvoir les supprimer")); + } else { + diagram->clearSelection(); + diagram->undoStack().push(new DeleteQGraphicsItemCommand(diagram, dc)); + dv->adjustSceneRect(); + } + } else if (value == "rotate_selection") { RotateSelectionCommand *c = new RotateSelectionCommand(diagram); diff --git a/sources/qetdiagrameditor.h b/sources/qetdiagrameditor.h index 5bd7b280a..463e0b8c0 100644 --- a/sources/qetdiagrameditor.h +++ b/sources/qetdiagrameditor.h @@ -54,6 +54,8 @@ class KAutoSaveFile; class QETDiagramEditor : public QETMainWindow { Q_OBJECT + + friend class TerminalStripEditorWindow; public: QETDiagramEditor( diff --git a/sources/qetgraphicsitem/element.cpp b/sources/qetgraphicsitem/element.cpp index a362b25d0..a11cc232e 100644 --- a/sources/qetgraphicsitem/element.cpp +++ b/sources/qetgraphicsitem/element.cpp @@ -35,6 +35,7 @@ #include "iostream" #include "../qetxml.h" #include "../qetversion.h" +#include "qgraphicsitemutility.h" #include #include @@ -236,7 +237,7 @@ void Element::paint( //Draw the selection rectangle if ( isSelected() || m_mouse_over ) { - drawSelection(painter, options); + QGIUtility::drawBoundingRectSelection(this, painter); } } @@ -334,34 +335,6 @@ void Element::drawAxes( /*** Methodes privees ***/ -/** - Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee. - @param painter Le QPainter a utiliser pour dessiner les bornes. - @param options Les options de style a prendre en compte -*/ -void Element::drawSelection( - QPainter *painter, - const QStyleOptionGraphicsItem *options) -{ - Q_UNUSED(options) - painter -> save(); - // Annulation des renderhints - painter -> setRenderHint(QPainter::Antialiasing, false); - painter -> setRenderHint(QPainter::TextAntialiasing, false); - painter -> setRenderHint(QPainter::SmoothPixmapTransform, false); - // Dessin du cadre de selection en gris - QPen t; - t.setColor(Qt::gray); - t.setStyle(Qt::DashDotLine); - t.setCosmetic(true); - painter -> setPen(t); - // Le dessin se fait a partir du rectangle delimitant - painter -> drawRoundedRect(boundingRect().adjusted(1, 1, -1, -1), - 10, - 10); - painter -> restore(); -} - /** Dessine le cadre de selection de l'element de maniere systematiquement non antialiasee. @param painter Le QPainter a utiliser pour dessiner les bornes. diff --git a/sources/qetgraphicsitem/element.h b/sources/qetgraphicsitem/element.h index 4a0e9c55d..0b89bfc41 100644 --- a/sources/qetgraphicsitem/element.h +++ b/sources/qetgraphicsitem/element.h @@ -198,9 +198,6 @@ class Element : public QetGraphicsItem void setSize(int, int); private: - void drawSelection( - QPainter *, - const QStyleOptionGraphicsItem *); void drawHighlight( QPainter *, const QStyleOptionGraphicsItem *); diff --git a/sources/qetgraphicsitem/qetgraphicsitem.cpp b/sources/qetgraphicsitem/qetgraphicsitem.cpp index 7ec07d33d..1dad86e0d 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.cpp +++ b/sources/qetgraphicsitem/qetgraphicsitem.cpp @@ -24,12 +24,31 @@ Default constructor @param parent : Parent Item */ +void QetGraphicsItem::showItem(QetGraphicsItem *item) +{ + if (item && item->diagram()) + { + item->diagram()->showMe(); + item->setSelected(true); + + //Zoom to the item + for(QGraphicsView *view : item->scene()->views()) + { + QRectF fit = item->sceneBoundingRect(); + fit.adjust(-200, -200, 200, 200); + view->fitInView(fit, Qt::KeepAspectRatioByExpanding); + } + } +} + QetGraphicsItem::QetGraphicsItem(QGraphicsItem *parent): QGraphicsObject(parent), is_movable_(true), m_first_move(true), snap_to_grid_(true) -{} +{ + setAcceptHoverEvents(true); +} QetGraphicsItem::~QetGraphicsItem() {} @@ -68,6 +87,11 @@ bool QetGraphicsItem::isHovered() const { return m_hovered; } +QPointF QetGraphicsItem::hoverMousePos() const +{ + return m_mouse_hover_pos; +} + /** @brief QetGraphicsItem::state @return the current state of this item @@ -166,6 +190,12 @@ void QetGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event) QGraphicsObject::hoverEnterEvent(event); } +void QetGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + QGraphicsObject::hoverMoveEvent(event); + m_mouse_hover_pos = event->pos(); +} + void QetGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { m_hovered = false; diff --git a/sources/qetgraphicsitem/qetgraphicsitem.h b/sources/qetgraphicsitem/qetgraphicsitem.h index 5042a6a15..307abdf99 100644 --- a/sources/qetgraphicsitem/qetgraphicsitem.h +++ b/sources/qetgraphicsitem/qetgraphicsitem.h @@ -28,6 +28,9 @@ class QetGraphicsItem : public QGraphicsObject { Q_OBJECT + public : + static void showItem (QetGraphicsItem *item); + public: //constructor destructor QetGraphicsItem(QGraphicsItem *parent = nullptr); @@ -43,6 +46,7 @@ class QetGraphicsItem : public QGraphicsObject virtual void setMovable (bool movable) { is_movable_ = movable;} bool isHovered() const; + QPointF hoverMousePos() const; virtual void editProperty () {} virtual QString name ()const @@ -57,6 +61,7 @@ class QetGraphicsItem : public QGraphicsObject void mouseMoveEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void hoverEnterEvent(QGraphicsSceneHoverEvent *event) override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; void hoverLeaveEvent(QGraphicsSceneHoverEvent *event) override; protected: @@ -68,6 +73,7 @@ class QetGraphicsItem : public QGraphicsObject private: bool m_hovered{false}; + QPointF m_mouse_hover_pos; }; diff --git a/sources/qetxml.cpp b/sources/qetxml.cpp index d842dca60..2a99543f7 100644 --- a/sources/qetxml.cpp +++ b/sources/qetxml.cpp @@ -953,4 +953,93 @@ bool qGraphicsItemPosFromXml(QGraphicsItem *item, const QDomElement &xml_elmt) return false; } +/** + * @brief orientationToAttribute + * Write the Qt::orientation has an attribute of @param element. + * Attribute name is 'orientation' value is 'horizontal' or 'vertical' + * @param orientation + * @param element + */ +void orientationToAttribute(const Qt::Orientation &orientation, QDomElement &element) +{ + element.setAttribute(QStringLiteral("orientation"), + orientation == Qt::Horizontal ? QStringLiteral("Horizontal") : + QStringLiteral("Vertical")); +} + +/** + * @brief orientationFromAttribute + * @param element + * @param def_value + * @return the Qt::Orientation read in @param element. If an error occur + * the returned orientation is @param def_value. + */ +Qt::Orientation orientationFromAttribute(const QDomElement &element, Qt::Orientation def_value) +{ + if (element.hasAttribute(QStringLiteral("orientation"))) { + const auto str {element.attribute(QStringLiteral("orientation"))}; + if (str == QLatin1String("Horizontal")) + return Qt::Horizontal; + else if (str == QLatin1String("Vertical")) + return Qt::Vertical; + } + //Error occur during reading, we return the default value + return def_value; +} + +void alignmentToAttribute(const Qt::Alignment &alignment, QDomElement &element) +{ + QStringList al; + if (alignment &Qt::AlignLeft) + al.append(QStringLiteral("Left")); + if (alignment &Qt::AlignRight) + al.append(QStringLiteral("Right")); + if (alignment &Qt::AlignHCenter) + al.append(QStringLiteral("HCenter")); + if (alignment &Qt::AlignJustify) + al.append(QStringLiteral("Justify")); + if (alignment &Qt::AlignTop) + al.append(QStringLiteral("Top")); + if (alignment &Qt::AlignBottom) + al.append(QStringLiteral("Bottom")); + if (alignment &Qt::AlignBottom) + al.append(QStringLiteral("VCenter")); + if (alignment &Qt::AlignBaseline) + al.append(QStringLiteral("Baseline")); + + element.setAttribute(QStringLiteral("alignment"),al.join(QStringLiteral(" "))); +} + +/** + * @brief alignmentFromAttribute + * @param element + * @return The alignment read in @param element. If an error + * occured the return Qt::alignment contain no set flag. + */ +Qt::Alignment alignmentFromAttribute(const QDomElement &element) +{ + Qt::Alignment al; + if (element.hasAttribute(QStringLiteral("alignment"))) { + const auto alignment {element.attribute(QStringLiteral("alignment"))}; + if(alignment.contains(QStringLiteral("Left"))) + al = al | Qt::AlignLeft; + if(alignment.contains(QStringLiteral("Right"))) + al = al | Qt::AlignRight; + if(alignment.contains(QStringLiteral("HCenter"))) + al = al | Qt::AlignHCenter; + if(alignment.contains(QStringLiteral("Justify"))) + al = al | Qt::AlignJustify; + if(alignment.contains(QStringLiteral("Top"))) + al = al | Qt::AlignTop; + if(alignment.contains(QStringLiteral("Bottom"))) + al = al | Qt::AlignBottom; + if(alignment.contains(QStringLiteral("VCenter"))) + al = al | Qt::AlignVCenter; + if(alignment.contains(QStringLiteral("Baseline"))) + al = al | Qt::AlignBaseline; + } + + return al; +} + } diff --git a/sources/qetxml.h b/sources/qetxml.h index d98756978..1e8445cf3 100644 --- a/sources/qetxml.h +++ b/sources/qetxml.h @@ -94,6 +94,12 @@ namespace QETXML QDomElement qGraphicsItemPosToXml(QGraphicsItem *item, QDomDocument &document); bool qGraphicsItemPosFromXml(QGraphicsItem *item, const QDomElement &xml_elmt); + void orientationToAttribute(const Qt::Orientation &orientation, QDomElement &element); + Qt::Orientation orientationFromAttribute(const QDomElement &element, Qt::Orientation def_value = Qt::Vertical); + + void alignmentToAttribute(const Qt::Alignment &alignment, QDomElement &element); + Qt::Alignment alignmentFromAttribute (const QDomElement &element); + QString boolToString(bool value); bool boolFromString(const QString &value, bool default_value = true, diff --git a/sources/svg/qetsvg.cpp b/sources/svg/qetsvg.cpp new file mode 100644 index 000000000..c1fa1bdca --- /dev/null +++ b/sources/svg/qetsvg.cpp @@ -0,0 +1,151 @@ +/* + Copyright 2006-2025 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 "qetsvg.h" + +#include +#include +#include <../qet.h> + +/** + * @brief QETSVG::rectToElmt + * Write a QRect as a svg rect element. + * @param rect + * @param parent_document + * @return + */ +QDomElement QETSVG::rectToElmt(const QRectF &rect, QDomDocument &parent_document) +{ + auto dom_element = parent_document.createElement(QStringLiteral("rect")); + if (!rect.isNull()) { + dom_element.setAttribute(QStringLiteral("x"), rect.x()); + yToAttribute(rect.y(), dom_element); + dom_element.setAttribute(QStringLiteral("width"), rect.width()); + heightToAttribute(rect.height(), dom_element); + } + return dom_element; +} + +/** + * @brief QETSVG::rectFromElmt + * @param xml_element : xml_element of an svg rect. + * The tag name must be 'rect' if not, the returned QRect is null. + * @return a svg rect to QRect + */ +QRectF QETSVG::rectFromElmt(const QDomElement &xml_element) +{ + QRectF rect_; + if (xml_element.tagName() == QLatin1String("rect")) { + rect_.setRect(xml_element.attribute(QStringLiteral("x"), QStringLiteral("0")).toDouble(), + yFromAttribute(xml_element, 0), + xml_element.attribute(QStringLiteral("width"), QStringLiteral("10")).toDouble(), + heightFromAttribute(xml_element, 10)); + } + return rect_; +} + +/** + * @brief QETSVG::yToAttribute + * @param y + * @param xml_element + */ +void QETSVG::yToAttribute(const qreal &y, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("y"), QString::number(y)); +} + +/** + * @brief QETSVG::yFromAttribute + * @param xml_element + * @param def_value + * @return + */ +qreal QETSVG::yFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("y"), &value_)) { + return value_; + } + return def_value; +} + +/** + * @brief QETSVG::heightToAttribute + * @param height + * @param xml_element + */ +void QETSVG::heightToAttribute(const qreal &height, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("height"), QString::number(height)); +} + +qreal QETSVG::heightFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("height"), &value_)) { + return value_; + } + return def_value; +} + +void QETSVG::rToAttribute(const qreal &r, QDomElement &xml_element) { + xml_element.setAttribute(QStringLiteral("r"), QString::number(r)); +} + +qreal QETSVG::rFromAttribute(const QDomElement &xml_element, const qreal &def_value) { + qreal value_; + if (QET::attributeIsAReal(xml_element, QStringLiteral("r"), &value_)) { + return value_; + } + return def_value; + +} + +void QETSVG::pointsToAttribute(const QVector &points, QDomElement &xml_element) +{ + QStringList strl_; + for (const auto &point : points) { + strl_.append(QString::number(point.x()) + + QString(",") + + QString::number(point.y())); + } + + xml_element.setAttribute(QStringLiteral("points"), strl_.join(" ")); +} + +/** + * @brief QETSVG::pointsFromAttribute + * @param xml_element + * @return a vector of points stored in attribute 'points' of @xml_element. + * The returned vector can be empty. + */ +QVector QETSVG::pointsFromAttribute(const QDomElement &xml_element) +{ + QVector vector_; + if (const auto string_points = xml_element.attribute(QStringLiteral("points")).split(QStringLiteral(" ")) ; + !string_points.isEmpty()) { + bool x_ok, y_ok; for (const auto &point : string_points) { + const auto string_x_y = point.split(QStringLiteral(",")); + if (string_x_y.size() == 2) { + const auto x = string_x_y[0].toDouble(&x_ok); + const auto y = string_x_y[1].toDouble(&y_ok); + if (x_ok && y_ok) { + vector_.append(QPointF{x,y}); + } + } + } + } + + return vector_; +} diff --git a/sources/svg/qetsvg.h b/sources/svg/qetsvg.h new file mode 100644 index 000000000..0577236ea --- /dev/null +++ b/sources/svg/qetsvg.h @@ -0,0 +1,51 @@ +/* + Copyright 2006-2025 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 QETSVG_H +#define QETSVG_H + +#include + +class QDomDocument; +class QPointF; +class QRectF; + +/** + * @namespace QETSVG + * @brief the QETSVG namespace provide function read and write svg. + * Some function work on xml element (ex rect) and some other + * work on attribute of an element (ex x) + */ +namespace QETSVG +{ + QDomElement rectToElmt(const QRectF &rect, QDomDocument &parent_document); + QRectF rectFromElmt(const QDomElement &xml_element); + + void yToAttribute(const qreal &y, QDomElement &xml_element); + qreal yFromAttribute(const QDomElement &xml_element, const qreal &def_value=0); + + void heightToAttribute(const qreal &height, QDomElement &xml_element); + qreal heightFromAttribute(const QDomElement &xml_element, const qreal &def_value=10); + + void rToAttribute(const qreal &r, QDomElement &xml_element); + qreal rFromAttribute(const QDomElement &xml_element, const qreal &def_value=1); + + void pointsToAttribute(const QVector &points, QDomElement &xml_element); + QVector pointsFromAttribute (const QDomElement &xml_element); +} + +#endif // QETSVG_H diff --git a/sources/undocommand/deleteqgraphicsitemcommand.cpp b/sources/undocommand/deleteqgraphicsitemcommand.cpp index 632c64a9a..ae145f25f 100644 --- a/sources/undocommand/deleteqgraphicsitemcommand.cpp +++ b/sources/undocommand/deleteqgraphicsitemcommand.cpp @@ -28,6 +28,8 @@ #include "../qetgraphicsitem/elementtextitemgroup.h" #include "../qetgraphicsitem/terminal.h" #include "addelementtextcommand.h" +#include "../TerminalStrip/realterminal.h" +#include "../TerminalStrip/physicalterminal.h" /** @brief DeleteQGraphicsItemCommand::DeleteQGraphicsItemCommand @@ -115,6 +117,36 @@ DeleteQGraphicsItemCommand::~DeleteQGraphicsItemCommand() m_diagram->qgiManager().release(m_removed_contents.items(DiagramContent::All)); } +/** + * @brief DeleteQGraphicsItemCommand::hasNonDeletableTerminal + * Return true if @content have terminal element which can't be deleted. + * The reason why a terminal can't be deleted is because they have bridge + * or belong to a physical terminal with more than one level. + * @param diagram + * @param content + * @param dialog + * @return + */ +bool DeleteQGraphicsItemCommand::hasNonDeletableTerminal(const DiagramContent &content) +{ + if (!content.m_terminal_elements.isEmpty()) + { + for (const auto &terminal : content.m_terminal_elements) + { + if (!terminal.isNull()) + { + if (terminal->parentTerminalStrip() + && (terminal->realTerminal()->isBridged() + || terminal->realTerminal()->physicalTerminal()->levelCount() != 1)) { + return true; + } + } + } + } + + return false; +} + /** @brief DeleteQGraphicsItemCommand::setPotentialsOfRemovedElements This function creates new conductors (if needed) for conserve the electrical potentials diff --git a/sources/undocommand/deleteqgraphicsitemcommand.h b/sources/undocommand/deleteqgraphicsitemcommand.h index c4ad2946b..3b2f62c59 100644 --- a/sources/undocommand/deleteqgraphicsitemcommand.h +++ b/sources/undocommand/deleteqgraphicsitemcommand.h @@ -34,10 +34,10 @@ class DeleteQGraphicsItemCommand : public QUndoCommand public: DeleteQGraphicsItemCommand(Diagram *diagram, const DiagramContent &content, QUndoCommand * parent = nullptr); ~DeleteQGraphicsItemCommand() override; + static bool hasNonDeletableTerminal(const DiagramContent &content); private: DeleteQGraphicsItemCommand(const DeleteQGraphicsItemCommand &); - void setPotentialsOfRemovedElements(); Terminal *terminalInSamePotential(Terminal *terminal, Conductor *conductor_to_exclude); diff --git a/sources/utils/qetutils.cpp b/sources/utils/qetutils.cpp index b724d8412..60934f9fd 100644 --- a/sources/utils/qetutils.cpp +++ b/sources/utils/qetutils.cpp @@ -132,3 +132,21 @@ bool QETUtils::sortBeginIntString(const QString &str_a, const QString &str_b) return str_a -1) { + return; + } + + auto px = font.pointSizeF()/72 * QFontMetrics{font}.fontDpi(); + font.setPixelSize(qRound(px)); +} diff --git a/sources/utils/qetutils.h b/sources/utils/qetutils.h index 2e485ddef..0b09bef52 100644 --- a/sources/utils/qetutils.h +++ b/sources/utils/qetutils.h @@ -31,6 +31,7 @@ namespace QETUtils QString marginsToString(const QMargins &margins); QMargins marginsFromString(const QString &string); qreal graphicsHandlerSize(QGraphicsItem *item); + void pixelSizedFont (QFont &font); bool sortBeginIntString(const QString &str_a, const QString &str_b); diff --git a/sources/xml/terminalstriplayoutpatternxml.cpp b/sources/xml/terminalstriplayoutpatternxml.cpp new file mode 100644 index 000000000..687dd5b53 --- /dev/null +++ b/sources/xml/terminalstriplayoutpatternxml.cpp @@ -0,0 +1,206 @@ +/* + Copyright 2006-2025 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 "terminalstriplayoutpatternxml.h" + +#include "../TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h" +#include "../qetxml.h" +#include "../svg/qetsvg.h" + +const QString LAYOUT_PATTERN_TAG_NAME { QStringLiteral("terminal_strip_layout_pattern") }; +const QString LAYOUTS_PATTERN_TAG_NAME { QStringLiteral("terminal_strip_layouts_pattern") }; + +/** + * @brief TerminalStripLayoutPatternXml::toXml + * Save a vector of @class TerminalStripLayoutPattern into main xml element + * with tagg name 'terminal_strip_layouts_pattern' who itself embedded each single @class TerminalStripLayoutPattern + * into a xml element with tag name 'terminal_strip_layout_pattern' (layout without 'S' at the end) + * @param patterns + * @param document + * @return + */ +QDomElement TerminalStripLayoutPatternXml::toXml(const QVector > &patterns, + QDomDocument &document) +{ + auto dom_element = document.createElement(LAYOUTS_PATTERN_TAG_NAME); + for (const auto &pattern : patterns) + { + const auto child_ = toXml(pattern, document); + if (!child_.isNull()) { + dom_element.appendChild(child_); + } + } + + return dom_element; +} + +/** + * @brief TerminalStripLayoutPatternXml::fromXml + * Load a vector of @class TerminalStripLayoutPattern from a main xml element + * with tagg name 'terminal_strip_layouts_pattern' who itself have several child + * with tag name 'terminal_strip_layout_pattern' (layout without 'S' at the end) for every + * @class TerminalStripLayoutPattern to load + * @param element + * @return + */ +QVector > TerminalStripLayoutPatternXml::fromXml(const QDomElement &element) +{ + QVector > returned_vector; + + for (const auto &dom_elmt : QETXML::subChild(element, + LAYOUTS_PATTERN_TAG_NAME, + LAYOUT_PATTERN_TAG_NAME)) + { + auto layout_pattern = QSharedPointer::create(); + fromXml(layout_pattern, dom_elmt); + + returned_vector << layout_pattern; + } + + return returned_vector; +} + +/** + * @brief TerminalStripLayoutPatternXml::toXml + * Save a @class TerminalStripLayoutPattern to a xml element with tag name terminal_strip_layout_pattern + * @param pattern + * @param document + * @return + */ +QDomElement TerminalStripLayoutPatternXml::toXml(const QSharedPointer &pattern, QDomDocument &document) +{ + auto pattern_xml = document.createElement(LAYOUT_PATTERN_TAG_NAME); + if (!pattern.isNull()) { + //Write strip pattern attributes + pattern_xml.setAttribute(QStringLiteral("name"), pattern->m_name); + pattern_xml.setAttribute(QStringLiteral("uuid"), pattern->m_uuid.toString()); + + //Write header properties + auto header_xml = document.createElement(QStringLiteral("header")); + header_xml.appendChild(QETSVG::rectToElmt(pattern->m_header_rect, document)); + + auto header_text_xml = document.createElement(QStringLiteral("text")); + QETXML::orientationToAttribute(pattern->m_header_text_orientation, header_text_xml); + QETXML::alignmentToAttribute(pattern->headerTextAlignment(),header_text_xml); + + //Write spacer properties + auto spacer_xml = document.createElement(QStringLiteral("spacer")); + spacer_xml.appendChild(QETSVG::rectToElmt(pattern->m_spacer_rect, document)); + + pattern_xml.appendChild(header_xml).appendChild(header_text_xml); + pattern_xml.appendChild(spacer_xml); + + //Write terminals properties + auto terminals_xml = document.createElement(QStringLiteral("terminals")); + for (const auto &rect : pattern->m_terminal_rect) { + terminals_xml.appendChild(QETSVG::rectToElmt(rect, document)); + } + + auto terminals_text_xml = document.createElement(QStringLiteral("text")); + QETXML::orientationToAttribute(pattern->m_terminals_text_orientation, terminals_text_xml); + QETXML::alignmentToAttribute(pattern->terminalsTextAlignment(),terminals_text_xml); + QETSVG::yToAttribute(pattern->m_terminals_text_y, terminals_text_xml); + QETSVG::heightToAttribute(pattern->m_terminals_text_height, terminals_text_xml); + terminals_xml.appendChild(terminals_text_xml); + + auto xref_text_xml = document.createElement(QStringLiteral("xref")); + QETXML::orientationToAttribute(pattern->m_xref_text_orientation, xref_text_xml); + QETXML::alignmentToAttribute(pattern->xrefTextAlignment(),xref_text_xml); + QETSVG::yToAttribute(pattern->m_xref_text_y, xref_text_xml); + QETSVG::heightToAttribute(pattern->m_xref_text_height, xref_text_xml); + terminals_xml.appendChild(xref_text_xml); + + auto bridge_xml = document.createElement(QStringLiteral("bridges")); + QETSVG::rToAttribute(pattern->m_bridge_point_d/2, bridge_xml); + QVector points_vector; + for (const auto &y : pattern->m_bridge_point_y_offset) { + points_vector.append(QPointF{0,y}); + } + QETSVG::pointsToAttribute(points_vector, bridge_xml); + terminals_xml.appendChild(bridge_xml); + + pattern_xml.appendChild(terminals_xml); + } + + return pattern_xml; +} + +/** + * @brief TerminalStripLayoutPatternXml::fromXml + * LOad a @class TerminalStripLayoutPattern from a xml element with tag name terminal_strip_layout_pattern + * @param layout + * @param element + */ +void TerminalStripLayoutPatternXml::fromXml(QSharedPointer &layout, const QDomElement &element) +{ + if (element.tagName() != LAYOUT_PATTERN_TAG_NAME) return; + layout->m_name = element.attribute(QStringLiteral("name"), layout->m_name); + layout->m_uuid.fromString(element.attribute(QStringLiteral("uuid"), layout->m_uuid.toString())); + + const auto header_xml = element.firstChildElement(QStringLiteral("header")); + if (!header_xml.isNull() && header_xml.hasAttribute(QStringLiteral("rect"))) { + layout->m_header_rect = QETSVG::rectFromElmt(header_xml); + } + + if (const auto header_text_xml = header_xml.firstChildElement(QStringLiteral("text")); + !header_text_xml.isNull()) { + layout->m_header_text_orientation = QETXML::orientationFromAttribute(header_text_xml, layout->m_header_text_orientation); + layout->setHeaderTextAlignment(QETXML::alignmentFromAttribute(header_text_xml)); + } + + const auto spacer_xml = element.firstChildElement(QStringLiteral("spacer")); + if (const auto rect = QETSVG::rectFromElmt(spacer_xml); + !rect.isNull()) { + layout->m_spacer_rect = rect; + } + + if (const auto terminals_xml = element.firstChildElement(QStringLiteral("terminals")); + !terminals_xml.isNull()) { + layout->m_terminal_rect.clear(); + for (const auto &terminal_rect_xml : QETXML::directChild(terminals_xml, QStringLiteral("rect"))) { + layout->m_terminal_rect.append(QETSVG::rectFromElmt(terminal_rect_xml)) ; + } + + if (const auto terminals_text_xml = terminals_xml.firstChildElement(QStringLiteral("text")); + !terminals_text_xml.isNull()) { + layout->m_terminals_text_orientation = QETXML::orientationFromAttribute(terminals_text_xml, layout->m_terminals_text_orientation); + layout->setTerminalsTextAlignment(QETXML::alignmentFromAttribute(terminals_text_xml)); + layout->m_terminals_text_y = QETSVG::yFromAttribute(terminals_text_xml); + layout->m_terminals_text_height = QETSVG::heightFromAttribute(terminals_text_xml); + } + + if (const auto xref_text_xml = terminals_xml.firstChildElement(QStringLiteral("xref")); + !xref_text_xml.isNull()) { + layout->m_xref_text_orientation = QETXML::orientationFromAttribute(xref_text_xml, layout->m_xref_text_orientation); + layout->setXrefTextAlignment(QETXML::alignmentFromAttribute(xref_text_xml)); + layout->m_xref_text_y = QETSVG::yFromAttribute(xref_text_xml); + layout->m_xref_text_height = QETSVG::heightFromAttribute(xref_text_xml); + } + + if (const auto bridge_xml = terminals_xml.firstChildElement(QStringLiteral("bridges")); + !bridge_xml.isNull()) { + layout->m_bridge_point_d = QETSVG::rFromAttribute(bridge_xml, 2.5)*2; + if (const auto points = QETSVG::pointsFromAttribute(bridge_xml); + points.size() == 4) { + layout->m_bridge_point_y_offset[0]= points[0].y(); + layout->m_bridge_point_y_offset[1]= points[1].y(); + layout->m_bridge_point_y_offset[2]= points[2].y(); + layout->m_bridge_point_y_offset[3]= points[3].y(); + } + } + } +} diff --git a/sources/xml/terminalstriplayoutpatternxml.h b/sources/xml/terminalstriplayoutpatternxml.h new file mode 100644 index 000000000..df6dba87b --- /dev/null +++ b/sources/xml/terminalstriplayoutpatternxml.h @@ -0,0 +1,41 @@ +/* + Copyright 2006-2025 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 TERMINALSTRIPLAYOUTPATTERNXML_H +#define TERMINALSTRIPLAYOUTPATTERNXML_H + +#include +#include + +class TerminalStripLayoutPattern; + +/** + * @brief The TerminalStripLayoutPatternXml class + * A class with static function used to save/restor a + * @class TerminalStripLayoutPattern to xml + */ +class TerminalStripLayoutPatternXml +{ + public: + static QDomElement toXml(const QVector> &patterns, QDomDocument &document); + static QVector> fromXml(const QDomElement &element); + + static QDomElement toXml (const QSharedPointer &pattern, QDomDocument &document); + static void fromXml(QSharedPointer &layout, const QDomElement &element); +}; + +#endif // TERMINALSTRIPLAYOUTPATTERNXML_H