diff --git a/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp index 8b145aef2..b1ee952e6 100644 --- a/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp @@ -522,6 +522,26 @@ struct BridgePoint qreal width{0}; }; + //True when at least one terminal of the strip carries a cable : the strip + //then needs the zone drawn under it to let the cables out, like the + //schematic style does. +bool haveCable(const AbstractTerminalStripInterface *strip) +{ + if (!strip) { + return false; + } + for (const auto &physical_t : strip->physicalTerminal()) + { + for (const auto &real_t : physical_t->realTerminals()) + { + if (real_t && !real_t->cable().isEmpty()) { + return true; + } + } + } + return false; +} + } //End anonymous namespace QRectF boundingRect(const AbstractTerminalStripInterface *strip, @@ -535,7 +555,20 @@ QRectF boundingRect(const AbstractTerminalStripInterface *strip, } } const qreal s_{pattern.m_realistic_px_per_mm}; - return QRectF{0, 0, width_mm_ * s_, pattern.m_realistic_length_mm * s_}; + const qreal length_{pattern.m_realistic_length_mm * s_}; + + //The cables are drawn under the strip, in the zone the schematic + //style reserves for them too + qreal extra_bottom_{0}; + if (pattern.m_cable_wire_length > 0 && haveCable(strip)) + { + //4 is the diameter of the circle at the end of the wires + extra_bottom_ = pattern.m_cable_wire_length + + std::max(0, pattern.m_cable_length) + + std::max(0, pattern.m_cable_end_length) + + 4; + } + return QRectF{0, 0, width_mm_ * s_, length_ + extra_bottom_}; } void paint(QPainter *painter, @@ -595,6 +628,7 @@ void paint(QPainter *painter, } QHash> bridges_; + QVector cable_cells_; for (const auto &g_ : geometry(&strip)) { @@ -603,6 +637,24 @@ void paint(QPainter *painter, const auto first_{g_.reals.first()}; const int levels_{static_cast(g_.reals.size())}; + //Cables (hoses) of this terminal : one wire exit by level, spread over + //the width of the body, all of them leaving the strip at its bottom edge + for (int k = 0 ; k < levels_ ; ++k) + { + const auto &real_t{g_.reals.at(k)}; + if (!real_t || real_t->cable().isEmpty()) { + continue; + } + Helpers::CableCell cell_; + cell_.x = x_ + w_ * (k + 0.5) / levels_; + cell_.bottom = length_; + cell_.cable = real_t->cable(); + cell_.wire = real_t->cableWire(); + cell_.shield = real_t->isShield(); + cell_.terminal = real_t; + cable_cells_.append(cell_); + } + //A terminal chosen in the catalog is drawn with its own clamp, so that a strip //mixing screw and spring terminals is drawn as it is. The spring-cage clamps //(opened with a screwdriver) are drawn like the push-in ones. @@ -793,6 +845,18 @@ void paint(QPainter *painter, draw_end_stop(); + //The cables under the strip : the wires of a cable join it, and the + //cable ends together in the box naming where it goes -- drawn exactly + //like the schematic style draws them, so both styles tell the same thing + if (!cable_cells_.isEmpty()) + { + painter->save(); + painter->setFont(pattern.font()); + painter->setPen(QPen(Qt::black, 0.5)); + Helpers::drawCables(painter, cable_cells_, pattern); + painter->restore(); + } + painter->restore(); } diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 70c5fe7da..52cd984e0 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -29,6 +29,10 @@ namespace TerminalStripDrawer { + //The cells of a cable drawing live with the helpers, so both drawing + //styles build the same thing and pass it to Helpers::drawCables() +using Helpers::CableCell; + /** * @brief TerminalStripDrawer::TerminalStripDrawer * @param strip @@ -259,20 +263,6 @@ void drawConnections(QPainter *painter, const QRectF &terminal_rect, qreal lengt } } -/** - * @brief The CableCell struct - * What is needed to draw the cable under a terminal. - */ -struct CableCell -{ - qreal x{0}; ///< x of the middle of the terminal, in the strip coordinates - qreal bottom{0}; ///< y of the bottom of the terminal - QString cable; ///< name of the cable (hose) - QString wire; ///< color / number of the wire - bool shield{false}; ///< true if the terminal is the shield of the cable - QSharedPointer terminal; ///< to ask where the cable goes -}; - /** * @brief drawCables * Draw the cables under the terminals. Consecutive terminals who have the same cable name @@ -941,6 +931,11 @@ void Helpers::drawTypeSymbol(QPainter *painter, const QRectF &box, ::TerminalStripDrawer::drawTypeSymbol(painter, box, type, led); } +void Helpers::drawCables(QPainter *painter, const QVector &cells, + const TerminalStripLayoutPattern &pattern) { + ::TerminalStripDrawer::drawCables(painter, cells, pattern); +} + /** * @brief TerminalStripDrawer::paint * @param painter @@ -1368,7 +1363,7 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->setPen(cable_pen); painter->setFont(m_pattern->font()); painter->setBrush(Qt::NoBrush); - drawCables(painter, cable_cells, *m_pattern); + Helpers::drawCables(painter, cable_cells, *m_pattern); painter->restore(); } } diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h index 7cbafd5ea..494262358 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h @@ -42,6 +42,22 @@ namespace TerminalStripDrawer //Symbol of the type of the terminal (fuse, diode, led...) scaled to fit in box void drawTypeSymbol(QPainter *painter, const QRectF &box, ElementData::TerminalType type, bool led); + //What is needed to draw the cable under a terminal + struct CableCell + { + qreal x{0}; ///< x of the middle of the terminal, in the strip coordinates + qreal bottom{0}; ///< y of the bottom of the terminal + QString cable; ///< name of the cable (hose) + QString wire; ///< color / number of the wire + bool shield{false}; ///< true if the terminal is the shield of the cable + QSharedPointer terminal; ///< to ask where the cable goes + }; + //Draw the cables under the terminals, whichever style draws them : + //consecutive terminals with the same cable share one cable, which ends + //together in a short stub and a box naming where it goes (see drawCables() + //in terminalstripdrawer.cpp for the whole drawing) + void drawCables(QPainter *painter, const QVector &cells, + const TerminalStripLayoutPattern &pattern); } } diff --git a/tests/qttest/tst_cabletarget.cpp b/tests/qttest/tst_cabletarget.cpp index ee1ef2dbf..f34dd92f8 100644 --- a/tests/qttest/tst_cabletarget.cpp +++ b/tests/qttest/tst_cabletarget.cpp @@ -17,6 +17,7 @@ */ #include "qetapptest.h" +#include "TerminalStrip/GraphicsItem/realisticterminalstripdrawer.h" #include "TerminalStrip/GraphicsItem/trueterminalstrip.h" #include "TerminalStrip/physicalterminal.h" #include "TerminalStrip/realterminal.h" @@ -51,6 +52,10 @@ the drawing -- the end zone the settings leave is what gives it the room, so three lines never end up squeezed into a tiny text. + Both drawing styles are covered: the schematic one and the + realistic one (the strip seen from above), which paint the same + cable through Helpers::drawCables(). + fixtures/every_feature.qet has the strip X1 (elements 891b70f2 and 4861e268) and the contact fc9cc920 wired to 891b70f2 by the conductor 8bd16d7a; the test gives the contact the Installation, @@ -169,6 +174,7 @@ private slots: void paintsWithTargetBox(); void wireLabelStaysOutOfTheTerminal(); void targetBoxKeepsTheDrawingFont(); + void realisticStyleDrawsTheCable(); }; void tst_cabletarget::init() @@ -445,6 +451,75 @@ void tst_cabletarget::targetBoxKeepsTheDrawingFont() QVERIFY(lowest + 2 >= row); } +/** + The realistic style draws the cable too. The strip seen from above + reserves the zone under it when one of its terminals carries a + cable, and the wires, the cable and the box naming where it goes + are painted in it -- exactly what the schematic style draws, since + both styles now share the same Helpers::drawCables(). +*/ +void tst_cabletarget::realisticStyleDrawsTheCable() +{ + QVERIFY(wireCableToTheContact()); + + const auto strips_ = m_project->terminalStrip(); + QVERIFY(!strips_.isEmpty()); + const auto strip_ = QSharedPointer{ + new TerminalStripDrawer::TrueTerminalStrip{strips_.first()}}; + TerminalStripLayoutPattern pattern_; + + const auto bounds_of = [&strip_, &pattern_]() { + return TerminalStripDrawer::Realistic::boundingRect(strip_.data(), + pattern_); + }; + const auto render = [&strip_, &pattern_](const QRectF &bounds) { + QImage image{bounds.size().toSize() + QSize{4, 4}, + QImage::Format_ARGB32_Premultiplied}; + image.fill(Qt::transparent); + QPainter painter{&image}; + painter.translate(-bounds.topLeft() + QPointF{2, 2}); + TerminalStripDrawer::Realistic::paint( + &painter, *strip_, pattern_, + TerminalStripLayoutPattern::DrawStyle::RealisticPushIn); + return image; + }; + + const QRectF with_bounds{bounds_of()}; + const QImage with_cable{render(with_bounds)}; + + //The body of the strip ends there : everything painted under it + //belongs to the cable + const qreal body_bottom{ + pattern_.m_realistic_length_mm * pattern_.m_realistic_px_per_mm}; + QVERIFY(with_bounds.height() > body_bottom); + + int painted_{0}; + for (auto y = qRound(body_bottom) + 4 ; y + 4 < with_cable.height() ; ++y) + { + for (auto x = 0 ; x + 4 < with_cable.width() ; ++x) + { + if (with_cable.pixel(x, y) != qRgba(0, 0, 0, 0)) { + ++painted_; + } + } + } + //The wires and the cable are drawn in that zone + QVERIFY(painted_ > 0); + + //The same strip, its terminal carries no cable name any more + Element *terminal_ = element( + QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}")); + QVERIFY(terminal_); + ElementData terminal_data_{terminal_->elementData()}; + terminal_data_.m_informations.addValue(RealTerminal::cableInfoKey(), + QString()); + terminal_->setElementData(terminal_data_); + + //No cable to let out : the strip does not reserve the zone + const QRectF without_bounds{bounds_of()}; + QVERIFY(without_bounds.height() < with_bounds.height()); +} + int main(int argc, char **argv) { QStandardPaths::setTestModeEnabled(true);