diff --git a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp index f094ec10e..cdfc7ad02 100644 --- a/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/demoterminalstrip.cpp @@ -38,10 +38,13 @@ namespace TerminalStripDrawer class DemoRealTerminal : public AbstractRealTerminalInterface { public: - DemoRealTerminal(const QString &label, const QString &xref, const QUuid &bridge) : + DemoRealTerminal(const QString &label, const QString &xref, const QUuid &bridge, + ElementData::TerminalType type = ElementData::TTGeneric, bool led = false) : m_label { label }, m_xref{ xref }, - m_bridge { bridge } + m_bridge { bridge }, + m_type { type }, + m_led { led } {} QString label() const override { @@ -60,9 +63,19 @@ namespace TerminalStripDrawer return m_xref; } + ElementData::TerminalType type() const override { + return m_type; + } + + bool isLed() const override { + return m_led; + } + private: QString m_label, m_xref; QUuid m_bridge; + ElementData::TerminalType m_type; + bool m_led; }; class DemoPhysicalTerminal : public AbstractPhysicalTerminalInterface @@ -109,19 +122,19 @@ namespace TerminalStripDrawer real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("24vdc"), QStringLiteral("1_A1"), - lvl_1)}; + lvl_1, ElementData::TTFuse, false)}; real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("0vdc"), QStringLiteral("1_A2"), - lvl_2)}; + lvl_2, ElementData::TTSectional, false)}; real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("signal"), QStringLiteral("1_A3"), - lvl_3)}; + lvl_3, ElementData::TTDiode, false)}; real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("teach"), QStringLiteral("1_A4"), - lvl_4)}; + lvl_4, ElementData::TTGround, false)}; m_physical_terminal << QSharedPointer { new DemoPhysicalTerminal {real_terminals_vector}}; @@ -129,11 +142,11 @@ namespace TerminalStripDrawer real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("24vdc"), QStringLiteral("2_A1"), - lvl_1)}; + lvl_1, ElementData::TTGeneric, true)}; real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("0vdc"), QStringLiteral("2_A2"), - lvl_2)}; + lvl_2, ElementData::TTFuse, true)}; real_terminals_vector << QSharedPointer { new DemoRealTerminal( QStringLiteral("signal"), QStringLiteral("2_A3"), diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index d23ee9e6d..35a81417c 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -44,7 +44,7 @@ class TerminalStripLayoutPattern TerminalStripLayoutPattern(); //Header of terminal strip - QRectF m_header_rect{0,30,50,130}; + QRectF m_header_rect{0,30,50,146}; Qt::Orientation m_header_text_orientation{Qt::Horizontal}; void setHeaderTextAlignment(const Qt::Alignment &alignment); Qt::Alignment headerTextAlignment() const; @@ -60,10 +60,10 @@ class TerminalStripLayoutPattern //Terminals QVector m_terminal_rect { - QRectF{0, 0, 20, 190}, - QRectF{0, 10, 20, 170}, - QRectF{0, 20, 20, 150}, - QRectF{0, 30, 20, 130} + QRectF{0, 0, 20, 206}, + QRectF{0, 10, 20, 186}, + QRectF{0, 20, 20, 166}, + QRectF{0, 30, 20, 146} }; //Terminal text @@ -82,6 +82,13 @@ class TerminalStripLayoutPattern qreal m_xref_text_y{95}; Qt::Orientation m_xref_text_orientation {Qt::Vertical}; + //Symbol of the terminal type (fuse, sectional, diode, ground, led). + //A height of 0 disable the symbol. + qreal m_type_symbol_y{160}; + qreal m_type_symbol_height{14}; + //Length of the connection drawn above and under each terminal, + //in the middle of the terminal. 0 disable the connections. + qreal m_connection_length{10}; qreal m_bridge_point_d{5}; QVector m_bridge_point_y_offset{50,70,90,110}; diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index ee94b3b77..92a162e54 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -20,6 +20,8 @@ #include #include +#include + namespace TerminalStripDrawer { /** @@ -38,6 +40,156 @@ void TerminalStripDrawer::setStrip(QSharedPointerdrawLine(QPointF{0, -7}, QPointF{0, 7}); + painter->drawRect(QRectF{-3, -5, 6, 10}); +} + +void drawSectionalSymbol(QPainter *painter) +{ + painter->drawLine(QPointF{0, -7}, QPointF{0, 7}); + painter->drawLine(QPointF{-4, 2}, QPointF{4, -2}); +} + +void drawDiodeSymbol(QPainter *painter) +{ + const qreal t{symbol_height / 3}; + const QPointF triangle[3] { {-t, -t}, {t, -t}, {0, t} }; + painter->drawLine(QPointF{0, -7}, QPointF{0, -t}); + painter->drawPolygon(triangle, 3); + painter->drawLine(QPointF{-t, t}, QPointF{t, t}); + painter->drawLine(QPointF{0, t}, QPointF{0, 7}); +} + +void drawLedSymbol(QPainter *painter) +{ + drawDiodeSymbol(painter); + const qreal t{symbol_height / 3}; + //The two rays + painter->drawLine(QPointF{t + 0.5, -1}, QPointF{t + 3.5, -4}); + painter->drawLine(QPointF{t + 0.5, 2}, QPointF{t + 3.5, -1}); +} + +void drawGroundSymbol(QPainter *painter) +{ + painter->drawLine(QPointF{0, -7}, QPointF{0, -2}); + painter->drawLine(QPointF{-5, -2}, QPointF{5, -2}); + painter->drawLine(QPointF{-3, 1}, QPointF{3, 1}); + painter->drawLine(QPointF{-1, 4}, QPointF{1, 4}); +} + +/** + * @brief drawScaled + * Call @a draw with the painter moved by @a dx and scaled by @a factor. + * The width of the pen is kept constant. + */ +template +void drawScaled(QPainter *painter, qreal dx, qreal factor, Func draw) +{ + painter->save(); + painter->translate(dx, 0); + painter->scale(factor, factor); + auto pen_{painter->pen()}; + pen_.setWidthF(pen_.widthF() / factor); + painter->setPen(pen_); + draw(painter); + painter->restore(); +} + +/** + * @brief drawTypeSymbol + * Draw the symbol of a terminal type in @a box. The symbol is scaled + * to fit in @a box, so it never overflow on the neighbouring terminal. + * The painter must have a pen set, the brush is ignored. + * @param painter + * @param box : area available for the symbol, in the painter coordinates + * @param type : type of the terminal, a generic terminal have no symbol + * @param led : if true a led symbol is drawn. If the terminal have + * also a type (fuse...), the type symbol and the led are drawn side by side. + */ +void drawTypeSymbol(QPainter *painter, const QRectF &box, ElementData::TerminalType type, bool led) +{ + const bool have_type{type != ElementData::TTGeneric}; + if (!led && !have_type) { + return; + } + + const qreal scale_{qMin(box.width() / symbol_width, box.height() / symbol_height)}; + if (scale_ <= 0) { + return; + } + + painter->save(); + painter->setBrush(Qt::NoBrush); + painter->translate(box.center()); + painter->scale(scale_, scale_); + auto pen_{painter->pen()}; + pen_.setWidthF(pen_.widthF() / scale_); + painter->setPen(pen_); + + auto draw_type = [type](QPainter *p) + { + switch (type) + { + case ElementData::TTFuse : drawFuseSymbol(p); break; + case ElementData::TTSectional : drawSectionalSymbol(p); break; + case ElementData::TTDiode : drawDiodeSymbol(p); break; + case ElementData::TTGround : drawGroundSymbol(p); break; + default: break; + } + }; + + if (led && have_type) + { + //Not enough place for two full size symbols, draw them smaller side by side + drawScaled(painter, -5, 0.7, draw_type); + drawScaled(painter, 2.5, 0.7, drawLedSymbol); + } + else if (led) { + drawLedSymbol(painter); + } + else { + draw_type(painter); + } + + painter->restore(); +} + +/** + * @brief drawConnections + * Draw a connection above and a connection under @a terminal_rect, in the middle + * of the rect. A connection is a short line ended by a little circle. + * @param painter + * @param terminal_rect + * @param length : the total length of a connection, circle included + */ +void drawConnections(QPainter *painter, const QRectF &terminal_rect, qreal length) +{ + const qreal radius{qMin(length / 4, 2)}; + const qreal x{terminal_rect.width() / 2}; + const qreal top{terminal_rect.top()}; + const qreal bottom{terminal_rect.top() + terminal_rect.height()}; + + painter->drawLine(QPointF{x, top}, QPointF{x, top - length + radius * 2}); + painter->drawEllipse(QPointF{x, top - length + radius}, radius, radius); + + painter->drawLine(QPointF{x, bottom}, QPointF{x, bottom + length - radius * 2}); + painter->drawEllipse(QPointF{x, bottom + length - radius}, radius, radius); +} + +} //End anonymous namespace + /** * @brief TerminalStripDrawer::paint * @param painter @@ -141,6 +293,21 @@ void TerminalStripDrawer::paint(QPainter *painter) terminal_rect = m_pattern->m_terminal_rect[index_]; //Draw terminal rect painter->drawRect(terminal_rect); + + //Draw the symbol of the terminal type (fuse, ground, led...) + if (m_pattern->m_type_symbol_height > 0 && real_terminal_vector[i]) + { + drawTypeSymbol(painter, + QRectF{0, m_pattern->m_type_symbol_y, + terminal_rect.width(), m_pattern->m_type_symbol_height}, + real_terminal_vector[i]->type(), + real_terminal_vector[i]->isLed()); + } + + //Draw the connections, above and under the terminal + if (m_pattern->m_connection_length > 0) { + drawConnections(painter, terminal_rect, m_pattern->m_connection_length); + } //Draw a stronger line if the current terminal have level //and the current level is the first if (real_t_count > 1 && i == 0) @@ -280,7 +447,21 @@ void TerminalStripDrawer::paint(QPainter *painter) QRectF TerminalStripDrawer::boundingRect() const { - return QRectF{0, 0, width(), height()};; + QRectF rect_{0, 0, width(), height()}; + + //The connections are drawn above and under the terminals + if (m_pattern && m_pattern->m_connection_length > 0) + { + const auto length_{m_pattern->m_connection_length}; + qreal top_{0}; + for (const auto &terminal_rect : std::as_const(m_pattern->m_terminal_rect)) { + top_ = std::min(top_, terminal_rect.top() - length_); + } + rect_.setBottom(rect_.bottom() + length_); + rect_.setTop(top_); + } + + return rect_; } void TerminalStripDrawer::setLayout(QSharedPointer layout) diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index 26de183b4..bec643415 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -22,6 +22,7 @@ #include #include "properties/terminalstriplayoutpattern.h" +#include "../../properties/elementdata.h" class QPainter; class TerminalStrip; @@ -56,6 +57,10 @@ namespace TerminalStripDrawer virtual bool isBridged() const = 0; virtual AbstractBridgeInterface* bridge() const = 0; virtual QString xref() const = 0; + //Type and led are only used to draw the symbol of the terminal. + //They are not pure virtual, so an implementation can ignore them. + virtual ElementData::TerminalType type() const { return ElementData::TTGeneric; } + virtual bool isLed() const { return false; } }; class AbstractPhysicalTerminalInterface diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp index 67527dc26..23a2b492f 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp @@ -128,6 +128,16 @@ namespace TerminalStripDrawer } } + ElementData::TerminalType TrueRealTerminal::type() const + { + return m_real ? m_real->type() : ElementData::TTGeneric; + } + + bool TrueRealTerminal::isLed() const + { + return m_real ? m_real->isLed() : false; + } + TrueBridge::TrueBridge(QSharedPointer bridge) : m_bridge { bridge } {} diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h index ad760592e..37238f1b7 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h @@ -59,6 +59,8 @@ namespace TerminalStripDrawer bool isBridged() const override; AbstractBridgeInterface* bridge() const override; QString xref() const override; + ElementData::TerminalType type() const override; + bool isLed() const override; private: QSharedPointer m_real; diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index 9b1a3506a..bf1a897a5 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -151,6 +151,11 @@ void TerminalStripLayoutEditor::valueEdited() 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(); + //Terminal type symbol + m_layout.data()->m_type_symbol_y = ui->m_type_symbol_y_sb->value(); + m_layout.data()->m_type_symbol_height = ui->m_type_symbol_height_sb->value(); + m_layout.data()->m_connection_length = ui->m_connection_length_sb->value(); + updateUi(); m_preview_strip_item.update(); } @@ -256,6 +261,10 @@ void TerminalStripLayoutEditor::updateUi() ui->m_xref_y_sb->setValue(data->m_xref_text_y); ui->m_xref_height_sb->setValue(data->m_xref_text_height); + ui->m_type_symbol_y_sb->setValue(data->m_type_symbol_y); + ui->m_type_symbol_height_sb->setValue(data->m_type_symbol_height); + ui->m_connection_length_sb->setValue(data->m_connection_length); + m_ui_updating = false; updatePreview(); } diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index 08b1dae34..15d784f40 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -459,6 +459,50 @@ + + + + Symbol + + + Qt::AlignCenter + + + + + + + 1000 + + + + + + + Height of the terminal type symbol (fuse, ground, led...). 0 disable the symbol. + + + 1000 + + + + + + + Connection length + + + + + + + Length of the connections drawn above and under each terminal. 0 disable the connections. + + + 1000 + + + @@ -1094,6 +1138,54 @@ + + m_type_symbol_y_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 900 + 398 + + + 480 + 311 + + + + + m_type_symbol_height_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 900 + 398 + + + 480 + 311 + + + + + m_connection_length_sb + valueChanged(int) + TerminalStripLayoutEditor + valueEdited() + + + 700 + 431 + + + 480 + 311 + + + valueEdited()