mirror of
https://github.com/qelectrotech/qelectrotech-source-mirror.git
synced 2026-10-25 23:54:22 +01:00
Preserve master/slave links when pasting or duplicating a folio
Reviving #659, closed 2026-09-10 purely to clear a review backlog (#630), not on merit. Rebuilt fresh against current master rather than merged from the old branch (elementspanelwidget.cpp had drifted enough that a textual merge risked silently losing content, as it did earlier in this same session for a different revival). Builds discussion #607. Cutting/copying a linked group of elements -- a relay coil with its contacts, a PLC master with its slave I/O elements -- dropped the master/slave link entirely. Traced end to end: Element::toXml() writes each partner's uuid into <link_uuid>, Element::fromXml() reads it back into a deferred, unresolved buffer (tmp_uuids_link), and the only code that ever resolves that buffer is initLink(QETProject *) -- called only from Diagram::refreshContents(), itself only called from full project load and macro-block insertion. Neither DiagramView::paste() nor ElementsPanelWidget::duplicateDiagram() ever call it, so tmp_uuids_link is populated correctly and never resolved: the link is silently dropped. duplicateDiagram() already knew this and worked around it by calling clearPendingLinks() -- correct to not link back to a stale source, but it meant folio duplication never preserved a link either. Added Element::initLink(const QList<Element *> &candidates) -- resolves against a caller-supplied list instead of a project-wide search. The scoping is the subtle part: right after the XML round-trip and before uuids are renewed, a pasted/duplicated element's tmp_uuids_link still holds its source's original partner uuid, which at that exact moment still equals the not-yet-renewed uuid of that partner's own copy, if it was carried along in the same batch. Resolving only within the batch is what stops a linked pair pasted together from matching an original element left elsewhere that happens to still carry that same soon-to-be-replaced uuid. If only one half of a linked group is in the batch, its entry finds no match and is dropped -- the same "leave it unlinked" outcome as before. Wired into PasteDiagramCommand::redo(), before the existing newUuid() loop and gated by the same first_redo flag. Wired into duplicateDiagram() the same way, replacing its clearPendingLinks() call (initLink() clears tmp_uuids_link internally, matched or not). Verified live -- the original PR's own test plan left both of these unchecked, so this closes that gap rather than repeating it. Built a project with a linked PLC master/slave pair (qet-mcp's link_elements), then drove the real interaction under Xvfb: Ctrl+A, Ctrl+C, Ctrl+V: originals 95ad58fc <-> e728632c (unchanged) pasted 513e6bf8 <-> 29aa60b4 (linked to each other) Right-click folio > "Copier et coller": originals 95ad58fc <-> e728632c (unchanged) duplicated 0a33ccb4 <-> 3264fe66 (linked to each other) Neither copy links back to an original or comes in unlinked. Qt 6.10.2, ctest 13/13. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,23 @@ void PasteDiagramCommand::redo()
|
||||
{
|
||||
first_redo = false;
|
||||
|
||||
//Resolve a linked master/slave pair pasted together (bugtracker
|
||||
//#607) before anything below renews their uuids: at this exact
|
||||
//moment a pasted element's tmp_uuids_link still holds its
|
||||
//source's original partner uuid, which still equals the
|
||||
//not-yet-renewed uuid of that partner's own pasted copy if it
|
||||
//was carried along in the same batch. Scoped to this batch only
|
||||
//(not a project-wide search), so a pair pasted together links to
|
||||
//each other and not to an original element left elsewhere that
|
||||
//happens to still carry that same soon-to-be-replaced uuid. If
|
||||
//only one half of a linked group was pasted, its link entry
|
||||
//simply finds no match here and is dropped -- same "leave it
|
||||
//unlinked" outcome as always.
|
||||
const QList <Element *> elmts_list = content.m_elements;
|
||||
for (Element *e : elmts_list) {
|
||||
e->initLink(elmts_list);
|
||||
}
|
||||
|
||||
//make new uuid for every pasted conductor, because old uuid are
|
||||
//the uuid of the copied conductor
|
||||
const QList <Conductor *> all_pasted_conductors = content.conductors();
|
||||
@@ -85,7 +102,6 @@ void PasteDiagramCommand::redo()
|
||||
}
|
||||
|
||||
//this is the first paste, we do some actions for the new element
|
||||
const QList <Element *> elmts_list = content.m_elements;
|
||||
for (Element *e : elmts_list)
|
||||
{
|
||||
//make new uuid, because old uuid are the uuid of the copied element
|
||||
|
||||
Reference in New Issue
Block a user