Merge pull request #1353 from ispyisail/feat/dxf-block-data

Add symbol part data to DXF blocks as hidden attributes (#1339)
This commit is contained in:
Laurent Trinques
2026-10-07 06:34:16 +02:00
committed by GitHub
3 changed files with 80 additions and 9 deletions
+44
View File
@@ -35,6 +35,7 @@
#include "qetgraphicsitem/independenttextitem.h"
#include "qetgraphicsitem/qetshapeitem.h"
#include "qetgraphicsitem/terminal.h"
#include "qetinformation.h"
#include "textlines.h"
#include <QGraphicsSimpleTextItem>
@@ -436,6 +437,49 @@ void DxfExport::write(Diagram *diagram, int width, int height,
}
attribute_texts << dti;
}
//The rest of what is known about a symbol (manufacturer,
//reference, supplier, quantity...) as hidden attributes, so a
//CAD program can list the parts from the drawing. A field
//already written as a visible attribute (dxf_attributes) is not
//repeated; the label formula is how the label is made, not
//part data.
for (Element *elmt : std::as_const(list_elements)) {
const QString block = block_names.value(elmt -> location().toString());
if (block.isEmpty())
continue;
const DiagramContext information = elmt -> elementInformations();
const QPointF insert(elmt -> pos().x() * Createdxf::xScale,
Createdxf::sheetHeight - elmt -> pos().y() * Createdxf::yScale);
for (const QString &key : QETInformation::elementInfoKeys()) {
if (key == QETInformation::ELMT_FORMULA)
continue;
const QString value = information.value(key).toString();
const QString tag = Createdxf::blockName(key);
if (value.isEmpty() || used_tags.value(elmt).contains(tag))
continue;
used_tags[elmt] << tag;
Createdxf::Attribute attribute;
attribute.tag = tag;
attribute.text = value;
attribute.x = insert.x();
attribute.y = insert.y();
attribute.height = 9 * Createdxf::yScale;
attribute.invisible = true;
attribute.layer = Layer::SymbolTexts;
attributes[elmt] << attribute;
if (!defined_tags[block].contains(tag)) {
defined_tags[block] << tag;
Createdxf::Attribute definition = attribute;
definition.x = 0;
definition.y = Createdxf::sheetHeight;
definition.text.clear();
attribute_definitions[block] << definition;
}
}
}
}
//A block is drawn as if its symbol sat unturned at the folio's
+1
View File
@@ -31,6 +31,7 @@
<inputs/>
<elementInformations>
<elementInformation name="label" show="1">K1</elementInformation>
<elementInformation name="manufacturer" show="1">Schneider</elementInformation>
</elementInformations>
<dynamic_texts>
<dynamic_elmt_text Halignment="AlignLeft" Valignment="AlignTop" font="Liberation Sans,9,-1,5,50,0,0,0,0,0,Regular" frame="false" keep_visual_rotation="false" rotation="0" rotation_point_center="false" text_from="ElementInfo" text_width="-1" uuid="{7d2b8e3f-0c65-4e30-9079-3f0d0f0a7b01}" x="0" y="25">
+35 -9
View File
@@ -22,8 +22,8 @@
/**
--export-dxf --dxf-blocks (issue #1339): a symbol placed twice is one
BLOCK and two INSERTs, the second turned a quarter, and each symbol's
label, with --dxf-attributes, is an attribute of its INSERT;
without the switches there is neither.
information is a hidden attribute of it; with --dxf-attributes its
label is a visible one. Without the switches there is neither.
*/
class tst_dxfblocks : public QObject
{
@@ -88,13 +88,14 @@ private slots:
const auto pairs = exportPairs({QStringLiteral("--dxf-attributes")});
QVERIFY2(!pairs.isEmpty(), "--export-dxf --dxf-attributes failed");
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2")),
(QStringList{QStringLiteral("LABEL"), QStringLiteral("LABEL")}));
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("1")),
(QStringList{QStringLiteral("K1"), QStringLiteral("K2")}));
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2"))
.count(QStringLiteral("LABEL")), 2);
const QStringList texts = values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("1"));
QVERIFY(texts.contains(QStringLiteral("K1")));
QVERIFY(texts.contains(QStringLiteral("K2")));
//Defined once in the block, and no longer a loose text
QCOMPARE(values(pairs, QStringLiteral("ATTDEF"), QStringLiteral("2")),
QStringList{QStringLiteral("LABEL")});
QCOMPARE(values(pairs, QStringLiteral("ATTDEF"), QStringLiteral("2"))
.count(QStringLiteral("LABEL")), 1);
QVERIFY(!values(pairs, QStringLiteral("TEXT"), QStringLiteral("1")).contains(QStringLiteral("K1")));
}
@@ -102,10 +103,35 @@ private slots:
{
const auto pairs = exportPairs({QStringLiteral("--dxf-blocks")});
QVERIFY2(!pairs.isEmpty(), "--export-dxf --dxf-blocks failed");
QVERIFY(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2")).isEmpty());
//Only hidden attributes (70 = 1); the labels are texts
QVERIFY(!values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("70")).contains(QStringLiteral("0")));
QVERIFY(values(pairs, QStringLiteral("TEXT"), QStringLiteral("1")).contains(QStringLiteral("K1")));
}
void dataAsHiddenAttributes()
{
//The label is a text, so it is part data too: K1's label and
//manufacturer, K2's label, all hidden (70 = 1)
auto pairs = exportPairs({QStringLiteral("--dxf-blocks")});
QVERIFY2(!pairs.isEmpty(), "--export-dxf --dxf-blocks failed");
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2")),
(QStringList{QStringLiteral("LABEL"), QStringLiteral("MANUFACTURER"),
QStringLiteral("LABEL")}));
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("70")),
(QStringList{QStringLiteral("1"), QStringLiteral("1"), QStringLiteral("1")}));
QVERIFY(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("1"))
.contains(QStringLiteral("Schneider")));
//With the labels as attributes, the label is not repeated
pairs = exportPairs({QStringLiteral("--dxf-attributes")});
QVERIFY2(!pairs.isEmpty(), "--export-dxf --dxf-attributes failed");
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2")),
(QStringList{QStringLiteral("LABEL"), QStringLiteral("MANUFACTURER"),
QStringLiteral("LABEL")}));
QCOMPARE(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("70")),
(QStringList{QStringLiteral("0"), QStringLiteral("1"), QStringLiteral("0")}));
}
void flatWithoutSwitch()
{
const auto pairs = exportPairs({});