mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-05 18:54:14 +02:00
checkContinuity: catch cross-folio report-link colour/style mismatches
New report_link_mismatch finding (severity "warning", not "error" the way potential_mismatch is): a next_report/previous_report folio-jump pair whose conductors disagree on colour, style, num, or any of the other checked properties. Unlike potential_mismatch, this one is not proof of external tampering -- LinkElementCommand::isLinkable() only ever checks type and freedom (see its own doc comment), never conductor properties, so nothing in QElectroTech copies one side's colour onto the other when a report link is made or keeps them in sync afterwards. This is a real, unenforced gap reachable through completely ordinary use, not a defect a script or the GUI could introduce. Reproduces qelectrotech/qelectrotech-source-mirror#974 exactly: downloaded the reporter's actual project, traced the mismatched wire to a "Folio suivant"/"Folio precedent" link pair, and confirmed via query that the two sides read color="#0000ff" and color="#55aa00" while the link's other four conductors (0V/Low/High/Ground) matched -- ruling out a rendering artifact. Verified fresh with a synthetic reproduction (tests in misc/qet-mcp) using the shipped 02going_arrow.elmt/ 01coming_arrow.elmt pair, giving exactly one finding, not one per folio-link conductor. Also fixes a real gap in the existing potential_mismatch check while here: checked_properties was missing "color" and "style" entirely, checking only "conductor_color" (ConductorProperties::m_wire_color, a separate free-text documentation field, typically empty) -- meaning the same-folio version of this exact bug class would have gone undetected too. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -3912,10 +3912,18 @@ QVariantList QetScriptApi::checkContinuity(int folioIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// "color"/"style" are the rendered pen -- what a person actually sees
|
||||
// as "this wire is blue" -- distinct from "conductor_color"
|
||||
// (ConductorProperties::m_wire_color), a separate free-text
|
||||
// documentation field that is typically empty and says nothing about
|
||||
// how the wire is drawn. A mismatch check that only covered the
|
||||
// documentation field would miss exactly the visible kind of
|
||||
// inconsistency a person would report (issue #974: the two halves of
|
||||
// one folio-link conductor drawn in different colours).
|
||||
static const QStringList checked_properties = {
|
||||
QStringLiteral("num"), QStringLiteral("conductor_color"),
|
||||
QStringLiteral("conductor_section"), QStringLiteral("function"),
|
||||
QStringLiteral("bus"), QStringLiteral("cable")};
|
||||
QStringLiteral("num"), QStringLiteral("color"), QStringLiteral("style"),
|
||||
QStringLiteral("conductor_color"), QStringLiteral("conductor_section"),
|
||||
QStringLiteral("function"), QStringLiteral("bus"), QStringLiteral("cable")};
|
||||
|
||||
QSet<Conductor *> visited;
|
||||
for (int f = 0; f < diagrams.count(); ++f) {
|
||||
@@ -3954,6 +3962,73 @@ QVariantList QetScriptApi::checkContinuity(int folioIndex)
|
||||
}
|
||||
}
|
||||
|
||||
// report_link_mismatch (warning, not error): a next_report/
|
||||
// previous_report pair -- QElectroTech's folio-jump-arrow links,
|
||||
// e.g. "Folio suivant"/"Folio précédent" -- is meant to represent one
|
||||
// wire continuing across a folio boundary, but LinkElementCommand::
|
||||
// isLinkable() only ever checks type and freedom (see its own doc
|
||||
// comment), never conductor properties. Nothing in QElectroTech
|
||||
// copies one side's colour/style/num onto the other when the link is
|
||||
// made, or keeps them in sync afterwards, so this is a real,
|
||||
// unenforced gap rather than something a script or the GUI could
|
||||
// have broken -- hence "warning", not "error" the way
|
||||
// potential_mismatch is (which the app's own edits can never
|
||||
// produce, so any occurrence there is definitely external tampering).
|
||||
// Terminals are matched by index between the two linked elements: a
|
||||
// report pair is authored as matching symbols carrying the same set
|
||||
// of wires in the same declared order, the same convention terminal
|
||||
// indexing already follows everywhere else in this API.
|
||||
QSet<Element *> visited_report;
|
||||
for (int f = 0; f < diagrams.count(); ++f) {
|
||||
if (folioIndex >= 0 && f != folioIndex) continue;
|
||||
DiagramContent content(diagrams.at(f), false);
|
||||
for (Element *elmt : std::as_const(content.m_elements)) {
|
||||
if (elmt->linkType() != Element::NextReport
|
||||
&& elmt->linkType() != Element::PreviousReport) continue;
|
||||
if (visited_report.contains(elmt)) continue;
|
||||
|
||||
const QList<Element *> linked = elmt->linkedElements();
|
||||
for (Element *other : linked) {
|
||||
if (visited_report.contains(other)) continue;
|
||||
visited_report << elmt << other;
|
||||
|
||||
const QList<Terminal *> ta = elmt->terminals();
|
||||
const QList<Terminal *> tb = other->terminals();
|
||||
const int n = qMin(ta.count(), tb.count());
|
||||
auto *other_diagram = qobject_cast<Diagram *>(other->scene());
|
||||
const int other_folio = other_diagram ? diagrams.indexOf(other_diagram) : -1;
|
||||
|
||||
for (int i = 0; i < n; ++i) {
|
||||
const QList<Conductor *> ca = ta.at(i)->conductors();
|
||||
const QList<Conductor *> cb = tb.at(i)->conductors();
|
||||
// ambiguous (>1) or unconnected (0) on either side:
|
||||
// nothing to meaningfully compare
|
||||
if (ca.count() != 1 || cb.count() != 1) continue;
|
||||
|
||||
for (const QString &prop : checked_properties) {
|
||||
const QString va = conductorPropertyValue(ca.first()->properties(), prop);
|
||||
const QString vb = conductorPropertyValue(cb.first()->properties(), prop);
|
||||
if (va == vb) continue;
|
||||
QVariantMap finding;
|
||||
finding.insert(QStringLiteral("kind"), QStringLiteral("report_link_mismatch"));
|
||||
finding.insert(QStringLiteral("severity"), QStringLiteral("warning"));
|
||||
finding.insert(QStringLiteral("folio"), f);
|
||||
finding.insert(QStringLiteral("element"), elmt->uuid().toString());
|
||||
finding.insert(QStringLiteral("otherFolio"), other_folio);
|
||||
finding.insert(QStringLiteral("otherElement"), other->uuid().toString());
|
||||
finding.insert(QStringLiteral("terminal"), i);
|
||||
finding.insert(QStringLiteral("property"), prop);
|
||||
finding.insert(QStringLiteral("values"), QStringList{va, vb});
|
||||
finding.insert(QStringLiteral("message"),
|
||||
QStringLiteral("folio-link conductor disagrees on %1 across the "
|
||||
"link: '%2' vs '%3'").arg(prop, va, vb));
|
||||
findings << finding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return findings;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user