mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-23 07:04:14 +02:00
dc92a57873
Reading where a cable lands meant going back to the drawing: the strip editor said which cable a terminal carries and which core, but never what the cable goes to. A single core (1x16) could not be followed from the terminal to its piece at all. The new Target column names it: Installation, Location and Label (BMK) of the piece the wires land on, past this strip, joined in one line -- the very three fields the strip drawing writes in the box under its cable, in the same order (RealTerminal::cableTarget()). It is worked out of the project like the Cable cells and so follows their rule: a target the drawing names is read only, for only the drawing decides it, and a cell nothing is worked out for takes an edit, so a target the drawing cannot find -- a cable landing on a piece with no Installation, Location nor Label set, a cable going to another strip -- is still worth naming by hand. The text typed in is stored in the element (RealTerminal::cableTargetInfoKey()) and kept until a cable works a target out again, and back once that cable goes, exactly like a cable designation typed by hand: the automatic value is never written, so no stale text can be left behind. The column takes the width of its own text, so a long Installation is never cut off. A text typed in is written the way the fields are shown in the column, "Installation / Location / Label", and gives one line per field: the box under the cable draws three lines without any slash in them, just like a target worked out from the project, instead of one long line carrying its separators as text. tst_terminalcableauto checks the column is empty -- and editable -- without a cable, reads "Plant 7 / Cabinet 7 / -S7" with one, goes empty -- and editable again -- when the core is removed, takes no edit while the drawing names the target, and is headed "Target"; a second case checks a target typed in by hand is taken by the cell, stored by Apply, shown again by a fresh model, set aside for the read only target of the drawing once a cable lands somewhere worth naming, and back once that cable goes; a third one the line per field. tst_cable target paints a strip whose cable ends on one field and the same strip ending on three, the second box two lines deeper than the first.
622 lines
21 KiB
C++
622 lines
21 KiB
C++
/*
|
|
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/realisticterminalstripdrawer.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.
|
|
|
|
Also here: the box at the end of a cable is written at the font of
|
|
the drawing -- the end zone the settings leave is what gives it the
|
|
room, so three lines never end up squeezed into a tiny text. A
|
|
target typed in by hand is written the way the fields are shown in
|
|
the column, "Installation / Location / Label", and the box draws one
|
|
line per field, with no slash in it.
|
|
|
|
Both drawing styles are covered: the schematic one and the
|
|
realistic one (the strip seen from above), which paint the same
|
|
cable through Helpers::drawCables().
|
|
|
|
fixtures/every_feature.qet has the strip X1 (elements 891b70f2 and
|
|
4861e268) and the contact fc9cc920 wired to 891b70f2 by the
|
|
conductor 8bd16d7a; the test gives the contact the Installation,
|
|
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 targetBoxKeepsTheDrawingFont();
|
|
void typedTargetIsDrawnInItsOwnLines();
|
|
void realisticStyleDrawsTheCable();
|
|
};
|
|
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
The box at the end of a cable keeps the font of the drawing: with
|
|
its three lines (Installation, Location and Label) and the end zone
|
|
the settings leave, the text is still written at the font of the
|
|
strip instead of being squeezed into a tiny one. The box is the
|
|
lowest thing the strip draws, so its bottom line is the lowest
|
|
painted row, and it must land where three lines of that font need
|
|
it to.
|
|
*/
|
|
void tst_cabletarget::targetBoxKeepsTheDrawingFont()
|
|
{
|
|
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());
|
|
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);
|
|
painter.end();
|
|
|
|
qreal lowest{-1};
|
|
for (auto y = 0 ; y < image.height() ; ++y)
|
|
{
|
|
for (auto x = 0 ; x < image.width() ; ++x)
|
|
{
|
|
if (image.pixel(x, y) != qRgba(0, 0, 0, 0)) {
|
|
lowest = y;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
QVERIFY(lowest >= 0);
|
|
|
|
//The end zone the default layout leaves is what gives the box its
|
|
//room: three lines of the default font must fit in it, or the text
|
|
//of a target is squeezed down again by the drawing itself
|
|
const QFontMetricsF metrics{pattern_->font()};
|
|
const qreal room{pattern_->m_cable_end_length
|
|
- qMin<qreal>(6, pattern_->m_cable_end_length)};
|
|
QVERIFY2(metrics.height() * 3 + 4 <= room,
|
|
"the default end zone leaves no room for three lines of the "
|
|
"default font, a target would be squeezed again");
|
|
|
|
//Where the bottom line of the box lands when it holds the three
|
|
//lines of its text at the font of the drawing
|
|
const qreal terminals_bottom{pattern_->m_terminal_rect.at(3).bottom()};
|
|
const qreal bar_2{terminals_bottom + pattern_->m_cable_wire_length
|
|
+ pattern_->m_cable_length};
|
|
const qreal box_bottom{bar_2 + qMin<qreal>(6, pattern_->m_cable_end_length)
|
|
+ metrics.height() * 3 + 4};
|
|
|
|
//The strip draws nothing under the box, so the lowest painted row
|
|
//is its bottom line -- within a pixel, the outline of a rectangle
|
|
//is painted on its edge
|
|
const qreal row{box_bottom - bounds.top() + 2};
|
|
QVERIFY(lowest + 2 >= row);
|
|
}
|
|
|
|
/**
|
|
The realistic style draws the cable too. The strip seen from above
|
|
reserves the zone under it when one of its terminals carries a
|
|
cable, and the wires, the cable and the box naming where it goes
|
|
are painted in it -- exactly what the schematic style draws, since
|
|
both styles now share the same Helpers::drawCables().
|
|
*/
|
|
void tst_cabletarget::realisticStyleDrawsTheCable()
|
|
{
|
|
QVERIFY(wireCableToTheContact());
|
|
|
|
const auto strips_ = m_project->terminalStrip();
|
|
QVERIFY(!strips_.isEmpty());
|
|
const auto strip_ = QSharedPointer<TerminalStripDrawer::TrueTerminalStrip>{
|
|
new TerminalStripDrawer::TrueTerminalStrip{strips_.first()}};
|
|
TerminalStripLayoutPattern pattern_;
|
|
|
|
const auto bounds_of = [&strip_, &pattern_]() {
|
|
return TerminalStripDrawer::Realistic::boundingRect(strip_.data(),
|
|
pattern_);
|
|
};
|
|
const auto render = [&strip_, &pattern_](const QRectF &bounds) {
|
|
QImage image{bounds.size().toSize() + QSize{4, 4},
|
|
QImage::Format_ARGB32_Premultiplied};
|
|
image.fill(Qt::transparent);
|
|
QPainter painter{&image};
|
|
painter.translate(-bounds.topLeft() + QPointF{2, 2});
|
|
TerminalStripDrawer::Realistic::paint(
|
|
&painter, *strip_, pattern_,
|
|
TerminalStripLayoutPattern::DrawStyle::RealisticPushIn);
|
|
return image;
|
|
};
|
|
|
|
const QRectF with_bounds{bounds_of()};
|
|
const QImage with_cable{render(with_bounds)};
|
|
|
|
//The body of the strip ends there : everything painted under it
|
|
//belongs to the cable
|
|
const qreal body_bottom{
|
|
pattern_.m_realistic_length_mm * pattern_.m_realistic_px_per_mm};
|
|
QVERIFY(with_bounds.height() > body_bottom);
|
|
|
|
int painted_{0};
|
|
for (auto y = qRound(body_bottom) + 4 ; y + 4 < with_cable.height() ; ++y)
|
|
{
|
|
for (auto x = 0 ; x + 4 < with_cable.width() ; ++x)
|
|
{
|
|
if (with_cable.pixel(x, y) != qRgba(0, 0, 0, 0)) {
|
|
++painted_;
|
|
}
|
|
}
|
|
}
|
|
//The wires and the cable are drawn in that zone
|
|
QVERIFY(painted_ > 0);
|
|
|
|
//The same strip, its terminal carries no cable name any more
|
|
Element *terminal_ = element(
|
|
QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
|
QVERIFY(terminal_);
|
|
ElementData terminal_data_{terminal_->elementData()};
|
|
terminal_data_.m_informations.addValue(RealTerminal::cableInfoKey(),
|
|
QString());
|
|
terminal_->setElementData(terminal_data_);
|
|
|
|
//No cable to let out : the strip does not reserve the zone
|
|
const QRectF without_bounds{bounds_of()};
|
|
QVERIFY(without_bounds.height() < with_bounds.height());
|
|
}
|
|
|
|
/**
|
|
A target typed in by hand is written the way the fields are shown in
|
|
the column, "Installation / Location / Label": the box under the
|
|
cable draws one line per field, with no slash in it. The picture of
|
|
a strip whose cable ends on three fields is therefore that much
|
|
deeper than the picture of the same strip with one single field --
|
|
two lines of the font of the drawing.
|
|
*/
|
|
void tst_cabletarget::typedTargetIsDrawnInItsOwnLines()
|
|
{
|
|
//The cable lands on a piece which names nothing, so there is no
|
|
//target of the drawing and the box takes what is typed in
|
|
QVERIFY(wireCableToTheContact());
|
|
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 auto a_ = terminalInStrip(
|
|
QStringLiteral("{891b70f2-2822-41c3-9f94-28efb448b5c4}"));
|
|
QVERIFY(a_);
|
|
QVERIFY(a_->cableTarget().isEmpty());
|
|
Element *terminal_ = a_->element();
|
|
QVERIFY(terminal_);
|
|
|
|
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);
|
|
painter.end();
|
|
return image;
|
|
};
|
|
const auto lowest_row = [](const QImage &image_) {
|
|
qreal lowest{-1};
|
|
for (auto y = 0 ; y < image_.height() ; ++y)
|
|
{
|
|
for (auto x = 0 ; x < image_.width() ; ++x)
|
|
{
|
|
if (image_.pixel(x, y) != qRgba(0, 0, 0, 0)) {
|
|
lowest = y;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return lowest;
|
|
};
|
|
const auto type_in = [terminal_](const QString &text_) {
|
|
ElementData data_{terminal_->elementData()};
|
|
data_.m_informations.addValue(RealTerminal::cableTargetInfoKey(), text_);
|
|
terminal_->setElementData(data_);
|
|
};
|
|
|
|
//One field: the box holds one single line
|
|
type_in(QStringLiteral("Boiler room"));
|
|
const qreal one_line{lowest_row(render())};
|
|
QVERIFY(one_line >= 0);
|
|
|
|
//Three fields: the box is two lines deeper, at the font of the
|
|
//drawing -- the slashes are only there to separate the fields in
|
|
//the column, the box never draws them
|
|
type_in(QStringLiteral("Boiler room / Cabinet 3 / -K3"));
|
|
QCOMPARE(a_->cableTarget(), (QVector<QString>{QStringLiteral("Boiler room"),
|
|
QStringLiteral("Cabinet 3"),
|
|
QStringLiteral("-K3")}));
|
|
const qreal three_lines{lowest_row(render())};
|
|
const QFontMetricsF metrics{pattern_->font()};
|
|
QVERIFY2(three_lines - one_line > 1.5 * metrics.height(),
|
|
"three fields must give a box two lines deeper than one field");
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
QStandardPaths::setTestModeEnabled(true);
|
|
return QetAppTest::run<tst_cabletarget>(argc, argv);
|
|
}
|
|
|
|
#include "tst_cabletarget.moc"
|