| 1041 | } |
| 1042 | |
| 1043 | void QmitknnInteractiveToolGUI::OnToolDeactivated() |
| 1044 | { |
| 1045 | if (!m_AutoCreatedLabelValue.has_value()) |
| 1046 | return; |
| 1047 | |
| 1048 | // Capture state locally and clear our tracking. Lock() returns a |
| 1049 | // SmartPointer that keeps the segmentation alive for the deferred call. |
| 1050 | auto segmentationPtr = m_AutoCreatedLabelSegmentation.Lock(); |
| 1051 | const auto value = *m_AutoCreatedLabelValue; |
| 1052 | const auto previousActive = m_PreviousActiveLabelValue; |
| 1053 | auto* inspector = this->GetMultiLabelInspector(); |
| 1054 | this->InvalidateAutoCreatedLabel(); |
| 1055 | |
| 1056 | if (segmentationPtr.IsNull()) |
| 1057 | return; |
| 1058 | |
| 1059 | // Defer the destructive part to the next event-loop tick. |
| 1060 | // |
| 1061 | // - Normal user-initiated tool switch: the Qt event loop is alive, so the |
| 1062 | // lambda fires a tick later, after any synchronous BlueBerry chatter |
| 1063 | // from the tool-switch path has settled. |
| 1064 | // |
| 1065 | // - Workbench close: BlueBerry's Workbench::Close() runs synchronously and |
| 1066 | // tears down views/widgets in a sequence that leaves some segmentation |
| 1067 | // observers (renderer mappers, etc.) dangling. When it eventually quits |
| 1068 | // the Qt event loop, pending single-shot timers are discarded, so our |
| 1069 | // lambda never fires and RemoveLabel is never called. Harmless: the |
| 1070 | // unused label vanishes with the application anyway. |
| 1071 | QTimer::singleShot(0, qApp, [segmentationPtr, value, previousActive, inspector]() { |
| 1072 | if (QCoreApplication::closingDown()) |
| 1073 | return; |
| 1074 | |
| 1075 | auto* segmentation = segmentationPtr.GetPointer(); |
| 1076 | |
| 1077 | if (segmentation == nullptr || !segmentation->ExistLabel(value)) |
| 1078 | return; |
| 1079 | |
| 1080 | if (!segmentation->IsEmpty(value, 0)) |
| 1081 | return; |
| 1082 | |
| 1083 | const auto* activeLabel = segmentation->GetActiveLabel(); |
| 1084 | if (activeLabel != nullptr && activeLabel->GetValue() == value) |
| 1085 | { |
| 1086 | mitk::MultiLabelSegmentation::LabelValueType fallback = 0; |
| 1087 | bool haveFallback = false; |
| 1088 | |
| 1089 | if (previousActive.has_value() && *previousActive != value && segmentation->ExistLabel(*previousActive)) |
| 1090 | { |
| 1091 | fallback = *previousActive; |
| 1092 | haveFallback = true; |
| 1093 | } |
| 1094 | else |
| 1095 | { |
| 1096 | for (const auto& label : segmentation->GetLabels()) |
| 1097 | { |
| 1098 | if (label.IsNotNull() && label->GetValue() != value) |
| 1099 | { |
| 1100 | fallback = label->GetValue(); |
nothing calls this directly
no test coverage detected