mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-23 23:44:13 +02:00
Merge M10+M9a: name the cable target, keep wire numbers out
# Conflicts: # sources/TerminalStrip/realterminal.cpp # tests/qttest/CMakeLists.txt
This commit is contained in:
@@ -270,14 +270,18 @@ struct CableCell
|
||||
QString cable; ///< name of the cable (hose)
|
||||
QString wire; ///< color / number of the wire
|
||||
bool shield{false}; ///< true if the terminal is the shield of the cable
|
||||
QSharedPointer<AbstractRealTerminalInterface> terminal; ///< to ask where the cable goes
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief drawCables
|
||||
* Draw the cables under the terminals. Consecutive terminals who have the same cable name
|
||||
* share the same cable: the wires go down from the terminals, join in the cable,
|
||||
* and leave the cable with the same wire marks. The shield is linked to a dashed ellipse
|
||||
* drawn around the cable.
|
||||
* share the same cable: the wires go down from the terminals and join in the cable.
|
||||
* The cable ends together -- a short stub, then a box naming where the cable goes
|
||||
* (Installation, Location and Label of the piece it lands on). It does not fan out
|
||||
* again after the cable: the wires drawn there suggested each core went its own way
|
||||
* towards the target, which said nothing about where that target is.
|
||||
* The shield is linked to a dashed ellipse drawn around the cable.
|
||||
* @param painter : the pen and the font must be set
|
||||
* @param cells : one cell per terminal, in the drawing order
|
||||
* @param pattern
|
||||
@@ -295,19 +299,45 @@ void drawCables(QPainter *painter, const QVector<CableCell> &cells, const Termin
|
||||
const qreal text_height{font_metrics.height()};
|
||||
|
||||
//Draw a mark (small oblique line) on a wire and the number of the wire next to it.
|
||||
//The text is written from the bottom to the top, at the left of the wire.
|
||||
const auto draw_wire_mark = [&](qreal x, qreal mark_y, const QString &text, bool text_above)
|
||||
//The text is written from the bottom to the top, at the left of the wire, starting
|
||||
//above the mark and running towards the terminal: the font shrinks while the text
|
||||
//is longer than the room left between the mark and the terminal, and what still
|
||||
//does not fit is clipped away, so a long number never runs into the drawing of
|
||||
//the terminal. The room left is @a terminal_bottom the bottom of that terminal.
|
||||
const auto draw_wire_mark = [&](qreal x, qreal mark_y, qreal terminal_bottom, const QString &text)
|
||||
{
|
||||
painter->drawLine(QPointF{x - 3, mark_y + 3}, QPointF{x + 3, mark_y - 3});
|
||||
if (text.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal text_width{font_metrics.horizontalAdvance(text)};
|
||||
//Room left between the mark and the terminal
|
||||
const qreal room{mark_y - 4 - (terminal_bottom + 2)};
|
||||
if (room <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
QFont text_font{painter->font()};
|
||||
if (text_font.pixelSize() <= 0 && text_font.pointSizeF() > 0) {
|
||||
text_font.setPixelSize(qMax(4, qRound(text_font.pointSizeF() * 96.0 / 72.0)));
|
||||
}
|
||||
while (QFontMetricsF{text_font}.horizontalAdvance(text) > room &&
|
||||
text_font.pixelSize() > 4) {
|
||||
text_font.setPixelSize(text_font.pixelSize() - 1);
|
||||
}
|
||||
|
||||
const QFontMetricsF fitted_metrics{text_font};
|
||||
const qreal fitted_width{fitted_metrics.horizontalAdvance(text)};
|
||||
const qreal fitted_height{fitted_metrics.height()};
|
||||
painter->save();
|
||||
painter->translate(x - 1, text_above ? mark_y - 4 : mark_y + 4 + text_width);
|
||||
painter->setFont(text_font);
|
||||
//The clip keeps the text under the terminal even when a number is
|
||||
//so long that the smallest font does not fit it any more
|
||||
painter->setClipRect(QRectF{x - 1 - fitted_height, terminal_bottom + 2,
|
||||
fitted_height + 1, room});
|
||||
painter->translate(x - 1, mark_y - 4);
|
||||
painter->rotate(270);
|
||||
painter->drawText(QRectF{0, -text_height, text_width + 2, text_height},
|
||||
painter->drawText(QRectF{0, -fitted_height, fitted_width + 2, fitted_height},
|
||||
Qt::AlignLeft | Qt::AlignVCenter,
|
||||
text);
|
||||
painter->restore();
|
||||
@@ -350,25 +380,63 @@ void drawCables(QPainter *painter, const QVector<CableCell> &cells, const Termin
|
||||
const qreal cable_x{(min_x + max_x) / 2};
|
||||
const qreal bar_1_y{max_bottom + wire_length};
|
||||
const qreal bar_2_y{bar_1_y + cable_length};
|
||||
const qreal end_y{bar_2_y + end_length};
|
||||
|
||||
//Wires between the terminals and the cable
|
||||
for (const auto &wire : std::as_const(wires))
|
||||
{
|
||||
painter->drawLine(QPointF{wire.x, wire.bottom}, QPointF{wire.x, bar_1_y});
|
||||
draw_wire_mark(wire.x, qMax(wire.bottom + 4, bar_1_y - 10), wire.wire, true);
|
||||
draw_wire_mark(wire.x, qMax(wire.bottom + 4, bar_1_y - 10), wire.bottom, wire.wire);
|
||||
}
|
||||
painter->drawLine(QPointF{min_x, bar_1_y}, QPointF{max_x, bar_1_y});
|
||||
|
||||
//The cable
|
||||
painter->drawLine(QPointF{cable_x, bar_1_y}, QPointF{cable_x, bar_2_y});
|
||||
|
||||
//Wires after the cable
|
||||
//The bundle stays together at the end: the cross bar, a short
|
||||
//stub, and a box naming where the cable goes -- the Installation,
|
||||
//Location and Label (BMK) of the piece it lands on, the same
|
||||
//three fields the cable list shows. The lines shrink to the end
|
||||
//zone the settings leave, so the box never grows past the strip.
|
||||
painter->drawLine(QPointF{min_x, bar_2_y}, QPointF{max_x, bar_2_y});
|
||||
for (const auto &wire : std::as_const(wires))
|
||||
const qreal stub{qMin<qreal>(6, end_length)};
|
||||
painter->drawLine(QPointF{cable_x, bar_2_y}, QPointF{cable_x, bar_2_y + stub});
|
||||
|
||||
const auto target_lines{wires.first().terminal ? wires.first().terminal->cableTarget()
|
||||
: QVector<QString>()};
|
||||
if (!target_lines.isEmpty() && end_length - stub > 4)
|
||||
{
|
||||
painter->drawLine(QPointF{wire.x, bar_2_y}, QPointF{wire.x, end_y});
|
||||
draw_wire_mark(wire.x, qMin(bar_2_y + 10, end_y), wire.wire, false);
|
||||
QFont box_font{painter->font()};
|
||||
if (box_font.pixelSize() <= 0 && box_font.pointSizeF() > 0) {
|
||||
box_font.setPixelSize(qMax(4, qRound(box_font.pointSizeF() * 96.0 / 72.0)));
|
||||
}
|
||||
const qreal room{end_length - stub};
|
||||
const auto fits_the_end_zone = [&target_lines, room](const QFont &font_) {
|
||||
return QFontMetricsF{font_}.height() * target_lines.size() + 4 <= room;
|
||||
};
|
||||
while (!fits_the_end_zone(box_font) && box_font.pixelSize() > 4) {
|
||||
box_font.setPixelSize(box_font.pixelSize() - 1);
|
||||
}
|
||||
|
||||
const QFontMetricsF box_metrics{box_font};
|
||||
qreal box_width{6};
|
||||
for (const QString &line_ : target_lines) {
|
||||
box_width = qMax(box_width, box_metrics.horizontalAdvance(line_) + 6);
|
||||
}
|
||||
const qreal box_height{box_metrics.height() * target_lines.size() + 4};
|
||||
const QRectF box{cable_x - box_width / 2, bar_2_y + stub, box_width, box_height};
|
||||
|
||||
painter->save();
|
||||
painter->setFont(box_font);
|
||||
painter->drawRect(box);
|
||||
for (auto i = 0 ; i < target_lines.size() ; ++i)
|
||||
{
|
||||
painter->drawText(QRectF{box.left() + 1,
|
||||
box.top() + 2 + i * box_metrics.height(),
|
||||
box.width() - 2, box_metrics.height()},
|
||||
Qt::AlignCenter,
|
||||
target_lines.at(i));
|
||||
}
|
||||
painter->restore();
|
||||
}
|
||||
|
||||
//The shield, linked to an ellipse around the cable
|
||||
@@ -1037,6 +1105,7 @@ void TerminalStripDrawer::paint(QPainter *painter)
|
||||
cable_cell.cable = real_terminal_vector[i]->cable();
|
||||
cable_cell.wire = real_terminal_vector[i]->cableWire();
|
||||
cable_cell.shield = real_terminal_vector[i]->isShield();
|
||||
cable_cell.terminal = real_terminal_vector[i];
|
||||
}
|
||||
const bool have_cable{m_pattern->m_cable_wire_length > 0 && !cable_cell.cable.isEmpty()};
|
||||
cable_cells.append(cable_cell);
|
||||
|
||||
@@ -78,6 +78,12 @@ namespace TerminalStripDrawer
|
||||
virtual QString cable() const { return QString(); }
|
||||
virtual QString cableWire() const { return QString(); }
|
||||
virtual bool isShield() const { return false; }
|
||||
//Installation, Location and Label (BMK) of the piece the cable
|
||||
//goes to at its far end -- the same three fields the cable list
|
||||
//shows for a target -- drawn in a box under the cable. Empty
|
||||
//when the terminal has no cable, or when the cable lands on
|
||||
//nothing past the strip's own terminals.
|
||||
virtual QVector<QString> cableTarget() const { return QVector<QString>(); }
|
||||
//Color and width (mm) of the terminal, only used to draw the terminal.
|
||||
//An invalid color means "no override" : the default color of the type is used.
|
||||
//A width <= 0 means "unknown" : the default width of the layout is used.
|
||||
|
||||
@@ -153,6 +153,11 @@ namespace TerminalStripDrawer
|
||||
return m_real ? m_real->isShield() : false;
|
||||
}
|
||||
|
||||
QVector<QString> TrueRealTerminal::cableTarget() const
|
||||
{
|
||||
return m_real ? m_real->cableTarget() : QVector<QString>();
|
||||
}
|
||||
|
||||
QColor TrueRealTerminal::color() const
|
||||
{
|
||||
return m_real ? m_real->color() : QColor();
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace TerminalStripDrawer
|
||||
QString cable() const override;
|
||||
QString cableWire() const override;
|
||||
bool isShield() const override;
|
||||
QVector<QString> cableTarget() const override;
|
||||
QColor color() const override;
|
||||
QColor stripeColor() const override;
|
||||
qreal widthMm() const override;
|
||||
|
||||
@@ -22,11 +22,16 @@
|
||||
#include "terminalcolor.h"
|
||||
#include "terminalcatalog.h"
|
||||
#include "../qetgraphicsitem/conductor.h"
|
||||
#include "../qetinformation.h"
|
||||
#include "../qetgraphicsitem/element.h"
|
||||
#include "../qetgraphicsitem/terminal.h"
|
||||
#include "../qetinformation.h"
|
||||
#include "../diagram.h"
|
||||
#include "../cable/cable.h"
|
||||
#include "../cable/cablemanager.h"
|
||||
#include "../qetproject.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QSet>
|
||||
|
||||
namespace
|
||||
{
|
||||
@@ -400,6 +405,144 @@ bool RealTerminal::isShield() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RealTerminal::cableTarget
|
||||
* Where the cable of this terminal goes at its far end: the
|
||||
* Installation, Location and Label (BMK) of the first piece the
|
||||
* wires of the cable land on, past the strip's own terminals, in
|
||||
* plan order -- the same three fields the cable list shows for a
|
||||
* target, in the same order. An empty field is left out; a terminal
|
||||
* with no cable, or a cable which lands on nothing else, gives no
|
||||
* lines at all.
|
||||
*
|
||||
* The cable is the one the wires drawn to this terminal carry; a
|
||||
* cable name typed by hand, with no wire behind it, is looked up by
|
||||
* its name among the cables of the project.
|
||||
* @return the lines to write in the box under the cable
|
||||
*/
|
||||
QVector<QString> RealTerminal::cableTarget() const
|
||||
{
|
||||
if (m_spare || m_element.isNull()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
TerminalStrip *strip_ = parentStrip();
|
||||
if (!strip_ || !strip_->project()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
QETProject *project_{strip_->project()};
|
||||
|
||||
//The cable the wires drawn to this terminal are part of
|
||||
QUuid cable_uuid_;
|
||||
for (Terminal *terminal_ : m_element->terminals())
|
||||
{
|
||||
if (!terminal_) {
|
||||
continue;
|
||||
}
|
||||
for (Conductor *conductor_ : terminal_->conductors())
|
||||
{
|
||||
if (conductor_ && !conductor_->properties().m_cable_uuid.isNull()) {
|
||||
cable_uuid_ = conductor_->properties().m_cable_uuid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!cable_uuid_.isNull()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cable_uuid_.isNull())
|
||||
{
|
||||
//A cable name typed by hand, no wire behind it: the first
|
||||
//cable of the project drawn under that name
|
||||
const auto name_{cable()};
|
||||
if (name_.isEmpty()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
for (Cable *cable_ : project_->cables())
|
||||
{
|
||||
if (cable_ && cable_->designation() == name_) {
|
||||
cable_uuid_ = cable_->uuid();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cable_uuid_.isNull()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
}
|
||||
|
||||
//The own side: this strip's terminals never are the target
|
||||
QSet<QUuid> own_;
|
||||
for (const auto &physical_ : strip_->physicalTerminal())
|
||||
{
|
||||
if (!physical_) {
|
||||
continue;
|
||||
}
|
||||
for (const auto &real_ : physical_->realTerminals()) {
|
||||
if (real_ && real_->element()) {
|
||||
own_.insert(real_->element()->uuid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Where the wires of the cable land: one piece whatever the
|
||||
//number of its cores, never a report (the cable continues on
|
||||
//the sheet the report points to) and never the strip's own
|
||||
//terminals. Same rule as the cable list (cablelistrows.cpp).
|
||||
QHash<QUuid, Element *> landed_;
|
||||
for (Diagram *diagram_ : project_->diagrams())
|
||||
{
|
||||
for (Conductor *conductor_ : diagram_->conductors())
|
||||
{
|
||||
if (!conductor_ || conductor_->properties().m_cable_uuid != cable_uuid_) {
|
||||
continue;
|
||||
}
|
||||
Terminal *ends_[2] = {conductor_->terminal1, conductor_->terminal2};
|
||||
for (Terminal *terminal_ : ends_)
|
||||
{
|
||||
if (!terminal_) {
|
||||
continue;
|
||||
}
|
||||
Element *element_ = terminal_->parentElement();
|
||||
if (!element_ || (element_->linkType() & Element::AllReport)) {
|
||||
continue;
|
||||
}
|
||||
if (own_.contains(element_->uuid())) {
|
||||
continue;
|
||||
}
|
||||
landed_.insert(element_->uuid(), element_);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (landed_.isEmpty()) {
|
||||
return QVector<QString>();
|
||||
}
|
||||
|
||||
//The first piece in plan order is the target, as the cable
|
||||
//list chooses it
|
||||
Element *target_{nullptr};
|
||||
for (Element *element_ : std::as_const(landed_)) {
|
||||
if (!target_ || comparPos(element_, target_)) {
|
||||
target_ = element_;
|
||||
}
|
||||
}
|
||||
|
||||
const DiagramContext informations_{target_->elementInformations()};
|
||||
const auto installation_{informations_.value(QETInformation::ELMT_PLANT).toString()};
|
||||
const auto location_{informations_.value(QETInformation::ELMT_LOCATION).toString()};
|
||||
const auto label_{informations_.value(QETInformation::ELMT_LABEL).toString()};
|
||||
|
||||
QVector<QString> lines_;
|
||||
if (!installation_.isEmpty()) {
|
||||
lines_ << installation_;
|
||||
}
|
||||
if (!location_.isEmpty()) {
|
||||
lines_ << location_;
|
||||
}
|
||||
if (!label_.isEmpty()) {
|
||||
lines_ << label_;
|
||||
}
|
||||
return lines_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RealTerminal::color
|
||||
* @return The color set by the user for this terminal, drawn in the
|
||||
|
||||
@@ -75,6 +75,7 @@ class RealTerminal
|
||||
QString cableWire() const;
|
||||
bool cableIsAutomatic() const;
|
||||
bool isShield() const;
|
||||
QVector<QString> cableTarget() const;
|
||||
QColor color() const;
|
||||
QColor stripeColor() const;
|
||||
qreal section() const;
|
||||
|
||||
Reference in New Issue
Block a user