fix(vtk): 列表选中全局互斥+任意类型ds选中显子树贴合轴
- 解除 CategorySection itemSelectionChanged→datasetSelected 的 voxel-only 门控, 各类型段(反演帘面/轨迹/三维体等)选中均发选中信号→显子树贴合坐标轴 - 新增 CategorySection::clearSelection()(QSignalBlocker 下清选,不回发信号) - CategoryAnalysisTab 选中转发改为跨段互斥:某段选中非空则清其余各段选中, 全列至多一个 ds 选中;inSelectionSync_ 兜底防重入 - 复用既有 applyFittedAxes/subtreeDsIds/datasetBounds,无平行路径 - voxel 切片/异常高亮、视口点选贴合轴对称、T3 gnomon 均未回归
This commit is contained in:
parent
fcabf4c59f
commit
0e449e082d
|
|
@ -68,7 +68,19 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d
|
|||
&CategoryAnalysisTab::sliceExportDatRequested);
|
||||
connect(sec, &CategorySection::anomalyVisibilityChanged, this,
|
||||
&CategoryAnalysisTab::anomalyVisibilityChanged);
|
||||
connect(sec, &CategorySection::datasetSelected, this, &CategoryAnalysisTab::datasetSelected);
|
||||
// 全列互斥选中:某段选中非空数据行 → 清其余各段选中,保证整列至多一个 ds 选中,
|
||||
// 避免「电阻率段与三维体段各选一行」的二义(贴合轴该听谁)。clearSelection 内部 QSignalBlocker
|
||||
// 阻断,被清段不回发 datasetSelected(空),无环路;inSelectionSync_ 为兜底防重入。
|
||||
connect(sec, &CategorySection::datasetSelected, this,
|
||||
[this, sec](const QString& dsId, const QString& ddCode) {
|
||||
if (!dsId.isEmpty() && !inSelectionSync_) {
|
||||
inSelectionSync_ = true;
|
||||
for (auto* other : ordered_)
|
||||
if (other != sec) other->clearSelection();
|
||||
inSelectionSync_ = false;
|
||||
}
|
||||
emit datasetSelected(dsId, ddCode);
|
||||
});
|
||||
connect(sec, &CategorySection::planeZChanged, this, &CategoryAnalysisTab::planeZChanged);
|
||||
connect(sec, &CategorySection::basemapKindChanged, this,
|
||||
&CategoryAnalysisTab::basemapKindChanged);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,7 @@ private:
|
|||
QVBoxLayout* col_ = nullptr; // 段堆叠布局(末项=尾部弹簧)
|
||||
QWidget* placeholder_ = nullptr; // 全空时显示的占位提示(与 scroll_ 同级,互斥显隐)
|
||||
std::map<std::string, QStringList> checkedBySeg_; // 各段当前勾选(合并成并集)
|
||||
bool inSelectionSync_ = false; // 跨段互斥清选进行中标记(防重入信号环,clearSelection 已阻断信号,此为兜底)
|
||||
};
|
||||
|
||||
} // namespace geopro::app
|
||||
|
|
|
|||
|
|
@ -158,19 +158,21 @@ CategorySection::CategorySection(const geopro::data::CategoryDescriptor& desc,
|
|||
// 属性弹窗改由右键「详情」触发(detailRequested),双击不再弹属性框(决策6:三维体只适配、静默)。
|
||||
emit datasetActivated(id, it->data(0, kDsDdCodeRole).toString(), it->data(0, kDsNameRole).toString());
|
||||
});
|
||||
if (desc_.id == "voxel") { // 仅三维体段提供右键操作菜单(体/切片/异常)
|
||||
list_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(list_, &QTreeWidget::customContextMenuRequested, this, &CategorySection::showContextMenu);
|
||||
// 树选中切片/异常 → VTK 高亮联动(正向 list→VTK)。
|
||||
// 树选中任意数据行 → datasetSelected(各类型段通用):驱动该 ds 子树贴合坐标轴(spec §3.2),
|
||||
// 并由上层 CategoryAnalysisTab 做全列互斥。voxel 段切片/异常的 VTK 高亮由上层据 ddCode 处理,
|
||||
// 故此信号对所有段发射即可,任意类型选中都能显子树贴合轴(非仅三维体)。
|
||||
// 空选中(点树空白/清选)→ 发空 datasetSelected:上层据此恢复全景轴、清高亮(贴合轴取消)。
|
||||
connect(list_, &QTreeWidget::itemSelectionChanged, this, [this] {
|
||||
const auto items = list_->selectedItems();
|
||||
// 空选中(点树空白/清选)→ 发空 datasetSelected:上层据此恢复全景轴、清高亮(贴合轴取消,spec §3.2)。
|
||||
if (items.isEmpty()) { emit datasetSelected(QString(), QString()); return; }
|
||||
QTreeWidgetItem* it = items.first();
|
||||
const QString id = it->data(0, kDsIdRole).toString();
|
||||
const QString dd = it->data(0, kDsDdCodeRole).toString();
|
||||
if (!id.isEmpty() && dd != QStringLiteral("container")) emit datasetSelected(id, dd);
|
||||
});
|
||||
if (desc_.id == "voxel") { // 仅三维体段提供右键操作菜单(体/切片/异常)
|
||||
list_->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(list_, &QTreeWidget::customContextMenuRequested, this, &CategorySection::showContextMenu);
|
||||
}
|
||||
body->addWidget(list_, 1);
|
||||
|
||||
|
|
@ -247,6 +249,13 @@ void CategorySection::selectItem(const QString& dsId) {
|
|||
list_->setCurrentItem(nullptr); // 空 dsId / 未找到 → 清选中
|
||||
}
|
||||
|
||||
void CategorySection::clearSelection() {
|
||||
if (!list_) return;
|
||||
const QSignalBlocker block(list_); // 跨段互斥清选:被清段不回发 datasetSelected(空),避免环路/误恢复全景轴
|
||||
list_->setCurrentItem(nullptr);
|
||||
list_->clearSelection();
|
||||
}
|
||||
|
||||
void CategorySection::setChecked(const QString& dsId, bool on) {
|
||||
for (QTreeWidgetItemIterator it(list_); *it; ++it)
|
||||
if ((*it)->data(0, kDsIdRole).toString() == dsId &&
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ public:
|
|||
void setBusy(const QString& dsId, bool busy);
|
||||
void clearAllBusy(); // 撤回本段所有 spinner(失败兜底)
|
||||
void selectItem(const QString& dsId); // 程序化选中某行(VTK→list 反向联动);空/未找到=清选中
|
||||
void clearSelection(); // 清本段树选中(信号阻断,不回发 datasetSelected);供跨段全列互斥用
|
||||
QStringList checkedIds() const { return checkedDsIds(); } // 当前勾选 ds(异常显隐同步用)
|
||||
void refreshArrayFilter() { refreshArrayCombo(); } // 装置枚举异步加载后重填下拉
|
||||
bool isExpanded() const; // 段头展开态(供外层按折叠状态重分配 stretch,实现"折叠向上收")
|
||||
|
|
|
|||
Loading…
Reference in New Issue