From b034b1a634da009a0a2dbb2405d8d2a185d175b1 Mon Sep 17 00:00:00 2001 From: ispyisail Date: Fri, 21 Aug 2026 21:06:41 +1200 Subject: [PATCH] Add --export-wiring: the wiring list, headless The wiring_list_view added by this slice was only reachable through the GUI, which meant the one thing worth proving about it -- that it still describes the project -- could not be checked without a person clicking. This is the same shape as the existing --export-bom, which reads element_nomenclature_view, and it makes the view verifiable in CI. It also makes this slice useful on its own: a from-to wiring list is a thing people want as a CSV, and it no longer waits on the dialog in the next slice. There is deliberately an overlap with --export-cables, which produces the same logical list from the document XML rather than the database. Keeping both is the point: running them and diffing them is a direct check that the cache and the document still agree, which nothing else in the codebase can do. Measured on the example corpus, the two also differ in what they can actually fill in. Rows carrying any endpoint data: --export-cables --export-wiring industrial.qet 0 / 671 541 / 671 m_000.qet 0 / 457 362 / 457 affuteuse_250h.qet 0 / 263 197 / 263 tremie_vibrante.qet 0 / 77 61 / 77 tableau_domestique.qet 58 / 130 104 / 130 Both return a row per conductor; the XML-derived one leaves the component and terminal columns empty on the older projects, and emits an unresolved "%id" in its folio column. That is not an argument for removing it -- it carries columns the view does not, and it is the independent second opinion -- but it does mean the database path is the one with the data on the projects people actually have. The terminal-name columns come back empty on most projects. That is absent source data, not a loss in transit: tableau_domestique.qet has no terminal name on 457 of 457 terminals, and industrial.qet stores the "_" placeholder on 1421 of 1790. Co-Authored-By: Claude Opus 5 --- sources/cli_export.cpp | 51 ++++++++++++++++++++++++++++++++++++++++++ sources/cli_export.h | 6 +++++ 2 files changed, 57 insertions(+) diff --git a/sources/cli_export.cpp b/sources/cli_export.cpp index add222935..526207971 100644 --- a/sources/cli_export.cpp +++ b/sources/cli_export.cpp @@ -70,6 +70,7 @@ const QHash &exportFlags() {"--export-cables", "cables"}, {"--export-wires", "wires"}, {"--export-bom", "bom"}, + {"--export-wiring", "wiring"}, {"--export-nets", "nets"}, {"--export-links", "links"}, {"--info", "info"}, @@ -525,6 +526,54 @@ QHash folioIndex(QETProject &project) return folio; } +/// From-to wiring list: one row per conductor, each endpoint resolved to its +/// element label and terminal name. +/// +/// Reads wiring_list_view out of the project database. --export-cables produces +/// the same logical list from the document XML instead, and the two are meant +/// to agree: running both and diffing them is a direct check that the database +/// still describes the project, which is otherwise only observable through the +/// GUI. +int exportWiring(QETProject &project, const QString &output) +{ + // The project database is built lazily; force a (re)build before querying. + project.dataBase()->updateDB(); + + static const QStringList columns { + "wire_number", "from_element_label", "from_terminal", + "to_element_label", "to_terminal", "diagram_position", "conductor_uuid" + }; + + QSqlQuery query = project.dataBase()->newQuery( + "SELECT " % columns.join(", ") % + " FROM wiring_list_view ORDER BY diagram_position, wire_number"); + if (!query.exec()) { + err << "Wiring list query failed: " << query.lastError().text() << "\n"; + return 1; + } + + QString csv = columns.join(";") % "\n"; + int rows = 0; + while (query.next()) { + QStringList values; + for (int i = 0; i < columns.size(); ++i) + values << csvField(query.value(i).toString()); + csv += values.join(";") % "\n"; + ++rows; + } + + QFile file(output); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + err << "Cannot open '" << output << "' for writing.\n"; + return 1; + } + QTextStream fout(&file); + fout << csv; + file.close(); + out << "Exported " << rows << " conductor(s) -> " << output << "\n"; + return 0; +} + /// Electrical nets: groups of terminals joined into one potential. /// Walks QET's own potential graph, so each net is a connected component /// of terminals across all folios. The ground truth for connectivity. @@ -823,6 +872,8 @@ int run(const QStringList &args) return exportCsv(project, format, output); if (format == "bom") return exportBom(project, output); + if (format == "wiring") + return exportWiring(project, output); if (format == "nets") return exportNets(project, output); if (format == "links") diff --git a/sources/cli_export.h b/sources/cli_export.h index 2354fbfc1..81380f43a 100644 --- a/sources/cli_export.h +++ b/sources/cli_export.h @@ -48,6 +48,7 @@ namespace CLIExport { qelectrotech --export-cables qelectrotech --export-wires qelectrotech --export-bom + qelectrotech --export-wiring qelectrotech --export-nets qelectrotech --export-links qelectrotech --info [output.json] @@ -60,6 +61,11 @@ namespace CLIExport { 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. + wiring: from-to wiring list (one row per conductor) as CSV, read from + the project database. Same logical list as `cables`, which + reads the document XML instead; the two are meant to agree, + so diffing them checks that the database still describes the + project. nets: electrical nets (connected-terminal groups) as JSON. links: element cross-references (coil/contact) as CSV, with unresolved links flagged.