diff --git a/src/app/main.cpp b/src/app/main.cpp index 9f6e6e5..6bfc25b 100644 --- a/src/app/main.cpp +++ b/src/app/main.cpp @@ -510,7 +510,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re QAction* aAnoPoint = anomMenu->addAction(QStringLiteral("点")); QAction* aAnoLine = anomMenu->addAction(QStringLiteral("线")); QAction* aAnoFace = anomMenu->addAction(QStringLiteral("面")); - QAction* aSave = menu.addAction(QStringLiteral("保存")); + // 「保存」仅对未保存(临时)切片显示——已保存切片定稿锁定、不可再改/再存(用户要求)。 + QAction* aSave = interactionMgr->selectedSliceDsId().empty() + ? menu.addAction(QStringLiteral("保存")) + : nullptr; QMenu* expMenu = menu.addMenu(QStringLiteral("导出")); QAction* aImg = expMenu->addAction(QStringLiteral("图片")); QAction* aDat = expMenu->addAction(QStringLiteral("dat")); @@ -630,7 +633,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re []() { /* onCancel:放弃,无需处理 */ }); return; } - if (chosen == aSave) { + if (aSave != nullptr && chosen == aSave) { int axis = 3; geopro::render::interact::Vec3 o{}, p1{}, p2{}; if (!interactionMgr->selectedSlicePlane(axis, o, p1, p2)) return; diff --git a/src/app/panels/columns/CategorySection.cpp b/src/app/panels/columns/CategorySection.cpp index e6e8a58..a5f8ace 100644 --- a/src/app/panels/columns/CategorySection.cpp +++ b/src/app/panels/columns/CategorySection.cpp @@ -344,9 +344,7 @@ void CategorySection::showContextMenu(const QPoint& pos) { sl->addAction(QStringLiteral("左右"), this, [this, id] { emit sliceRequested(SliceAxis::LeftRight, id); }); sl->addAction(QStringLiteral("任意"), this, [this, id] { emit sliceRequested(SliceAxis::Oblique, id); }); menu.addAction(QStringLiteral("色阶"), this, [this, id] { emit colorScaleRequested(id); }); - } else if (ddCode == QStringLiteral("dd_slice")) { // 切片 - menu.addAction(QStringLiteral("保存"), this, [this, id] { emit sliceSaveRequested(id); }); - menu.addAction(QStringLiteral("另存为"), this, [this, id] { emit sliceSaveAsRequested(id); }); + } else if (ddCode == QStringLiteral("dd_slice")) { // 切片(列表中均为已保存=定稿锁定,无保存/另存) QMenu* ex = menu.addMenu(QStringLiteral("导出")); ex->addAction(QStringLiteral("图片"), this, [this, id] { emit sliceExportImageRequested(id); }); ex->addAction(QStringLiteral("dat"), this, [this, id] { emit sliceExportDatRequested(id); }); diff --git a/src/render/interact/InteractionManager.cpp b/src/render/interact/InteractionManager.cpp index 5291f8c..1b6f63a 100644 --- a/src/render/interact/InteractionManager.cpp +++ b/src/render/interact/InteractionManager.cpp @@ -168,6 +168,7 @@ void InteractionManager::showSavedSlice(const std::string& dsId, int axis, const tool->setVolumeDsId(volumeDsId); SliceTool* tp = tool.get(); tool->onInteract = [this, tp]() { selectByTool(tp); }; + tool->setInteractive(false); // 已保存切片定稿锁定:不可移动/旋转(用户要求);仍可拾取选中/右键 slices_.push_back(std::move(tool)); selected_ = static_cast(slices_.size()) - 1; updateSelectionVisual(); // 程序化显示(syncSlices):不发 onSliceSelectionChanged,避免列表选中被刷 @@ -289,6 +290,7 @@ std::string InteractionManager::selectedSliceVolumeDsId() const { void InteractionManager::tagSelectedSlice(const std::string& dsId) { if (selected_ < 0 || selected_ >= static_cast(slices_.size())) return; slices_[static_cast(selected_)]->setDsId(dsId); + slices_[static_cast(selected_)]->setInteractive(false); // 保存即定稿锁定(不可改) } vtkImageData* InteractionManager::selectedSliceImage() const { diff --git a/src/render/interact/SliceTool.cpp b/src/render/interact/SliceTool.cpp index 26052f2..45b1b19 100644 --- a/src/render/interact/SliceTool.cpp +++ b/src/render/interact/SliceTool.cpp @@ -171,6 +171,10 @@ vtkImageData* SliceTool::reslicedOutput() const { return widget_ ? widget_->GetResliceOutput() : nullptr; } +void SliceTool::setInteractive(bool on) { + if (widget_) widget_->SetInteraction(on ? 1 : 0); // 关=锁移动/旋转/光标,纹理仍显示 +} + vtkSmartPointer SliceTool::coloredResliceImage() const { if (!widget_) return nullptr; vtkImageMapToColors* cm = widget_->GetColorMap(); // widget 内部把 reslice 经 LUT 上色 → 纹理 diff --git a/src/render/interact/SliceTool.hpp b/src/render/interact/SliceTool.hpp index 277c9b4..dfcbd56 100644 --- a/src/render/interact/SliceTool.hpp +++ b/src/render/interact/SliceTool.hpp @@ -80,6 +80,9 @@ public: // 与屏幕切片纹理同源的着色输出(widget 自己的 ColorMap 输出, RGBA, 逐像素一致, 外区透明)。 // 异常截图/导出用它而非另建 LUT,避免与屏幕配色不一致(用户实测差异大)。 vtkSmartPointer coloredResliceImage() const; + // 开/关 widget 鼠标交互(移动/旋转/光标)。关=锁定但仍显示(已保存切片定稿不可改); + // 拾取选中/右键菜单由 PickInteractorStyle 独立处理,不受此影响。 + void setInteractive(bool on); // 关闭:Off() 并解除 interactor 绑定(幂等)。 void close();