| 695 | |
| 696 | |
| 697 | void CircleToolsPlugin::opFindMoveToLayer(Document_Interface* doc, QWidget* parent) { |
| 698 | const QString title = QStringLiteral("CircleTools"); |
| 699 | |
| 700 | RefCircle ref; |
| 701 | if (!promptReferenceCircle(doc, parent, ref)) return; |
| 702 | |
| 703 | double tol = 0.0; |
| 704 | if (!promptTolerance(doc, parent, tol)) return; |
| 705 | |
| 706 | int layerMode = 0; |
| 707 | QString layerName; |
| 708 | if (!promptLayerFilter(doc, parent, layerMode, layerName)) return; |
| 709 | |
| 710 | QString targetLayer; |
| 711 | if (!promptTargetLayerCombo(doc, parent, title, targetLayer)) return; |
| 712 | |
| 713 | ensureLayerExists(doc, targetLayer); |
| 714 | |
| 715 | const CircleStats statsBefore = scanCircleStats(doc); |
| 716 | logSep(); |
| 717 | logLine(QStringLiteral("opFindMoveToLayer START refDia=%1 tol=%2 layerMode=%3 layerName='%4' target='%5'") |
| 718 | .arg(ref.diameter).arg(tol).arg(layerMode).arg(layerName).arg(targetLayer)); |
| 719 | logLine(QStringLiteral("BEFORE %1").arg(statsText(statsBefore))); |
| 720 | |
| 721 | QList<Plug_Entity*> all; |
| 722 | if (!doc->getAllEntities(&all, false)) return; |
| 723 | |
| 724 | int matched = 0; |
| 725 | int checked = 0; |
| 726 | |
| 727 | QSet<qulonglong> seenIds; |
| 728 | QSet<QString> seenGeom; |
| 729 | QSet<QString> matchedGeomKeys; |
| 730 | QList<Plug_Entity*> toMove; |
| 731 | toMove.reserve(all.size()); |
| 732 | |
| 733 | // Pass 1: scan + count using a stable de-dup (prevents "imaginary" extra circles) |
| 734 | for (Plug_Entity* e : all) { |
| 735 | if (!e) continue; |
| 736 | QHash<int, QVariant> data; |
| 737 | e->getData(&data); |
| 738 | |
| 739 | if (!isCircle(data)) continue; |
| 740 | |
| 741 | // IMPORTANT: ignore invisible entities (undo/redo history, not shown in the drawing) |
| 742 | const int vis = data.contains(DPI::VISIBLE) ? data.value(DPI::VISIBLE).toInt() : 1; |
| 743 | if (vis != 1) continue; |
| 744 | |
| 745 | const QString lay = data.value(DPI::LAYER).toString(); |
| 746 | if (layerMode == 1 && lay != ref.layer) continue; |
| 747 | if (layerMode == 2 && lay != layerName) continue; |
| 748 | |
| 749 | // Dedupe ALWAYS also by geometry: |
| 750 | // fixes cases where the same real circle appears as multiple wrappers (even with different EID) |
| 751 | const QString gk = circleGeomKey(data); |
| 752 | if (seenGeom.contains(gk)) continue; |
| 753 | seenGeom.insert(gk); |
| 754 |
nothing calls this directly
no test coverage detected