From 9699b314b0a383331005b598aaa3154f26cbc29a Mon Sep 17 00:00:00 2001 From: ispyisail Date: Wed, 7 Oct 2026 09:56:26 +1300 Subject: [PATCH] Add an option to export a symbol's texts as DXF block attributes (#1339) With symbols as blocks and the new "DXF : textes des symboles en attributs" option (--dxf-attributes on the command line), a symbol's own texts (its label, function, comment...) are attributes of its INSERT instead of loose texts, so a CAD program moves them with the symbol and can list or edit them. Each is written exactly where, and as, the text was. A text showing an information field is tagged with its name (LABEL, FUNCTION...), a typed text TEXT1, TEXT2...; a text's second line gets _2. The block defines each tag once, placed where the first symbol has it. Its own option, off by default, because LibreCAD (2.2.1.5) does not show attributes: the labels would vanish there. AutoCAD shows them. The text geometry moves into textLines(), shared with the text loop, so the attributes and the plain texts cannot drift apart. Co-Authored-By: Claude Opus 5.5 --- sources/cli_export.cpp | 9 +- sources/cli_export.h | 5 +- sources/createdxf.cpp | 43 ++++++- sources/createdxf.h | 3 + sources/dxfexport.cpp | 181 ++++++++++++++++++++++----- sources/exportproperties.cpp | 5 + sources/exportproperties.h | 1 + sources/exportpropertieswidget.cpp | 12 ++ sources/exportpropertieswidget.h | 1 + tests/qttest/fixtures/dxf_blocks.qet | 20 ++- tests/qttest/tst_dxfblocks.cpp | 29 ++++- 11 files changed, 266 insertions(+), 43 deletions(-) diff --git a/sources/cli_export.cpp b/sources/cli_export.cpp index ec4185a86..fb2d94869 100644 --- a/sources/cli_export.cpp +++ b/sources/cli_export.cpp @@ -332,7 +332,7 @@ int exportImages(QETProject &project, const QString &format, /// (DxfExport) with the dialog's default options -- the export settings of /// the preferences -- so both give the same file. int exportDxf(QETProject &project, const QString &out_dir, bool showTerminals, - bool dxfBlocks) + bool dxfBlocks, bool dxfAttributes) { const QList diagrams = project.diagrams(); if (diagrams.isEmpty()) { @@ -345,8 +345,10 @@ int exportDxf(QETProject &project, const QString &out_dir, bool showTerminals, properties.format = QStringLiteral("DXF"); if (showTerminals) properties.draw_terminals = true; - if (dxfBlocks) + if (dxfBlocks || dxfAttributes) properties.dxf_blocks = true; + if (dxfAttributes) + properties.dxf_attributes = true; int index = 0; bool has_images = false; @@ -986,6 +988,7 @@ int run(const QStringList &args) QStringList filtered = args; const bool showTerminals = filtered.removeAll("--show-terminals") > 0; const bool dxfBlocks = filtered.removeAll("--dxf-blocks") > 0; + const bool dxfAttributes = filtered.removeAll("--dxf-attributes") > 0; // --no-slaves and --no-junctions leave rows out of --export-bom. const bool includeSlaves = filtered.removeAll("--no-slaves") == 0; const bool includeJunctions = filtered.removeAll("--no-junctions") == 0; @@ -1042,7 +1045,7 @@ int run(const QStringList &args) if (format == "pdf") return exportPdf(project, output, showTerminals); if (format == "dxf") - return exportDxf(project, output, showTerminals, dxfBlocks); + return exportDxf(project, output, showTerminals, dxfBlocks, dxfAttributes); if (format == "cables" || format == "wires") return exportCsv(project, format, output); if (format == "bom") diff --git a/sources/cli_export.h b/sources/cli_export.h index 1838fa347..efb3ad59e 100644 --- a/sources/cli_export.h +++ b/sources/cli_export.h @@ -45,7 +45,7 @@ namespace CLIExport { qelectrotech --export-pdf [--show-terminals] qelectrotech --export-png [--show-terminals] qelectrotech --export-svg [--show-terminals] - qelectrotech --export-dxf [--show-terminals] [--dxf-blocks] + qelectrotech --export-dxf [--show-terminals] [--dxf-blocks] [--dxf-attributes] qelectrotech --export-cables qelectrotech --export-wires qelectrotech --export-bom [--no-slaves] [--no-junctions] @@ -68,6 +68,9 @@ namespace CLIExport { the list export modes. --dxf-blocks: write each symbol as a DXF block, placed with one INSERT per use, so a CAD program selects it as one object. + --dxf-attributes: as --dxf-blocks, and a symbol's texts (its label, + function...) are attributes of its INSERT. LibreCAD does not + show attributes. cables: wiring list (one row per conductor) as CSV. wires: list of distinct wire numbers as CSV. bom: bill of materials (one row per element) as CSV. diff --git a/sources/createdxf.cpp b/sources/createdxf.cpp index bb4e3223c..36c42fbf3 100644 --- a/sources/createdxf.cpp +++ b/sources/createdxf.cpp @@ -393,7 +393,7 @@ void Createdxf::drawInsert(const QString &fileName, To_Dxf << 0 << "\r\n"; To_Dxf << "ATTRIB" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << layer << "\r\n"; + To_Dxf << (attribute.layer.isEmpty() ? layer : attribute.layer) << "\r\n"; To_Dxf << 62 << "\r\n"; To_Dxf << entityColour(attribute.colour) << "\r\n"; To_Dxf << 10 << "\r\n"; @@ -424,6 +424,47 @@ void Createdxf::drawInsert(const QString &fileName, file.close(); } +/** + @brief Createdxf::drawAttdef + Define an attribute of the block being written (between + dxfBlockBegin() and dxfBlockEnd()): its tag, where it sits and how it + looks; @a attribute's text is the default value. +*/ +void Createdxf::drawAttdef(const QString &fileName, const Attribute &attribute) +{ + QFile file(fileName); + if (!file.open(QFile::Append)) + return; + QTextStream To_Dxf(&file); + To_Dxf << 0 << "\r\n"; + To_Dxf << "ATTDEF" << "\r\n"; + To_Dxf << 8 << "\r\n"; + To_Dxf << (attribute.layer.isEmpty() ? layer : attribute.layer) << "\r\n"; + To_Dxf << 62 << "\r\n"; + To_Dxf << entityColour(attribute.colour) << "\r\n"; + To_Dxf << 10 << "\r\n"; + To_Dxf << attribute.x << "\r\n"; + To_Dxf << 20 << "\r\n"; + To_Dxf << attribute.y << "\r\n"; + To_Dxf << 30 << "\r\n"; + To_Dxf << 0.0 << "\r\n"; + To_Dxf << 40 << "\r\n"; + To_Dxf << attribute.height << "\r\n"; + To_Dxf << 1 << "\r\n"; + To_Dxf << singleLine(attribute.text) << "\r\n"; + To_Dxf << 3 << "\r\n"; + To_Dxf << attribute.tag << "\r\n"; + To_Dxf << 2 << "\r\n"; + To_Dxf << attribute.tag << "\r\n"; + To_Dxf << 70 << "\r\n"; + To_Dxf << (attribute.invisible ? 1 : 0) << "\r\n"; + To_Dxf << 50 << "\r\n"; + To_Dxf << attribute.rotation << "\r\n"; + To_Dxf << 41 << "\r\n"; + To_Dxf << attribute.xScaleW << "\r\n"; + file.close(); +} + /** @brief Createdxf::blockName @return @a name as a block or attribute name an R10 reader accepts: diff --git a/sources/createdxf.h b/sources/createdxf.h index 87d15c6b9..47d3cd24c 100644 --- a/sources/createdxf.h +++ b/sources/createdxf.h @@ -54,6 +54,7 @@ class Createdxf double xScaleW = 1; int colour = 0; bool invisible = false; + QString layer; ///< empty: the INSERT's layer }; static void drawInsert(const QString &fileName, const QString &name, @@ -61,6 +62,8 @@ class Createdxf double y, double rotation, const QList &attributes = {}); + static void drawAttdef(const QString &fileName, + const Attribute &attribute); static QString blockName(const QString &name); // you can add more functions to create more drawings. static void drawCircle( diff --git a/sources/dxfexport.cpp b/sources/dxfexport.cpp index c04cdc71c..db46ffd59 100644 --- a/sources/dxfexport.cpp +++ b/sources/dxfexport.cpp @@ -149,6 +149,65 @@ namespace { } } + /// One line of a text as the export writes it: where it starts, in + /// scene coordinates, its size, and its angle (degrees, clockwise) + struct TextLine + { + QString text; + QPointF pos; + qreal font_size; + qreal angle; + }; + + /// The lines of @a dti that are written, one under the other as drawn + QList textLines(DiagramTextItem *dti) + { + qreal fontSize = dti -> font().pointSizeF(); + if (fontSize < 0) + fontSize = dti -> font().pixelSize(); + + qreal angle = dti -> rotation(); + + QGraphicsItem *parent = dti->parentItem(); + while (parent) { + angle += parent->rotation(); + parent = parent->parentItem(); + } + + qreal angler = angle * M_PI/180; + int xdir = -sin(angler); + int ydir = -cos(angler); + qreal x = (dti->scenePos().x()) + + xdir * fontSize * 1.8 + - ydir * fontSize; + qreal y = dti->scenePos().y() + - ydir * fontSize * 1.8 + - xdir * fontSize * 0.9; + //As drawn: a text with a width is wrapped + QStringList lines = TextLines::layoutLines(dti -> document()); + qreal offset = fontSize * 1.6; + QList result; + foreach (QString line, lines) { + if (line.size() > 0 && line != "_" ) + result << TextLine{line, QPointF(x, y), fontSize, angle}; + x += offset * xdir; + y -= offset * ydir; + } + return result; + } + + /// @a tag, or @a tag with _2, _3... if @a used has it, at most 31 + /// characters + QString uniqueTag(const QString &tag, const QSet &used) + { + QString unique = tag; + for (int i = 2 ; used.contains(unique) ; ++i) { + const QString suffix = QStringLiteral("_%1").arg(i); + unique = tag.left(31 - suffix.size()) + suffix; + } + return unique; + } + /// Nothing would be drawn for @a elmt (its definition is missing) bool drawsNothing(Element *elmt, bool draw_terminals) { @@ -304,14 +363,92 @@ void DxfExport::write(Diagram *diagram, int width, int height, } } + //With dxf_attributes, a symbol's own texts (its label, its + //function...) become attributes of its INSERT, written where the + //text would be, so a CAD program moves them with the symbol and + //lists them. Off by default: LibreCAD does not show attributes, + //so the labels would vanish there. Tagged + //with the information they show (LABEL, FUNCTION...), or TEXT1, + //TEXT2... for a typed text; a second line gets _2. The block + //defines each tag once, where the first symbol has it. + QHash> attributes; + QHash> attribute_definitions; // block -> ATTDEFs + QSet attribute_texts; + { + QHash> used_tags; + QHash typed_texts; + QHash> defined_tags; + for (DiagramTextItem *dti : std::as_const(list_texts)) { + if (!properties.dxf_attributes) + break; + auto *deti = qgraphicsitem_cast(dti); + Element *elmt = deti ? deti -> parentElement() : nullptr; + const QString block = elmt + ? block_names.value(elmt -> location().toString()) + : QString(); + if (block.isEmpty()) + continue; + + const QString base = + deti -> textFrom() == DynamicElementTextItem::ElementInfo + && !deti -> infoName().isEmpty() + ? Createdxf::blockName(deti -> infoName()) + : QStringLiteral("TEXT%1").arg(++typed_texts[elmt]); + //From the folio into the block: undo the INSERT + const QPointF insert(elmt -> pos().x() * Createdxf::xScale, + Createdxf::sheetHeight - elmt -> pos().y() * Createdxf::yScale); + const double turn = std::fmod(360 - elmt -> orientation() * 90, 360); + const QTransform to_block = QTransform() + .translate(0, Createdxf::sheetHeight) + .rotate(-turn) + .translate(-insert.x(), -insert.y()); + + const QList lines = textLines(dti); + for (int i = 0 ; i < lines.size() ; ++i) { + const TextLine &line = lines.at(i); + const QString tag = uniqueTag( + i == 0 ? base : base + QStringLiteral("_%1").arg(i + 1), + used_tags.value(elmt)); + used_tags[elmt] << tag; + + Createdxf::Attribute attribute; + attribute.tag = tag; + attribute.text = line.text; + attribute.x = line.pos.x() * Createdxf::xScale; + attribute.y = Createdxf::sheetHeight - line.pos.y() * Createdxf::yScale; + attribute.height = line.font_size * Createdxf::yScale; + attribute.rotation = 360 - line.angle; + attribute.xScaleW = 0.72; + attribute.colour = Createdxf::dxfColor(dti -> color()); + attribute.layer = Layer::SymbolTexts; + attributes[elmt] << attribute; + + if (!defined_tags[block].contains(tag)) { + defined_tags[block] << tag; + Createdxf::Attribute definition = attribute; + const QPointF in_block = to_block.map(QPointF(attribute.x, attribute.y)); + definition.x = in_block.x(); + definition.y = in_block.y(); + definition.rotation = std::fmod(attribute.rotation - turn + 720, 360); + definition.text.clear(); + attribute_definitions[block] << definition; + } + } + attribute_texts << dti; + } + } + //A block is drawn as if its symbol sat unturned at the folio's //origin, which is DXF (0, sheetHeight); that is its base point. Createdxf::dxfBegin(file_path, Layer::all(), [&]() { for (Element *model : std::as_const(block_models)) { - Createdxf::dxfBlockBegin(file_path, - block_names.value(model -> location().toString()), - 0, Createdxf::sheetHeight); + const QString block = block_names.value(model -> location().toString()); + const QList definitions = attribute_definitions.value(block); + Createdxf::dxfBlockBegin(file_path, block, 0, Createdxf::sheetHeight, + !definitions.isEmpty()); drawSymbol(file_path, model, 0, 0, 0, properties.draw_terminals); + for (const Createdxf::Attribute &definition : definitions) + Createdxf::drawAttdef(file_path, definition); Createdxf::dxfBlockEnd(file_path); } }); @@ -354,7 +491,8 @@ void DxfExport::write(Diagram *diagram, int width, int height, Createdxf::drawInsert(file_path, block, elem_pos_x * Createdxf::xScale, Createdxf::sheetHeight - elem_pos_y * Createdxf::yScale, - std::fmod(360 - rotation_angle, 360)); + std::fmod(360 - rotation_angle, 360), + attributes.value(elmt)); } } @@ -417,39 +555,14 @@ void DxfExport::write(Diagram *diagram, int width, int height, //Draw text items foreach(DiagramTextItem *dti, list_texts) { + //Already written as an attribute of its symbol's INSERT + if (attribute_texts.contains(dti)) + continue; //A free text, or a symbol's own text (its label and the like) Createdxf::layer = qgraphicsitem_cast(dti) ? Layer::Texts : Layer::SymbolTexts; - qreal fontSize = dti -> font().pointSizeF(); - if (fontSize < 0) - fontSize = dti -> font().pixelSize(); - - qreal angle = dti -> rotation(); - - QGraphicsItem *parent = dti->parentItem(); - while (parent) { - angle += parent->rotation(); - parent = parent->parentItem(); - } - - qreal angler = angle * M_PI/180; - int xdir = -sin(angler); - int ydir = -cos(angler); - qreal x = (dti->scenePos().x()) - + xdir * fontSize * 1.8 - - ydir * fontSize; - qreal y = dti->scenePos().y() - - ydir * fontSize * 1.8 - - xdir * fontSize * 0.9; - //As drawn: a text with a width is wrapped - QStringList lines = TextLines::layoutLines(dti -> document()); - qreal offset = fontSize * 1.6; - foreach (QString line, lines) { - if (line.size() > 0 && line != "_" ) - Createdxf::drawText(file_path, line, QPointF(x, y), fontSize, 360-angle, Createdxf::dxfColor(dti->color()), 0.72 ); - x += offset * xdir; - y -= offset * ydir; - } + for (const TextLine &line : textLines(dti)) + Createdxf::drawText(file_path, line.text, line.pos, line.font_size, 360-line.angle, Createdxf::dxfColor(dti->color()), 0.72 ); } //Draw the slave cross-reference labels diff --git a/sources/exportproperties.cpp b/sources/exportproperties.cpp index 3f11f213e..cd53bc806 100644 --- a/sources/exportproperties.cpp +++ b/sources/exportproperties.cpp @@ -38,6 +38,7 @@ ExportProperties::ExportProperties() : draw_bg_transparent(false), draw_colored_conductors(true), dxf_blocks(false), + dxf_attributes(false), exported_area(QET::BorderArea) { } @@ -80,6 +81,8 @@ void ExportProperties::toSettings(QSettings &settings, draw_colored_conductors); settings.setValue(prefix % "dxfblocks", dxf_blocks); + settings.setValue(prefix % "dxfattributes", + dxf_attributes); settings.setValue(prefix % "area", QET::diagramAreaToString(exported_area)); } @@ -120,6 +123,8 @@ void ExportProperties::fromSettings(QSettings &settings, true ).toBool(); dxf_blocks = settings.value(prefix % "dxfblocks", false).toBool(); + dxf_attributes = settings.value(prefix % "dxfattributes", + false).toBool(); exported_area = QET::diagramAreaFromString( settings.value( diff --git a/sources/exportproperties.h b/sources/exportproperties.h index c9489496a..c8feca461 100644 --- a/sources/exportproperties.h +++ b/sources/exportproperties.h @@ -51,6 +51,7 @@ class ExportProperties { bool draw_bg_transparent; ///< Whether to use transparency for SVG-Export bool draw_colored_conductors; ///< Whether to render conductors colors bool dxf_blocks; ///< DXF: each symbol as a block, placed with an INSERT + bool dxf_attributes; ///< DXF, with dxf_blocks: a symbol's texts as attributes of its INSERT QET::DiagramArea exported_area; ///< Area of diagrams to be rendered }; #endif diff --git a/sources/exportpropertieswidget.cpp b/sources/exportpropertieswidget.cpp index e95a5cb6d..0ce0dac46 100644 --- a/sources/exportpropertieswidget.cpp +++ b/sources/exportpropertieswidget.cpp @@ -67,6 +67,7 @@ ExportProperties ExportPropertiesWidget::exportProperties() const export_properties.draw_bg_transparent = draw_bg_transparent -> isChecked(); export_properties.draw_colored_conductors = draw_colored_conductors -> isChecked(); export_properties.dxf_blocks = dxf_blocks -> isChecked(); + export_properties.dxf_attributes = dxf_attributes -> isChecked(); export_properties.exported_area = export_border -> isChecked() ? QET::BorderArea : QET::ElementsArea; return(export_properties); @@ -91,6 +92,8 @@ void ExportPropertiesWidget::setExportProperties(const ExportProperties &export_ draw_bg_transparent -> setChecked(export_properties.draw_bg_transparent); draw_colored_conductors -> setChecked(export_properties.draw_colored_conductors); dxf_blocks -> setChecked(export_properties.dxf_blocks); + dxf_attributes -> setChecked(export_properties.dxf_attributes); + dxf_attributes -> setEnabled(export_properties.dxf_blocks); if (export_properties.exported_area == QET::BorderArea) { export_border -> setChecked(true); @@ -226,6 +229,12 @@ void ExportPropertiesWidget::build() dxf_blocks = new QCheckBox(tr("DXF : symboles en blocs"), groupbox_options); dxf_blocks -> setToolTip(tr("Chaque symbole devient un bloc DXF, sélectionnable d'un clic dans un logiciel de CAO")); optionshlayout -> addWidget(dxf_blocks, 4, 1); + + // with blocks, a symbol's texts as attributes of its block + dxf_attributes = new QCheckBox(tr("DXF : textes des symboles en attributs"), groupbox_options); + dxf_attributes -> setToolTip(tr("Les textes d'un symbole (repère, fonction...) deviennent des attributs de son bloc. LibreCAD n'affiche pas les attributs.")); + optionshlayout -> addWidget(dxf_attributes, 5, 1); + connect(dxf_blocks, &QCheckBox::toggled, dxf_attributes, &QCheckBox::setEnabled); vboxLayout -> addWidget(groupbox_options); @@ -242,6 +251,7 @@ void ExportPropertiesWidget::build() setTabOrder(draw_terminals, draw_colored_conductors); setTabOrder(draw_colored_conductors, draw_bg_transparent); setTabOrder(draw_bg_transparent, dxf_blocks); + setTabOrder(dxf_blocks, dxf_attributes); // connexion du bouton permettant le choix du repertoire connect(button_browse, &QPushButton::released, this, &ExportPropertiesWidget::slot_chooseADirectory); @@ -258,6 +268,7 @@ void ExportPropertiesWidget::build() connect(draw_bg_transparent, &QCheckBox::stateChanged, this, &ExportPropertiesWidget::optionChanged); connect(draw_colored_conductors, &QCheckBox::stateChanged, this, &ExportPropertiesWidget::optionChanged); connect(dxf_blocks, &QCheckBox::stateChanged, this, &ExportPropertiesWidget::optionChanged); + connect(dxf_attributes, &QCheckBox::stateChanged, this, &ExportPropertiesWidget::optionChanged); #else connect(draw_grid, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); connect(draw_border, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); @@ -267,5 +278,6 @@ void ExportPropertiesWidget::build() connect(draw_bg_transparent, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); connect(draw_colored_conductors, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); connect(dxf_blocks, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); + connect(dxf_attributes, &QCheckBox::checkStateChanged, this, &ExportPropertiesWidget::optionChanged); #endif } diff --git a/sources/exportpropertieswidget.h b/sources/exportpropertieswidget.h index f00032c65..5b96e4273 100644 --- a/sources/exportpropertieswidget.h +++ b/sources/exportpropertieswidget.h @@ -66,6 +66,7 @@ class ExportPropertiesWidget : public QWidget { QCheckBox *draw_bg_transparent; QCheckBox *draw_colored_conductors; QCheckBox *dxf_blocks; + QCheckBox *dxf_attributes; QRadioButton *export_border; QRadioButton *export_elements; QButtonGroup *exported_content_choices; diff --git a/tests/qttest/fixtures/dxf_blocks.qet b/tests/qttest/fixtures/dxf_blocks.qet index ffd6f9c4f..a1118d8e8 100644 --- a/tests/qttest/fixtures/dxf_blocks.qet +++ b/tests/qttest/fixtures/dxf_blocks.qet @@ -29,13 +29,29 @@ - + + K1 + + + + K1 + label + + - + + K2 + + + + K2 + label + + diff --git a/tests/qttest/tst_dxfblocks.cpp b/tests/qttest/tst_dxfblocks.cpp index bc409c85d..5857f96c9 100644 --- a/tests/qttest/tst_dxfblocks.cpp +++ b/tests/qttest/tst_dxfblocks.cpp @@ -21,8 +21,9 @@ /** --export-dxf --dxf-blocks (issue #1339): a symbol placed twice is one - BLOCK and two INSERTs, the second turned a quarter; without the switch - there is neither. + 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. */ class tst_dxfblocks : public QObject { @@ -82,6 +83,29 @@ private slots: QCOMPARE(values(pairs, QStringLiteral("CIRCLE"), QStringLiteral("8")).size(), 1); } + void labelsAsAttributes() + { + 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")})); + //Defined once in the block, and no longer a loose text + QCOMPARE(values(pairs, QStringLiteral("ATTDEF"), QStringLiteral("2")), + QStringList{QStringLiteral("LABEL")}); + QVERIFY(!values(pairs, QStringLiteral("TEXT"), QStringLiteral("1")).contains(QStringLiteral("K1"))); + } + + void labelsStayTextsWithBlocksOnly() + { + const auto pairs = exportPairs({QStringLiteral("--dxf-blocks")}); + QVERIFY2(!pairs.isEmpty(), "--export-dxf --dxf-blocks failed"); + QVERIFY(values(pairs, QStringLiteral("ATTRIB"), QStringLiteral("2")).isEmpty()); + QVERIFY(values(pairs, QStringLiteral("TEXT"), QStringLiteral("1")).contains(QStringLiteral("K1"))); + } + void flatWithoutSwitch() { const auto pairs = exportPairs({}); @@ -89,6 +113,7 @@ private slots: QVERIFY(values(pairs, QStringLiteral("BLOCK"), QStringLiteral("2")).isEmpty()); QVERIFY(values(pairs, QStringLiteral("INSERT"), QStringLiteral("2")).isEmpty()); QCOMPARE(values(pairs, QStringLiteral("CIRCLE"), QStringLiteral("8")).size(), 2); + QVERIFY(values(pairs, QStringLiteral("TEXT"), QStringLiteral("1")).contains(QStringLiteral("K1"))); } };