diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp index e11ede4a3..0bbb726b5 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.cpp @@ -171,6 +171,32 @@ namespace } } +/** + * @brief TerminalStripLayoutPattern::drawStyleToString + * @return the string used to save @a style in the project xml (terminal strip item) + */ +QString TerminalStripLayoutPattern::drawStyleToString(DrawStyle style) +{ + switch (style) { + case DrawStyle::RealisticPushIn : return QStringLiteral("realistic_push_in"); + case DrawStyle::RealisticScrew : return QStringLiteral("realistic_screw"); + default : return QStringLiteral("schematic"); + } +} + +/** + * @brief TerminalStripLayoutPattern::drawStyleFromString + * @return the style saved as @a string, or @a default_style if @a string is unknown or empty + * (item saved before the drawing styles : the schematic style is kept). + */ +TerminalStripLayoutPattern::DrawStyle TerminalStripLayoutPattern::drawStyleFromString(const QString &string, DrawStyle default_style) +{ + if (string == QLatin1String("schematic")) return DrawStyle::Schematic; + if (string == QLatin1String("realistic_push_in") || string == QLatin1String("realistic")) return DrawStyle::RealisticPushIn; + if (string == QLatin1String("realistic_screw")) return DrawStyle::RealisticScrew; + return default_style; +} + /** * @brief TerminalStripLayoutPattern::xmlTagName * @return the tag name of the xml element used by toXml / fromXml @@ -228,6 +254,11 @@ QDomElement TerminalStripLayoutPattern::toXml(QDomDocument &document) const element.setAttribute(QStringLiteral("bridge_point_y_offset_%1").arg(i), m_bridge_point_y_offset.at(i)); } + element.setAttribute(QStringLiteral("realistic_px_per_mm"), m_realistic_px_per_mm); + element.setAttribute(QStringLiteral("realistic_length_mm"), m_realistic_length_mm); + element.setAttribute(QStringLiteral("realistic_end_stops"), m_realistic_end_stops ? 1 : 0); + element.setAttribute(QStringLiteral("realistic_group_marker"), m_realistic_group_marker ? 1 : 0); + return element; } @@ -290,4 +321,19 @@ void TerminalStripLayoutPattern::fromXml(const QDomElement &layout_element) for (auto i = 0; i < m_bridge_point_y_offset.size(); ++i) { m_bridge_point_y_offset[i] = realFromXml(layout_element, QStringLiteral("bridge_point_y_offset_%1").arg(i), m_bridge_point_y_offset.at(i)); } + + const auto px_per_mm_ = realFromXml(layout_element, QStringLiteral("realistic_px_per_mm"), m_realistic_px_per_mm); + if (px_per_mm_ > 0) { + m_realistic_px_per_mm = px_per_mm_; + } + const auto length_mm_ = realFromXml(layout_element, QStringLiteral("realistic_length_mm"), m_realistic_length_mm); + if (length_mm_ > 0) { + m_realistic_length_mm = length_mm_; + } + if (layout_element.hasAttribute(QStringLiteral("realistic_end_stops"))) { + m_realistic_end_stops = layout_element.attribute(QStringLiteral("realistic_end_stops")).toInt() != 0; + } + if (layout_element.hasAttribute(QStringLiteral("realistic_group_marker"))) { + m_realistic_group_marker = layout_element.attribute(QStringLiteral("realistic_group_marker")).toInt() != 0; + } } diff --git a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h index b432783b2..4dc941601 100644 --- a/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h +++ b/sources/TerminalStrip/GraphicsItem/properties/terminalstriplayoutpattern.h @@ -44,6 +44,37 @@ class TerminalStripLayoutPattern public: TerminalStripLayoutPattern(); + /** + * @brief The DrawStyle enum + * How the terminals of a strip are drawn. + * The style is chosen for each terminal strip item, when the item is + * added to a folio (see TerminalStripItem::setDrawStyle), the layout + * only hold the values used by the styles. + * Schematic : the classic drawing (header, xrefs, symbols, connections, cables). + * RealisticPushIn : the strip seen from above, at scale, like the mounting + * drawing of a cabinet : end stops, group marker, push-in wire entries. + * RealisticScrew : same as RealisticPushIn, with screw clamps. + * The schematic style use most of the values of this class, + * the realistic styles use the values prefixed by m_realistic_. + */ + enum class DrawStyle { + Schematic = 0, + RealisticPushIn = 1, + RealisticScrew = 2 + }; + static QString drawStyleToString(DrawStyle style); + static DrawStyle drawStyleFromString(const QString &string, DrawStyle default_style); + + //Realistic style + //Scale of the drawing : number of pixels for one millimeter + qreal m_realistic_px_per_mm{4.0}; + //Length (mm) of a terminal along the wires, from the top to the bottom + qreal m_realistic_length_mm{60.0}; + //Draw an end stop at each end of the strip + bool m_realistic_end_stops{true}; + //Draw a group marker carrier with the name of the strip, after the first end stop + bool m_realistic_group_marker{true}; + //Header of terminal strip QRectF m_header_rect{0,30,50,146}; Qt::Orientation m_header_text_orientation{Qt::Horizontal}; diff --git a/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp new file mode 100644 index 000000000..431b6c1e2 --- /dev/null +++ b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.cpp @@ -0,0 +1,564 @@ +/* + Copyright 2006-2026 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 "realisticterminalstripdrawer.h" +#include "terminalstripdrawerhelpers.h" + +#include +#include +#include +#include +#include + +#include + +namespace TerminalStripDrawer { +namespace Realistic { + +namespace { + + //Width (mm) of the accessories. Values of usual products, enough for a drawing. +constexpr qreal end_stop_width_mm{8.0}; +constexpr qreal group_marker_width_mm{11.0}; +constexpr qreal separator_width_mm{1.5}; + //Biggest radius of a wire entry (mm), for the wide terminals +constexpr qreal max_entry_radius_mm{1.9}; + + //Vertical layout of a terminal, in fraction of its length (top = 0, bottom = 1). + //The wire entries are in [entries_top, band_top] and [band_bottom, 1 - entries_top], + //the middle band (marker tag, bridge channels) is in [band_top, band_bottom]. +constexpr qreal entries_top{0.04}; +constexpr qreal band_top{0.40}; +constexpr qreal band_bottom{0.60}; +constexpr qreal channels_top{0.405}; +constexpr qreal channels_bottom{0.445}; + + //Colors of the accessories, close to the real products +const QColor end_stop_color{232, 228, 220}; +const QColor end_stop_grip_color{35, 35, 35}; +const QColor group_marker_color{168, 168, 168}; +const QColor group_marker_text_color{200, 0, 0}; +const QColor band_color{85, 85, 85}; +const QColor channel_color{55, 55, 55}; +const QColor bridge_color{200, 30, 30}; +const QColor separator_color{196, 196, 198}; + +/** + * @brief The PhysicalGeometry struct + * What is needed to draw a physical terminal. + */ +struct PhysicalGeometry +{ + qreal width_mm{0}; + bool separator_after{false}; //A separator plate is mounted after this terminal + QVector> reals; +}; + +/** + * @return the physical terminals of @a strip with their width, in the drawing order. + * The width of a physical terminal is the biggest width of its real terminals, + * or the reference width if no width is known. + */ +QVector geometry(const AbstractTerminalStripInterface *strip) +{ + QVector geometry_; + if (!strip) { + return geometry_; + } + + for (const auto &physical_t : strip->physicalTerminal()) + { + if (!physical_t) { + continue; + } + PhysicalGeometry g_; + for (const auto &real_t : physical_t->realTerminals()) + { + if (!real_t) { + continue; + } + g_.reals.append(real_t); + g_.width_mm = std::max(g_.width_mm, real_t->widthMm()); + g_.separator_after = g_.separator_after || real_t->hasSeparatorAfter(); + if (g_.reals.size() == 4) { //Same limit than the schematic style + break; + } + } + if (g_.reals.isEmpty()) { + continue; + } + if (g_.width_mm <= 0) { + g_.width_mm = Helpers::referenceTerminalWidthMm(); + } + geometry_.append(g_); + } + return geometry_; +} + +qreal endStopWidthMm(const TerminalStripLayoutPattern &pattern) { + if (!pattern.m_realistic_end_stops) { + return 0; + } + return end_stop_width_mm; +} + +qreal groupMarkerWidthMm(const TerminalStripLayoutPattern &pattern) { + return pattern.m_realistic_group_marker ? group_marker_width_mm : 0; +} + +/** + * @brief fitFont + * Reduce the pixel size of the font of @a painter so that @a text fit in + * @a length (along the text) and @a thickness (across the text). + * The font is never enlarged. + */ +void fitFont(QPainter *painter, const QString &text, qreal length, qreal thickness) +{ + auto font_{painter->font()}; + qreal size_{font_.pixelSize() > 0 ? qreal(font_.pixelSize()) : font_.pointSizeF()}; + const QFontMetricsF metrics_{font_}; + qreal factor_{1}; + if (metrics_.horizontalAdvance(text) > length && length > 0) { + factor_ = std::min(factor_, length / metrics_.horizontalAdvance(text)); + } + if (metrics_.height() > thickness && thickness > 0) { + factor_ = std::min(factor_, thickness / metrics_.height()); + } + if (factor_ < 1) + { + size_ = std::max(2.0, size_ * factor_); + if (font_.pixelSize() > 0) { + font_.setPixelSize(std::max(1, static_cast(size_))); + } else { + font_.setPointSizeF(size_); + } + painter->setFont(font_); + } +} + +/** + * @brief drawVerticalText + * Draw @a text from the bottom to the top, centered in @a rect. + * The font is reduced if needed. + */ +void drawVerticalText(QPainter *painter, const QRectF &rect, const QString &text, const QColor &color) +{ + if (text.isEmpty() || rect.isEmpty()) { + return; + } + painter->save(); + fitFont(painter, text, rect.height() - 2, rect.width() - 1); + painter->setPen(color); + painter->translate(rect.left(), rect.bottom()); + painter->rotate(270); + painter->drawText(QRectF{0, 0, rect.height(), rect.width()}, + Qt::AlignCenter, text); + painter->restore(); +} + +/** + * @brief drawGrip + * Draw a black ribbed grip (end of an end stop). + */ +void drawGrip(QPainter *painter, const QRectF &rect) +{ + painter->save(); + painter->setBrush(end_stop_grip_color); + painter->drawRect(rect); + painter->setPen(QPen(QColor(150, 150, 150), 0)); + const qreal step_{std::max(1.5, rect.height() / 5)}; + for (qreal y = rect.top() + step_ ; y < rect.bottom() - 0.5 ; y += step_) { + painter->drawLine(QPointF{rect.left() + 1, y}, QPointF{rect.right() - 1, y}); + } + painter->restore(); +} + +/** + * @brief drawEndStop + * Draw an end stop seen from above : a light body with a black grip at each end, + * the fixing screw, the key slot and the locking part. + * @param rect : the whole end stop + */ +void drawEndStop(QPainter *painter, const QRectF &rect) +{ + painter->save(); + painter->setBrush(end_stop_color); + painter->drawRect(rect); + + const qreal w_{rect.width()}; + const qreal h_{rect.height()}; + const qreal cx_{rect.center().x()}; + const qreal grip_h_{h_ * 0.08}; + drawGrip(painter, QRectF{rect.left(), rect.top(), w_, grip_h_}); + drawGrip(painter, QRectF{rect.left(), rect.bottom() - grip_h_, w_, grip_h_}); + + //Fixing screw + const qreal screw_r_{std::min(w_ * 0.3, h_ * 0.05)}; + const QPointF screw_c_{cx_, rect.top() + h_ * 0.25}; + painter->setBrush(QColor(60, 60, 60)); + painter->drawEllipse(screw_c_, screw_r_, screw_r_); + painter->setBrush(QColor(20, 20, 20)); + painter->drawEllipse(screw_c_, screw_r_ * 0.65, screw_r_ * 0.65); + + //Key slot : a narrow slot with a wider middle + painter->setBrush(QColor(210, 205, 195)); + const qreal slot_w_{w_ * 0.22}; + painter->drawRoundedRect(QRectF{cx_ - slot_w_ / 2, rect.top() + h_ * 0.36, slot_w_, h_ * 0.26}, 1, 1); + painter->drawRect(QRectF{cx_ - slot_w_, rect.top() + h_ * 0.45, slot_w_ * 2, h_ * 0.06}); + + //Locking part + painter->setBrush(QColor(20, 20, 20)); + const qreal lock_w_{w_ * 0.36}; + painter->drawRect(QRectF{cx_ - lock_w_ / 2, rect.top() + h_ * 0.68, lock_w_, h_ * 0.07}); + painter->drawEllipse(QPointF{cx_, rect.top() + h_ * 0.79}, lock_w_ * 0.35, lock_w_ * 0.35); + + painter->restore(); +} + +/** + * @brief drawSeparator + * Draw a separator plate (partition plate) seen from above : + * a thin plate as long as the terminals, with rounded ends and a light edge. + */ +void drawSeparator(QPainter *painter, const QRectF &rect) +{ + painter->save(); + painter->setPen(QPen(separator_color.darker(170), 0.5)); + painter->setBrush(separator_color); + const qreal r_{std::min(rect.width() / 2, qreal(2.0))}; + painter->drawRoundedRect(rect, r_, r_); + //Light edge, the plate is a bit higher than the terminals + painter->setPen(QPen(separator_color.lighter(118), std::max(0.5, rect.width() * 0.25))); + painter->drawLine(QPointF{rect.left() + rect.width() * 0.35, rect.top() + r_}, + QPointF{rect.left() + rect.width() * 0.35, rect.bottom() - r_}); + painter->restore(); +} + +/** + * @brief drawGroupMarker + * Draw the group marker carrier with the name of the strip on a white label. + */ +void drawGroupMarker(QPainter *painter, const QRectF &rect, const QString &text) +{ + painter->save(); + painter->setBrush(group_marker_color); + painter->drawRect(rect); + + if (!text.isEmpty()) + { + //White label : as long as the text, centered on the carrier + const qreal label_w_{rect.width() * 0.6}; + fitFont(painter, text, rect.height() * 0.8, label_w_ - 2); + const qreal text_len_{QFontMetricsF{painter->font()}.horizontalAdvance(text)}; + const qreal label_h_{std::min(rect.height() * 0.85, text_len_ + label_w_ * 0.6)}; + const QRectF label_{rect.center().x() - label_w_ / 2, + rect.center().y() - label_h_ / 2, + label_w_, label_h_}; + painter->setBrush(Qt::white); + painter->drawRect(label_); + drawVerticalText(painter, label_, text, group_marker_text_color); + } + painter->restore(); +} + +/** + * @brief drawWireEntry + * Draw one wire entry of a terminal. + * Push-in : a black hole. + * Screw : the head of the clamping screw, with the hole of the wire next to it. + * @param center : center of the entry + * @param width : width of the terminal + * @param row_h : height available for the entry + * @param max_r : biggest radius of the entry (a wide terminal don't have a huge hole) + * @param outer : -1 if the end of the terminal is above the entry (top half), +1 if it is under (bottom half) + * @param screw : true for a screw clamp + */ +void drawWireEntry(QPainter *painter, const QPointF ¢er, qreal width, qreal row_h, + qreal max_r, qreal outer, const QColor &fill, bool screw) +{ + painter->save(); + if (!screw) + { + const qreal r_{std::min({width * 0.32, row_h * 0.3, max_r})}; + painter->setBrush(Qt::black); + painter->drawEllipse(center, r_, r_); + } + else + { + //Hole of the wire, toward the end of the terminal + const qreal hole_{std::min({width * 0.45, row_h * 0.22, max_r * 1.6})}; + const qreal hole_y_{outer < 0 ? center.y() - row_h * 0.38 : center.y() + row_h * 0.38 - hole_}; + painter->setBrush(Qt::black); + painter->drawRect(QRectF{center.x() - hole_ / 2, hole_y_, hole_, hole_}); + //Screw head, toward the middle of the terminal + const qreal r_{std::min({width * 0.36, row_h * 0.26, max_r * 1.1})}; + const QPointF c_{center.x(), center.y() - outer * row_h * 0.08}; + painter->setBrush(fill.darker(125)); + painter->drawEllipse(c_, r_ * 1.15, r_ * 1.15); + painter->setBrush(QColor(175, 175, 175)); + painter->drawEllipse(c_, r_, r_); + painter->setPen(QPen(Qt::black, std::max(0.6, r_ * 0.25))); + painter->drawLine(QPointF{c_.x() - r_ * 0.7, c_.y()}, QPointF{c_.x() + r_ * 0.7, c_.y()}); + } + painter->restore(); +} + +/** + * @brief drawEntriesHalf + * Draw the rows of wire entries of one half of a terminal (top or bottom). + * One row by level. Each row have a few ribs at its outer side and a line + * at its inner side, like the real terminals. + * @param outer : y of the outer side of the half (end of the terminal) + * @param inner : y of the inner side of the half (middle band). For the bottom half outer > inner. + * @param max_r : biggest radius of a wire entry + */ +void drawEntriesHalf(QPainter *painter, const QRectF &body, qreal outer, qreal inner, + int levels, qreal max_r, const QColor &fill, bool screw) +{ + const qreal row_h_{(inner - outer) / levels}; //Negative for the bottom half + const qreal abs_row_h_{std::abs(row_h_)}; + const QPen rib_pen_{fill.darker(170), 0}; + + for (int k = 0 ; k < levels ; ++k) + { + const qreal a_{outer + k * row_h_}; + //Ribs + painter->save(); + painter->setPen(rib_pen_); + for (const qreal f_ : {0.12, 0.22, 0.32}) { + const qreal y_{a_ + f_ * row_h_}; + painter->drawLine(QPointF{body.left(), y_}, QPointF{body.right(), y_}); + } + //Limit of the row + if (k > 0) { + painter->drawLine(QPointF{body.left(), a_}, QPointF{body.right(), a_}); + } + painter->restore(); + + drawWireEntry(painter, QPointF{body.center().x(), a_ + 0.67 * row_h_}, + body.width(), abs_row_h_, max_r, row_h_ > 0 ? -1 : 1, fill, screw); + } +} + +/** + * @brief The BridgePoint struct + * Where a bridge is plugged. + */ +struct BridgePoint +{ + QPointF point; + qreal width{0}; +}; + +} //End anonymous namespace + +QRectF boundingRect(const AbstractTerminalStripInterface *strip, + const TerminalStripLayoutPattern &pattern) +{ + qreal width_mm_{2 * endStopWidthMm(pattern) + groupMarkerWidthMm(pattern)}; + for (const auto &g_ : geometry(strip)) { + width_mm_ += g_.width_mm; + if (g_.separator_after) { + width_mm_ += separator_width_mm; + } + } + const qreal s_{pattern.m_realistic_px_per_mm}; + return QRectF{0, 0, width_mm_ * s_, pattern.m_realistic_length_mm * s_}; +} + +void paint(QPainter *painter, + const AbstractTerminalStripInterface &strip, + const TerminalStripLayoutPattern &pattern, + TerminalStripLayoutPattern::DrawStyle style, + bool preview_draw) +{ + const bool screw_{style == TerminalStripLayoutPattern::DrawStyle::RealisticScrew}; + const qreal s_{pattern.m_realistic_px_per_mm}; + const qreal length_{pattern.m_realistic_length_mm * s_}; + if (s_ <= 0 || length_ <= 0) { + return; + } + + painter->save(); + painter->setRenderHint(QPainter::Antialiasing, true); + painter->setFont(pattern.font()); + painter->setPen(QPen(Qt::black, 0.5)); + + if (preview_draw) + { + painter->save(); + painter->setPen(Qt::blue); + painter->setBrush(Qt::NoBrush); + painter->drawRect(boundingRect(&strip, pattern)); + painter->restore(); + } + + qreal x_{0}; + + //The accessories are a bit shorter than the terminals, centered on them + const qreal end_stop_w_{endStopWidthMm(pattern) * s_}; + const qreal end_stop_h_{length_ * 0.88}; + const qreal end_stop_y_{(length_ - end_stop_h_) / 2}; + auto draw_end_stop = [&]() + { + if (end_stop_w_ <= 0) { + return; + } + const QRectF rect_{x_, end_stop_y_, end_stop_w_, end_stop_h_}; + drawEndStop(painter, rect_); + x_ += end_stop_w_; + }; + + draw_end_stop(); + + if (pattern.m_realistic_group_marker) + { + const qreal w_{group_marker_width_mm * s_}; + const qreal h_{length_ * 0.72}; + drawGroupMarker(painter, QRectF{x_, (length_ - h_) / 2, w_, h_}, strip.name()); + x_ += w_; + } + + QHash> bridges_; + + for (const auto &g_ : geometry(&strip)) + { + const qreal w_{g_.width_mm * s_}; + const QRectF body_{x_, 0, w_, length_}; + const auto first_{g_.reals.first()}; + const int levels_{static_cast(g_.reals.size())}; + + QColor fill_, stripe_; + Helpers::terminalColors(first_, fill_, stripe_); + if (!fill_.isValid()) { + fill_ = QColor(150, 150, 150); + } + + //Body + painter->save(); + painter->setPen(QPen(fill_.darker(220), 0.5)); + painter->setBrush(fill_); + painter->drawRect(body_); + if (stripe_.isValid()) + { + //Two-tone terminal (PE) : the stripe color on the left part, like the real ones + painter->setPen(Qt::NoPen); + painter->setBrush(stripe_); + painter->drawRect(QRectF{body_.left(), body_.top(), w_ * 0.6, length_}); + } + painter->restore(); + + //Wire entries : one row by level, at the top and at the bottom + const qreal max_r_{max_entry_radius_mm * s_}; + drawEntriesHalf(painter, body_, length_ * entries_top, length_ * band_top, levels_, max_r_, fill_, screw_); + drawEntriesHalf(painter, body_, length_ * (1 - entries_top), length_ * band_bottom, levels_, max_r_, fill_, screw_); + + //Middle band, with one bridge channel by level + painter->save(); + painter->setPen(Qt::NoPen); + painter->setBrush(band_color); + painter->drawRect(QRectF{x_, length_ * band_top, w_, length_ * (band_bottom - band_top)}); + painter->setBrush(channel_color); + const qreal channel_h_{length_ * (channels_bottom - channels_top) / levels_}; + for (int k = 0 ; k < levels_ ; ++k) { + painter->drawRect(QRectF{x_ + w_ * 0.15, length_ * channels_top + (k + 0.2) * channel_h_, + w_ * 0.7, channel_h_ * 0.6}); + } + painter->restore(); + + //Symbol of the type (fuse, led...), at the bottom of the band + const bool have_symbol_{first_->type() != ElementData::TTGeneric || first_->isLed()}; + const qreal tag_top_{length_ * 0.455}; + const qreal tag_bottom_{length_ * (have_symbol_ ? 0.535 : 0.59)}; + if (have_symbol_) + { + painter->save(); + painter->setPen(QPen(Qt::white, 0.5)); + Helpers::drawTypeSymbol(painter, QRectF{x_, length_ * 0.54, w_, length_ * 0.055}, + first_->type(), first_->isLed()); + painter->restore(); + } + + //Marker tag with the number(s) of the terminal + QStringList numbers_; + for (const auto &real_t : g_.reals) { + numbers_ << Helpers::terminalNumber(real_t->label()); + } + const bool sectional_{first_->type() == ElementData::TTSectional}; + const QRectF tag_{x_ + std::min(0.6 * s_, w_ * 0.12), tag_top_, + w_ - 2 * std::min(0.6 * s_, w_ * 0.12), tag_bottom_ - tag_top_}; + painter->save(); + painter->setPen(QPen(QColor(120, 120, 120), 0.3)); + painter->setBrush(sectional_ ? QColor(Qt::black) : QColor(Qt::white)); + painter->drawRect(tag_); + painter->restore(); + drawVerticalText(painter, tag_, numbers_.join(QStringLiteral(" / ")), + sectional_ ? QColor(Qt::white) : QColor(Qt::black)); + + //Bridge points : one channel by level + for (int k = 0 ; k < levels_ ; ++k) + { + const auto &real_t{g_.reals.at(k)}; + if (!real_t->isBridged()) { + continue; + } + QScopedPointer bridge_{real_t->bridge()}; + if (!bridge_) { + continue; + } + const qreal channel_h_{length_ * (channels_bottom - channels_top) / levels_}; + const qreal y_{length_ * channels_top + (k + 0.5) * channel_h_}; + bridges_[bridge_->uuid()].append(BridgePoint{QPointF{x_ + w_ / 2, y_}, w_}); + } + + x_ += w_; + + //Separator plate after the terminal + if (g_.separator_after) + { + const qreal sep_w_{separator_width_mm * s_}; + drawSeparator(painter, QRectF{x_, 0, sep_w_, length_}); + x_ += sep_w_; + } + } + + //Bridges : a red comb plugged in the channels + for (const auto &points_ : std::as_const(bridges_)) + { + if (points_.size() < 2) { + continue; + } + painter->save(); + const qreal thickness_{std::max(1.0, 0.9 * s_)}; + painter->setPen(QPen(bridge_color, thickness_, Qt::SolidLine, Qt::FlatCap)); + painter->drawLine(points_.first().point, points_.last().point); + painter->setPen(Qt::NoPen); + painter->setBrush(bridge_color.darker(140)); + for (const auto &p_ : points_) { + const qreal r_{std::min(p_.width * 0.18, thickness_ * 0.8)}; + painter->drawEllipse(p_.point, r_, r_); + } + painter->restore(); + } + + draw_end_stop(); + + painter->restore(); +} + +} //End namespace Realistic +} //End namespace TerminalStripDrawer diff --git a/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.h new file mode 100644 index 000000000..97afa0206 --- /dev/null +++ b/sources/TerminalStrip/GraphicsItem/realisticterminalstripdrawer.h @@ -0,0 +1,50 @@ +/* + Copyright 2006-2026 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 REALISTICTERMINALSTRIPDRAWER_H +#define REALISTICTERMINALSTRIPDRAWER_H + +#include "terminalstripdrawer.h" + +class QPainter; + +/** + * Drawing of a terminal strip at scale, seen from above, like the + * mounting drawing of a cabinet. Used by the styles + * RealisticPushIn and RealisticScrew of TerminalStripLayoutPattern. + * + * The strip is drawn from the left to the right : + * end stop, group marker carrier (with the name of the strip), terminals, end stop. + * The width of each terminal is its real width (mm) multiplied by the scale of the layout. + * A terminal with several levels is drawn with one row of wire entries by level, + * at the top and at the bottom. + */ +namespace TerminalStripDrawer +{ + namespace Realistic + { + QRectF boundingRect(const AbstractTerminalStripInterface *strip, + const TerminalStripLayoutPattern &pattern); + void paint(QPainter *painter, + const AbstractTerminalStripInterface &strip, + const TerminalStripLayoutPattern &pattern, + TerminalStripLayoutPattern::DrawStyle style, + bool preview_draw = false); + } +} + +#endif // REALISTICTERMINALSTRIPDRAWER_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp index 789226ab7..cefecbdd2 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.cpp @@ -16,6 +16,8 @@ along with QElectroTech. If not, see . */ #include "terminalstripdrawer.h" +#include "terminalstripdrawerhelpers.h" +#include "realisticterminalstripdrawer.h" #include #include @@ -834,12 +836,51 @@ QColor contrastColor(const QColor &background) } //End anonymous namespace +/* + * Helpers : give to the other drawing styles access to + * the functions of the anonymous namespace. + */ +qreal Helpers::referenceTerminalWidthMm() { + return reference_terminal_width_mm; +} + +void Helpers::terminalColors(const QSharedPointer &real_t, + QColor &fill, QColor &stripe) +{ + const auto colors_{::TerminalStripDrawer::terminalColors(real_t)}; + fill = colors_.fill; + stripe = colors_.stripe; +} + +QColor Helpers::contrastColor(const QColor &background) { + return ::TerminalStripDrawer::contrastColor(background); +} + +QString Helpers::terminalNumber(const QString &label) { + return ::TerminalStripDrawer::terminalNumber(label); +} + +void Helpers::drawTypeSymbol(QPainter *painter, const QRectF &box, + ElementData::TerminalType type, bool led) { + ::TerminalStripDrawer::drawTypeSymbol(painter, box, type, led); +} + /** * @brief TerminalStripDrawer::paint * @param painter */ void TerminalStripDrawer::paint(QPainter *painter) { + if (m_strip && m_pattern && m_draw_style != TerminalStripLayoutPattern::DrawStyle::Schematic) + { + //No xref in the realistic styles + m_united_xref_text_rect = QRectF(); + m_xref_rects.clear(); + m_hovered_xref = hoverTerminal{}; + Realistic::paint(painter, *m_strip, *m_pattern, m_draw_style, m_preview_draw); + return; + } + if (m_strip && m_pattern) { m_united_xref_text_rect = QRectF(); @@ -1195,6 +1236,25 @@ void TerminalStripDrawer::paint(QPainter *painter) painter->translate(terminal_rect.width(),0); x_offset += terminal_rect.width(); } + + //Separator plate after the physical terminal : a thick line + //on the full height of the terminal, after its last level + const bool separator_after_ = std::any_of(real_terminal_vector.cbegin(), real_terminal_vector.cend(), + [](const QSharedPointer &real_t) { + return real_t && real_t->hasSeparatorAfter(); + }); + if (separator_after_ && real_t_count > 0 && offset_ >= 0 && offset_ < 4) + { + const auto &rect_{m_pattern->m_terminal_rect.at(offset_)}; + painter->save(); + QPen separator_pen_{painter->pen()}; + separator_pen_.setColor(Qt::black); + separator_pen_.setWidthF(3); + separator_pen_.setCapStyle(Qt::FlatCap); + painter->setPen(separator_pen_); + painter->drawLine(QPointF{0, rect_.top() - 3}, QPointF{0, rect_.top() + rect_.height() + 3}); + painter->restore(); + } physical_index++; } painter->restore(); @@ -1225,6 +1285,10 @@ void TerminalStripDrawer::paint(QPainter *painter) QRectF TerminalStripDrawer::boundingRect() const { + if (m_pattern && m_draw_style != TerminalStripLayoutPattern::DrawStyle::Schematic) { + return Realistic::boundingRect(m_strip.data(), *m_pattern); + } + QRectF rect_{0, 0, width(), height()}; if (m_pattern) @@ -1292,6 +1356,19 @@ void TerminalStripDrawer::setPreviewDraw(bool draw) { m_preview_draw = draw; } +/** + * @brief TerminalStripDrawer::setDrawStyle + * Set how the terminals are drawn (schematic, realistic...). + * The values used by each style come from the layout. + */ +void TerminalStripDrawer::setDrawStyle(TerminalStripLayoutPattern::DrawStyle style) { + m_draw_style = style; +} + +TerminalStripLayoutPattern::DrawStyle TerminalStripDrawer::drawStyle() const { + return m_draw_style; +} + void TerminalStripDrawer::setMouseHoverPos(const QPointF &pos) { m_last_mouse_pos_in_xrefs_rect = m_united_xref_text_rect.contains(m_mouse_hover_pos); diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h index ca8917e30..04d92cec5 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawer.h @@ -85,6 +85,8 @@ namespace TerminalStripDrawer //Second color of a two-tone color (like green/yellow), drawn as stripes over color() virtual QColor stripeColor() const { return QColor(); } virtual qreal widthMm() const { return 0; } + //A separator plate is mounted after the terminal (drawn by the realistic styles) + virtual bool hasSeparatorAfter() const { return false; } }; class AbstractPhysicalTerminalInterface @@ -121,6 +123,9 @@ namespace TerminalStripDrawer void setPreviewDraw(bool draw = true); + void setDrawStyle(TerminalStripLayoutPattern::DrawStyle style); + TerminalStripLayoutPattern::DrawStyle drawStyle() const; + void setMouseHoverPos(const QPointF &pos); bool mouseHoverXref() const; bool needUpdate(); @@ -135,6 +140,7 @@ namespace TerminalStripDrawer QSharedPointer m_strip; QSharedPointer m_pattern; bool m_preview_draw { false }; + TerminalStripLayoutPattern::DrawStyle m_draw_style { TerminalStripLayoutPattern::DrawStyle::Schematic }; QPointF m_mouse_hover_pos; QRectF m_united_xref_text_rect; bool m_last_mouse_pos_in_xrefs_rect{false}; diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h b/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h new file mode 100644 index 000000000..7cbafd5ea --- /dev/null +++ b/sources/TerminalStrip/GraphicsItem/terminalstripdrawerhelpers.h @@ -0,0 +1,48 @@ +/* + Copyright 2006-2026 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 TERMINALSTRIPDRAWERHELPERS_H +#define TERMINALSTRIPDRAWERHELPERS_H + +#include "terminalstripdrawer.h" + +class QPainter; + +/** + * Functions shared by the drawing styles of a terminal strip + * (schematic style in terminalstripdrawer.cpp, realistic style in realisticterminalstripdrawer.cpp). + */ +namespace TerminalStripDrawer +{ + namespace Helpers + { + //Width (mm) of the reference terminal (2.5 mm2), used when the width of a terminal is unknown + qreal referenceTerminalWidthMm(); + //Fill color and stripe color (can be invalid) of a terminal + void terminalColors(const QSharedPointer &real_t, + QColor &fill, QColor &stripe); + //Black or white, the more readable on background + QColor contrastColor(const QColor &background); + //Number of a terminal : "1" for "XAUZ1:1" + QString terminalNumber(const QString &label); + //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); + } +} + +#endif // TERMINALSTRIPDRAWERHELPERS_H diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp index fc706fc1b..1867b8032 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.cpp @@ -205,6 +205,26 @@ void TerminalStripItem::setLayout(QSharedPointer lay m_drawer.setLayout(layout); } +/** + * @brief TerminalStripItem::setDrawStyle + * Set how this item draw the terminals (schematic, realistic...). + * The style is chosen when the item is added to a folio and saved with the item. + * @param style + */ +void TerminalStripItem::setDrawStyle(TerminalStripLayoutPattern::DrawStyle style) +{ + if (style == m_drawer.drawStyle()) { + return; + } + prepareGeometryChange(); + m_drawer.setDrawStyle(style); + update(); +} + +TerminalStripLayoutPattern::DrawStyle TerminalStripItem::drawStyle() const { + return m_drawer.drawStyle(); +} + void TerminalStripItem::setDefaultLayout() { if (m_strip && m_strip->project()) { diff --git a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h index b5c29c67c..b4cd5d77f 100644 --- a/sources/TerminalStrip/GraphicsItem/terminalstripitem.h +++ b/sources/TerminalStrip/GraphicsItem/terminalstripitem.h @@ -54,6 +54,8 @@ class TerminalStripItem : public QetGraphicsItem void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override; void refreshPending(); void setLayout(QSharedPointer layout); + void setDrawStyle(TerminalStripLayoutPattern::DrawStyle style); + TerminalStripLayoutPattern::DrawStyle drawStyle() const; /** * @brief The PdfRef struct diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp index f96fcc356..8b6e66462 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.cpp @@ -168,6 +168,11 @@ namespace TerminalStripDrawer return m_real ? m_real->widthMm() : 0; } + bool TrueRealTerminal::hasSeparatorAfter() const + { + return m_real ? m_real->hasSeparatorAfter() : false; + } + TrueBridge::TrueBridge(QSharedPointer bridge) : m_bridge { bridge } {} diff --git a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h index 4438eb97f..807a29f4e 100644 --- a/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h +++ b/sources/TerminalStrip/GraphicsItem/trueterminalstrip.h @@ -67,6 +67,7 @@ namespace TerminalStripDrawer QColor color() const override; QColor stripeColor() const override; qreal widthMm() const override; + bool hasSeparatorAfter() const override; private: QSharedPointer m_real; diff --git a/sources/TerminalStrip/realterminal.cpp b/sources/TerminalStrip/realterminal.cpp index 4ad4bcd54..afd308385 100644 --- a/sources/TerminalStrip/realterminal.cpp +++ b/sources/TerminalStrip/realterminal.cpp @@ -264,6 +264,20 @@ qreal RealTerminal::widthMm() const return 0; } +/** + * @brief RealTerminal::hasSeparatorAfter + * @return true if a separator plate (partition plate) is mounted + * after this terminal, between this terminal and the next one of the strip. + * Used to separate groups of terminals (voltages, functions...). + */ +bool RealTerminal::hasSeparatorAfter() const { + if (m_element) { + return QET::infoFlagIsTrue( + m_element->elementData().m_informations.value(separatorInfoKey()).toString()); + } + return false; +} + /** * @brief RealTerminal::conductor * @return diff --git a/sources/TerminalStrip/realterminal.h b/sources/TerminalStrip/realterminal.h index b14969464..5946e707e 100644 --- a/sources/TerminalStrip/realterminal.h +++ b/sources/TerminalStrip/realterminal.h @@ -71,6 +71,7 @@ class RealTerminal QColor stripeColor() const; qreal section() const; qreal widthMm() const; + bool hasSeparatorAfter() const; //Keys used to store the cable data in the element informations static QString cableInfoKey() { return QStringLiteral("terminal_cable"); } @@ -81,6 +82,8 @@ class RealTerminal static QString sectionInfoKey() { return QStringLiteral("terminal_section"); } //Key used to store the width (mm) of the terminal, drawn in the terminal strip static QString widthInfoKey() { return QStringLiteral("terminal_width"); } + //Key used to store if a separator plate is mounted after the terminal + static QString separatorInfoKey() { return QStringLiteral("terminal_separator"); } QString conductor() const; diff --git a/sources/TerminalStrip/ui/addterminalstripitemdialog.cpp b/sources/TerminalStrip/ui/addterminalstripitemdialog.cpp index fe4c77d8b..0c0eb8752 100644 --- a/sources/TerminalStrip/ui/addterminalstripitemdialog.cpp +++ b/sources/TerminalStrip/ui/addterminalstripitemdialog.cpp @@ -24,6 +24,8 @@ #include "../../diagram.h" #include "../../qet.h" + +#include void AddTerminalStripItemDialog::openDialog(Diagram *diagram, QWidget *parent) { AddTerminalStripItemDialog d(diagram->project(), parent); @@ -33,6 +35,7 @@ void AddTerminalStripItemDialog::openDialog(Diagram *diagram, QWidget *parent) if (strip_) { auto item_ = new TerminalStripItem(strip_); + item_->setDrawStyle(static_cast(d.selectedDrawStyle())); diagram->addItem(item_); item_->setPos(50, 50); @@ -77,6 +80,16 @@ TerminalStrip *AddTerminalStripItemDialog::selectedTerminalStrip() const return nullptr; } +/** + * @brief AddTerminalStripItemDialog::selectedDrawStyle + * @return The drawing style chosen for the new item, + * as an int value of TerminalStripLayoutPattern::DrawStyle. + * The index of the combo box is the value of the enum. + */ +int AddTerminalStripItemDialog::selectedDrawStyle() const { + return std::clamp(ui->m_draw_style_cb->currentIndex(), 0, 2); +} + void AddTerminalStripItemDialog::fillComboBox() { if (m_project) diff --git a/sources/TerminalStrip/ui/addterminalstripitemdialog.h b/sources/TerminalStrip/ui/addterminalstripitemdialog.h index 02eb3bd26..0c1c1d36c 100644 --- a/sources/TerminalStrip/ui/addterminalstripitemdialog.h +++ b/sources/TerminalStrip/ui/addterminalstripitemdialog.h @@ -41,6 +41,7 @@ class AddTerminalStripItemDialog : public QDialog explicit AddTerminalStripItemDialog(QETProject *project, QWidget *parent = nullptr); ~AddTerminalStripItemDialog(); TerminalStrip *selectedTerminalStrip() const; + int selectedDrawStyle() const; void fillComboBox(); private: diff --git a/sources/TerminalStrip/ui/addterminalstripitemdialog.ui b/sources/TerminalStrip/ui/addterminalstripitemdialog.ui index f2300f856..f2ac6d61e 100644 --- a/sources/TerminalStrip/ui/addterminalstripitemdialog.ui +++ b/sources/TerminalStrip/ui/addterminalstripitemdialog.ui @@ -24,6 +24,35 @@ + + + + Drawing style : + + + + + + + How the terminals are drawn. The realistic styles draw the strip at scale, seen from above, with the real width of each terminal. + + + + Schematic + + + + + Realistic (push-in) + + + + + Realistic (screw) + + + + diff --git a/sources/TerminalStrip/ui/modelTerminalData.h b/sources/TerminalStrip/ui/modelTerminalData.h index 97ad958ca..7e6d9e2ac 100644 --- a/sources/TerminalStrip/ui/modelTerminalData.h +++ b/sources/TerminalStrip/ui/modelTerminalData.h @@ -38,6 +38,7 @@ struct modelRealTerminalData mrtd.conductor_ = real_t->conductor(); mrtd.led_ = real_t->isLed(); mrtd.shield_ = real_t->isShield(); + mrtd.separator_ = real_t->hasSeparatorAfter(); mrtd.color_ = real_t->color(); mrtd.stripe_color_ = real_t->stripeColor(); mrtd.section_ = real_t->section(); @@ -60,6 +61,7 @@ struct modelRealTerminalData QString conductor_; bool led_ = false; bool shield_ = false; + bool separator_ = false; //A separator plate is mounted after the terminal QColor color_; //Invalid = no color set by the user QColor stripe_color_; //Second color of a two-tone color, invalid if plain qreal section_ = 0; //In mm2, 0 = no section set by the user diff --git a/sources/TerminalStrip/ui/terminalstripeditor.cpp b/sources/TerminalStrip/ui/terminalstripeditor.cpp index ceafd9c33..a31fa46b8 100644 --- a/sources/TerminalStrip/ui/terminalstripeditor.cpp +++ b/sources/TerminalStrip/ui/terminalstripeditor.cpp @@ -222,6 +222,7 @@ void TerminalStripEditor::apply() set_info(RealTerminal::colorInfoKey(), TerminalColor::toSpec(data_.color_, data_.stripe_color_)); set_info(RealTerminal::sectionInfoKey(), data_.section_ > 0 ? QString::number(data_.section_, 'g', 6) : QString()); set_info(RealTerminal::widthInfoKey(), data_.width_mm_ > 0 ? QString::number(data_.width_mm_, 'g', 6) : QString()); + set_info(RealTerminal::separatorInfoKey(), data_.separator_ ? QStringLiteral("true") : QString()); if (element->elementData() != current_data) m_project->undoStack()->push(new ChangeElementDataCommand(element, current_data)); diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp index f67087017..64ab52a35 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.cpp @@ -17,6 +17,8 @@ */ #include +#include + #include "terminalstriplayouteditor.h" #include "ui_terminalstriplayouteditor.h" #include "../GraphicsItem/properties/terminalstriplayoutpattern.h" @@ -33,6 +35,26 @@ TerminalStripLayoutEditor::TerminalStripLayoutEditor(QSharedPointerm_graphics_view->setBackgroundBrush(Qt::white); ui->m_graphics_view->scene()->addItem(&m_preview_strip_item); + + //Drawing style + //The style is chosen for each item when it is added to a folio, + //here it only change the preview, to see the values of each style. + connect(ui->m_draw_style_cb, &QComboBox::currentIndexChanged, this, [this](int index) { + m_preview_strip_item.prepareGeometryChange(); + m_preview_strip_item.m_drawer.setDrawStyle( + static_cast(std::clamp(index, 0, 2))); + m_preview_strip_item.update(); + updatePreview(); + }); + connect(ui->m_realistic_scale_sb, &QDoubleSpinBox::valueChanged, + this, &TerminalStripLayoutEditor::valueEdited); + connect(ui->m_realistic_length_sb, &QSpinBox::valueChanged, + this, &TerminalStripLayoutEditor::valueEdited); + connect(ui->m_realistic_end_stops_cb, &QCheckBox::toggled, + this, &TerminalStripLayoutEditor::valueEdited); + connect(ui->m_realistic_group_marker_cb, &QCheckBox::toggled, + this, &TerminalStripLayoutEditor::valueEdited); + updateUi(); } @@ -159,6 +181,12 @@ void TerminalStripLayoutEditor::valueEdited() m_layout.data()->m_cable_length = ui->m_cable_length_sb->value(); m_layout.data()->m_cable_end_length = ui->m_cable_end_length_sb->value(); + //Values of the realistic styles + m_layout.data()->m_realistic_px_per_mm = ui->m_realistic_scale_sb->value(); + m_layout.data()->m_realistic_length_mm = ui->m_realistic_length_sb->value(); + m_layout.data()->m_realistic_end_stops = ui->m_realistic_end_stops_cb->isChecked(); + m_layout.data()->m_realistic_group_marker = ui->m_realistic_group_marker_cb->isChecked(); + updateUi(); m_preview_strip_item.update(); } @@ -271,6 +299,12 @@ void TerminalStripLayoutEditor::updateUi() ui->m_cable_length_sb->setValue(data->m_cable_length); ui->m_cable_end_length_sb->setValue(data->m_cable_end_length); + //Values of the realistic styles + ui->m_realistic_scale_sb->setValue(data->m_realistic_px_per_mm); + ui->m_realistic_length_sb->setValue(qRound(data->m_realistic_length_mm)); + ui->m_realistic_end_stops_cb->setChecked(data->m_realistic_end_stops); + ui->m_realistic_group_marker_cb->setChecked(data->m_realistic_group_marker); + m_ui_updating = false; updatePreview(); } diff --git a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui index 73b8c3ac9..d44f681c5 100644 --- a/sources/TerminalStrip/ui/terminalstriplayouteditor.ui +++ b/sources/TerminalStrip/ui/terminalstriplayouteditor.ui @@ -540,6 +540,88 @@ + + + + Preview style + + + + + + + Style of the preview only. The style of a terminal strip plan is chosen when it is added to a folio. + + + + Schematic + + + + + Realistic (push-in) + + + + + Realistic (screw) + + + + + + + + Scale (px/mm) / length (mm) + + + + + + + Number of pixels for one millimeter of terminal. + + + 1 + + + 0.5 + + + 50.0 + + + 0.5 + + + + + + + Length of a terminal along the wires, in millimeter. + + + 10 + + + 300 + + + + + + + End stops + + + + + + + Group marker + + + diff --git a/sources/TerminalStrip/ui/terminalstripmodel.cpp b/sources/TerminalStrip/ui/terminalstripmodel.cpp index 029647257..54e5ed8f1 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.cpp +++ b/sources/TerminalStrip/ui/terminalstripmodel.cpp @@ -55,8 +55,9 @@ const int SHIELD_CELL = 14; const int COLOR_CELL = 15; const int SECTION_CELL = 16; const int WIDTH_CELL = 17; +const int SEPARATOR_CELL = 18; -const int COLUMN_COUNT = 18; +const int COLUMN_COUNT = 19; static QVector UNMODIFIED_CELL_VECTOR(COLUMN_COUNT, false); @@ -130,6 +131,7 @@ TerminalStripModel::Column TerminalStripModel::columnTypeForIndex(const QModelIn case 15 : return Color; case 16 : return Section; case 17 : return Width; + case 18 : return Separator; default : return Invalid; } } @@ -236,6 +238,11 @@ QVariant TerminalStripModel::data(const QModelIndex &index, int role) const { return mrtd.shield_ ? Qt::Checked : Qt::Unchecked; } + else if (role == Qt::CheckStateRole && + index.column() == SEPARATOR_CELL) + { + return mrtd.separator_ ? Qt::Checked : Qt::Unchecked; + } else if (role == Qt::BackgroundRole && index.column() < COLUMN_COUNT ) { if (m_modified_cell.contains(mrtd.element_) && @@ -327,6 +334,12 @@ bool TerminalStripModel::setData(const QModelIndex &index, const QVariant &value modified_ = true; modified_cell = SHIELD_CELL; } + else if (column_ == SEPARATOR_CELL) + { + mrtd.separator_ = value.toBool(); + modified_ = true; + modified_cell = SEPARATOR_CELL; + } else if (column_ == COLOR_CELL && role == Qt::EditRole) { @@ -417,6 +430,7 @@ QVariant TerminalStripModel::headerData(int section, Qt::Orientation orientation case COLOR_CELL: return tr("Color"); case SECTION_CELL: return tr("Section (mm²)"); case WIDTH_CELL: return tr("Width (mm)"); + case SEPARATOR_CELL: return tr("Separator plate after"); default : return QVariant(); } } @@ -434,7 +448,7 @@ Qt::ItemFlags TerminalStripModel::flags(const QModelIndex &index) const || c == CABLE_CELL || c == CABLE_WIRE_CELL || c == COLOR_CELL || c == SECTION_CELL || c == WIDTH_CELL) flags = flags | Qt::ItemIsEditable; - if (c == LED_CELL || c == SHIELD_CELL) { + if (c == LED_CELL || c == SHIELD_CELL || c == SEPARATOR_CELL) { flags = flags | Qt::ItemIsUserCheckable; } return flags; diff --git a/sources/TerminalStrip/ui/terminalstripmodel.h b/sources/TerminalStrip/ui/terminalstripmodel.h index 1a1f89fc5..8c2b48fb0 100644 --- a/sources/TerminalStrip/ui/terminalstripmodel.h +++ b/sources/TerminalStrip/ui/terminalstripmodel.h @@ -65,6 +65,7 @@ class TerminalStripModel : public QAbstractTableModel Color = 15, Section = 16, Width = 17, + Separator = 18, Invalid = 99 }; diff --git a/sources/xml/terminalstripitemxml.cpp b/sources/xml/terminalstripitemxml.cpp index 0b0290f51..0f9087d39 100644 --- a/sources/xml/terminalstripitemxml.cpp +++ b/sources/xml/terminalstripitemxml.cpp @@ -95,6 +95,12 @@ QDomElement TerminalStripItemXml::toXml(TerminalStripItem *item, QDomDocument &d dom_element.appendChild(QETXML::qGraphicsItemPosToXml(item, document)); + //Drawing style of the item, not saved for the default (schematic) style + if (item->drawStyle() != TerminalStripLayoutPattern::DrawStyle::Schematic) { + dom_element.setAttribute(QStringLiteral("draw_style"), + TerminalStripLayoutPattern::drawStyleToString(item->drawStyle())); + } + return dom_element; } else { return QDomElement(); @@ -134,6 +140,11 @@ bool TerminalStripItemXml::fromXml(TerminalStripItem *item, QETProject *project, bool b{QETXML::qGraphicsItemPosFromXml(item, xml_elmt.firstChildElement(QStringLiteral("pos")))}; + //Item saved before the drawing styles : no attribute, schematic style + item->setDrawStyle(TerminalStripLayoutPattern::drawStyleFromString( + xml_elmt.attribute(QStringLiteral("draw_style")), + TerminalStripLayoutPattern::DrawStyle::Schematic)); + return (a && b); } return false;