feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
5 changed files with 59 additions and 19 deletions
Showing only changes of commit 5e15941cd2 - Show all commits

View File

@ -62,6 +62,7 @@
#include <QStatusBar> #include <QStatusBar>
#include <QStyle> #include <QStyle>
#include <QSurfaceFormat> #include <QSurfaceFormat>
#include <QSignalBlocker>
#include <QTimer> #include <QTimer>
#include <QToolBar> #include <QToolBar>
#include <QTreeWidget> #include <QTreeWidget>
@ -593,9 +594,11 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
// ── 左上对象树勾选 → 拉取各 TM 的 ds 子树按维度分发到三栏列表spec §6.1/§8── // ── 左上对象树勾选 → 拉取各 TM 的 ds 子树按维度分发到三栏列表spec §6.1/§8──
// 渲染由三栏勾选框驱动Task 7Column3DDataset::checkedDatasetsChanged → setCheckedDatasets // 渲染由三栏勾选框驱动Task 7Column3DDataset::checkedDatasetsChanged → setCheckedDatasets
auto generation = std::make_shared<unsigned long long>(0);
QObject::connect( QObject::connect(
objectTree, &geopro::app::ObjectTreePanel::checkedTmsChanged, &window, objectTree, &geopro::app::ObjectTreePanel::checkedTmsChanged, &window,
[&projectRepo, &nav, drawer, emptyState](const QStringList& tmIds) { [&projectRepo, &nav, drawer, emptyState, generation](const QStringList& tmIds) {
const unsigned long long myGen = ++(*generation);
emptyState->setVisible(tmIds.isEmpty()); // 有勾选→隐藏引导层,露出中央渲染 emptyState->setVisible(tmIds.isEmpty()); // 有勾选→隐藏引导层,露出中央渲染
if (tmIds.isEmpty()) { if (tmIds.isEmpty()) {
drawer->col3D()->setDatasets({}); drawer->col3D()->setDatasets({});
@ -606,7 +609,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
// 多 TM 异步汇总:每个 TM 取整棵 ds 子树,全部回来后按维度分发到三栏。 // 多 TM 异步汇总:每个 TM 取整棵 ds 子树,全部回来后按维度分发到三栏。
auto acc = std::make_shared<std::vector<geopro::data::DsRow>>(); auto acc = std::make_shared<std::vector<geopro::data::DsRow>>();
auto remaining = std::make_shared<int>(tmIds.size()); auto remaining = std::make_shared<int>(tmIds.size());
auto finish = [acc, drawer]() { auto finish = [acc, drawer, generation, myGen]() {
if (*generation != myGen) return; // 已被更新的勾选批次取代→丢弃陈旧结果
geopro::app::DimBuckets b = geopro::app::splitByDimension(*acc); geopro::app::DimBuckets b = geopro::app::splitByDimension(*acc);
drawer->col3D()->setDatasets(b.dim3D); drawer->col3D()->setDatasets(b.dim3D);
drawer->col2D()->setDatasets(b.dim2D); drawer->col2D()->setDatasets(b.dim2D);
@ -771,14 +775,22 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
if (vtkFsBtn) { if (vtkFsBtn) {
vtkFsBtn->setCheckable(true); vtkFsBtn->setCheckable(true);
QObject::connect(vtkFsBtn, &QToolButton::toggled, &window, QObject::connect(vtkFsBtn, &QToolButton::toggled, &window,
[applyFullscreen, vtkDock, allDocks](bool on) { [applyFullscreen, vtkDock, allDocks, detailFsBtn](bool on) {
if (on && detailFsBtn && detailFsBtn->isChecked()) {
QSignalBlocker b(detailFsBtn);
detailFsBtn->setChecked(false);
}
applyFullscreen(vtkDock, allDocks, on); applyFullscreen(vtkDock, allDocks, on);
}); });
} }
if (detailFsBtn) { if (detailFsBtn) {
detailFsBtn->setCheckable(true); detailFsBtn->setCheckable(true);
QObject::connect(detailFsBtn, &QToolButton::toggled, &window, QObject::connect(detailFsBtn, &QToolButton::toggled, &window,
[applyFullscreen, detailDock, allDocks](bool on) { [applyFullscreen, detailDock, allDocks, vtkFsBtn](bool on) {
if (on && vtkFsBtn && vtkFsBtn->isChecked()) {
QSignalBlocker b(vtkFsBtn);
vtkFsBtn->setChecked(false);
}
applyFullscreen(detailDock, allDocks, on); applyFullscreen(detailDock, allDocks, on);
}); });
} }

View File

@ -5,6 +5,7 @@
#include <QFormLayout> #include <QFormLayout>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QSignalBlocker>
#include <QTreeWidget> #include <QTreeWidget>
#include <QTreeWidgetItemIterator> #include <QTreeWidgetItemIterator>
#include <QVBoxLayout> #include <QVBoxLayout>
@ -78,12 +79,20 @@ Column2DDataset::Column2DDataset(QWidget* parent) : QWidget(parent) {
} }
void Column2DDataset::setDatasets(const std::vector<geopro::data::DsRow>& rows) { void Column2DDataset::setDatasets(const std::vector<geopro::data::DsRow>& rows) {
populateDatasetList(list_, rows, /*append=*/false); {
for (QTreeWidgetItemIterator it(list_); *it; ++it) { QSignalBlocker blocker(list_);
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); populateDatasetList(list_, rows, /*append=*/false);
if ((*it)->checkState(0) != Qt::Checked) for (QTreeWidgetItemIterator it(list_); *it; ++it) {
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable);
(*it)->setCheckState(0, Qt::Unchecked); (*it)->setCheckState(0, Qt::Unchecked);
} }
} // blocker released here
// 填充后统一发一次(新载入必为空选):清掉上一次的渲染勾选
QStringList ids;
for (QTreeWidgetItemIterator it(list_); *it; ++it)
if ((*it)->checkState(0) == Qt::Checked)
ids << (*it)->data(0, kDsIdRole).toString();
emit checkedDatasetsChanged(ids);
} }
} // namespace geopro::app } // namespace geopro::app

View File

@ -1,6 +1,7 @@
#include "panels/columns/Column3DAnalysis.hpp" #include "panels/columns/Column3DAnalysis.hpp"
#include <QMenu> #include <QMenu>
#include <QSignalBlocker>
#include <QTreeWidget> #include <QTreeWidget>
#include <QTreeWidgetItem> #include <QTreeWidgetItem>
#include <QTreeWidgetItemIterator> #include <QTreeWidgetItemIterator>
@ -37,12 +38,20 @@ Column3DAnalysis::Column3DAnalysis(QWidget* parent) : QWidget(parent) {
} }
void Column3DAnalysis::setDatasets(const std::vector<geopro::data::DsRow>& rows) { void Column3DAnalysis::setDatasets(const std::vector<geopro::data::DsRow>& rows) {
populateDatasetList(tree_, rows, /*append=*/false); {
for (QTreeWidgetItemIterator it(tree_); *it; ++it) { QSignalBlocker blocker(tree_);
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); populateDatasetList(tree_, rows, /*append=*/false);
if ((*it)->checkState(0) != Qt::Checked) for (QTreeWidgetItemIterator it(tree_); *it; ++it) {
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable);
(*it)->setCheckState(0, Qt::Unchecked); (*it)->setCheckState(0, Qt::Unchecked);
} }
} // blocker released here
// 填充后统一发一次(新载入必为空选):清掉上一次的渲染勾选
QStringList ids;
for (QTreeWidgetItemIterator it(tree_); *it; ++it)
if ((*it)->checkState(0) == Qt::Checked)
ids << (*it)->data(0, kDsIdRole).toString();
emit checkedItemsChanged(ids);
} }
void Column3DAnalysis::onContextMenu(const QPoint& pos) { void Column3DAnalysis::onContextMenu(const QPoint& pos) {

View File

@ -15,6 +15,7 @@ class Column3DAnalysis : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit Column3DAnalysis(QWidget* parent = nullptr); explicit Column3DAnalysis(QWidget* parent = nullptr);
// 本期:按 ds parentId 建树(切片挂源数据下);完整 对象→三维体→切片 三级树待后端数据(P4)。
void setDatasets(const std::vector<geopro::data::DsRow>& rows); // Analysis 维度(三维体/切片) void setDatasets(const std::vector<geopro::data::DsRow>& rows); // Analysis 维度(三维体/切片)
signals: signals:

View File

@ -5,6 +5,7 @@
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QPushButton> #include <QPushButton>
#include <QSignalBlocker>
#include <QSlider> #include <QSlider>
#include <QTreeWidget> #include <QTreeWidget>
#include <QTreeWidgetItemIterator> #include <QTreeWidgetItemIterator>
@ -125,12 +126,20 @@ Column3DDataset::Column3DDataset(QWidget* parent) : QWidget(parent) {
} }
void Column3DDataset::setDatasets(const std::vector<geopro::data::DsRow>& rows) { void Column3DDataset::setDatasets(const std::vector<geopro::data::DsRow>& rows) {
populateDatasetList(list_, rows, /*append=*/false); {
for (QTreeWidgetItemIterator it(list_); *it; ++it) { QSignalBlocker blocker(list_);
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable); populateDatasetList(list_, rows, /*append=*/false);
if ((*it)->checkState(0) != Qt::Checked) for (QTreeWidgetItemIterator it(list_); *it; ++it) {
(*it)->setFlags((*it)->flags() | Qt::ItemIsUserCheckable);
(*it)->setCheckState(0, Qt::Unchecked); (*it)->setCheckState(0, Qt::Unchecked);
} }
} // blocker released here
// 填充后统一发一次(新载入必为空选):清掉上一次的渲染勾选
QStringList ids;
for (QTreeWidgetItemIterator it(list_); *it; ++it)
if ((*it)->checkState(0) == Qt::Checked)
ids << (*it)->data(0, kDsIdRole).toString();
emit checkedDatasetsChanged(ids);
} }
} // namespace geopro::app } // namespace geopro::app