From 7d718bb9a027adb9fe475fcd5fbb04fbc9c53aff Mon Sep 17 00:00:00 2001 From: Laurent Trinques Date: Sat, 23 May 2026 15:50:11 +0200 Subject: [PATCH] crossrefitem: fix terminal name sorting for power contacts The previous sort used QString::toInt() to order terminal names, which returns 0 for any string containing a non-numeric prefix (e.g. "R1", "R2", "L1", "L2"...). This caused undefined sort order and incorrect pole pairing in the Xref contact mirror. Example: a 4-pole NC power contact with terminals R1..R8 was displaying R1/R3, R5/R7, R2/R4, R6/R8 instead of the correct R1/R2, R3/R4, R5/R6, R7/R8. Fix: extract the trailing numeric part of each terminal name and compare prefixes separately. If both names share the same prefix and both have a trailing number, sort numerically on that number; otherwise fall back to full string comparison. This covers all naming conventions: "1"/"2"/"3", "R1"/"R2"/"R3", "L1"/"L2"/"L3", etc. Applied in both drawContact() and setUpCrossBoundingRect(). --- sources/qetgraphicsitem/crossrefitem.cpp | 26 ++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/sources/qetgraphicsitem/crossrefitem.cpp b/sources/qetgraphicsitem/crossrefitem.cpp index cf342bade..4a5ab07a7 100644 --- a/sources/qetgraphicsitem/crossrefitem.cpp +++ b/sources/qetgraphicsitem/crossrefitem.cpp @@ -560,7 +560,16 @@ void CrossRefItem::setUpCrossBoundingRect(QPainter &painter) if (is_power) { std::sort(tnames.begin(), tnames.end(), [](const QString &a, const QString &b){ - return a.toInt() < b.toInt(); + int i_a = a.size(); + while (i_a > 0 && a[i_a-1].isDigit()) --i_a; + int i_b = b.size(); + while (i_b > 0 && b[i_b-1].isDigit()) --i_b; + bool a_ok = false, b_ok = false; + int ai = a.mid(i_a).toInt(&a_ok); + int bi = b.mid(i_b).toInt(&b_ok); + if (a_ok && b_ok && a.left(i_a) == b.left(i_b)) + return ai < bi; + return a < b; }); } } @@ -741,9 +750,22 @@ QRectF CrossRefItem::drawContact(QPainter &painter, int flags, Element *elmt, in } if (is_power_ctc) { + // Sort terminals alphanumerically so names like "R1","R2"... or "1","2"... + // are ordered correctly. Extract trailing digits for numeric comparison; + // fall back to full string comparison when no digits are found. std::sort(terminal_names.begin(), terminal_names.end(), [](const QString &a, const QString &b){ - return a.toInt() < b.toInt(); + // Extract trailing numeric part + int i_a = a.size(); + while (i_a > 0 && a[i_a-1].isDigit()) --i_a; + int i_b = b.size(); + while (i_b > 0 && b[i_b-1].isDigit()) --i_b; + bool a_ok = false, b_ok = false; + int ai = a.mid(i_a).toInt(&a_ok); + int bi = b.mid(i_b).toInt(&b_ok); + if (a_ok && b_ok && a.left(i_a) == b.left(i_b)) + return ai < bi; + return a < b; }); // Pick the pair for this pole: pole 0 → [0,1], pole 1 → [2,3], etc. int idx = pole_index * 2;