From d95e744494bc410cd049cf490e91a026ace5e410 Mon Sep 17 00:00:00 2001 From: Kellermorph Date: Sun, 9 Aug 2026 09:11:40 +0200 Subject: [PATCH] autoBreakConductors: share conductors_handled/used_terminals across batch When multiple elements are pasted or moved in one batch, each call to autoBreakConductors() now receives the shared state from the previous call. This prevents two elements in the same batch from independently claiming the same conductor, which would result in a double-delete on redo(). Requested by ispyisail in PR review. --- sources/autobreakconductor.cpp | 7 +++---- sources/autobreakconductor.h | 21 +++++++++++++------ sources/diagramcommands.cpp | 5 ++++- .../diagramevent/diagrameventaddelement.cpp | 5 ++++- sources/elementsmover.cpp | 5 ++++- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/sources/autobreakconductor.cpp b/sources/autobreakconductor.cpp index 2e2966f73..944f106d8 100644 --- a/sources/autobreakconductor.cpp +++ b/sources/autobreakconductor.cpp @@ -71,16 +71,15 @@ qreal distanceToSegment(const QPointF &point, const QLineF &segment) QSet autoBreakConductors( Diagram *diagram, Element *element, - QUndoCommand *parent) + QUndoCommand *parent, + QList &conductors_handled, + QSet &used_terminals) { QSet broken_endpoints; if (!diagram->project()->autoBreakConductor()) return broken_endpoints; - QList conductors_handled; - QSet used_terminals; - foreach (Terminal *t, element->terminals()) { if (used_terminals.contains(t)) diff --git a/sources/autobreakconductor.h b/sources/autobreakconductor.h index 532eecd05..3818e6c5b 100644 --- a/sources/autobreakconductor.h +++ b/sources/autobreakconductor.h @@ -19,10 +19,12 @@ #define AUTOBREAKCONDUCTOR_H #include +#include class Diagram; class Element; class Terminal; +class Conductor; class QUndoCommand; /** @@ -32,17 +34,24 @@ class QUndoCommand; element's terminal. Broken conductors from the same circuit (sharing the same far-end endpoint) are broken together; independent crossing conductors are left untouched. - @param diagram the diagram containing the conductors - @param element the element whose terminals trigger breaks - @param parent undo command under which break/reconnect sub-commands - are created (may be nullptr, in which case no undo is - recorded) + @param diagram the diagram containing the conductors + @param element the element whose terminals trigger breaks + @param parent undo command under which break/reconnect + sub-commands are created + @param conductors_handled shared list of conductors already claimed by + a previous call in the same batch (prevents + double-processing when multiple elements are + broken in one pass) + @param used_terminals shared set of terminals already used as + connect_to or other_terminal in the same batch @return set of terminals that were connected to a broken conductor's far-end (useful for preventing duplicate auto-connect) */ QSet autoBreakConductors( Diagram *diagram, Element *element, - QUndoCommand *parent); + QUndoCommand *parent, + QList &conductors_handled, + QSet &used_terminals); #endif // AUTOBREAKCONDUCTOR_H diff --git a/sources/diagramcommands.cpp b/sources/diagramcommands.cpp index 467524fd3..ab3a6fdeb 100644 --- a/sources/diagramcommands.cpp +++ b/sources/diagramcommands.cpp @@ -115,8 +115,11 @@ void PasteDiagramCommand::redo() if (diagram->project()->autoBreakConductor()) { m_break_cmd = new QUndoCommand(); + QList conductors_handled; + QSet used_terminals; for (Element *e : content.m_elements) { - autoBreakConductors(diagram, e, m_break_cmd); + autoBreakConductors(diagram, e, m_break_cmd, + conductors_handled, used_terminals); } if (m_break_cmd->childCount() == 0) { delete m_break_cmd; diff --git a/sources/diagramevent/diagrameventaddelement.cpp b/sources/diagramevent/diagrameventaddelement.cpp index 14b7cd5ed..94a84d7dc 100644 --- a/sources/diagramevent/diagrameventaddelement.cpp +++ b/sources/diagramevent/diagrameventaddelement.cpp @@ -265,7 +265,10 @@ void DiagramEventAddElement::addElement() //Auto break conductor: if a terminal of the new element lies on an existing //conductor, break the conductor and reconnect through the new element's terminal. //Track the endpoints of broken conductors so auto-connect doesn't create duplicates. - QSet broken_endpoints = autoBreakConductors(m_diagram, element, undo_object); + QList conductors_handled; + QSet used_terminals; + QSet broken_endpoints = autoBreakConductors(m_diagram, element, undo_object, + conductors_handled, used_terminals); //Auto-connect: collect all aligned pairs first, then filter and process. QList> aligned_pairs; diff --git a/sources/elementsmover.cpp b/sources/elementsmover.cpp index f07427349..28c8c344d 100644 --- a/sources/elementsmover.cpp +++ b/sources/elementsmover.cpp @@ -184,8 +184,11 @@ void ElementsMover::endMovement() //the element. The element is already at its final position on screen. if (m_diagram->project()->autoBreakConductor()) { + QList conductors_handled; + QSet used_terminals; for (Element *e : m_moved_content.m_elements) { - autoBreakConductors(m_diagram, e, undo_object); + autoBreakConductors(m_diagram, e, undo_object, + conductors_handled, used_terminals); } }