diff --git a/sources/bordertitleblock.cpp b/sources/bordertitleblock.cpp index 7878d1a9f..f63877eb4 100644 --- a/sources/bordertitleblock.cpp +++ b/sources/bordertitleblock.cpp @@ -19,6 +19,7 @@ #include "bordercelllabels.h" #include "createdxf.h" +#include "dxfexport.h" #include "diagram.h" #include "diagramposition.h" #include "math.h" @@ -706,6 +707,7 @@ void BorderTitleBlock::drawDxf( // render the titleblock, using the TitleBlockTemplate object if (display_titleblock_) { + Createdxf::layer = DxfExport::Layer::TitleBlock; //qp -> translate(titleblock_rect_.topLeft()); QRectF rect = titleBlockRect(); m_titleblock_template_renderer -> renderDxf(rect, diff --git a/sources/createdxf.cpp b/sources/createdxf.cpp index 28fff363e..87cd2c91a 100644 --- a/sources/createdxf.cpp +++ b/sources/createdxf.cpp @@ -42,6 +42,7 @@ namespace { } } double Createdxf::yScale = 1; +QString Createdxf::layer = QStringLiteral("0"); Createdxf::Createdxf() { @@ -51,9 +52,12 @@ Createdxf::~Createdxf() { } -/* Header section of every DXF file.*/ -void Createdxf::dxfBegin (const QString& fileName) +/* Header section of every DXF file. + @param layers : the layers the entities will be written on, declared in + the LAYER table beside layer "0", which every DXF has. */ +void Createdxf::dxfBegin (const QString& fileName, const QStringList &layers) { + layer = QStringLiteral("0"); // Creation of an output stream object in text mode. // Header section of every dxf file. @@ -223,6 +227,35 @@ void Createdxf::dxfBegin (const QString& fileName) To_Dxf << 0.00 << "\r\n"; To_Dxf << 0 << "\r\n"; + To_Dxf << "ENDTAB" << "\r\n"; + + // Layers: "0" plus the ones the entities use, all white/black + // (colour 7) and continuous, so a file looks the same as before + // until the user changes a layer. + QStringList all_layers{QStringLiteral("0")}; + for (const QString &name : layers) { + if (!all_layers.contains(name)) + all_layers << name; + } + To_Dxf << 0 << "\r\n"; + To_Dxf << "TABLE" << "\r\n"; + To_Dxf << 2 << "\r\n"; + To_Dxf << "LAYER" << "\r\n"; + To_Dxf << 70 << "\r\n"; + To_Dxf << all_layers.size() << "\r\n"; + for (const QString &name : std::as_const(all_layers)) { + To_Dxf << 0 << "\r\n"; + To_Dxf << "LAYER" << "\r\n"; + To_Dxf << 2 << "\r\n"; + To_Dxf << name << "\r\n"; + To_Dxf << 70 << "\r\n"; + To_Dxf << 0 << "\r\n"; + To_Dxf << 62 << "\r\n"; + To_Dxf << 7 << "\r\n"; + To_Dxf << 6 << "\r\n"; + To_Dxf << "CONTINUOUS" << "\r\n"; + } + To_Dxf << 0 << "\r\n"; To_Dxf << "ENDTAB" << "\r\n"; To_Dxf << 0 << "\r\n"; To_Dxf << "ENDSEC" << "\r\n"; @@ -248,6 +281,7 @@ void Createdxf::dxfBegin (const QString& fileName) */ void Createdxf::dxfEnd(const QString& fileName) { + layer = QStringLiteral("0"); // Creation of an output stream object in text mode. if (!fileName.isEmpty()) { QFile file(fileName); @@ -298,7 +332,7 @@ void Createdxf::drawCircle( To_Dxf << 0 << "\r\n"; To_Dxf << "CIRCLE" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << colour << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ is the Center point of circle @@ -346,7 +380,7 @@ void Createdxf::drawLine ( To_Dxf << 0 << "\r\n"; To_Dxf << "LINE" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << colour << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; @@ -671,7 +705,7 @@ void Createdxf::drawArc( To_Dxf << 0 << "\r\n"; To_Dxf << "ARC" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << color << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ is the Center point of circle @@ -727,7 +761,7 @@ void Createdxf::drawText( To_Dxf << 0 << "\r\n"; To_Dxf << "TEXT" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << colour << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ @@ -780,7 +814,7 @@ void Createdxf::drawTextAligned( To_Dxf << 0 << "\r\n"; To_Dxf << "TEXT" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << colour << "\r\n"; // Colour Code To_Dxf << 10 << "\r\n"; // XYZ @@ -861,7 +895,7 @@ void Createdxf::drawPolyline(const QString &filepath, To_Dxf << 0 << "\r\n"; To_Dxf << "POLYLINE" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 62 << "\r\n"; To_Dxf << colorcode << "\r\n"; // Colour Code To_Dxf << 66 << "\r\n"; @@ -887,7 +921,7 @@ void Createdxf::drawPolyline(const QString &filepath, To_Dxf << 0 << "\r\n"; To_Dxf << "VERTEX" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name To_Dxf << 70 << "\r\n"; To_Dxf << 32 << "\r\n"; To_Dxf << 10 << "\r\n"; @@ -901,7 +935,7 @@ void Createdxf::drawPolyline(const QString &filepath, To_Dxf << 0 << "\r\n"; To_Dxf << "SEQEND" << "\r\n"; To_Dxf << 8 << "\r\n"; - To_Dxf << 0 << "\r\n"; // Layer number (default layer in autocad) + To_Dxf << layer << "\r\n"; // Layer name file.close(); } diff --git a/sources/createdxf.h b/sources/createdxf.h index b2ef93e7a..5fb042e82 100644 --- a/sources/createdxf.h +++ b/sources/createdxf.h @@ -18,6 +18,7 @@ #ifndef CREATEDXF_H #define CREATEDXF_H #include +#include #include #include @@ -30,7 +31,7 @@ class Createdxf public: Createdxf(); ~Createdxf(); - static void dxfBegin (const QString&); + static void dxfBegin (const QString&, const QStringList &layers = QStringList()); static void dxfEnd(const QString&); // you can add more functions to create more drawings. static void drawCircle( @@ -159,6 +160,9 @@ class Createdxf static const double sheetHeight; static double xScale; static double yScale; + /// Layer every entity is written on, "0" unless set; the + /// layers themselves are declared by dxfBegin() (discussion #1071). + static QString layer; }; #endif // CREATEDXF_H diff --git a/sources/dxfexport.cpp b/sources/dxfexport.cpp index 7d3d8818e..0ac1182b8 100644 --- a/sources/dxfexport.cpp +++ b/sources/dxfexport.cpp @@ -81,8 +81,12 @@ void DxfExport::write(Diagram *diagram, int width, int height, Createdxf::xScale = Createdxf::sheetWidth / double(width); Createdxf::yScale = Createdxf::sheetHeight / double(height); - Createdxf::dxfBegin(file_path); + Createdxf::dxfBegin(file_path, Layer::all()); + //Each kind of content on its own layer (discussion #1071). The + //border's title block switches to Layer::TitleBlock itself, see + //BorderTitleBlock::drawDxf(). + Createdxf::layer = Layer::Border; //Add project elements (lines, rectangles, circles, texts) to dxf file if (properties.draw_border) { QRectF rect(Diagram::margin,Diagram::margin,width,height); @@ -154,9 +158,11 @@ void DxfExport::write(Diagram *diagram, int width, int height, } // Draw shapes + Createdxf::layer = Layer::Shapes; foreach (QetShapeItem *qsi, list_shapes) qsi->toDXF(file_path, qsi->pen()); // Draw tables + Createdxf::layer = Layer::Tables; foreach (QetGraphicsTableItem *gti, list_tables) { gti->toDXF(file_path); } @@ -171,6 +177,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, ElementPictureFactory::primitives primitives = ElementPictureFactory::instance()->getPrimitives(elmt->location()); + Createdxf::layer = Layer::SymbolTexts; for(QGraphicsSimpleTextItem *text : primitives.m_texts) { qreal fontSize = text->font().pointSizeF(); @@ -200,6 +207,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, } } + Createdxf::layer = Layer::Symbols; for (QLineF line : primitives.m_lines) { QTransform t = QTransform().translate(elem_pos_x,elem_pos_y).rotate(rotation_angle); @@ -249,6 +257,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, Createdxf::drawArcEllipse(file_path, r, startAngle, spanAngle, hotspot, rotation_angle, 0); } if (properties.draw_terminals) { + Createdxf::layer = Layer::Terminals; // Draw terminals QList list_terminals = elmt->terminals(); QColor col("red"); @@ -272,8 +281,10 @@ void DxfExport::write(Diagram *diagram, int width, int height, } poly << cond->pos()+segment->secondPoint(); } + Createdxf::layer = Layer::Wires; Createdxf::drawPolyline(file_path,poly,0); //Draw conductor text item + Createdxf::layer = Layer::WireNumbers; ConductorTextItem *textItem = cond -> textItem(); if (textItem) { @@ -302,6 +313,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, } // Draw the junctions + Createdxf::layer = Layer::Junctions; QList junctions_list = cond->junctions(); if (!junctions_list.isEmpty()) { foreach(QPointF point, junctions_list) { @@ -312,6 +324,9 @@ void DxfExport::write(Diagram *diagram, int width, int height, //Draw text items foreach(DiagramTextItem *dti, list_texts) { + //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(); @@ -344,6 +359,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, } //Draw the slave cross-reference labels + Createdxf::layer = Layer::Xrefs; for (QGraphicsTextItem *xref : std::as_const(list_xref_texts)) { qreal fontSize = xref->font().pointSizeF(); @@ -382,6 +398,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, //Draw the master-side cross-reference items (table/cross), replaying //their existing paint() unmodified through DxfPaintEngine instead of //hand-porting drawAsCross()/drawAsContacts()/drawAsPlcTable(). + Createdxf::layer = Layer::Xrefs; for (CrossRefItem *xref : std::as_const(list_master_xrefs)) { DxfPaintDevice dxf_device(file_path); @@ -401,6 +418,7 @@ void DxfExport::write(Diagram *diagram, int width, int height, //actually turns the drawPixmap() call inside paint() into a //placeholder outline, since this DXF dialect has no raster image //entity to draw instead. + Createdxf::layer = Layer::Images; for (DiagramImageItem *image : std::as_const(list_images)) { DxfPaintDevice dxf_device(file_path); diff --git a/sources/dxfexport.h b/sources/dxfexport.h index e1c98e5bb..b9f1c0b2d 100644 --- a/sources/dxfexport.h +++ b/sources/dxfexport.h @@ -21,6 +21,7 @@ #include #include #include +#include class Diagram; class ExportProperties; @@ -32,6 +33,34 @@ class ExportProperties; */ namespace DxfExport { + /// The layers of an exported folio (discussion #1071). Fixed and + /// untranslated, so a CAD user's layer filters and scripts work + /// whatever language QElectroTech runs in; prefixed so they sort + /// together and do not clash with the recipient's own layers. + namespace Layer + { + inline const QString Border = QStringLiteral("QET_BORDER"); + inline const QString TitleBlock = QStringLiteral("QET_TITLEBLOCK"); + inline const QString Symbols = QStringLiteral("QET_SYMBOLS"); + inline const QString SymbolTexts = QStringLiteral("QET_SYMBOL_TEXTS"); + inline const QString Terminals = QStringLiteral("QET_TERMINALS"); + inline const QString Wires = QStringLiteral("QET_WIRES"); + inline const QString WireNumbers = QStringLiteral("QET_WIRE_NUMBERS"); + inline const QString Junctions = QStringLiteral("QET_JUNCTIONS"); + inline const QString Texts = QStringLiteral("QET_TEXTS"); + inline const QString Xrefs = QStringLiteral("QET_XREFS"); + inline const QString Shapes = QStringLiteral("QET_SHAPES"); + inline const QString Tables = QStringLiteral("QET_TABLES"); + inline const QString Images = QStringLiteral("QET_IMAGES"); + + inline QStringList all() + { + return {Border, TitleBlock, Symbols, SymbolTexts, Terminals, + Wires, WireNumbers, Junctions, Texts, Xrefs, Shapes, + Tables, Images}; + } + } + QSize folioSize(Diagram *diagram, const ExportProperties &properties); void write(Diagram *diagram, int width, int height, const QString &path, const ExportProperties &properties);