mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-23 07:04:14 +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;
|
||||
|
||||
@@ -343,6 +343,11 @@ qet_add_app_test(tst_linepivotresize tst_linepivotresize.cpp)
|
||||
# creates cannot come out in another order than the sort it then pushes.
|
||||
qet_add_app_test(tst_terminalstriporder tst_terminalstriporder.cpp)
|
||||
|
||||
# The strip graphic names where a cable goes at its far end -- Installation,
|
||||
# Location and Label of the first piece its wires land on past the strip, in
|
||||
# plan order, the same three fields the cable list computes for a target.
|
||||
qet_add_app_test(tst_cabletarget tst_cabletarget.cpp)
|
||||
|
||||
# legacyelementtypes.h is header-only: the rewrite of element type names in
|
||||
# nomenclature queries saved before June 2022.
|
||||
add_executable(tst_legacyelementtypes tst_legacyelementtypes.cpp)
|
||||
|
||||
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
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 "qetapptest.h"
|
||||
|
||||
#include "TerminalStrip/GraphicsItem/trueterminalstrip.h"
|
||||
#include "TerminalStrip/physicalterminal.h"
|
||||
#include "TerminalStrip/realterminal.h"
|
||||
#include "TerminalStrip/terminalstrip.h"
|
||||
#include "cable/cable.h"
|
||||
#include "conductorproperties.h"
|
||||
#include "diagram.h"
|
||||
#include "properties/elementdata.h"
|
||||
#include "qetgraphicsitem/conductor.h"
|
||||
#include "qetgraphicsitem/element.h"
|
||||
#include "qetinformation.h"
|
||||
#include "qetproject.h"
|
||||
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <QStandardPaths>
|
||||
|
||||
/**
|
||||
The terminal strip graphic names where a cable goes: 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 computes for a target
|
||||
(cablelistrows.cpp), so the strip and the list can never disagree.
|
||||
The graphic draws them in a small box under the cable, the bundle
|
||||
staying together (RealTerminal::cableTarget()).
|
||||
|
||||
Also here: the number of a wire must stay in the room left between
|
||||
its mark and the terminal -- it shrinks, and what does not fit is
|
||||
clipped, so it never runs into the drawing of the terminal.
|
||||
|
||||
fixtures/every_feature.qet has the strip X1 (elements 891b70f2 and
|
||||
4861e268) and the contact fc9cc920 wired to 891b70f2 by the
|
||||
conductor 8bd16d7a; the test gives the contact the Installation,
|
||||
Location and Label it reads back. The conductor 584b452e joins the
|
||||
two strip terminals to each other. No conductor of the fixture
|
||||
belongs to a cable yet.
|
||||
*/
|
||||
class tst_cabletarget : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QETProject *m_project = nullptr;
|
||||
|
||||
Element *element(const QString &uuid) const
|
||||
{
|
||||
for (Diagram *diagram_ : m_project->diagrams()) {
|
||||
for (Element *element_ : diagram_->elements()) {
|
||||
if (element_->uuid().toString() == uuid) {
|
||||
return element_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QSharedPointer<RealTerminal> terminalInStrip(const QString &element_uuid) const
|
||||
{
|
||||
const auto strips_ = m_project->terminalStrip();
|
||||
if (strips_.isEmpty()) {
|
||||
return {};
|
||||
}
|
||||
for (const auto &real_ : strips_.first()->realTerminals()) {
|
||||
if (real_ && real_->element()
|
||||
&& real_->element()->uuid().toString() == element_uuid) {
|
||||
return real_;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
Conductor *conductor(const QString &uuid) const
|
||||
{
|
||||
for (Diagram *diagram_ : m_project->diagrams()) {
|
||||
for (Conductor *conductor_ : diagram_->conductors()) {
|
||||
if (conductor_ && conductor_->uuid().toString() == uuid) {
|
||||
return conductor_;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Let the drawn wires of @a conductor_ belong to the cable @a cable_uuid.
|
||||
void claimCable(Conductor *conductor_, const QUuid &cable_uuid) const
|
||||
{
|
||||
auto properties_ = conductor_->properties();
|
||||
properties_.m_cable_uuid = cable_uuid;
|
||||
conductor_->setProperties(properties_);
|
||||
}
|
||||
|
||||
/**
|
||||
Same setup for the value and the drawing test: the contact the
|
||||
strip's wire lands on carries the three fields the test reads
|
||||
back (the fixture's own block has none), the wire belongs to a
|
||||
new cable, and the terminal carries that cable's name the way
|
||||
the strip editor stores it -- without a name the strip draws no
|
||||
cable at all. @return false when the fixture is not the one this
|
||||
test was written for.
|
||||
*/
|
||||
bool wireCableToTheContact()
|
||||
{
|
||||
Element *contact_ = element(
|
||||
QStringLiteral("{fc9cc920-5822-421a-916e-a17100acdcf6}"));
|
||||
if (!contact_) {
|
||||
return false;
|
||||
}
|
||||
ElementData contact_data_{contact_->elementData()};
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_PLANT,
|
||||
QStringLiteral("Plant 7"));
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_LOCATION,
|
||||
QStringLiteral("Cabinet 7"));
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_LABEL,
|
||||
QStringLiteral("-S7"));
|
||||
contact_->setElementData(contact_data_);
|
||||
|
||||
Cable *cable_ = m_project->newCable();
|
||||
Conductor *wired_ = conductor(
|
||||
QStringLiteral("{8bd16d7a-18c4-4fa0-9495-8dab65fd6408}"));
|
||||
if (!cable_ || !wired_) {
|
||||
return false;
|
||||
}
|
||||
claimCable(wired_, cable_->uuid());
|
||||
|
||||
//The name of the cable on the terminal, the way the strip
|
||||
//editor stores it: without it the strip draws no cable at all
|
||||
Element *terminal_ = element(
|
||||
QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
||||
if (!terminal_) {
|
||||
return false;
|
||||
}
|
||||
ElementData terminal_data_{terminal_->elementData()};
|
||||
terminal_data_.m_informations.addValue(RealTerminal::cableInfoKey(),
|
||||
QStringLiteral("X99"));
|
||||
terminal_->setElementData(terminal_data_);
|
||||
return true;
|
||||
}
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void noCableNoTarget();
|
||||
void targetIsTheOtherPiece();
|
||||
void ownStripIsNoTarget();
|
||||
void spareHasNoTarget();
|
||||
void paintsWithTargetBox();
|
||||
void wireLabelStaysOutOfTheTerminal();
|
||||
};
|
||||
|
||||
void tst_cabletarget::init()
|
||||
{
|
||||
const QString fixture_ = QFINDTESTDATA("fixtures/every_feature.qet");
|
||||
QVERIFY(!fixture_.isEmpty());
|
||||
m_project = new QETProject(fixture_);
|
||||
QCOMPARE(m_project->state(), QETProject::Ok);
|
||||
}
|
||||
|
||||
void tst_cabletarget::cleanup()
|
||||
{
|
||||
delete m_project;
|
||||
m_project = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
Nothing to name when no wire of the terminal belongs to a cable and
|
||||
no cable of the project is drawn under a name the terminal carries.
|
||||
*/
|
||||
void tst_cabletarget::noCableNoTarget()
|
||||
{
|
||||
const auto a_ = terminalInStrip(QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
||||
const auto b_ = terminalInStrip(QStringLiteral("{4861e268-d344-413e-a86f-034ea5ada16c}"));
|
||||
QVERIFY(a_);
|
||||
QVERIFY(b_);
|
||||
QVERIFY(a_->cable().isEmpty());
|
||||
QVERIFY(a_->cableTarget().isEmpty());
|
||||
QVERIFY(b_->cableTarget().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
The cable of the strip lands on the contact past it: the three
|
||||
fields of that piece, in the order the cable list shows them
|
||||
(Installation, Location, Label), and nothing of the strip itself.
|
||||
*/
|
||||
void tst_cabletarget::targetIsTheOtherPiece()
|
||||
{
|
||||
QVERIFY(wireCableToTheContact());
|
||||
|
||||
const auto a_ = terminalInStrip(QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
||||
QVERIFY(a_);
|
||||
QCOMPARE(a_->cableTarget(),
|
||||
QVector<QString>({
|
||||
QStringLiteral("Plant 7"),
|
||||
QStringLiteral("Cabinet 7"),
|
||||
QStringLiteral("-S7"),
|
||||
}));
|
||||
|
||||
//The other strip terminal carries no claimed wire of its own
|
||||
//(584b452e joins it to a_ and is not claimed) and no cable name,
|
||||
//so it has no target to name
|
||||
const auto b_ = terminalInStrip(QStringLiteral("{4861e268-d344-413e-a86f-034ea5ada16c}"));
|
||||
QVERIFY(b_);
|
||||
QVERIFY(b_->cableTarget().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
A cable whose wires only ever join the terminals of the strip
|
||||
itself lands on nothing past the strip: no target, no box.
|
||||
*/
|
||||
void tst_cabletarget::ownStripIsNoTarget()
|
||||
{
|
||||
Cable *cable_ = m_project->newCable();
|
||||
QVERIFY(cable_);
|
||||
Conductor *inside_ = conductor(
|
||||
QStringLiteral("{584b452e-a885-491a-98f1-fd348610b5e0}"));
|
||||
QVERIFY(inside_);
|
||||
claimCable(inside_, cable_->uuid());
|
||||
|
||||
const auto a_ = terminalInStrip(QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
||||
const auto b_ = terminalInStrip(QStringLiteral("{4861e268-d344-413e-a86f-034ea5ada16c}"));
|
||||
QVERIFY(a_);
|
||||
QVERIFY(b_);
|
||||
QVERIFY(a_->cableTarget().isEmpty());
|
||||
QVERIFY(b_->cableTarget().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
A spare terminal stands on no folio and is wired to nothing: it has
|
||||
no target to name either.
|
||||
*/
|
||||
void tst_cabletarget::spareHasNoTarget()
|
||||
{
|
||||
ElementData data_;
|
||||
data_.m_informations.addValue(QStringLiteral("label"),
|
||||
QStringLiteral("AAA"));
|
||||
const auto spare_ = RealTerminal::createSpare(data_);
|
||||
QVERIFY(spare_);
|
||||
QVERIFY(spare_->isSpare());
|
||||
QVERIFY(spare_->cableTarget().isEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
The strip graphic draws the box: the same strip painted with
|
||||
something to name at the end of the cable and painted with nothing
|
||||
to name come out as two different pictures -- the box is the
|
||||
difference. Painting it also runs the whole drawCables() path.
|
||||
*/
|
||||
void tst_cabletarget::paintsWithTargetBox()
|
||||
{
|
||||
QVERIFY(wireCableToTheContact());
|
||||
|
||||
const auto strips_ = m_project->terminalStrip();
|
||||
QVERIFY(!strips_.isEmpty());
|
||||
TerminalStripDrawer::TerminalStripDrawer drawer{
|
||||
QSharedPointer<TerminalStripDrawer::TrueTerminalStrip>{
|
||||
new TerminalStripDrawer::TrueTerminalStrip{strips_.first()}},
|
||||
QSharedPointer<TerminalStripLayoutPattern>{new TerminalStripLayoutPattern}};
|
||||
|
||||
const QRectF bounds{drawer.boundingRect()};
|
||||
QVERIFY(!bounds.isEmpty());
|
||||
|
||||
const auto render = [&drawer, &bounds]() {
|
||||
QImage image{bounds.size().toSize() + QSize{4, 4},
|
||||
QImage::Format_ARGB32_Premultiplied};
|
||||
image.fill(Qt::transparent);
|
||||
QPainter painter{&image};
|
||||
painter.translate(-bounds.topLeft() + QPointF{2, 2});
|
||||
drawer.paint(&painter);
|
||||
return image;
|
||||
};
|
||||
|
||||
const QImage with_box{render()};
|
||||
|
||||
//Nothing left to name at the far end of the cable
|
||||
Element *contact_ = element(
|
||||
QStringLiteral("{fc9cc920-5822-421a-916e-a17100acdcf6}"));
|
||||
QVERIFY(contact_);
|
||||
ElementData contact_data_{contact_->elementData()};
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_PLANT, QString());
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_LOCATION, QString());
|
||||
contact_data_.m_informations.addValue(QETInformation::ELMT_LABEL, QString());
|
||||
contact_->setElementData(contact_data_);
|
||||
|
||||
const QImage without_box{render()};
|
||||
QVERIFY(with_box != without_box);
|
||||
}
|
||||
|
||||
/**
|
||||
The number of a wire is written next to its mark, in the room left
|
||||
between the mark and the terminal: it shrinks to fit there, and what
|
||||
still does not fit is clipped away, so a long number never runs into
|
||||
the drawing of the terminal. The two pictures -- one with a number
|
||||
long enough to reach into the terminal, one without any -- must be
|
||||
the same above the bottom of the terminal, and differ below it (the
|
||||
number is drawn somewhere).
|
||||
*/
|
||||
void tst_cabletarget::wireLabelStaysOutOfTheTerminal()
|
||||
{
|
||||
QVERIFY(wireCableToTheContact());
|
||||
|
||||
auto pattern_ = QSharedPointer<TerminalStripLayoutPattern>{new TerminalStripLayoutPattern};
|
||||
const auto strips_ = m_project->terminalStrip();
|
||||
QVERIFY(!strips_.isEmpty());
|
||||
TerminalStripDrawer::TerminalStripDrawer drawer{
|
||||
QSharedPointer<TerminalStripDrawer::TrueTerminalStrip>{
|
||||
new TerminalStripDrawer::TrueTerminalStrip{strips_.first()}},
|
||||
pattern_};
|
||||
|
||||
const QRectF bounds{drawer.boundingRect()};
|
||||
QVERIFY(!bounds.isEmpty());
|
||||
|
||||
const auto render = [&drawer, &bounds]() {
|
||||
QImage image{bounds.size().toSize() + QSize{4, 4},
|
||||
QImage::Format_ARGB32_Premultiplied};
|
||||
image.fill(Qt::transparent);
|
||||
QPainter painter{&image};
|
||||
painter.translate(-bounds.topLeft() + QPointF{2, 2});
|
||||
drawer.paint(&painter);
|
||||
return image;
|
||||
};
|
||||
|
||||
//A number much longer than the room left over the mark
|
||||
Element *terminal_ = element(
|
||||
QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
||||
QVERIFY(terminal_);
|
||||
ElementData terminal_data_{terminal_->elementData()};
|
||||
terminal_data_.m_informations.addValue(
|
||||
RealTerminal::cableWireInfoKey(),
|
||||
QStringLiteral("gnge-gnge-gnge-gnge-gnge"));
|
||||
terminal_->setElementData(terminal_data_);
|
||||
const QImage with_label{render()};
|
||||
|
||||
//The same strip, the wire carries no number at all
|
||||
terminal_data_.m_informations.addValue(RealTerminal::cableWireInfoKey(),
|
||||
QString());
|
||||
terminal_->setElementData(terminal_data_);
|
||||
const QImage without_label{render()};
|
||||
|
||||
//The number is drawn: the two pictures differ
|
||||
QVERIFY(with_label != without_label);
|
||||
|
||||
//The terminals of this strip all stand on the last level of the
|
||||
//pattern, so their bottom is the same rectangle
|
||||
const qreal terminal_bottom{pattern_->m_terminal_rect.at(3).bottom()};
|
||||
const auto rows_to_check{qMin(qRound(terminal_bottom - bounds.topLeft().y() + 2),
|
||||
with_label.height())};
|
||||
for (auto y = 0 ; y < rows_to_check ; ++y)
|
||||
{
|
||||
for (auto x = 0 ; x < with_label.width() ; ++x)
|
||||
{
|
||||
QCOMPARE(with_label.pixel(x, y), without_label.pixel(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QStandardPaths::setTestModeEnabled(true);
|
||||
return QetAppTest::run<tst_cabletarget>(argc, argv);
|
||||
}
|
||||
|
||||
#include "tst_cabletarget.moc"
|
||||
Reference in New Issue
Block a user