| 483 | return true; |
| 484 | } |
| 485 | static bool pickCirclesByClick(Document_Interface* doc, QWidget* parent, QList<Plug_Entity*>& outSel, const QString& purpose) { |
| 486 | outSel.clear(); |
| 487 | if (!doc) return false; |
| 488 | |
| 489 | const QString title = QStringLiteral("CircleTools"); |
| 490 | |
| 491 | QSet<qulonglong> seenIds; |
| 492 | QSet<QString> seenGeom; |
| 493 | |
| 494 | for (;;) { |
| 495 | // IMPORTANT: QC_ActionGetEnt completes on LEFT click. |
| 496 | // Right-click behavior is inconsistent across builds (can crash in some setups), |
| 497 | // therefore we finish picking with ESC / cancel, or with the dialog below. |
| 498 | Plug_Entity* ent = doc->getEnt( |
| 499 | QStringLiteral("Click a CIRCLE to %1.\nPress ESC to finish picking.") |
| 500 | .arg(purpose) |
| 501 | ); |
| 502 | |
| 503 | if (!ent) break; // ESC / cancel => finish |
| 504 | |
| 505 | QHash<int, QVariant> data; |
| 506 | ent->getData(&data); |
| 507 | |
| 508 | if (data.value(DPI::ETYPE).toInt() != static_cast<int>(DPI::CIRCLE)) { |
| 509 | delete ent; |
| 510 | continue; |
| 511 | } |
| 512 | |
| 513 | const qulonglong eid = static_cast<qulonglong>(data.value(DPI::EID).toULongLong()); |
| 514 | if (eid != 0) { |
| 515 | if (seenIds.contains(eid)) { |
| 516 | delete ent; |
| 517 | continue; |
| 518 | } |
| 519 | seenIds.insert(eid); |
| 520 | } else { |
| 521 | const QString k = circleGeomKey(data); |
| 522 | if (seenGeom.contains(k)) { |
| 523 | delete ent; |
| 524 | continue; |
| 525 | } |
| 526 | seenGeom.insert(k); |
| 527 | } |
| 528 | |
| 529 | outSel.append(ent); |
| 530 | |
| 531 | const auto ret = QMessageBox::question( |
| 532 | parent, |
| 533 | title, |
| 534 | QStringLiteral("Add another circle?\n\nYes = pick more\nNo = finish"), |
| 535 | QMessageBox::Yes | QMessageBox::No, |
| 536 | QMessageBox::Yes |
| 537 | ); |
| 538 | if (ret != QMessageBox::Yes) break; |
| 539 | } |
| 540 | |
| 541 | if (outSel.isEmpty()) { |
| 542 | QMessageBox::information(parent, |
no test coverage detected