Merge master into feat/qetz-db-truth-v2

The .qetz files take this branch's side: it already holds #1473, and
adds the folio parts to join().

qetscriptapi.cpp: #1456 gave setConductorProperty() the voltage that
crosses a function separated terminal element; here that function hands
its work to applyConductorProperties(), so the change goes there, with
the properties captured before the pushes. The database path for folios
not built already gives up at such a terminal, so it builds the folio and
takes the same route.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ispyisail
2026-10-14 18:57:29 +13:00
28 changed files with 708 additions and 44 deletions
+9
View File
@@ -271,6 +271,15 @@ qet_add_app_test(tst_rotateselectionimage tst_rotateselectionimage.cpp)
# it selected and records no undo step (#1414); the key goes to the view.
qet_add_app_test(tst_imagehandleescape tst_imagehandleescape.cpp)
# SVG export with smaller pictures (--svg-small-pictures, the export dialog's
# option): a picture drawn at a tenth of its size is stored at four times
# that, a small one whole; without the option every picture is whole.
qet_add_app_test(tst_svgsmallpictures tst_svgsmallpictures.cpp)
add_dependencies(tst_svgsmallpictures qelectrotech)
target_link_libraries(tst_svgsmallpictures PRIVATE Qt::Svg)
target_compile_definitions(tst_svgsmallpictures PRIVATE
"QET_TEST_BINARY_PATH=\"$<TARGET_FILE:qelectrotech>\"")
# TextResizeHandles: the corner handles that change the width of a text box,
# on a plain QGraphicsTextItem with the "textWidth" property QET texts have.
add_executable(
@@ -0,0 +1,41 @@
<project title="A large picture shown small" uuid="{3f6a2c91-8d47-4b5e-a0c3-91e2d7b4f600}" version="0.200.1">
<properties>
<property name="saveddate" show="1">10/2/26</property>
<property name="saveddate-eu" show="1">02-10-2026</property>
<property name="saveddate-us" show="1">2026-10-02</property>
<property name="savedfilename" show="1">svg_small_pictures</property>
<property name="savedtime" show="1">18:39</property>
</properties>
<usage enabled="true" time_spent="0"/>
<newdiagrams>
<border cols="17" colsize="60" displaycols="true" displayrows="true" rows="8" rowsize="80"/>
<inset author="" auto_page_num="" date="null" displayAt="bottom" filename="" folio="" indexrev="" locmach="" plant="" title="" version=""/>
<conductors bicolor="false" bus="" cable="" color2="#000000" condsize="1" conductor_color="" conductor_section="" dash-size="1" displaytext="1" formula="" function="" horizontal-alignment="AlignBottom" horizrotatetext="0" num="_" numsize="7" onetextperfolio="0" tension_protocol="" text_color="#000000" type="multi" vertical-alignment="AlignRight" vertirotatetext="270"/>
<report label="%f-%l%c"/>
<xrefs>
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="coil" xrefpos="AlignBottom"/>
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="commutator" xrefpos="AlignBottom"/>
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="plc" xrefpos="AlignBottom"/>
<xref delayprefix="" displayhas="cross" master_label="%f-%l%c" offset="0" powerprefix="" showallconfiguredslaves="false" showpowerctc="true" showterminalname="true" slave_label="(%f-%l%c)" slave_offset="0" snapto="label" switchprefix="" type="protection" xrefpos="AlignBottom"/>
</xrefs>
<conductors_autonums auto_break_conductors="false" current_autonum="" freeze_new_conductors="false"/>
<folio_autonums/>
<element_autonums current_autonum="" freeze_new_elements="false"/>
<guides/>
</newdiagrams>
<diagram author="" auto_page_num="" cols="17" colsize="60" date="null" displayAt="bottom" displaycols="true" displayrows="true" filename="" folio="" freezeNewConductor="false" freezeNewElement="false" height="660" indexrev="" locmach="" order="1" plant="" rows="8" rowsize="80" title="" uuid="{3f6a2c91-8d47-4b5e-a0c3-91e2d7b4f610}" version="0.200.1-dev">
<defaultconductor bicolor="false" bus="" cable="" color2="#000000" condsize="1" conductor_color="" conductor_section="" dash-size="1" displaytext="1" formula="" function="" horizontal-alignment="AlignBottom" horizrotatetext="0" num="_" numsize="7" onetextperfolio="0" tension_protocol="" text_color="#000000" type="multi" vertical-alignment="AlignRight" vertirotatetext="270"/>
<inputs/>
<images>
<image z="0" rotation="0" y="100" x="100" size="0.1" is_movable="1">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</image>
<image z="0" rotation="0" y="300" x="100" size="1" is_movable="1">iVBORw0KGgoAAAANSUhEUgAAACgAAAAeCAIAAADRv8uKAAAAP0lEQVR42u3PMQoAIAwEwRVC1F/7dFuxFoKwqS7XHNNgJSR0OMP1Pu+DQckFs2pYsWLFihUrVqxYsWLFir8Rb7mhAuQBqxaIAAAAAElFTkSuQmCC</image>
</images>
</diagram>
<collection>
<category name="import">
<names>
<name lang="en">Imported elements</name>
</names>
</category>
</collection>
</project>
+155
View File
@@ -29,6 +29,10 @@ class FakeWire : public QObject
ConductorProperties properties() const { return m_properties; }
void setProperties(const ConductorProperties &p) { m_properties = p; }
QSet<FakeWire *> relatedPotentialConductors() const { return m_potential; }
// The wires of the other side of a function separated terminal
// element: same electrical node, but only the voltage /
// protocol crosses.
QSet<FakeWire *> functionSeparatedConductors() const { return m_separated; }
QPointF pos() const { return m_pos; }
// Joins wires into one potential; like the real one, a wire's
@@ -41,10 +45,24 @@ class FakeWire : public QObject
w->m_potential.insert(o);
}
// Marks two groups as separated by a function separated
// terminal element, without joining their potentials.
static void separate(const QList<FakeWire *> &one,
const QList<FakeWire *> &other)
{
for (FakeWire *w : one)
for (FakeWire *o : other)
{
w->m_separated.insert(o);
o->m_separated.insert(w);
}
}
ConductorProperties m_properties;
private:
QSet<FakeWire *> m_potential;
QSet<FakeWire *> m_separated;
QPointF m_pos;
};
@@ -102,6 +120,143 @@ class tst_conductormultiedit : public QObject
(QSet<FakeWire *> {&a, &b, &c, &d}));
}
// A function separated terminal element: the other side of the
// terminal is reached too, but only the voltage / protocol
// crosses it -- not the function, not the number.
void functionSeparatedGetsVoltageProtocolOnly()
{
FakeWire a("1", "fnA", "", {}), b("2", "fnB", "", {}),
c("3", "fnC", "", {});
FakeWire::join({&a, &b});
FakeWire::separate({&a}, {&c});
QSet<FakeWire *> separated;
const Wires t = ConductorMultiEdit::targets(Wires {&a}, true,
&separated);
QCOMPARE(QSet<FakeWire *>(t.begin(), t.end()),
(QSet<FakeWire *> {&a, &b, &c}));
QCOMPARE(separated, (QSet<FakeWire *> {&c}));
// A caller that does not know about the rule gets the
// separated side left out, as before
QCOMPARE(ConductorMultiEdit::targets(Wires {&a}, true),
(Wires {&a, &b}));
const ConductorProperties shown = a.properties();
ConductorProperties after = edited(shown,
&ConductorProperties::m_function, "PWR");
after.m_tension_protocol = "24V";
QUndoStack stack;
stack.push(ConductorMultiEdit::undo(t, shown, after, separated));
QCOMPARE(stack.count(), 1);
for (FakeWire *w : {&a, &b})
{
QCOMPARE(w->m_properties.m_function, QStringLiteral("PWR"));
QCOMPARE(w->m_properties.m_tension_protocol,
QStringLiteral("24V"));
}
QCOMPARE(c.m_properties.m_function, QStringLiteral("fnC"));
QCOMPARE(c.m_properties.text, QStringLiteral("3"));
QCOMPARE(c.m_properties.m_tension_protocol, QStringLiteral("24V"));
stack.undo();
QVERIFY(c.properties().m_tension_protocol.isEmpty());
QCOMPARE(c.m_properties.m_function, QStringLiteral("fnC"));
}
// The explicitly picked side of a separation: selecting one
// wire on each side and editing them edits them both, in
// full -- however the selection happens to be walked (#review)
void selectedWireIsNeverSeparated()
{
FakeWire a("1", "fnA", "", {}), c("3", "fnC", "", {});
FakeWire::separate({&a}, {&c});
const ConductorProperties original_a = a.properties();
const ConductorProperties original_c = c.properties();
const ConductorProperties after = edited(original_a,
&ConductorProperties::m_function, "PWR");
for (const Wires &selection : {Wires {&a, &c}, Wires {&c, &a}})
{
//Each order starts from the same, unedited state
a.setProperties(original_a);
c.setProperties(original_c);
QSet<FakeWire *> separated;
const Wires t = ConductorMultiEdit::targets(selection, true,
&separated);
//c is picked, so it is not "the far side" of anything
QCOMPARE(separated, (QSet<FakeWire *> {}));
QUndoStack stack;
QUndoCommand *undo = ConductorMultiEdit::undo(t, original_a,
after, separated);
QVERIFY(undo);
stack.push(undo);
QCOMPARE(a.m_properties.m_function, QStringLiteral("PWR"));
QCOMPARE(c.m_properties.m_function, QStringLiteral("PWR"));
}
}
// A wire that belongs to the potential as well -- on any path,
// however far that path runs -- takes the full edit, even when a
// separation also reaches it. The fake's potential is one hop
// deep, unlike the real one, so the shared potential is stated
// in full here.
void wireReachableBothWaysIsNotSeparated()
{
FakeWire a("1", "fnA", "", {}), b("2", "fnB", "", {}),
c("3", "fnC", "", {});
FakeWire::join({&a, &b, &c});
FakeWire::separate({&a}, {&c});
QSet<FakeWire *> separated;
const Wires t = ConductorMultiEdit::targets(Wires {&a}, true,
&separated);
QCOMPARE(QSet<FakeWire *>(t.begin(), t.end()),
(QSet<FakeWire *> {&a, &b, &c}));
QCOMPARE(separated, (QSet<FakeWire *> {}));
const ConductorProperties shown = a.properties();
QUndoStack stack;
stack.push(ConductorMultiEdit::undo(t, shown, edited(shown,
&ConductorProperties::m_function, "PWR"), separated));
QCOMPARE(c.m_properties.m_function, QStringLiteral("PWR"));
}
// The far side only takes the voltage when the edit changed it:
// editing the function of a 24 V wire must leave the 0 V one
// at 0 V, not drag it along (#review)
void separatedWireKeepsVoltageWhenNotEdited()
{
FakeWire a("1", "fnA", "", {}), c("3", "fnC", "", {});
FakeWire::separate({&a}, {&c});
a.m_properties.m_tension_protocol = "24V";
c.m_properties.m_tension_protocol = "0V";
QSet<FakeWire *> separated;
const Wires t = ConductorMultiEdit::targets(Wires {&a}, true,
&separated);
const ConductorProperties shown = a.properties();
QUndoStack stack;
//Only the function changes: the far side changes nothing
stack.push(ConductorMultiEdit::undo(t, shown, edited(shown,
&ConductorProperties::m_function, "PWR"), separated));
QCOMPARE(c.m_properties.m_function, QStringLiteral("fnC"));
QCOMPARE(c.m_properties.m_tension_protocol, QStringLiteral("0V"));
//Now the voltage changes too: it crosses, and only it
const ConductorProperties shown_now = a.properties();
stack.push(ConductorMultiEdit::undo(t, shown_now, edited(shown_now,
&ConductorProperties::m_tension_protocol, "30V"), separated));
QCOMPARE(c.m_properties.m_tension_protocol, QStringLiteral("30V"));
QCOMPARE(c.m_properties.m_function, QStringLiteral("fnC"));
QCOMPARE(a.m_properties.m_tension_protocol, QStringLiteral("30V"));
}
// One edit of three wires: each takes the function, keeps its
// own number and cable; one undo restores all three exactly
void undoRedoThreeWires()
+143
View File
@@ -0,0 +1,143 @@
/*
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 "qetgraphicsitem/diagramimageitem.h"
#include <QBuffer>
#include <QDomDocument>
#include <QPicture>
#include <QProcess>
#include <QRegularExpression>
#include <QSvgGenerator>
#include <QTemporaryDir>
/**
SVG export with "smaller pictures" (ExportProperties::svg_small_pictures,
--svg-small-pictures) stores each picture at four times the size it is
drawn at when that is smaller than the picture, and at full resolution
otherwise. fixtures/svg_small_pictures.qet has an 800x600 picture drawn
at a tenth of its size and a 40x30 one at full size.
*/
class tst_svgsmallpictures : public QObject
{
Q_OBJECT
QString m_fixture;
/// Pixel size of each picture embedded in @p svg, smallest first
static QList<QSize> embeddedSizes(const QByteArray &svg)
{
static const QRegularExpression data(
QStringLiteral("data:image/png;base64,([A-Za-z0-9+/=\\s]+)"));
QList<QSize> sizes;
auto it = data.globalMatch(QString::fromLatin1(svg));
while (it.hasNext())
sizes << QImage::fromData(QByteArray::fromBase64(
it.next().captured(1).toLatin1())).size();
std::sort(sizes.begin(), sizes.end(), [](const QSize &a, const QSize &b) {
return a.width() < b.width();
});
return sizes;
}
QByteArray exportWithCli(const QStringList &extra)
{
QTemporaryDir dir;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert(QStringLiteral("QT_QPA_PLATFORM"), QStringLiteral("offscreen"));
QProcess proc;
proc.setProcessEnvironment(env);
proc.start(QStringLiteral(QET_TEST_BINARY_PATH),
QStringList{QStringLiteral("--export-svg"), m_fixture, dir.path()} + extra);
if (!proc.waitForFinished(60000) || proc.exitCode() != 0)
return {};
const QStringList files = QDir(dir.path()).entryList({QStringLiteral("*.svg")});
QFile svg(QDir(dir.path()).filePath(files.value(0)));
return svg.open(QIODevice::ReadOnly) ? svg.readAll() : QByteArray();
}
/// As ExportDialog::generateSvg(): the folio drawn into a QPicture,
/// played into the SVG generator
static QByteArray exportLikeTheDialog(Diagram *diagram, bool small)
{
const QSize size = diagram->imageSize();
QPicture picture;
diagram->setSmallPictures(small);
diagram->toPaintDevice(picture, size.width(), size.height());
diagram->setSmallPictures(false);
QByteArray svg;
QBuffer buffer(&svg);
buffer.open(QIODevice::WriteOnly);
QSvgGenerator generator;
generator.setSize(size);
generator.setOutputDevice(&buffer);
QPainter painter(&generator);
picture.play(&painter);
painter.end();
return svg;
}
private slots:
void initTestCase()
{
m_fixture = QFINDTESTDATA("fixtures/svg_small_pictures.qet");
QVERIFY2(!m_fixture.isEmpty(), "fixture project not found");
QVERIFY(QetAppTest::editor());
}
void cliFullResolutionByDefault()
{
const QByteArray svg = exportWithCli({});
QVERIFY2(!svg.isEmpty(), "--export-svg failed");
QCOMPARE(embeddedSizes(svg), (QList<QSize>{QSize(40, 30), QSize(800, 600)}));
}
void cliSmallPictures()
{
const QByteArray svg = exportWithCli({QStringLiteral("--svg-small-pictures")});
QVERIFY2(!svg.isEmpty(), "--export-svg --svg-small-pictures failed");
// 800 x 600 drawn at 0.1, times 4; the 40 x 30 one is kept whole
QCOMPARE(embeddedSizes(svg), (QList<QSize>{QSize(40, 30), QSize(320, 240)}));
}
void dialogSmallPicturesThenFullAgain()
{
QFile file(m_fixture);
QVERIFY(file.open(QIODevice::ReadOnly));
QDomDocument document;
QVERIFY(document.setContent(&file));
const QDomElement image_xml = document.elementsByTagName(
QStringLiteral("image")).at(0).toElement();
Diagram *diagram = QetAppTest::diagram();
auto *picture = new DiagramImageItem();
QVERIFY(picture->fromXml(image_xml));
diagram->addItem(picture);
QCOMPARE(embeddedSizes(exportLikeTheDialog(diagram, true)),
QList<QSize>{QSize(320, 240)});
// The option lasts for one export only
QVERIFY(!diagram->smallPictures());
QCOMPARE(embeddedSizes(exportLikeTheDialog(diagram, false)),
QList<QSize>{QSize(800, 600)});
delete picture;
}
};
QET_APP_TEST_MAIN(tst_svgsmallpictures)
#include "tst_svgsmallpictures.moc"