mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-19 20:44:16 +02:00
Merge master (0b0c20fdb: realistic drawer in the CMake sources) into fix/terminal-orientation-empty
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XCdg2Er2vYhB8Vwa5G7fSR
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -0,0 +1,791 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "realisticterminalstripdrawer.h"
|
||||
#include "terminalstripdrawerhelpers.h"
|
||||
|
||||
#include <QFontMetricsF>
|
||||
#include <QHash>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPair>
|
||||
#include <QScopedPointer>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
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};
|
||||
const QColor fuse_holder_color{38, 38, 40};
|
||||
const QColor knife_color{240, 120, 0};
|
||||
const QColor led_color{220, 20, 20};
|
||||
|
||||
/**
|
||||
* @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<QSharedPointer<AbstractRealTerminalInterface>> reals;
|
||||
//Index of the physical terminal in the strip, and of each real terminal
|
||||
//in the physical terminal : the same indexes than the schematic style,
|
||||
//used to find the element of a clicked terminal.
|
||||
int physical_index{-1};
|
||||
QVector<int> real_indexes;
|
||||
};
|
||||
|
||||
/**
|
||||
* @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<PhysicalGeometry> geometry(const AbstractTerminalStripInterface *strip)
|
||||
{
|
||||
QVector<PhysicalGeometry> geometry_;
|
||||
if (!strip) {
|
||||
return geometry_;
|
||||
}
|
||||
|
||||
int physical_index_{-1};
|
||||
for (const auto &physical_t : strip->physicalTerminal())
|
||||
{
|
||||
++physical_index_;
|
||||
if (!physical_t) {
|
||||
continue;
|
||||
}
|
||||
PhysicalGeometry g_;
|
||||
g_.physical_index = physical_index_;
|
||||
int real_index_{-1};
|
||||
for (const auto &real_t : physical_t->realTerminals())
|
||||
{
|
||||
++real_index_;
|
||||
if (!real_t) {
|
||||
continue;
|
||||
}
|
||||
g_.reals.append(real_t);
|
||||
g_.real_indexes.append(real_index_);
|
||||
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<qreal>(2.0, size_ * factor_);
|
||||
if (font_.pixelSize() > 0) {
|
||||
font_.setPixelSize(std::max(1, static_cast<int>(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<qreal>(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 leverZone
|
||||
* Vertical zone (in fraction of the length of the terminal) of the lever of a
|
||||
* fuse terminal or of the knife of a disconnect terminal, centered on the middle
|
||||
* band. For a terminal with one level, the lever goes from a wire entry to the other
|
||||
* (a bit shorter with screw clamps, whose screw heads are nearer the middle),
|
||||
* for a terminal with levels it stay on the middle band, between the wire entries.
|
||||
*/
|
||||
QPair<qreal, qreal> leverZone(int levels, bool screw)
|
||||
{
|
||||
if (levels > 1) {
|
||||
return qMakePair(qreal(0.395), qreal(0.605));
|
||||
}
|
||||
return screw ? qMakePair(qreal(0.345), qreal(0.655))
|
||||
: qMakePair(qreal(0.315), qreal(0.685));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief drawFuseHolder
|
||||
* Draw the hinged fuse holder of a fuse terminal, seen from above : a black lever
|
||||
* on the middle of the terminal with its hinge pin, a window on the fuse,
|
||||
* a ribbed grip at the other end and, for a fuse with led, the led.
|
||||
* The marker tag and the symbol are drawn after, on the lever.
|
||||
* @param x : left of the terminal
|
||||
* @param w : width of the terminal
|
||||
* @param length : length of the terminal
|
||||
*/
|
||||
void drawFuseHolder(QPainter *painter, qreal x, qreal w, qreal length, int levels, bool screw, bool led)
|
||||
{
|
||||
const auto zone_{leverZone(levels, screw)};
|
||||
const qreal top_{length * zone_.first};
|
||||
const qreal bottom_{length * zone_.second};
|
||||
const qreal inset_{w * 0.08};
|
||||
const QRectF lever_{x + inset_, top_, w - 2 * inset_, bottom_ - top_};
|
||||
const qreal cx_{x + w / 2};
|
||||
|
||||
painter->save();
|
||||
painter->setPen(QPen(Qt::black, 0.5));
|
||||
painter->setBrush(fuse_holder_color);
|
||||
painter->drawRoundedRect(lever_, w * 0.12, w * 0.12);
|
||||
|
||||
//Hinge pin
|
||||
const qreal pin_r_{w * 0.12};
|
||||
painter->setPen(QPen(QColor(90, 90, 90), 0.4));
|
||||
painter->setBrush(QColor(150, 150, 150));
|
||||
painter->drawEllipse(QPointF{cx_, top_ + pin_r_ * 2}, pin_r_, pin_r_);
|
||||
|
||||
//Window on the fuse, under the hinge pin and above the marker tag,
|
||||
//only when there is enough room
|
||||
const qreal window_top_{std::max(length * 0.38, top_ + pin_r_ * 3.4)};
|
||||
const qreal window_bottom_{length * 0.445};
|
||||
if (levels == 1 && window_bottom_ - window_top_ > length * 0.03)
|
||||
{
|
||||
painter->setPen(QPen(QColor(110, 110, 110), 0.4));
|
||||
painter->setBrush(QColor(205, 205, 200));
|
||||
painter->drawRoundedRect(QRectF{cx_ - w * 0.25, window_top_, w * 0.5, window_bottom_ - window_top_}, 1, 1);
|
||||
//The fuse in the window
|
||||
painter->setPen(QPen(QColor(120, 90, 40), std::max<qreal>(0.5, w * 0.08)));
|
||||
const qreal margin_{(window_bottom_ - window_top_) * 0.1};
|
||||
painter->drawLine(QPointF{cx_, window_top_ + margin_}, QPointF{cx_, window_bottom_ - margin_});
|
||||
}
|
||||
|
||||
//Ribbed grip at the other end
|
||||
painter->setPen(QPen(QColor(110, 110, 110), 0.4));
|
||||
const qreal grip_top_{bottom_ - (bottom_ - top_) * 0.13};
|
||||
for (int i = 0 ; i < 3 ; ++i) {
|
||||
const qreal y_{grip_top_ + i * (bottom_ - grip_top_) / 3};
|
||||
painter->drawLine(QPointF{lever_.left() + w * 0.12, y_}, QPointF{lever_.right() - w * 0.12, y_});
|
||||
}
|
||||
|
||||
//Led : lit when the fuse is blown. Between the type symbol
|
||||
//(bottom of the middle band) and the grip, whatever the length of the lever.
|
||||
const qreal symbol_bottom_{length * 0.595};
|
||||
if (led && grip_top_ > symbol_bottom_)
|
||||
{
|
||||
const qreal led_r_{std::min({w * 0.13, length * 0.012, (grip_top_ - symbol_bottom_) * 0.45})};
|
||||
painter->setPen(QPen(led_color.darker(160), 0.4));
|
||||
painter->setBrush(led_color);
|
||||
painter->drawEllipse(QPointF{cx_, (symbol_bottom_ + grip_top_) / 2}, led_r_, led_r_);
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief drawDisconnectKnife
|
||||
* Draw the orange knife of a disconnect terminal, seen from above :
|
||||
* a narrow lever on the middle of the terminal with its hinge and its grip.
|
||||
*/
|
||||
void drawDisconnectKnife(QPainter *painter, qreal x, qreal w, qreal length, int levels, bool screw)
|
||||
{
|
||||
const auto zone_{leverZone(levels, screw)};
|
||||
const qreal top_{length * zone_.first};
|
||||
const qreal bottom_{length * zone_.second};
|
||||
const qreal cx_{x + w / 2};
|
||||
const qreal knife_w_{w * 0.56};
|
||||
|
||||
painter->save();
|
||||
painter->setPen(QPen(knife_color.darker(170), 0.5));
|
||||
painter->setBrush(knife_color);
|
||||
painter->drawRoundedRect(QRectF{cx_ - knife_w_ / 2, top_, knife_w_, bottom_ - top_},
|
||||
knife_w_ * 0.3, knife_w_ * 0.3);
|
||||
|
||||
//Hinge
|
||||
const qreal pin_r_{knife_w_ * 0.22};
|
||||
painter->setBrush(knife_color.darker(150));
|
||||
painter->drawEllipse(QPointF{cx_, top_ + pin_r_ * 2}, pin_r_, pin_r_);
|
||||
|
||||
//Grip
|
||||
painter->setPen(QPen(knife_color.darker(190), 0.5));
|
||||
const qreal grip_top_{bottom_ - (bottom_ - top_) * 0.12};
|
||||
for (int i = 0 ; i < 3 ; ++i) {
|
||||
const qreal y_{grip_top_ + i * (bottom_ - grip_top_) / 3};
|
||||
painter->drawLine(QPointF{cx_ - knife_w_ * 0.3, y_}, QPointF{cx_ + knife_w_ * 0.3, y_});
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief drawTestSockets
|
||||
* Draw the two test sockets of a test terminal : a brass ring with a black hole.
|
||||
* For a terminal with one level they are between the wire entries and the middle band,
|
||||
* for a terminal with levels (no room between the entries) they are in the middle band,
|
||||
* in place of the bridge channels and of the type symbol.
|
||||
*/
|
||||
void drawTestSockets(QPainter *painter, qreal x, qreal w, qreal length, qreal s, int levels, bool screw, const QColor &fill)
|
||||
{
|
||||
const qreal r_{std::min({w * 0.22, 1.2 * s, length * 0.018})};
|
||||
const qreal offset_{levels > 1 ? 0.425 : (screw ? 0.37 : 0.355)};
|
||||
painter->save();
|
||||
for (const qreal f_ : {offset_, 1 - offset_})
|
||||
{
|
||||
const QPointF c_{x + w / 2, length * f_};
|
||||
painter->setPen(QPen(fill.darker(200), 0.4));
|
||||
painter->setBrush(QColor(200, 170, 60)); //Brass
|
||||
painter->drawEllipse(c_, r_, r_);
|
||||
painter->setPen(Qt::NoPen);
|
||||
painter->setBrush(Qt::black);
|
||||
painter->drawEllipse(c_, r_ * 0.55, r_ * 0.55);
|
||||
}
|
||||
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<qreal>(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<qreal>(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 QPointF &hover_pos,
|
||||
QVector<XrefRect> *xref_rects)
|
||||
{
|
||||
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<QUuid, QVector<BridgePoint>> 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<int>(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();
|
||||
|
||||
//Specific parts of some types of terminal
|
||||
const auto type_{first_->type()};
|
||||
switch (type_)
|
||||
{
|
||||
case ElementData::TTFuse:
|
||||
drawFuseHolder(painter, x_, w_, length_, levels_, screw_, first_->isLed());
|
||||
break;
|
||||
case ElementData::TTSectional:
|
||||
drawDisconnectKnife(painter, x_, w_, length_, levels_, screw_);
|
||||
break;
|
||||
case ElementData::TTTestSocket:
|
||||
drawTestSockets(painter, x_, w_, length_, s_, levels_, screw_, fill_);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
//Symbol of the type (fuse, led...), at the bottom of the band
|
||||
//A test terminal with levels have its test sockets in place of the symbol
|
||||
const bool have_symbol_{(first_->type() != ElementData::TTGeneric || first_->isLed())
|
||||
&& !(type_ == ElementData::TTTestSocket && levels_ > 1)};
|
||||
const qreal tag_top_{length_ * 0.455};
|
||||
const bool sockets_in_band_{type_ == ElementData::TTTestSocket && levels_ > 1};
|
||||
const qreal tag_bottom_{length_ * (have_symbol_ || sockets_in_band_ ? 0.535 : 0.59)};
|
||||
if (have_symbol_)
|
||||
{
|
||||
painter->save();
|
||||
//Black on the orange knife, white on the dark band and on the fuse holder
|
||||
painter->setPen(QPen(type_ == ElementData::TTSectional ? QColor(Qt::black) : QColor(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));
|
||||
|
||||
//Clickable zones : the whole terminal for a terminal with one level,
|
||||
//the rows of wire entries of the level (top and bottom) for a terminal with levels.
|
||||
//Only the terminals with an xref (element placed on a folio) are clickable.
|
||||
QVector<XrefRect> terminal_rects_;
|
||||
for (int k = 0 ; k < levels_ ; ++k)
|
||||
{
|
||||
if (g_.reals.at(k)->xref().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
const int physical_{g_.physical_index};
|
||||
const int real_{g_.real_indexes.at(k)};
|
||||
if (levels_ == 1) {
|
||||
terminal_rects_.append({body_, physical_, real_});
|
||||
} else {
|
||||
const qreal top_h_{length_ * (band_top - entries_top) / levels_};
|
||||
terminal_rects_.append({QRectF{x_, length_ * entries_top + k * top_h_, w_, top_h_}, physical_, real_});
|
||||
terminal_rects_.append({QRectF{x_, length_ * (1 - entries_top) - (k + 1) * top_h_, w_, top_h_}, physical_, real_});
|
||||
}
|
||||
}
|
||||
if (xref_rects) {
|
||||
*xref_rects << terminal_rects_;
|
||||
}
|
||||
|
||||
//Highlight the terminal under the mouse, like the xref of the schematic style
|
||||
if (!hover_pos.isNull())
|
||||
{
|
||||
int hovered_real_{-1};
|
||||
for (const auto &r_ : std::as_const(terminal_rects_)) {
|
||||
if (r_.rect.contains(hover_pos)) {
|
||||
hovered_real_ = r_.real;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (hovered_real_ >= 0)
|
||||
{
|
||||
painter->save();
|
||||
painter->setPen(QPen(QColor(0, 90, 255), std::max<qreal>(1.0, 0.4 * s_)));
|
||||
painter->setBrush(Qt::NoBrush);
|
||||
for (const auto &r_ : std::as_const(terminal_rects_)) {
|
||||
if (r_.real == hovered_real_) {
|
||||
painter->drawRect(r_.rect.adjusted(0.5, 0.5, -0.5, -0.5));
|
||||
}
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
//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<AbstractBridgeInterface> 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<qreal>(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
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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.
|
||||
*
|
||||
* paint() fill @a xref_rects with the zone of each terminal which have an xref,
|
||||
* with the same indexes than the schematic style : the item use them to go to the
|
||||
* element on double click, to show the xref in a tool tip and to make clickable
|
||||
* links in an exported PDF. The terminal under @a hover_pos is outlined in blue.
|
||||
*/
|
||||
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,
|
||||
const QPointF &hover_pos = QPointF(),
|
||||
QVector<XrefRect> *xref_rects = nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // REALISTICTERMINALSTRIPDRAWER_H
|
||||
@@ -16,6 +16,8 @@
|
||||
along with QElectroTech. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "terminalstripdrawer.h"
|
||||
#include "terminalstripdrawerhelpers.h"
|
||||
#include "realisticterminalstripdrawer.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QPolygonF>
|
||||
@@ -834,12 +836,64 @@ 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<AbstractRealTerminalInterface> &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)
|
||||
{
|
||||
//The realistic styles don't write the xrefs, but each terminal
|
||||
//is a clickable zone, like the xref text of the schematic style.
|
||||
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,
|
||||
m_mouse_hover_pos, &m_xref_rects);
|
||||
for (const auto &xref_rect : std::as_const(m_xref_rects))
|
||||
{
|
||||
m_united_xref_text_rect = m_united_xref_text_rect.isNull() ?
|
||||
xref_rect.rect :
|
||||
m_united_xref_text_rect.united(xref_rect.rect);
|
||||
if (m_hovered_xref.physical < 0 && !m_mouse_hover_pos.isNull()
|
||||
&& xref_rect.rect.contains(m_mouse_hover_pos)) {
|
||||
m_hovered_xref.physical = xref_rect.physical;
|
||||
m_hovered_xref.real = xref_rect.real;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_strip && m_pattern)
|
||||
{
|
||||
m_united_xref_text_rect = QRectF();
|
||||
@@ -1195,6 +1249,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<AbstractRealTerminalInterface> &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 +1298,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 +1369,35 @@ 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TerminalStripDrawer::xrefAt
|
||||
* @param pos : position in the coordinates of the item
|
||||
* @return the physical and real index of the terminal whose xref zone
|
||||
* (drawn by the last call of paint()) contains @a pos, or -1 if none.
|
||||
*/
|
||||
hoverTerminal TerminalStripDrawer::xrefAt(const QPointF &pos) const
|
||||
{
|
||||
for (const auto &xref_rect : m_xref_rects) {
|
||||
if (xref_rect.rect.contains(pos)) {
|
||||
return hoverTerminal{xref_rect.physical, xref_rect.real};
|
||||
}
|
||||
}
|
||||
return hoverTerminal{};
|
||||
}
|
||||
|
||||
void TerminalStripDrawer::setMouseHoverPos(const QPointF &pos)
|
||||
{
|
||||
m_last_mouse_pos_in_xrefs_rect = m_united_xref_text_rect.contains(m_mouse_hover_pos);
|
||||
|
||||
@@ -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,10 +123,14 @@ 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();
|
||||
hoverTerminal hoveredXref() const;
|
||||
hoverTerminal xrefAt(const QPointF &pos) const;
|
||||
QVector<XrefRect> xrefRects() const;
|
||||
|
||||
private:
|
||||
@@ -135,6 +141,7 @@ namespace TerminalStripDrawer
|
||||
QSharedPointer <AbstractTerminalStripInterface> m_strip;
|
||||
QSharedPointer<TerminalStripLayoutPattern> 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};
|
||||
|
||||
@@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#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<AbstractRealTerminalInterface> &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
|
||||
@@ -142,12 +142,43 @@ void TerminalStripItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
|
||||
if (m_drawer.needUpdate()) {
|
||||
update();
|
||||
}
|
||||
|
||||
//The realistic styles don't write the xref : show it in a tool tip
|
||||
if (m_drawer.drawStyle() != TerminalStripLayoutPattern::DrawStyle::Schematic) {
|
||||
setToolTip(xrefToolTip(m_drawer.xrefAt(hoverMousePos())));
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalStripItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
|
||||
{
|
||||
QetGraphicsItem::hoverLeaveEvent(event);
|
||||
m_drawer.setMouseHoverPos(QPointF{});
|
||||
setToolTip(QString());
|
||||
//Remove the highlight of the xref (or of the terminal) under the mouse
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TerminalStripItem::xrefToolTip
|
||||
* @param terminal : physical and real index of a terminal of the strip
|
||||
* @return the text of the tool tip of @a terminal : its label and its xref,
|
||||
* or an empty string if @a terminal is invalid.
|
||||
*/
|
||||
QString TerminalStripItem::xrefToolTip(const TerminalStripDrawer::hoverTerminal &terminal) const
|
||||
{
|
||||
if (!m_strip || terminal.physical < 0 || terminal.real < 0) {
|
||||
return QString();
|
||||
}
|
||||
const auto physical_terminal{m_strip->physicalTerminal(terminal.physical)};
|
||||
if (physical_terminal.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
const auto real_terminal{physical_terminal->realTerminal(terminal.real)};
|
||||
if (real_terminal.isNull() || real_terminal->Xref().isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
return tr("%1 : %2\nDouble-click to go to the element")
|
||||
.arg(real_terminal->label(), real_terminal->Xref());
|
||||
}
|
||||
|
||||
void TerminalStripItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
||||
@@ -205,6 +236,26 @@ void TerminalStripItem::setLayout(QSharedPointer<TerminalStripLayoutPattern> 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()) {
|
||||
|
||||
@@ -54,6 +54,8 @@ class TerminalStripItem : public QetGraphicsItem
|
||||
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) override;
|
||||
void refreshPending();
|
||||
void setLayout(QSharedPointer<TerminalStripLayoutPattern> layout);
|
||||
void setDrawStyle(TerminalStripLayoutPattern::DrawStyle style);
|
||||
TerminalStripLayoutPattern::DrawStyle drawStyle() const;
|
||||
|
||||
/**
|
||||
* @brief The PdfRef struct
|
||||
@@ -73,6 +75,7 @@ class TerminalStripItem : public QetGraphicsItem
|
||||
|
||||
private:
|
||||
void setDefaultLayout();
|
||||
QString xrefToolTip(const TerminalStripDrawer::hoverTerminal &terminal) const;
|
||||
|
||||
private:
|
||||
QPointer<TerminalStrip> m_strip;
|
||||
|
||||
@@ -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<TerminalStripBridge> bridge) :
|
||||
m_bridge { bridge }
|
||||
{}
|
||||
|
||||
@@ -67,6 +67,7 @@ namespace TerminalStripDrawer
|
||||
QColor color() const override;
|
||||
QColor stripeColor() const override;
|
||||
qreal widthMm() const override;
|
||||
bool hasSeparatorAfter() const override;
|
||||
|
||||
private:
|
||||
QSharedPointer<RealTerminal> m_real;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include "../../diagram.h"
|
||||
|
||||
#include "../../qet.h"
|
||||
|
||||
#include <algorithm>
|
||||
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<TerminalStripLayoutPattern::DrawStyle>(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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -24,6 +24,35 @@
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_terminal_strip_cb"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_draw_style">
|
||||
<property name="text">
|
||||
<string>Drawing style :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="m_draw_style_cb">
|
||||
<property name="toolTip">
|
||||
<string>How the terminals are drawn. The realistic styles draw the strip at scale, seen from above, with the real width of each terminal.</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Schematic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Realistic (push-in)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Realistic (screw)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
*/
|
||||
#include <QFontDialog>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "terminalstriplayouteditor.h"
|
||||
#include "ui_terminalstriplayouteditor.h"
|
||||
#include "../GraphicsItem/properties/terminalstriplayoutpattern.h"
|
||||
@@ -33,6 +35,26 @@ TerminalStripLayoutEditor::TerminalStripLayoutEditor(QSharedPointer<TerminalStri
|
||||
// the application palette.
|
||||
ui->m_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<TerminalStripLayoutPattern::DrawStyle>(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();
|
||||
}
|
||||
|
||||
@@ -540,6 +540,88 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="2">
|
||||
<widget class="QLabel" name="label_draw_style">
|
||||
<property name="text">
|
||||
<string>Preview style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="3" colspan="2">
|
||||
<widget class="QComboBox" name="m_draw_style_cb">
|
||||
<property name="toolTip">
|
||||
<string>Style of the preview only. The style of a terminal strip plan is chosen when it is added to a folio.</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Schematic</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Realistic (push-in)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Realistic (screw)</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="2">
|
||||
<widget class="QLabel" name="label_realistic_scale">
|
||||
<property name="text">
|
||||
<string>Scale (px/mm) / length (mm)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="3">
|
||||
<widget class="QDoubleSpinBox" name="m_realistic_scale_sb">
|
||||
<property name="toolTip">
|
||||
<string>Number of pixels for one millimeter of terminal.</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.5</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>50.0</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.5</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="12" column="4">
|
||||
<widget class="QSpinBox" name="m_realistic_length_sb">
|
||||
<property name="toolTip">
|
||||
<string>Length of a terminal along the wires, in millimeter.</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>300</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="3">
|
||||
<widget class="QCheckBox" name="m_realistic_end_stops_cb">
|
||||
<property name="text">
|
||||
<string>End stops</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="13" column="4">
|
||||
<widget class="QCheckBox" name="m_realistic_group_marker_cb">
|
||||
<property name="text">
|
||||
<string>Group marker</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -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<bool> 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;
|
||||
|
||||
@@ -65,6 +65,7 @@ class TerminalStripModel : public QAbstractTableModel
|
||||
Color = 15,
|
||||
Section = 16,
|
||||
Width = 17,
|
||||
Separator = 18,
|
||||
Invalid = 99
|
||||
};
|
||||
|
||||
|
||||
@@ -395,9 +395,6 @@ void GeneralConfigurationPage::applyConf()
|
||||
if (!ui->m_live_assistant->isChecked()) LiveServer::instance().stop();
|
||||
#endif
|
||||
}
|
||||
//What an assistant reads about this QElectroTech follows the change
|
||||
AssistantInfo::write();
|
||||
|
||||
//GENERIC PANEL
|
||||
settings.setValue("genericpanel/folio",ui->m_use_folio_label->isChecked());
|
||||
|
||||
@@ -565,6 +562,12 @@ void GeneralConfigurationPage::applyConf()
|
||||
diagram->update();
|
||||
}
|
||||
}
|
||||
|
||||
//What an assistant reads about this QElectroTech follows the
|
||||
//change. Written last: the collection and title block paths are
|
||||
//applied above, and an assistant launching a headless run takes
|
||||
//the user and company collections from this file.
|
||||
AssistantInfo::write();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user